Blame test/mpi/group/gtranksperf.c

Packit Service c5cf8c
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
Packit Service c5cf8c
/*
Packit Service c5cf8c
 *  (C) 2010 by Argonne National Laboratory.
Packit Service c5cf8c
 *      See COPYRIGHT in top-level directory.
Packit Service c5cf8c
 */
Packit Service c5cf8c
#include "mpi.h"
Packit Service c5cf8c
#include <stdio.h>
Packit Service c5cf8c
#include <stdlib.h>
Packit Service c5cf8c
#include "mpitest.h"
Packit Service c5cf8c
Packit Service c5cf8c
#include <math.h>       /* for fabs(3) */
Packit Service c5cf8c
Packit Service c5cf8c
/* Measure and compare the relative performance of MPI_Group_translate_ranks
Packit Service c5cf8c
 * with small and large group2 sizes but a constant number of ranks.  This
Packit Service c5cf8c
 * serves as a performance sanity check for the Scalasca use case where we
Packit Service c5cf8c
 * translate to MPI_COMM_WORLD ranks.  The performance should only depend on the
Packit Service c5cf8c
 * number of ranks passed, not the size of either group (especially group2).
Packit Service c5cf8c
 *
Packit Service c5cf8c
 * This test is probably only meaningful for large-ish process counts, so we may
Packit Service c5cf8c
 * not be able to run this test by default in the nightlies. */
