summaryrefslogtreecommitdiffstats
path: root/src/H5mpi.c
diff options
context:
space:
mode:
authorDana Robinson <derobins@hdfgroup.org>2019-08-26 17:26:31 (GMT)
committerDana Robinson <derobins@hdfgroup.org>2019-08-26 17:26:31 (GMT)
commit3bcbce5538eb334948311c5afeaef7c050056dca (patch)
tree6cd5acd99efe330d33fbc775ed88ea40b73ce684 /src/H5mpi.c
parent884ad149e29f7c99487af676f0bbcd88cbf2735f (diff)
downloadhdf5-3bcbce5538eb334948311c5afeaef7c050056dca.zip
hdf5-3bcbce5538eb334948311c5afeaef7c050056dca.tar.gz
hdf5-3bcbce5538eb334948311c5afeaef7c050056dca.tar.bz2
Added H5Pset/get_mpi_params calls and unified them with the MPI-I/O
VFD info in H5FDmpio.c.
Diffstat (limited to 'src/H5mpi.c')
-rw-r--r--src/H5mpi.c229
1 files changed, 212 insertions, 17 deletions
diff --git a/src/H5mpi.c b/src/H5mpi.c
index ea6b33f..aec1e03 100644
--- a/src/H5mpi.c
+++ b/src/H5mpi.c
@@ -16,14 +16,10 @@
*
*/
-
#include "H5private.h" /* Generic Functions */
-#include "H5CXprivate.h" /* API Contexts */
#include "H5Eprivate.h" /* Error handling */
-#include "H5Fprivate.h" /* File access */
-#include "H5FDprivate.h" /* File drivers */
-#include "H5FDmpi.h" /* Common MPI file driver */
-#include "H5Pprivate.h" /* Property lists */
+#include "H5MMprivate.h" /* Memory Management */
+
#ifdef H5_HAVE_PARALLEL
@@ -32,6 +28,9 @@
*
* Purpose: Duplicate an MPI communicator.
*
+ * Does not duplicate MPI_COMM_NULL. Instead, comm_new will
+ * be set to MPI_COMM_NULL directly.
+ *
* The new communicator is returned via the comm_new pointer.
*
* Return: SUCCEED/FAIL
@@ -50,19 +49,26 @@ H5_mpi_comm_dup(MPI_Comm comm, MPI_Comm *comm_new)
/* Check arguments */
if (!comm_new)
HGOTO_ERROR(H5E_INTERNAL, H5E_BADVALUE, FAIL, "comm_new cannot be NULL")
- if (MPI_COMM_NULL == comm)
- HGOTO_ERROR(H5E_INTERNAL, H5E_BADVALUE, FAIL, "can't duplicate MPI_COMM_NULL")
- /* Duplicate the MPI communicator */
- if (MPI_SUCCESS != (mpi_code = MPI_Comm_dup(comm, &comm_dup)))
- HMPI_GOTO_ERROR(FAIL, "MPI_Comm_dup failed", mpi_code)
+ /* Handle MPI_COMM_NULL separately */
+ if (MPI_COMM_NULL == comm) {
+ /* Don't duplicate MPI_COMM_NULL since that's an error in MPI */
+ comm_dup = MPI_COMM_NULL;
+ }
+ else {
- /* Set MPI_ERRORS_RETURN on comm_dup so that MPI failures are not fatal,
- * and return codes can be checked and handled.
- */
- if (MPI_SUCCESS != (mpi_code = MPI_Comm_set_errhandler(comm_dup, MPI_ERRORS_RETURN)))
- HMPI_GOTO_ERROR(FAIL, "MPI_Errhandler_set failed", mpi_code)
+ /* Duplicate the MPI communicator */
+ if (MPI_SUCCESS != (mpi_code = MPI_Comm_dup(comm, &comm_dup)))
+ HMPI_GOTO_ERROR(FAIL, "MPI_Comm_dup failed", mpi_code)
+
+ /* Set MPI_ERRORS_RETURN on comm_dup so that MPI failures are not fatal,
+ * and return codes can be checked and handled.
+ */
+ if (MPI_SUCCESS != (mpi_code = MPI_Comm_set_errhandler(comm_dup, MPI_ERRORS_RETURN)))
+ HMPI_GOTO_ERROR(FAIL, "MPI_Errhandler_set failed", mpi_code)
+ }
+
/* Copy the new communicator to the return argument */
*comm_new = comm_dup;
@@ -108,7 +114,7 @@ H5_mpi_info_dup(MPI_Info info, MPI_Info *info_new)
/* Duplicate the MPI info */
if (info == MPI_INFO_NULL) {
/* Don't duplicate MPI_INFO_NULL. Just copy it. */
- info_dup = info;
+ info_dup = MPI_INFO_NULL;
}
else {
/* Duplicate the info */
@@ -194,5 +200,194 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* End H5_mpi_info_free() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5_mpi_comm_cmp
+ *
+ * Purpose: Compares two MPI communicators.
+ *
+ * Note that passing MPI_COMM_NULL to this function will not
+ * throw errors, unlike MPI_Comm_compare().
+ *
+ * We consider MPI communicators to be the "same" when the
+ * groups are identical. We don't care about the context
+ * since that will always be different as we call MPI_Comm_dup
+ * when we store the communicator in the fapl.
+ *
+ * The out parameter is a value like strcmp. The value is
+ * undefined when the return value is FAIL.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5_mpi_comm_cmp(MPI_Comm comm1, MPI_Comm comm2, int *result)
+{
+ int mpi_code;
+ int mpi_result = MPI_IDENT;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Check arguments */
+ if (!result)
+ HGOTO_ERROR(H5E_INTERNAL, H5E_BADVALUE, FAIL, "result cannot be NULL")
+
+ /* Set out parameter to something reasonable in case something goes wrong */
+ *result = 0;
+
+ /* Can't pass MPI_COMM_NULL to MPI_Comm_compare() so we have to handle
+ * it in special cases.
+ */
+ if (MPI_COMM_NULL == comm1 && MPI_COMM_NULL == comm2) {
+ /* Special case of both communicators being MPI_COMM_NULL */
+ *result = 0;
+ }
+ else if (MPI_COMM_NULL == comm1 || MPI_COMM_NULL == comm2) {
+
+ /* Special case of one communicator being MPI_COMM_NULL */
+ *result = (MPI_Datatype)comm1 < (MPI_Datatype)comm2 ? -1 : 1;
+ }
+ else {
+
+ /* Normal communicator compare */
+
+ /* Compare the MPI communicators */
+ if (MPI_SUCCESS != (mpi_code = MPI_Comm_compare(comm1, comm2, &mpi_result)))
+ HMPI_GOTO_ERROR(FAIL, "MPI_Comm_compare failed", mpi_code)
+
+ /* Set the result
+ *
+ * The else clause should work regardless of whether MPI_Datatype is
+ * fundamentally an integer or a pointer.
+ */
+ if (MPI_IDENT == mpi_result || MPI_CONGRUENT == mpi_result)
+ *result = 0;
+ else
+ *result = (MPI_Datatype)comm1 < (MPI_Datatype)comm2 ? -1 : 1;
+ }
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5_mpi_comm_cmp() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5_mpi_info_cmp
+ *
+ * Purpose: Compares two MPI info objects.
+ *
+ * For our purposes, two mpi info objects are the "same" if
+ * they contain the same key-value pairs or are both
+ * MPI_INFO_NULL.
+ *
+ * The out parameter is a value like strcmp. The value is
+ * undefined when the return value is FAIL.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5_mpi_info_cmp(MPI_Info info1, MPI_Info info2, int *result)
+{
+ hbool_t same = FALSE;
+ char *key = NULL;
+ char *value1 = NULL;
+ char *value2 = NULL;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Check arguments */
+ if (!result)
+ HGOTO_ERROR(H5E_INTERNAL, H5E_BADVALUE, FAIL, "result cannot be NULL")
+
+ /* Check for MPI_INFO_NULL */
+ if (MPI_INFO_NULL == info1 && MPI_INFO_NULL == info2) {
+ /* Special case of both info objects being MPI_INFO_NULL */
+ same = TRUE;
+ }
+ else if (MPI_INFO_NULL == info1 || MPI_INFO_NULL == info2) {
+
+ /* Special case of one info object being MPI_INFO_NULL */
+ same = FALSE;
+ }
+ else {
+ int mpi_code;
+ int nkeys_1;
+ int nkeys_2;
+
+ /* Check if the number of keys is the same */
+ if (MPI_SUCCESS != (mpi_code = MPI_Info_get_nkeys(info1, &nkeys_1)))
+ HMPI_GOTO_ERROR(FAIL, "MPI_Info_get_nkeys failed", mpi_code)
+ if (MPI_SUCCESS != (mpi_code = MPI_Info_get_nkeys(info2, &nkeys_2)))
+ HMPI_GOTO_ERROR(FAIL, "MPI_Info_get_nkeys failed", mpi_code)
+
+ if (nkeys_1 != nkeys_2)
+ same = FALSE;
+ else if (0 == nkeys_1 && 0 == nkeys_2)
+ same = TRUE;
+ else {
+ int i;
+ int flag1 = -1;
+ int flag2 = -1;
+
+ /* Allocate buffers for iteration */
+ if (NULL == (key = (char *)H5MM_malloc(MPI_MAX_INFO_KEY * sizeof(char))))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+ if (NULL == (value1 = (char *)H5MM_malloc(MPI_MAX_INFO_VAL * sizeof(char))))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+ if (NULL == (value2 = (char *)H5MM_malloc(MPI_MAX_INFO_VAL * sizeof(char))))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+
+ /* Iterate over the keys, comparing them */
+ for (i = 0; i < nkeys_1; i++) {
+
+ same = TRUE;
+
+ /* Memset the buffers to zero */
+ HDmemset(key, 0, MPI_MAX_INFO_KEY);
+ HDmemset(value1, 0, MPI_MAX_INFO_VAL);
+ HDmemset(value2, 0, MPI_MAX_INFO_VAL);
+
+ /* Get the nth key */
+ if (MPI_SUCCESS != (mpi_code = MPI_Info_get_nthkey(info1, i, key)))
+ HMPI_GOTO_ERROR(FAIL, "MPI_Info_get_nthkey failed", mpi_code)
+
+ /* Get the values */
+ if (MPI_SUCCESS != (mpi_code = MPI_Info_get(info1, key, MPI_MAX_INFO_VAL, value1, &flag1)))
+ HMPI_GOTO_ERROR(FAIL, "MPI_Info_get failed", mpi_code)
+ if (MPI_SUCCESS != (mpi_code = MPI_Info_get(info2, key, MPI_MAX_INFO_VAL, value2, &flag2)))
+ HMPI_GOTO_ERROR(FAIL, "MPI_Info_get failed", mpi_code)
+
+ /* Compare values and flags */
+ if (!flag1 || !flag2 || HDmemcmp(value1, value2, MPI_MAX_INFO_VAL)) {
+ same = FALSE;
+ break;
+ }
+
+ } /* end for */
+ } /* end else */
+ } /* end else */
+
+ /* Set the output value */
+ if (same)
+ *result = 0;
+ else
+ *result = (MPI_Datatype)info1 < (MPI_Datatype)info2 ? -1 : 1;
+
+done:
+ if (key)
+ H5MM_xfree(key);
+ if (value1)
+ H5MM_xfree(value1);
+ if (value2)
+ H5MM_xfree(value2);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5_mpi_info_cmp() */
+
#endif /* H5_HAVE_PARALLEL */