Blame test/mpi/perf/dtpack.c

Packit Service c5cf8c
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
Packit Service c5cf8c
/*
Packit Service c5cf8c
 *  (C) 2008 by Argonne National Laboratory.
Packit Service c5cf8c
 *      See COPYRIGHT in top-level directory.
Packit Service c5cf8c
 */
Packit Service c5cf8c
/*
Packit Service c5cf8c
 * This code may be used to test the performance of some of the
Packit Service c5cf8c
 * noncontiguous datatype operations, including vector and indexed
Packit Service c5cf8c
 * pack and unpack operations.  To simplify the use of this code for
Packit Service c5cf8c
 * tuning an MPI implementation, it uses no communication, just the
Packit Service c5cf8c
 * MPI_Pack and MPI_Unpack routines.  In addition, the individual tests are
Packit Service c5cf8c
 * in separate routines, making it easier to compare the compiler-generated
Packit Service c5cf8c
 * code for the user (manual) pack/unpack with the code used by
Packit Service c5cf8c
 * the MPI implementation.  Further, to be fair to the MPI implementation,
Packit Service c5cf8c
 * the routines are passed the source and destination buffers; this ensures
Packit Service c5cf8c
 * that the compiler can't optimize for statically allocated buffers.
Packit Service c5cf8c
 */