Packit Service c5cf8c
Packit Service c5cf8c
/* number of iterations used for timing */
Packit Service c5cf8c
#define NUM_LOOPS (1000000)
Packit Service c5cf8c
Packit Service c5cf8c
int main(int argc, char *argv[])
Packit Service c5cf8c
{
Packit Service c5cf8c
    int errs = 0;
Packit Service c5cf8c
    int *ranks;
Packit Service c5cf8c
    int *ranksout;
Packit Service c5cf8c
    MPI_Group gworld, grev, gself;
Packit Service c5cf8c
    MPI_Comm comm;
Packit Service c5cf8c
    MPI_Comm commrev;
Packit Service c5cf8c
    int rank, size, i;
Packit Service c5cf8c
    double start, end, time1, time2;
Packit Service c5cf8c
Packit Service c5cf8c
    MTest_Init(&argc, &argv);
Packit Service c5cf8c
Packit Service c5cf8c
    comm = MPI_COMM_WORLD;
Packit Service c5cf8c
Packit Service c5cf8c
    MPI_Comm_size(comm, &size);
Packit Service c5cf8c
    MPI_Comm_rank(comm, &rank;;
Packit Service c5cf8c
Packit Service c5cf8c
    ranks = malloc(size * sizeof(int));
Packit Service c5cf8c
    ranksout = malloc(size * sizeof(int));
Packit Service c5cf8c
    if (!ranks || !ranksout) {
Packit Service c5cf8c
        fprintf(stderr, "out of memory\n");
Packit Service c5cf8c
        MPI_Abort(MPI_COMM_WORLD, 1);
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    /* generate a comm with the rank order reversed */
Packit Service c5cf8c
    MPI_Comm_split(comm, 0, (size - rank - 1), &commrev);
Packit Service c5cf8c
    MPI_Comm_group(commrev, &grev);
Packit Service c5cf8c
    MPI_Comm_group(MPI_COMM_SELF, &gself);
Packit Service c5cf8c
    MPI_Comm_group(comm, &gworld);
Packit Service c5cf8c
Packit Service c5cf8c
    /* sanity check correctness first */
Packit Service c5cf8c
    for (i = 0; i < size; i++) {
Packit Service c5cf8c
        ranks[i] = i;
Packit Service c5cf8c
        ranksout[i] = -1;
Packit Service c5cf8c
    }
Packit Service c5cf8c
    MPI_Group_translate_ranks(grev, size, ranks, gworld, ranksout);
Packit Service c5cf8c
    for (i = 0; i < size; i++) {
Packit Service c5cf8c
        if (ranksout[i] != (size - i - 1)) {
Packit Service c5cf8c
            if (rank == 0)
Packit Service c5cf8c
                printf("%d: (gworld) expected ranksout[%d]=%d, got %d\n", rank, i,
Packit Service c5cf8c
                       (size - rank - 1), ranksout[i]);
Packit Service c5cf8c
            ++errs;
Packit Service c5cf8c
        }
Packit Service c5cf8c
    }
Packit Service c5cf8c
    MPI_Group_translate_ranks(grev, size, ranks, gself, ranksout);
Packit Service c5cf8c
    for (i = 0; i < size; i++) {
Packit Service c5cf8c
        int expected = (i == (size - rank - 1) ? 0 : MPI_UNDEFINED);
Packit Service c5cf8c
        if (ranksout[i] != expected) {
Packit Service c5cf8c
            if (rank == 0)
Packit Service c5cf8c
                printf("%d: (gself) expected ranksout[%d]=%d, got %d\n", rank, i, expected,
Packit Service c5cf8c
                       ranksout[i]);
Packit Service c5cf8c
            ++errs;
Packit Service c5cf8c
        }
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    /* now compare relative performance */
Packit Service c5cf8c
Packit Service c5cf8c
    /* we needs lots of procs to get a group large enough to have meaningful
Packit Service c5cf8c
     * numbers.  On most testing machines this means that we're oversubscribing
Packit Service c5cf8c
     * cores in a big way, which might perturb the timing results.  So we make
Packit Service c5cf8c
     * sure everyone started up and then everyone but rank 0 goes to sleep to
Packit Service c5cf8c
     * let rank 0 do all the timings. */
Packit Service c5cf8c
    MPI_Barrier(comm);
Packit Service c5cf8c
Packit Service c5cf8c
    if (rank != 0) {
Packit Service c5cf8c
        MTestSleep(10);
Packit Service c5cf8c
    } else {    /* rank==0 */
Packit Service c5cf8c
Packit Service c5cf8c
        MTestSleep(1);  /* try to avoid timing while everyone else is making syscalls */
Packit Service c5cf8c
Packit Service c5cf8c
        MPI_Group_translate_ranks(grev, size, ranks, gworld, ranksout); /*throwaway iter */
Packit Service c5cf8c
        start = MPI_Wtime();
Packit Service c5cf8c
        for (i = 0; i < NUM_LOOPS; ++i) {
Packit Service c5cf8c
            MPI_Group_translate_ranks(grev, size, ranks, gworld, ranksout);
Packit Service c5cf8c
        }
Packit Service c5cf8c
        end = MPI_Wtime();
Packit Service c5cf8c
        time1 = end - start;
Packit Service c5cf8c
Packit Service c5cf8c
        MPI_Group_translate_ranks(grev, size, ranks, gself, ranksout);  /*throwaway iter */
Packit Service c5cf8c
        start = MPI_Wtime();
Packit Service c5cf8c
        for (i = 0; i < NUM_LOOPS; ++i) {
Packit Service c5cf8c
            MPI_Group_translate_ranks(grev, size, ranks, gself, ranksout);
Packit Service c5cf8c
        }
Packit Service c5cf8c
        end = MPI_Wtime();
Packit Service c5cf8c
        time2 = end - start;
Packit Service c5cf8c
Packit Service c5cf8c
        /* complain if the "gworld" time exceeds 2x the "gself" time */
Packit Service c5cf8c
        if (fabs(time1 - time2) > (2.00 * time2)) {
Packit Service c5cf8c
            printf("too much difference in MPI_Group_translate_ranks performance:\n");
Packit Service c5cf8c
            printf("time1=%f time2=%f\n", time1, time2);
Packit Service c5cf8c
            printf("(fabs(time1-time2)/time2)=%f\n", (fabs(time1 - time2) / time2));
Packit Service c5cf8c
            if (time1 < time2) {
Packit Service c5cf8c
                printf("also, (time1
Packit Service c5cf8c
            }
Packit Service c5cf8c
            ++errs;
Packit Service c5cf8c
        }
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    free(ranks);
Packit Service c5cf8c
    free(ranksout);
Packit Service c5cf8c
Packit Service c5cf8c
    MPI_Group_free(&grev);
Packit Service c5cf8c
    MPI_Group_free(&gself);
Packit Service c5cf8c
    MPI_Group_free(&gworld);
Packit Service c5cf8c
Packit Service c5cf8c
    MPI_Comm_free(&commrev);
Packit Service c5cf8c
Packit Service c5cf8c
    MTest_Finalize(errs);
Packit Service c5cf8c
Packit Service c5cf8c
    return MTestReturnValue(errs);
Packit Service c5cf8c
}