|
Packit Service |
c5cf8c |
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
|
|
Packit Service |
c5cf8c |
/*
|
|
Packit Service |
c5cf8c |
* (C) 2012 by Argonne National Laboratory.
|
|
Packit Service |
c5cf8c |
* See COPYRIGHT in top-level directory.
|
|
Packit Service |
c5cf8c |
*/
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/*
|
|
Packit Service |
c5cf8c |
* Tests that basic optimizations are performed on vector of vector datatypes.
|
|
Packit Service |
c5cf8c |
* As the "leaf" element is a large block (when properly optimized), the
|
|
Packit Service |
c5cf8c |
* performance of an MPI datatype should be nearly as good (if not better)
|
|
Packit Service |
c5cf8c |
* than manual packing (the threshold used in this test is *very* forgiving).
|
|
Packit Service |
c5cf8c |
* This test may be run with one process.
|
|
Packit Service |
c5cf8c |
*
|
|
Packit Service |
c5cf8c |
* If PACK_IS_NATIVE is defined, MPI_Pack stores exactly the same bytes as the
|
|
Packit Service |
c5cf8c |
* user would pack manually; in that case, there is a consistency check.
|
|
Packit Service |
c5cf8c |
*/
|
|
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 <string.h>
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#include "mpitest.h"
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#ifdef MPICH
|
|
Packit Service |
c5cf8c |
/* MPICH (as of 6/2012) packs the native bytes */
|
|
Packit Service |
c5cf8c |
#define PACK_IS_NATIVE
|
|
Packit Service |
c5cf8c |
#endif
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
static int verbose = 0;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
int main(int argc, char **argv)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
int vcount = 16, vblock = vcount * vcount / 2, vstride = 2 * vcount * vblock;
|
|
Packit Service |
c5cf8c |
int v2stride, typesize, packsize, i, position, errs = 0;
|
|
Packit Service |
c5cf8c |
char *inbuf, *outbuf, *outbuf2;
|
|
Packit Service |
c5cf8c |
MPI_Datatype ft1type, ft2type, ft3type;
|
|
Packit Service |
c5cf8c |
MPI_Datatype ftopttype;
|
|
Packit Service |
c5cf8c |
MPI_Aint lb, extent;
|
|
Packit Service |
c5cf8c |
double t0, t1;
|
|
Packit Service |
c5cf8c |
double tpack, tmanual, tpackopt;
|
|
Packit Service |
c5cf8c |
int ntry;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MTest_Init(&argc, &argv);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPI_Type_contiguous(6, MPI_FLOAT, &ft1type);
|
|
Packit Service |
c5cf8c |
MPI_Type_size(ft1type, &typesize);
|
|
Packit Service |
c5cf8c |
v2stride = vcount * vcount * vcount * vcount * typesize;
|
|
Packit Service |
c5cf8c |
MPI_Type_vector(vcount, vblock, vstride, ft1type, &ft2type);
|
|
Packit Service |
c5cf8c |
MPI_Type_create_hvector(2, 1, v2stride, ft2type, &ft3type);
|
|
Packit Service |
c5cf8c |
MPI_Type_commit(&ft3type);
|
|
Packit Service |
c5cf8c |
MPI_Type_free(&ft1type);
|
|
Packit Service |
c5cf8c |
MPI_Type_free(&ft2type);
|
|
Packit Service |
c5cf8c |
#if defined(MPICH) && defined(PRINT_DATATYPE_INTERNALS)
|
|
Packit Service |
c5cf8c |
/* To use MPIR_Datatype_debug to print the datatype internals,
|
|
Packit Service |
c5cf8c |
* you must configure MPICH with --enable-g=log */
|
|
Packit Service |
c5cf8c |
if (verbose) {
|
|
Packit Service |
c5cf8c |
printf("Original datatype:\n");
|
|
Packit Service |
c5cf8c |
MPIR_Datatype_debug(ft3type, 10);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
#endif
|
|
Packit Service |
c5cf8c |
/* The same type, but without using the contiguous type */
|
|
Packit Service |
c5cf8c |
MPI_Type_vector(vcount, 6 * vblock, 6 * vstride, MPI_FLOAT, &ft2type);
|
|
Packit Service |
c5cf8c |
MPI_Type_create_hvector(2, 1, v2stride, ft2type, &ftopttype);
|
|
Packit Service |
c5cf8c |
MPI_Type_commit(&ftopttype);
|
|
Packit Service |
c5cf8c |
MPI_Type_free(&ft2type);
|
|
Packit Service |
c5cf8c |
#if defined(MPICH) && defined(PRINT_DATATYPE_INTERNALS)
|
|
Packit Service |
c5cf8c |
if (verbose) {
|
|
Packit Service |
c5cf8c |
printf("\n\nMerged datatype:\n");
|
|
Packit Service |
c5cf8c |
MPIR_Datatype_debug(ftopttype, 10);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
#endif
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPI_Type_get_extent(ft3type, &lb, &extent);
|
|
Packit Service |
c5cf8c |
MPI_Type_size(ft3type, &typesize);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPI_Pack_size(1, ft3type, MPI_COMM_WORLD, &packsize);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
inbuf = (char *) malloc(extent);
|
|
Packit Service |
c5cf8c |
outbuf = (char *) malloc(packsize);
|
|
Packit Service |
c5cf8c |
outbuf2 = (char *) malloc(packsize);
|
|
Packit Service |
c5cf8c |
if (!inbuf) {
|
|
Packit Service |
c5cf8c |
fprintf(stderr, "Unable to allocate %ld for inbuf\n", (long) extent);
|
|
Packit Service |
c5cf8c |
MPI_Abort(MPI_COMM_WORLD, 1);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
if (!outbuf) {
|
|
Packit Service |
c5cf8c |
fprintf(stderr, "Unable to allocate %ld for outbuf\n", (long) packsize);
|
|
Packit Service |
c5cf8c |
MPI_Abort(MPI_COMM_WORLD, 1);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
if (!outbuf2) {
|
|
Packit Service |
c5cf8c |
fprintf(stderr, "Unable to allocate %ld for outbuf2\n", (long) packsize);
|
|
Packit Service |
c5cf8c |
MPI_Abort(MPI_COMM_WORLD, 1);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
for (i = 0; i < extent; i++) {
|
|
Packit Service |
c5cf8c |
inbuf[i] = i & 0x7f;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
position = 0;
|
|
Packit Service |
c5cf8c |
/* Warm up the code and data */
|
|
Packit Service |
c5cf8c |
MPI_Pack(inbuf, 1, ft3type, outbuf, packsize, &position, MPI_COMM_WORLD);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Pack using the vector of vector of contiguous */
|
|
Packit Service |
c5cf8c |
tpack = 1e12;
|
|
Packit Service |
c5cf8c |
for (ntry = 0; ntry < 5; ntry++) {
|
|
Packit Service |
c5cf8c |
position = 0;
|
|
Packit Service |
c5cf8c |
t0 = MPI_Wtime();
|
|
Packit Service |
c5cf8c |
MPI_Pack(inbuf, 1, ft3type, outbuf, packsize, &position, MPI_COMM_WORLD);
|
|
Packit Service |
c5cf8c |
t1 = MPI_Wtime() - t0;
|
|
Packit Service |
c5cf8c |
if (t1 < tpack)
|
|
Packit Service |
c5cf8c |
tpack = t1;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
MPI_Type_free(&ft3type);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Pack using vector of vector with big blocks (same type map) */
|
|
Packit Service |
c5cf8c |
tpackopt = 1e12;
|
|
Packit Service |
c5cf8c |
for (ntry = 0; ntry < 5; ntry++) {
|
|
Packit Service |
c5cf8c |
position = 0;
|
|
Packit Service |
c5cf8c |
t0 = MPI_Wtime();
|
|
Packit Service |
c5cf8c |
MPI_Pack(inbuf, 1, ftopttype, outbuf, packsize, &position, MPI_COMM_WORLD);
|
|
Packit Service |
c5cf8c |
t1 = MPI_Wtime() - t0;
|
|
Packit Service |
c5cf8c |
if (t1 < tpackopt)
|
|
Packit Service |
c5cf8c |
tpackopt = t1;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
MPI_Type_free(&ftopttype);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* User (manual) packing code.
|
|
Packit Service |
c5cf8c |
* Note that we exploit the fact that the vector type contains vblock
|
|
Packit Service |
c5cf8c |
* instances of a contiguous type of size 24, or equivalently a
|
|
Packit Service |
c5cf8c |
* single block of 24*vblock bytes.
|
|
Packit Service |
c5cf8c |
*/
|
|
Packit Service |
c5cf8c |
tmanual = 1e12;
|
|
Packit Service |
c5cf8c |
for (ntry = 0; ntry < 5; ntry++) {
|
|
Packit Service |
c5cf8c |
const char *ppe = (const char *) inbuf;
|
|
Packit Service |
c5cf8c |
int k, j;
|
|
Packit Service |
c5cf8c |
t0 = MPI_Wtime();
|
|
Packit Service |
c5cf8c |
position = 0;
|
|
Packit Service |
c5cf8c |
for (k = 0; k < 2; k++) { /* hvector count; blocksize is 1 */
|
|
Packit Service |
c5cf8c |
const char *ptr = ppe;
|
|
Packit Service |
c5cf8c |
for (j = 0; j < vcount; j++) { /* vector count */
|
|
Packit Service |
c5cf8c |
memcpy(outbuf2 + position, ptr, 24 * vblock);
|
|
Packit Service |
c5cf8c |
ptr += vstride * 24;
|
|
Packit Service |
c5cf8c |
position += 24 * vblock;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
ppe += v2stride;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
t1 = MPI_Wtime() - t0;
|
|
Packit Service |
c5cf8c |
if (t1 < tmanual)
|
|
Packit Service |
c5cf8c |
tmanual = t1;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Check on correctness */
|
|
Packit Service |
c5cf8c |
#ifdef PACK_IS_NATIVE
|
|
Packit Service |
c5cf8c |
if (memcmp(outbuf, outbuf2, position) != 0) {
|
|
Packit Service |
c5cf8c |
printf("Panic - pack buffers differ\n");
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
#endif
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (verbose) {
|
|
Packit Service |
c5cf8c |
printf("Bytes packed = %d\n", position);
|
|
Packit Service |
c5cf8c |
printf("MPI_Pack time = %e, opt version = %e, manual pack time = %e\n",
|
|
Packit Service |
c5cf8c |
tpack, tpackopt, tmanual);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* A factor of 4 is extremely generous, especially since the test suite
|
|
Packit Service |
c5cf8c |
* no longer builds any of the tests with optimization */
|
|
Packit Service |
c5cf8c |
if (4 * tmanual < tpack) {
|
|
Packit Service |
c5cf8c |
errs++;
|
|
Packit Service |
c5cf8c |
printf("MPI_Pack time = %e, manual pack time = %e\n", tpack, tmanual);
|
|
Packit Service |
c5cf8c |
printf("MPI_Pack time should be less than 4 times the manual time\n");
|
|
Packit Service |
c5cf8c |
printf("For most informative results, be sure to compile this test with optimization\n");
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
if (4 * tmanual < tpackopt) {
|
|
Packit Service |
c5cf8c |
errs++;
|
|
Packit Service |
c5cf8c |
printf("MPI_Pack with opt = %e, manual pack time = %e\n", tpackopt, tmanual);
|
|
Packit Service |
c5cf8c |
printf("MPI_Pack time should be less than 4 times the manual time\n");
|
|
Packit Service |
c5cf8c |
printf("For most informative results, be sure to compile this test with optimization\n");
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
free(inbuf);
|
|
Packit Service |
c5cf8c |
free(outbuf);
|
|
Packit Service |
c5cf8c |
free(outbuf2);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MTest_Finalize(errs);
|
|
Packit Service |
c5cf8c |
return MTestReturnValue(errs);
|
|
Packit Service |
c5cf8c |
}
|