|
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 |
}
|