Blame test/mpi/perf/indexperf.c

Packit 0848f5
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
Packit 0848f5
/*
Packit 0848f5
 *  (C) 2012 by Argonne National Laboratory.
Packit 0848f5
 *      See COPYRIGHT in top-level directory.
Packit 0848f5
 */
Packit 0848f5
Packit 0848f5
/*
Packit 0848f5
 * Tests that basic optimizations are performed on indexed datatypes.
Packit 0848f5
 *
Packit 0848f5
 * If PACK_IS_NATIVE is defined, MPI_Pack stores exactly the same bytes as the
Packit 0848f5
 * user would pack manually; in that case, there is a consistency check.
Packit 0848f5
 */
Packit 0848f5
Packit 0848f5
#ifdef MPICH
Packit 0848f5
/* MPICH (as of 6/2012) packs the native bytes */
Packit 0848f5
#define PACK_IS_NATIVE
Packit 0848f5
#endif
Packit 0848f5
Packit 0848f5
#include "mpi.h"
Packit 0848f5
#include <stdio.h>
Packit 0848f5
#include <stdlib.h>
Packit 0848f5
#include <string.h>
Packit 0848f5
Packit 0848f5
static int verbose = 0;
Packit 0848f5
Packit 0848f5
int main(int argc, char **argv)
Packit 0848f5
{
Packit 0848f5
    double *inbuf, *outbuf, *outbuf2;
Packit 0848f5
    MPI_Aint lb, extent;
Packit 0848f5
    int *index_displacement;
Packit 0848f5
    int icount, errs = 0;
Packit 0848f5
    int i, packsize, position, inbufsize;
Packit 0848f5
    MPI_Datatype itype1, stype1;
Packit 0848f5
    double t0, t1;
Packit 0848f5
    double tpack, tspack, tmanual;
Packit 0848f5
    int ntry;
Packit 0848f5
Packit 0848f5
    MPI_Init(&argc, &argv);
Packit 0848f5
Packit 0848f5
    icount = 2014;
Packit 0848f5
Packit 0848f5
    /* Create a simple block indexed datatype */
Packit 0848f5
    index_displacement = (int *) malloc(icount * sizeof(int));
Packit 0848f5
    if (!index_displacement) {
Packit 0848f5
        fprintf(stderr, "Unable to allocated index array of size %d\n", icount);
Packit 0848f5
        MPI_Abort(MPI_COMM_WORLD, 1);
Packit 0848f5
    }
Packit 0848f5
Packit 0848f5
    for (i = 0; i < icount; i++) {
Packit 0848f5
        index_displacement[i] = (i * 3 + (i % 3));
Packit 0848f5
    }
Packit 0848f5
Packit 0848f5
    MPI_Type_create_indexed_block(icount, 1, index_displacement, MPI_DOUBLE, &itype1);
Packit 0848f5
    MPI_Type_commit(&itype1);
Packit 0848f5
Packit 0848f5
#if defined(MPICH) && defined(PRINT_DATATYPE_INTERNALS)
Packit 0848f5
    /* To use MPIDU_Datatype_debug to print the datatype internals,
Packit 0848f5
     * you must configure MPICH with --enable-g=log */
Packit 0848f5
    if (verbose) {
Packit 0848f5
        printf("Block index datatype:\n");
Packit 0848f5
        MPIDU_Datatype_debug(itype1, 10);
Packit 0848f5
    }
Packit 0848f5
#endif
Packit 0848f5
    MPI_Type_get_extent(itype1, &lb, &extent);
Packit 0848f5
Packit 0848f5
    MPI_Pack_size(1, itype1, MPI_COMM_WORLD, &packsize);
Packit 0848f5
Packit 0848f5
    inbufsize = extent / sizeof(double);
Packit 0848f5
Packit 0848f5
    inbuf = (double *) malloc(extent);
Packit 0848f5
    outbuf = (double *) malloc(packsize);
Packit 0848f5
    outbuf2 = (double *) malloc(icount * sizeof(double));
Packit 0848f5
    if (!inbuf) {
Packit 0848f5
        fprintf(stderr, "Unable to allocate %ld for inbuf\n", (long) extent);
Packit 0848f5
        MPI_Abort(MPI_COMM_WORLD, 1);
Packit 0848f5
    }
Packit 0848f5
    if (!outbuf) {
Packit 0848f5
        fprintf(stderr, "Unable to allocate %ld for outbuf\n", (long) packsize);
Packit 0848f5
        MPI_Abort(MPI_COMM_WORLD, 1);
Packit 0848f5
    }
Packit 0848f5
    if (!outbuf2) {
Packit 0848f5
        fprintf(stderr, "Unable to allocate %ld for outbuf2\n", (long) packsize);
Packit 0848f5
        MPI_Abort(MPI_COMM_WORLD, 1);
Packit 0848f5
    }
Packit 0848f5
    for (i = 0; i < inbufsize; i++) {
Packit 0848f5
        inbuf[i] = (double) i;
Packit 0848f5
    }
Packit 0848f5
    position = 0;
Packit 0848f5
    /* Warm up the code and data */
Packit 0848f5
    MPI_Pack(inbuf, 1, itype1, outbuf, packsize, &position, MPI_COMM_WORLD);
Packit 0848f5
Packit 0848f5
    tpack = 1e12;
Packit 0848f5
    for (ntry = 0; ntry < 5; ntry++) {
Packit 0848f5
        position = 0;
Packit 0848f5
        t0 = MPI_Wtime();
Packit 0848f5
        MPI_Pack(inbuf, 1, itype1, outbuf, packsize, &position, MPI_COMM_WORLD);
Packit 0848f5
        t1 = MPI_Wtime() - t0;
Packit 0848f5
        if (t1 < tpack)
Packit 0848f5
            tpack = t1;
Packit 0848f5
    }
Packit 0848f5
Packit 0848f5
    {
Packit 0848f5
        int one = 1;
Packit 0848f5
        MPI_Aint displ = (MPI_Aint) inbuf;
Packit 0848f5
        MPI_Type_create_struct(1, &one, &displ, &itype1, &stype1);
Packit 0848f5
        MPI_Type_commit(&stype1);
Packit 0848f5
    }
Packit 0848f5
Packit 0848f5
    position = 0;
Packit 0848f5
    /* Warm up the code and data */
Packit 0848f5
    MPI_Pack(MPI_BOTTOM, 1, stype1, outbuf, packsize, &position, MPI_COMM_WORLD);
Packit 0848f5
Packit 0848f5
    tspack = 1e12;
Packit 0848f5
    for (ntry = 0; ntry < 5; ntry++) {
Packit 0848f5
        position = 0;
Packit 0848f5
        t0 = MPI_Wtime();
Packit 0848f5
        MPI_Pack(MPI_BOTTOM, 1, stype1, outbuf, packsize, &position, MPI_COMM_WORLD);
Packit 0848f5
        t1 = MPI_Wtime() - t0;
Packit 0848f5
        if (t1 < tspack)
Packit 0848f5
            tspack = t1;
Packit 0848f5
    }
Packit 0848f5
Packit 0848f5
    /*
Packit 0848f5
     * Simple manual pack (without explicitly unrolling the index block)
Packit 0848f5
     */
Packit 0848f5
    tmanual = 1e12;
Packit 0848f5
    for (ntry = 0; ntry < 5; ntry++) {
Packit 0848f5
        const double *ppe = (const double *) inbuf;
Packit 0848f5
        const int *id = (const int *) index_displacement;
Packit 0848f5
        int k, j;
Packit 0848f5
        t0 = MPI_Wtime();
Packit 0848f5
        position = 0;
Packit 0848f5
        for (i = 0; i < icount; i++) {
Packit 0848f5
            outbuf2[position++] = ppe[id[i]];
Packit 0848f5
        }
Packit 0848f5
        t1 = MPI_Wtime() - t0;
Packit 0848f5
        if (t1 < tmanual)
Packit 0848f5
            tmanual = t1;
Packit 0848f5
        /* Check on correctness */
Packit 0848f5
#ifdef PACK_IS_NATIVE
Packit 0848f5
        if (memcmp(outbuf, outbuf2, position) != 0) {
Packit 0848f5
            printf("Panic - pack buffers differ\n");
Packit 0848f5
        }
Packit 0848f5
#endif
Packit 0848f5
    }
Packit 0848f5
Packit 0848f5
    if (verbose) {
Packit 0848f5
        printf("Bytes packed = %d\n", position);
Packit 0848f5
        printf("MPI_Pack time = %e, manual pack time = %e\n", tpack, tmanual);
Packit 0848f5
        printf("Pack with struct = %e\n", tspack);
Packit 0848f5
    }
Packit 0848f5
Packit 0848f5
    /* The threshold here permits the MPI datatype to perform at up to
Packit 0848f5
     * only one half the performance of simple user code.  Note that the
Packit 0848f5
     * example code above may be made faster through careful use of const,
Packit 0848f5
     * restrict, and unrolling if the compiler doesn't already do that. */
Packit 0848f5
    if (2 * tmanual < tpack) {
Packit 0848f5
        errs++;
Packit 0848f5
        printf("MPI_Pack (block index) time = %e, manual pack time = %e\n", tpack, tmanual);
Packit 0848f5
        printf("MPI_Pack time should be less than 2 times the manual time\n");
Packit 0848f5
        printf("For most informative results, be sure to compile this test with optimization\n");
Packit 0848f5
    }
Packit 0848f5
    if (2 * tmanual < tspack) {
Packit 0848f5
        errs++;
Packit 0848f5
        printf("MPI_Pack (struct of block index)) time = %e, manual pack time = %e\n", tspack,
Packit 0848f5
               tmanual);
Packit 0848f5
        printf("MPI_Pack time should be less than 2 times the manual time\n");
Packit 0848f5
        printf("For most informative results, be sure to compile this test with optimization\n");
Packit 0848f5
    }
Packit 0848f5
    if (errs) {
Packit 0848f5
        printf(" Found %d errors\n", errs);
Packit 0848f5
    }
Packit 0848f5
    else {
Packit 0848f5
        printf(" No Errors\n");
Packit 0848f5
    }
Packit 0848f5
Packit 0848f5
    MPI_Type_free(&itype1);
Packit 0848f5
    MPI_Type_free(&stype1);
Packit 0848f5
Packit 0848f5
    free(inbuf);
Packit 0848f5
    free(outbuf);
Packit 0848f5
    free(outbuf2);
Packit 0848f5
    free(index_displacement);
Packit 0848f5
Packit 0848f5
    MPI_Finalize();
Packit 0848f5
    return 0;
Packit 0848f5
}