[mpich-commits] r10610 - in mpich2/trunk: src/mpid/common/datatype/dataloop test/mpi/datatype

goodell at mcs.anl.gov goodell at mcs.anl.gov
Wed Nov 14 11:20:14 CST 2012


Author: goodell
Date: 2012-11-14 11:20:14 -0600 (Wed, 14 Nov 2012)
New Revision: 10610

Modified:
   mpich2/trunk/src/mpid/common/datatype/dataloop/dataloop_create_indexed.c
   mpich2/trunk/test/mpi/datatype/indexed-misc.c
Log:
fix hindexed pointer-casting bugs

Bug report from Dmitry Durnov @ Intel.  This patch also includes a fix
based on code suggested by Dmitry.

No reviewer.

Modified: mpich2/trunk/src/mpid/common/datatype/dataloop/dataloop_create_indexed.c
===================================================================
--- mpich2/trunk/src/mpid/common/datatype/dataloop/dataloop_create_indexed.c	2012-11-12 17:07:38 UTC (rev 10609)
+++ mpich2/trunk/src/mpid/common/datatype/dataloop/dataloop_create_indexed.c	2012-11-14 17:20:14 UTC (rev 10610)
@@ -137,9 +137,14 @@
      */
     if (contig_count == 1)
     {
+        const void *disp_arr_tmp; /* no ternary assignment to avoid clang warnings */
+        if (dispinbytes)
+            disp_arr_tmp = &(((const MPI_Aint *)displacement_array)[first]);
+        else
+            disp_arr_tmp = &(((const int *)displacement_array)[first]);
 	err = PREPEND_PREFIX(Dataloop_create_blockindexed)(1,
 							   (int) old_type_count,
-							   &(((int *)displacement_array)[first]),
+							   disp_arr_tmp,
 							   dispinbytes,
 							   oldtype,
 							   dlp_p,
@@ -166,9 +171,14 @@
     }
     if (blksz == blocklength_array[first])
     {
+        const void *disp_arr_tmp; /* no ternary assignment to avoid clang warnings */
+        if (dispinbytes)
+            disp_arr_tmp = &(((const MPI_Aint *)displacement_array)[first]);
+        else
+            disp_arr_tmp = &(((const int *)displacement_array)[first]);
 	err = PREPEND_PREFIX(Dataloop_create_blockindexed)(icount-first,
 							   blksz,
-							   &(((int *)displacement_array)[first]),
+							   disp_arr_tmp,
 							   dispinbytes,
 							   oldtype,
 							   dlp_p,

Modified: mpich2/trunk/test/mpi/datatype/indexed-misc.c
===================================================================
--- mpich2/trunk/test/mpi/datatype/indexed-misc.c	2012-11-12 17:07:38 UTC (rev 10609)
+++ mpich2/trunk/test/mpi/datatype/indexed-misc.c	2012-11-14 17:20:14 UTC (rev 10610)
@@ -10,14 +10,38 @@
 #ifdef HAVE_STRING_H
 #include <string.h>
 #endif
+#include <assert.h>
+#include <limits.h>
 
-static int verbose = 0;
+static int verbose = 1;
 
+#define check(cond_)                                                                             \
+    do {                                                                                         \
+        if (!(cond_)) {                                                                          \
+            if (verbose) {                                                                       \
+                fprintf(stderr, "condition '%s' does not hold, at line %d\n", #cond_, __LINE__); \
+            }                                                                                    \
+            errs += 1;                                                                           \
+        }                                                                                        \
+    } while (0)
+
+#define check_err(err_, what_failed_)                                                 \
+    do {                                                                              \
+        if (err_) {                                                                   \
+            if (verbose) {                                                            \
+                fprintf(stderr, "error: %s, at line %d\n", (what_failed_), __LINE__); \
+            }                                                                         \
+            errs += (err_);                                                           \
+        }                                                                             \
+    } while (0)
+
 /* tests */
 int indexed_contig_test(void);
 int indexed_zeroblock_first_test(void);
 int indexed_zeroblock_middle_test(void);
 int indexed_zeroblock_last_test(void);
+int indexed_contig_leading_zero_test(void);
+int indexed_same_lengths(void);
 
 /* helper functions */
 int parse_args(int argc, char **argv);
@@ -62,6 +86,18 @@
 				err);
     errs += err;
 
+    err = indexed_contig_leading_zero_test();
+    if (err && verbose) fprintf(stderr,
+                                "%d errors in indexed_contig_leading_zero_test.\n",
+                                err);
+    errs += err;
+
+    err = indexed_same_lengths();
+    if (err && verbose) fprintf(stderr,
+                                "%d errors in indexed_contig_leading_zero_test.\n",
+                                err);
+    errs += err;
+
     /* print message and exit */
     if (errs) {
 	fprintf(stderr, "Found %d errors\n", errs);
@@ -299,6 +335,280 @@
     return errs;
 }
 
+/* very similar to indexed_zeroblock_first_test, but only has a single contig in
+ * order to catch a particular optimization path in MPICH's
+ * Dataloop_create_indexed routine */
+int indexed_contig_leading_zero_test(void)
+{
+    int err, errs = 0;
+
+    int i;
+    MPI_Datatype type = MPI_DATATYPE_NULL;
+    MPI_Datatype struct_type = MPI_DATATYPE_NULL;
+    MPI_Datatype types[2];
+    int len[3]  = { 0, 4, 0 };
+    int disp[3] = { INT_MAX, 2, INT_MAX};
+    MPI_Aint adisp[3];
+    MPI_Aint lb, ub;
+    int *buf = NULL;
+
+    err = MPI_Type_indexed(3, len, disp, MPI_INT, &type);
+    check_err(err, "creating indexed type in indexed_contig_leading_zero_test()");
+    err = MPI_Type_commit(&type);
+    check_err(err, "committing indexed type in indexed_contig_leading_zero_test()");
+
+    MPI_Type_lb(type, &lb);
+    check(lb == 2 * sizeof(int));
+    MPI_Type_ub(type, &ub);
+    check(ub == 6 * sizeof(int));
+
+    /* make sure packing/unpacking works (hits a simple "is_contig" case in
+     * MPICH's pack/unpack routines) */
+    buf = malloc(10*sizeof(int));
+    assert(buf != NULL);
+    for (i = 0; i < 10; ++i) {
+        buf[i] = i + 1;
+    }
+    err = pack_and_unpack((char *) buf, 1, type, 10 * sizeof(int));
+    check_err(err, "packing/unpacking in indexed_contig_leading_zero_test()");
+    for (i = 0; i < 10; ++i) {
+        int expected;
+        if (i >= 2 && i < 6)
+            expected = i + 1;
+        else
+            expected = 0;
+        check(buf[i] == expected);
+    }
+    free(buf);
+
+    /* -------------------------------------------------------------------- */
+    /* A more rigorous test of the indexed type.  Use a hard-to-optimize struct
+     * type to force a more complicated datatype processing path
+     * (MPID_Segment_manipulate in MPICH) */
+    len[0] = 1;
+    len[1] = 1;
+    adisp[0] = 0;
+    adisp[1] = 8*sizeof(int);
+    types[0] = type;
+    types[1] = MPI_INT;
+
+    /* struct layout: xx0123xx4x ('x' indicates a hole), one char is an
+     * MPI_INT */
+    MPI_Type_create_struct(2, len, adisp, types, &struct_type);
+    check_err(err, "creating struct type in indexed_contig_leading_zero_test()");
+    err = MPI_Type_commit(&struct_type);
+    check_err(err, "committing struct type in indexed_contig_leading_zero_test()");
+
+    buf = malloc(10*sizeof(int));
+    assert(buf != NULL);
+    for (i = 0; i < 10; ++i) {
+        buf[i] = i + 1;
+    }
+    err = pack_and_unpack((char *) buf, 1, struct_type, 10 * sizeof(int));
+    check_err(err, "packing/unpacking in indexed_contig_test()");
+
+    for (i = 0; i < 10; ++i) {
+        int expected;
+        if ((i >= 2 && i < 6) || i == 8)
+            expected = i + 1;
+        else
+            expected = 0;
+        check(buf[i] == expected);
+    }
+    free(buf);
+
+    MPI_Type_free(&struct_type);
+    MPI_Type_free( &type );
+
+    /* -------------------------------------------------------------------- */
+    /* now do the same as above, but with hindexed */
+    len[0] = 0;
+    len[1] = 4;
+    len[2] = 0;
+    /* use *_MAX vars to improve our chances of hitting any pointer-casting
+     * bugs in a big way (segfaults, etc.) */
+    if (sizeof(MPI_Aint) == sizeof(long long)) {
+        adisp[0] = (MPI_Aint)LLONG_MAX;
+        adisp[1] = 2*sizeof(int);
+        adisp[2] = (MPI_Aint)LLONG_MAX;
+    }
+    else {
+        adisp[0] = (MPI_Aint)INT_MAX;
+        adisp[1] = 2*sizeof(int);
+        adisp[2] = (MPI_Aint)INT_MAX;
+    }
+
+    err = MPI_Type_hindexed(3, len, adisp, MPI_INT, &type);
+    check_err(err, "creating hindexed type in indexed_contig_leading_zero_test()");
+
+    err = MPI_Type_commit(&type);
+    check_err(err, "committing hindexed type in indexed_contig_leading_zero_test()");
+
+    MPI_Type_lb(type, &lb);
+    check(lb == 2 * sizeof(int));
+    MPI_Type_ub(type, &ub);
+    check(ub == 6 * sizeof(int));
+
+    buf = malloc(10*sizeof(int));
+    assert(buf != NULL);
+    for (i = 0; i < 10; ++i) {
+        buf[i] = i + 1;
+    }
+    err = pack_and_unpack((char *) buf, 1, type, 10 * sizeof(int));
+    check_err(err, "packing/unpacking in indexed_contig_test()");
+
+    for (i = 0; i < 10; ++i) {
+        int expected;
+        if (i >= 2 && i < 6)
+            expected = i + 1;
+        else
+            expected = 0;
+        check(buf[i] == expected);
+    }
+    free(buf);
+
+    /* -------------------------------------------------------------------- */
+    /* A more rigorous test of the hindexed type.  Use a hard-to-optimize struct
+     * type to force a more complicated datatype processing path
+     * (MPID_Segment_manipulate in MPICH) */
+    len[0] = 1;
+    len[1] = 1;
+    adisp[0] = 0;
+    adisp[1] = 8*sizeof(int);
+
+    /* struct layout: xx0123xx4x ('x' indicates a hole), one char is an
+     * MPI_INT */
+    err = MPI_Type_create_struct(2, len, adisp, types, &struct_type);
+    check_err(err, "committing struct type in indexed_contig_leading_zero_test()");
+    err = MPI_Type_commit(&struct_type);
+    check_err(err, "committing struct type in indexed_contig_leading_zero_test()");
+
+    buf = malloc(10*sizeof(int));
+    assert(buf != NULL);
+    for (i = 0; i < 10; ++i) {
+        buf[i] = i + 1;
+    }
+    /* fails in old MPICH (3.0rc1 and earlier), despite correct ub/lb
+     * determination */
+    err = pack_and_unpack((char *) buf, 1, struct_type, 10 * sizeof(int));
+    check_err(err, "packing/unpacking in indexed_contig_test()");
+
+    for (i = 0; i < 10; ++i) {
+        int expected;
+        if ((i >= 2 && i < 6) || i == 8)
+            expected = i + 1;
+        else
+            expected = 0;
+        check(buf[i] == expected);
+    }
+    free(buf);
+
+    MPI_Type_free(&struct_type);
+    MPI_Type_free(&type);
+
+    return errs;
+}
+
+/* Test an indexed (and hindexed) type where the block length is the same for
+ * all blocks, but with differing displacements so that it cannot directly be
+ * converted to a vector type.  It is also important to add a dummy element at
+ * the beginning in order to cause int/MPI_Aint misalignment for the
+ * displacement of the first non-zero-width component. */
+int indexed_same_lengths(void)
+{
+    int err, errs = 0;
+
+    int i;
+    MPI_Datatype type = MPI_DATATYPE_NULL;
+    int len[4];
+    int disp[4];
+    MPI_Aint adisp[4];
+    MPI_Aint lb, ub;
+    int *buf = NULL;
+
+    len[0] = 0;
+    len[1] = 1;
+    len[2] = 1;
+    len[3] = 1;
+
+    disp[0] = 0;
+    disp[1] = 1;
+    disp[2] = 3;
+    disp[3] = 8;
+
+    err = MPI_Type_indexed(4, len, disp, MPI_INT, &type);
+    check_err(err, "creating indexed type in indexed_same_lengths()");
+    err = MPI_Type_commit(&type);
+    check_err(err, "committing indexed type in indexed_same_lengths()");
+
+    MPI_Type_lb(type, &lb);
+    check(lb == 1 * sizeof(int));
+    MPI_Type_ub(type, &ub);
+    check(ub == 9 * sizeof(int));
+
+    buf = malloc(10*sizeof(int));
+    assert(buf != NULL);
+    for (i = 0; i < 10; ++i) {
+        buf[i] = i + 1;
+    }
+    err = pack_and_unpack((char *) buf, 1, type, 10 * sizeof(int));
+    check_err(err, "packing/unpacking in indexed_same_lengths()");
+    for (i = 0; i < 10; ++i) {
+        int expected;
+        if (i == 1 || i == 3 || i == 8)
+            expected = i + 1;
+        else
+            expected = 0;
+        check(buf[i] == expected);
+    }
+    free(buf);
+
+    MPI_Type_free(&type);
+
+    /* -------------------------------------------------------------------- */
+    /* now do the same as above, but with hindexed */
+    len[0] = 0;
+    len[1] = 1;
+    len[2] = 1;
+    len[3] = 1;
+
+    adisp[0] = 0 * sizeof(int);
+    adisp[1] = 1 * sizeof(int);
+    adisp[2] = 3 * sizeof(int);
+    adisp[3] = 8 * sizeof(int);
+
+    err = MPI_Type_hindexed(4, len, adisp, MPI_INT, &type);
+    check_err(err, "creating hindexed type in indexed_same_lengths()");
+    err = MPI_Type_commit(&type);
+    check_err(err, "committing hindexed type in indexed_same_lengths()");
+
+    MPI_Type_lb(type, &lb);
+    check(lb == 1 * sizeof(int));
+    MPI_Type_ub(type, &ub);
+    check(ub == 9 * sizeof(int));
+
+    buf = malloc(10*sizeof(int));
+    assert(buf != NULL);
+    for (i = 0; i < 10; ++i) {
+        buf[i] = i + 1;
+    }
+    err = pack_and_unpack((char *) buf, 1, type, 10 * sizeof(int));
+    check_err(err, "packing/unpacking in indexed_same_lengths()");
+    for (i = 0; i < 10; ++i) {
+        int expected;
+        if (i == 1 || i == 3 || i == 8)
+            expected = i + 1;
+        else
+            expected = 0;
+        check(buf[i] == expected);
+    }
+    free(buf);
+
+    MPI_Type_free(&type);
+
+    return errs;
+}
+
 /* pack_and_unpack()
  *
  * Perform packing and unpacking of a buffer for the purposes of checking



More information about the commits mailing list