Packit Service c5cf8c
#include <stdio.h>
Packit Service c5cf8c
#include <stdlib.h>
Packit Service c5cf8c
#include <string.h>
Packit Service c5cf8c
#include "mpi.h"
Packit Service c5cf8c
Packit Service c5cf8c
/* Needed for restrict and const definitions */
Packit Service c5cf8c
#include "mpitest.h"
Packit Service c5cf8c
Packit Service c5cf8c
static int verbose = 0;
Packit Service c5cf8c
Packit Service c5cf8c
#define N_REPS 1000
Packit Service c5cf8c
#define THRESHOLD 0.10
Packit Service c5cf8c
#define VARIANCE_THRESHOLD ((THRESHOLD * THRESHOLD) / 2)
Packit Service c5cf8c
#define NTRIALS 10
Packit Service c5cf8c
Packit Service c5cf8c
double mean(double *list, int count);
Packit Service c5cf8c
double mean(double *list, int count)
Packit Service c5cf8c
{
Packit Service c5cf8c
    double retval;
Packit Service c5cf8c
    int i;
Packit Service c5cf8c
Packit Service c5cf8c
    retval = 0;
Packit Service c5cf8c
    for (i = 0; i < count; i++)
Packit Service c5cf8c
        retval += list[i];
Packit Service c5cf8c
    retval /= count;
Packit Service c5cf8c
Packit Service c5cf8c
    return retval;
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
double noise(double *list, int count);
Packit Service c5cf8c
double noise(double *list, int count)
Packit Service c5cf8c
{
Packit Service c5cf8c
    double *margin, retval;
Packit Service c5cf8c
    int i;
Packit Service c5cf8c
Packit Service c5cf8c
    if (!(margin = malloc(count * sizeof(double)))) {
Packit Service c5cf8c
        printf("Unable to allocate memory\n");
Packit Service c5cf8c
        return -1;
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    for (i = 0; i < count; i++)
Packit Service c5cf8c
        margin[i] = list[i] / mean(list, count);
Packit Service c5cf8c
Packit Service c5cf8c
    retval = 0;
Packit Service c5cf8c
    for (i = 0; i < count; i++) {
Packit Service c5cf8c
        retval += ((margin[i] - 1) * (margin[i] - 1));
Packit Service c5cf8c
    }
Packit Service c5cf8c
    retval /= count;
Packit Service c5cf8c
    if (retval < 0)
Packit Service c5cf8c
        retval = -retval;
Packit Service c5cf8c
Packit Service c5cf8c
    return retval;
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
/* Here are the tests */
Packit Service c5cf8c
Packit Service c5cf8c
/* Test packing a vector of individual doubles */
Packit Service c5cf8c
/* We don't use restrict in the function args because assignments between
Packit Service c5cf8c
   restrict pointers is not valid in C and some compilers, such as the
Packit Service c5cf8c
   IBM xlc compilers, flag that use as an error.*/
Packit Service c5cf8c
int TestVecPackDouble(int n, int stride,
Packit Service c5cf8c
                      double *avgTimeUser, double *avgTimeMPI, double *dest, const double *src);
Packit Service c5cf8c
int TestVecPackDouble(int n, int stride,
Packit Service c5cf8c
                      double *avgTimeUser, double *avgTimeMPI, double *dest, const double *src)
Packit Service c5cf8c
{
Packit Service c5cf8c
    double *restrict d_dest;
Packit Service c5cf8c
    const double *restrict d_src;
Packit Service c5cf8c
    register int i, j;
Packit Service c5cf8c
    int rep, position;
Packit Service c5cf8c
    double t1, t2, t[NTRIALS];
Packit Service c5cf8c
    MPI_Datatype vectype;
Packit Service c5cf8c
Packit Service c5cf8c
    /* User code */
Packit Service c5cf8c
    if (verbose)
Packit Service c5cf8c
        printf("TestVecPackDouble (USER): ");
Packit Service c5cf8c
    for (j = 0; j < NTRIALS; j++) {
Packit Service c5cf8c
        t1 = MPI_Wtime();
Packit Service c5cf8c
        for (rep = 0; rep < N_REPS; rep++) {
Packit Service c5cf8c
            i = n;
Packit Service c5cf8c
            d_dest = dest;
Packit Service c5cf8c
            d_src = src;
Packit Service c5cf8c
            while (i--) {
Packit Service c5cf8c
                *d_dest++ = *d_src;
Packit Service c5cf8c
                d_src += stride;
Packit Service c5cf8c
            }
Packit Service c5cf8c
        }
Packit Service c5cf8c
        t2 = MPI_Wtime() - t1;
Packit Service c5cf8c
        t[j] = t2;
Packit Service c5cf8c
        if (verbose)
Packit Service c5cf8c
            printf("%.3f ", t[j]);
Packit Service c5cf8c
    }
Packit Service c5cf8c
    if (verbose)
Packit Service c5cf8c
        printf("[%.3f]\n", noise(t, NTRIALS));
Packit Service c5cf8c
    /* If there is too much noise, discard the test */
Packit Service c5cf8c
    if (noise(t, NTRIALS) > VARIANCE_THRESHOLD) {
Packit Service c5cf8c
        *avgTimeUser = 0;
Packit Service c5cf8c
        *avgTimeMPI = 0;
Packit Service c5cf8c
        if (verbose)
Packit Service c5cf8c
            printf("Too much noise; discarding measurement\n");
Packit Service c5cf8c
        return 0;
Packit Service c5cf8c
    }
Packit Service c5cf8c
    *avgTimeUser = mean(t, NTRIALS) / N_REPS;
Packit Service c5cf8c
Packit Service c5cf8c
    /* MPI Vector code */
Packit Service c5cf8c
    MPI_Type_vector(n, 1, stride, MPI_DOUBLE, &vectype);
Packit Service c5cf8c
    MPI_Type_commit(&vectype);
Packit Service c5cf8c
Packit Service c5cf8c
    if (verbose)
Packit Service c5cf8c
        printf("TestVecPackDouble (MPI): ");
Packit Service c5cf8c
    for (j = 0; j < NTRIALS; j++) {
Packit Service c5cf8c
        t1 = MPI_Wtime();
Packit Service c5cf8c
        for (rep = 0; rep < N_REPS; rep++) {
Packit Service c5cf8c
            position = 0;
Packit Service c5cf8c
            MPI_Pack((void *) src, 1, vectype, dest, n * sizeof(double), &position, MPI_COMM_SELF);
Packit Service c5cf8c
        }
Packit Service c5cf8c
        t2 = MPI_Wtime() - t1;
Packit Service c5cf8c
        t[j] = t2;
Packit Service c5cf8c
        if (verbose)
Packit Service c5cf8c
            printf("%.3f ", t[j]);
Packit Service c5cf8c
    }
Packit Service c5cf8c
    if (verbose)
Packit Service c5cf8c
        printf("[%.3f]\n", noise(t, NTRIALS));
Packit Service c5cf8c
    /* If there is too much noise, discard the test */
Packit Service c5cf8c
    if (noise(t, NTRIALS) > VARIANCE_THRESHOLD) {
Packit Service c5cf8c
        *avgTimeUser = 0;
Packit Service c5cf8c
        *avgTimeMPI = 0;
Packit Service c5cf8c
        if (verbose)
Packit Service c5cf8c
            printf("Too much noise; discarding measurement\n");
Packit Service c5cf8c
    } else {
Packit Service c5cf8c
        *avgTimeMPI = mean(t, NTRIALS) / N_REPS;
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    MPI_Type_free(&vectype);
Packit Service c5cf8c
Packit Service c5cf8c
    return 0;
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
/* Test unpacking a vector of individual doubles */
Packit Service c5cf8c
/* See above for why restrict is not used in the function args */
Packit Service c5cf8c
int TestVecUnPackDouble(int n, int stride,
Packit Service c5cf8c
                        double *avgTimeUser, double *avgTimeMPI, double *dest, const double *src);
Packit Service c5cf8c
int TestVecUnPackDouble(int n, int stride,
Packit Service c5cf8c
                        double *avgTimeUser, double *avgTimeMPI, double *dest, const double *src)
Packit Service c5cf8c
{
Packit Service c5cf8c
    double *restrict d_dest;
Packit Service c5cf8c
    const double *restrict d_src;
Packit Service c5cf8c
    register int i, j;
Packit Service c5cf8c
    int rep, position;
Packit Service c5cf8c
    double t1, t2, t[NTRIALS];
Packit Service c5cf8c
    MPI_Datatype vectype;
Packit Service c5cf8c
Packit Service c5cf8c
    /* User code */
Packit Service c5cf8c
    if (verbose)
Packit Service c5cf8c
        printf("TestVecUnPackDouble (USER): ");
Packit Service c5cf8c
    for (j = 0; j < NTRIALS; j++) {
Packit Service c5cf8c
        t1 = MPI_Wtime();
Packit Service c5cf8c
        for (rep = 0; rep < N_REPS; rep++) {
Packit Service c5cf8c
            i = n;
Packit Service c5cf8c
            d_dest = dest;
Packit Service c5cf8c
            d_src = src;
Packit Service c5cf8c
            while (i--) {
Packit Service c5cf8c
                *d_dest = *d_src++;
Packit Service c5cf8c
                d_dest += stride;
Packit Service c5cf8c
            }
Packit Service c5cf8c
        }
Packit Service c5cf8c
        t2 = MPI_Wtime() - t1;
Packit Service c5cf8c
        t[j] = t2;
Packit Service c5cf8c
        if (verbose)
Packit Service c5cf8c
            printf("%.3f ", t[j]);
Packit Service c5cf8c
    }
Packit Service c5cf8c
    if (verbose)
Packit Service c5cf8c
        printf("[%.3f]\n", noise(t, NTRIALS));
Packit Service c5cf8c
    /* If there is too much noise, discard the test */
Packit Service c5cf8c
    if (noise(t, NTRIALS) > VARIANCE_THRESHOLD) {
Packit Service c5cf8c
        *avgTimeUser = 0;
Packit Service c5cf8c
        *avgTimeMPI = 0;
Packit Service c5cf8c
        if (verbose)
Packit Service c5cf8c
            printf("Too much noise; discarding measurement\n");
Packit Service c5cf8c
        return 0;
Packit Service c5cf8c
    }
Packit Service c5cf8c
    *avgTimeUser = mean(t, NTRIALS) / N_REPS;
Packit Service c5cf8c
Packit Service c5cf8c
    /* MPI Vector code */
Packit Service c5cf8c
    MPI_Type_vector(n, 1, stride, MPI_DOUBLE, &vectype);
Packit Service c5cf8c
    MPI_Type_commit(&vectype);
Packit Service c5cf8c
Packit Service c5cf8c
    if (verbose)
Packit Service c5cf8c
        printf("TestVecUnPackDouble (MPI): ");
Packit Service c5cf8c
    for (j = 0; j < NTRIALS; j++) {
Packit Service c5cf8c
        t1 = MPI_Wtime();
Packit Service c5cf8c
        for (rep = 0; rep < N_REPS; rep++) {
Packit Service c5cf8c
            position = 0;
Packit Service c5cf8c
            MPI_Unpack((void *) src, n * sizeof(double),
Packit Service c5cf8c
                       &position, dest, 1, vectype, MPI_COMM_SELF);
Packit Service c5cf8c
        }
Packit Service c5cf8c
        t2 = MPI_Wtime() - t1;
Packit Service c5cf8c
        t[j] = t2;
Packit Service c5cf8c
        if (verbose)
Packit Service c5cf8c
            printf("%.3f ", t[j]);
Packit Service c5cf8c
    }
Packit Service c5cf8c
    if (verbose)
Packit Service c5cf8c
        printf("[%.3f]\n", noise(t, NTRIALS));
Packit Service c5cf8c
    /* If there is too much noise, discard the test */
Packit Service c5cf8c
    if (noise(t, NTRIALS) > VARIANCE_THRESHOLD) {
Packit Service c5cf8c
        *avgTimeUser = 0;
Packit Service c5cf8c
        *avgTimeMPI = 0;
Packit Service c5cf8c
        if (verbose)
Packit Service c5cf8c
            printf("Too much noise; discarding measurement\n");
Packit Service c5cf8c
    } else {
Packit Service c5cf8c
        *avgTimeMPI = mean(t, NTRIALS) / N_REPS;
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    MPI_Type_free(&vectype);
Packit Service c5cf8c
Packit Service c5cf8c
    return 0;
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
/* Test packing a vector of 2-individual doubles */
Packit Service c5cf8c
/* See above for why restrict is not used in the function args */
Packit Service c5cf8c
int TestVecPack2Double(int n, int stride,
Packit Service c5cf8c
                       double *avgTimeUser, double *avgTimeMPI, double *dest, const double *src);
Packit Service c5cf8c
int TestVecPack2Double(int n, int stride,
Packit Service c5cf8c
                       double *avgTimeUser, double *avgTimeMPI, double *dest, const double *src)
Packit Service c5cf8c
{
Packit Service c5cf8c
    double *restrict d_dest;
Packit Service c5cf8c
    const double *restrict d_src;
Packit Service c5cf8c
    register int i, j;
Packit Service c5cf8c
    int rep, position;
Packit Service c5cf8c
    double t1, t2, t[NTRIALS];
Packit Service c5cf8c
    MPI_Datatype vectype;
Packit Service c5cf8c
Packit Service c5cf8c
    /* User code */
Packit Service c5cf8c
    if (verbose)
Packit Service c5cf8c
        printf("TestVecPack2Double (USER): ");
Packit Service c5cf8c
    for (j = 0; j < NTRIALS; j++) {
Packit Service c5cf8c
        t1 = MPI_Wtime();
Packit Service c5cf8c
        for (rep = 0; rep < N_REPS; rep++) {
Packit Service c5cf8c
            i = n;
Packit Service c5cf8c
            d_dest = dest;
Packit Service c5cf8c
            d_src = src;
Packit Service c5cf8c
            while (i--) {
Packit Service c5cf8c
                *d_dest++ = d_src[0];
Packit Service c5cf8c
                *d_dest++ = d_src[1];
Packit Service c5cf8c
                d_src += stride;
Packit Service c5cf8c
            }
Packit Service c5cf8c
        }
Packit Service c5cf8c
        t2 = MPI_Wtime() - t1;
Packit Service c5cf8c
        t[j] = t2;
Packit Service c5cf8c
        if (verbose)
Packit Service c5cf8c
            printf("%.3f ", t[j]);
Packit Service c5cf8c
    }
Packit Service c5cf8c
    if (verbose)
Packit Service c5cf8c
        printf("[%.3f]\n", noise(t, NTRIALS));
Packit Service c5cf8c
    /* If there is too much noise, discard the test */
Packit Service c5cf8c
    if (noise(t, NTRIALS) > VARIANCE_THRESHOLD) {
Packit Service c5cf8c
        *avgTimeUser = 0;
Packit Service c5cf8c
        *avgTimeMPI = 0;
Packit Service c5cf8c
        if (verbose)
Packit Service c5cf8c
            printf("Too much noise; discarding measurement\n");
Packit Service c5cf8c
        return 0;
Packit Service c5cf8c
    }
Packit Service c5cf8c
    *avgTimeUser = mean(t, NTRIALS) / N_REPS;
Packit Service c5cf8c
Packit Service c5cf8c
    /* MPI Vector code */
Packit Service c5cf8c
    MPI_Type_vector(n, 2, stride, MPI_DOUBLE, &vectype);
Packit Service c5cf8c
    MPI_Type_commit(&vectype);
Packit Service c5cf8c
Packit Service c5cf8c
    if (verbose)
Packit Service c5cf8c
        printf("TestVecPack2Double (MPI): ");
Packit Service c5cf8c
    for (j = 0; j < NTRIALS; j++) {
Packit Service c5cf8c
        t1 = MPI_Wtime();
Packit Service c5cf8c
        for (rep = 0; rep < N_REPS; rep++) {
Packit Service c5cf8c
            position = 0;
Packit Service c5cf8c
            MPI_Pack((void *) src, 1, vectype, dest, 2 * n * sizeof(double),
Packit Service c5cf8c
                     &position, MPI_COMM_SELF);
Packit Service c5cf8c
        }
Packit Service c5cf8c
        t2 = MPI_Wtime() - t1;
Packit Service c5cf8c
        t[j] = t2;
Packit Service c5cf8c
        if (verbose)
Packit Service c5cf8c
            printf("%.3f ", t[j]);
Packit Service c5cf8c
    }
Packit Service c5cf8c
    if (verbose)
Packit Service c5cf8c
        printf("[%.3f]\n", noise(t, NTRIALS));
Packit Service c5cf8c
    /* If there is too much noise, discard the test */
Packit Service c5cf8c
    if (noise(t, NTRIALS) > VARIANCE_THRESHOLD) {
Packit Service c5cf8c
        *avgTimeUser = 0;
Packit Service c5cf8c
        *avgTimeMPI = 0;
Packit Service c5cf8c
        if (verbose)
Packit Service c5cf8c
            printf("Too much noise; discarding measurement\n");
Packit Service c5cf8c
    } else {
Packit Service c5cf8c
        *avgTimeMPI = mean(t, NTRIALS) / N_REPS;
Packit Service c5cf8c
    }
Packit Service c5cf8c
    MPI_Type_free(&vectype);
Packit Service c5cf8c
Packit Service c5cf8c
    return 0;
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
/* This creates an indexed type that is like a vector (for simplicity
Packit Service c5cf8c
   of construction).  There is a possibility that the MPI implementation
Packit Service c5cf8c
   will recognize and simplify this (e.g., in MPI_Type_commit); if so,
Packit Service c5cf8c
   let us know and we'll add a version that is not as regular
Packit Service c5cf8c
*/
Packit Service c5cf8c
/* See above for why restrict is not used in the function args */
Packit Service c5cf8c
int TestIndexPackDouble(int n, int stride,
Packit Service c5cf8c
                        double *avgTimeUser, double *avgTimeMPI, double *dest, const double *src);
Packit Service c5cf8c
int TestIndexPackDouble(int n, int stride,
Packit Service c5cf8c
                        double *avgTimeUser, double *avgTimeMPI, double *dest, const double *src)
Packit Service c5cf8c
{
Packit Service c5cf8c
    double *restrict d_dest;
Packit Service c5cf8c
    const double *restrict d_src;
Packit Service c5cf8c
    register int i, j;
Packit Service c5cf8c
    int rep, position;
Packit Service c5cf8c
    int *restrict displs = 0;
Packit Service c5cf8c
    double t1, t2, t[NTRIALS];
Packit Service c5cf8c
    MPI_Datatype indextype;
Packit Service c5cf8c
Packit Service c5cf8c
    displs = (int *) malloc(n * sizeof(int));
Packit Service c5cf8c
    for (i = 0; i < n; i++)
Packit Service c5cf8c
        displs[i] = i * stride;
Packit Service c5cf8c
Packit Service c5cf8c
    /* User code */
Packit Service c5cf8c
    if (verbose)
Packit Service c5cf8c
        printf("TestIndexPackDouble (USER): ");
Packit Service c5cf8c
    for (j = 0; j < NTRIALS; j++) {
Packit Service c5cf8c
        t1 = MPI_Wtime();
Packit Service c5cf8c
        for (rep = 0; rep < N_REPS; rep++) {
Packit Service c5cf8c
            i = n;
Packit Service c5cf8c
            d_dest = dest;
Packit Service c5cf8c
            d_src = src;
Packit Service c5cf8c
            for (i = 0; i < n; i++) {
Packit Service c5cf8c
                *d_dest++ = d_src[displs[i]];
Packit Service c5cf8c
            }
Packit Service c5cf8c
        }
Packit Service c5cf8c
        t2 = MPI_Wtime() - t1;
Packit Service c5cf8c
        t[j] = t2;
Packit Service c5cf8c
        if (verbose)
Packit Service c5cf8c
            printf("%.3f ", t[j]);
Packit Service c5cf8c
    }
Packit Service c5cf8c
    if (verbose)
Packit Service c5cf8c
        printf("[%.3f]\n", noise(t, NTRIALS));
Packit Service c5cf8c
    /* If there is too much noise, discard the test */
Packit Service c5cf8c
    if (noise(t, NTRIALS) > VARIANCE_THRESHOLD) {
Packit Service c5cf8c
        *avgTimeUser = 0;
Packit Service c5cf8c
        *avgTimeMPI = 0;
Packit Service c5cf8c
        if (verbose)
Packit Service c5cf8c
            printf("Too much noise; discarding measurement\n");
Packit Service c5cf8c
        return 0;
Packit Service c5cf8c
    }
Packit Service c5cf8c
    *avgTimeUser = mean(t, NTRIALS) / N_REPS;
Packit Service c5cf8c
Packit Service c5cf8c
    /* MPI Index code */
Packit Service c5cf8c
    MPI_Type_create_indexed_block(n, 1, displs, MPI_DOUBLE, &indextype);
Packit Service c5cf8c
    MPI_Type_commit(&indextype);
Packit Service c5cf8c
Packit Service c5cf8c
    free(displs);
Packit Service c5cf8c
Packit Service c5cf8c
    if (verbose)
Packit Service c5cf8c
        printf("TestIndexPackDouble (MPI): ");
Packit Service c5cf8c
    for (j = 0; j < NTRIALS; j++) {
Packit Service c5cf8c
        t1 = MPI_Wtime();
Packit Service c5cf8c
        for (rep = 0; rep < N_REPS; rep++) {
Packit Service c5cf8c
            position = 0;
Packit Service c5cf8c
            MPI_Pack((void *) src, 1, indextype, dest, n * sizeof(double),
Packit Service c5cf8c
                     &position, MPI_COMM_SELF);
Packit Service c5cf8c
        }
Packit Service c5cf8c
        t2 = MPI_Wtime() - t1;
Packit Service c5cf8c
        t[j] = t2;
Packit Service c5cf8c
        if (verbose)
Packit Service c5cf8c
            printf("%.3f ", t[j]);
Packit Service c5cf8c
    }
Packit Service c5cf8c
    if (verbose)
Packit Service c5cf8c
        printf("[%.3f]\n", noise(t, NTRIALS));
Packit Service c5cf8c
    /* If there is too much noise, discard the test */
Packit Service c5cf8c
    if (noise(t, NTRIALS) > VARIANCE_THRESHOLD) {
Packit Service c5cf8c
        *avgTimeUser = 0;
Packit Service c5cf8c
        *avgTimeMPI = 0;
Packit Service c5cf8c
        if (verbose)
Packit Service c5cf8c
            printf("Too much noise; discarding measurement\n");
Packit Service c5cf8c
    } else {
Packit Service c5cf8c
        *avgTimeMPI = mean(t, NTRIALS) / N_REPS;
Packit Service c5cf8c
    }
Packit Service c5cf8c
    MPI_Type_free(&indextype);
Packit Service c5cf8c
Packit Service c5cf8c
    return 0;
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
int Report(const char *name, const char *packname, double avgTimeMPI, double avgTimeUser);
Packit Service c5cf8c
int Report(const char *name, const char *packname, double avgTimeMPI, double avgTimeUser)
Packit Service c5cf8c
{
Packit Service c5cf8c
    double diffTime, maxTime;
Packit Service c5cf8c
    int errs = 0;
Packit Service c5cf8c
Packit Service c5cf8c
    /* Move this into a common routine */
Packit Service c5cf8c
    diffTime = avgTimeMPI - avgTimeUser;
Packit Service c5cf8c
    if (diffTime < 0)
Packit Service c5cf8c
        diffTime = -diffTime;
Packit Service c5cf8c
    if (avgTimeMPI > avgTimeUser)
Packit Service c5cf8c
        maxTime = avgTimeMPI;
Packit Service c5cf8c
    else
Packit Service c5cf8c
        maxTime = avgTimeUser;
Packit Service c5cf8c
Packit Service c5cf8c
    if (verbose) {
Packit Service c5cf8c
        printf("%-30s:\t%g\t%g\t(%g%%)\n", name,
Packit Service c5cf8c
               avgTimeMPI, avgTimeUser, 100 * (diffTime / maxTime));
Packit Service c5cf8c
        fflush(stdout);
Packit Service c5cf8c
    }
Packit Service c5cf8c
    if (avgTimeMPI > avgTimeUser && (diffTime > THRESHOLD * maxTime)) {
Packit Service c5cf8c
        errs++;
Packit Service c5cf8c
        printf("%s:\tMPI %s code is too slow: MPI %g\t User %g\n",
Packit Service c5cf8c
               name, packname, avgTimeMPI, avgTimeUser);
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    return errs;
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
/* Finally, here's the main program */
Packit Service c5cf8c
int main(int argc, char *argv[])
Packit Service c5cf8c
{
Packit Service c5cf8c
    int n, stride, err, errs = 0;
Packit Service c5cf8c
    void *dest, *src;
Packit Service c5cf8c
    double avgTimeUser, avgTimeMPI;
Packit Service c5cf8c
Packit Service c5cf8c
    MTest_Init(&argc, &argv);
Packit Service c5cf8c
    if (getenv("MPITEST_VERBOSE"))
Packit Service c5cf8c
        verbose = 1;
Packit Service c5cf8c
Packit Service c5cf8c
    n = 30000;
Packit Service c5cf8c
    stride = 4;
Packit Service c5cf8c
    dest = (void *) malloc(n * sizeof(double));
Packit Service c5cf8c
    src = (void *) malloc(n * ((1 + stride) * sizeof(double)));
Packit Service c5cf8c
    /* Touch the source and destination arrays */
Packit Service c5cf8c
    memset(src, 0, n * (1 + stride) * sizeof(double));
Packit Service c5cf8c
    memset(dest, 0, n * sizeof(double));
Packit Service c5cf8c
Packit Service c5cf8c
    err = TestVecPackDouble(n, stride, &avgTimeUser, &avgTimeMPI, dest, src);
Packit Service c5cf8c
    errs += Report("VecPackDouble", "Pack", avgTimeMPI, avgTimeUser);
Packit Service c5cf8c
Packit Service c5cf8c
    err = TestVecUnPackDouble(n, stride, &avgTimeUser, &avgTimeMPI, src, dest);
Packit Service c5cf8c
    errs += Report("VecUnPackDouble", "Unpack", avgTimeMPI, avgTimeUser);
Packit Service c5cf8c
Packit Service c5cf8c
    err = TestIndexPackDouble(n, stride, &avgTimeUser, &avgTimeMPI, dest, src);
Packit Service c5cf8c
    errs += Report("VecIndexDouble", "Pack", avgTimeMPI, avgTimeUser);
Packit Service c5cf8c
Packit Service c5cf8c
    free(dest);
Packit Service c5cf8c
    free(src);
Packit Service c5cf8c
Packit Service c5cf8c
    dest = (void *) malloc(2 * n * sizeof(double));
Packit Service c5cf8c
    src = (void *) malloc((1 + n) * ((1 + stride) * sizeof(double)));
Packit Service c5cf8c
    memset(dest, 0, 2 * n * sizeof(double));
Packit Service c5cf8c
    memset(src, 0, (1 + n) * (1 + stride) * sizeof(double));
Packit Service c5cf8c
    err = TestVecPack2Double(n, stride, &avgTimeUser, &avgTimeMPI, dest, src);
Packit Service c5cf8c
    errs += Report("VecPack2Double", "Pack", avgTimeMPI, avgTimeUser);
Packit Service c5cf8c
Packit Service c5cf8c
    free(dest);
Packit Service c5cf8c
    free(src);
Packit Service c5cf8c
Packit Service c5cf8c
    fflush(stdout);
Packit Service c5cf8c
    MTest_Finalize(errs);
Packit Service c5cf8c
Packit Service c5cf8c
    return MTestReturnValue(errs);
Packit Service c5cf8c
}