From 1e739c2226b0d968e269803007b15712a356132b Mon Sep 17 00:00:00 2001 From: Hui Zhou Date: Fri, 25 Dec 2020 16:15:42 -0600 Subject: [PATCH 01/11] pt2pt: make bsend buffer functions large compatible Need use MPI_Aint internally for buffer sizes to accommodate large count. --- src/binding/c/pt2pt_api.txt | 5 ----- src/include/mpir_bsend.h | 4 ++-- src/mpi/pt2pt/bsendutil.c | 19 +++++++++++-------- 3 files changed, 13 insertions(+), 15 deletions(-) diff --git a/src/binding/c/pt2pt_api.txt b/src/binding/c/pt2pt_api.txt index 6846cb66cc7..23f33f7a286 100644 --- a/src/binding/c/pt2pt_api.txt +++ b/src/binding/c/pt2pt_api.txt @@ -150,11 +150,6 @@ MPI_Buffer_detach: really the address of a void pointer. See the rationale in the standard for more details. */ -{ - mpi_errno = MPIR_Bsend_detach(buffer_addr, size); - if (mpi_errno != MPI_SUCCESS) - goto fn_fail; -} MPI_Ibsend: .desc: Starts a nonblocking buffered send diff --git a/src/include/mpir_bsend.h b/src/include/mpir_bsend.h index bc372234c54..89b8eb363ea 100644 --- a/src/include/mpir_bsend.h +++ b/src/include/mpir_bsend.h @@ -61,8 +61,8 @@ typedef struct MPII_Bsend_data { } MPII_Bsend_data_t; /* Function Prototypes for the bsend utility functions */ -int MPIR_Bsend_attach(void *, int); -int MPIR_Bsend_detach(void *, int *); +int MPIR_Bsend_attach(void *, MPI_Aint); +int MPIR_Bsend_detach(void *, MPI_Aint *); int MPIR_Bsend_isend(const void *, int, MPI_Datatype, int, int, MPIR_Comm *, MPIR_Request **); int MPIR_Bsend_free_req_seg(MPIR_Request *); diff --git a/src/mpi/pt2pt/bsendutil.c b/src/mpi/pt2pt/bsendutil.c index bc64bc8ac3e..461e60237af 100644 --- a/src/mpi/pt2pt/bsendutil.c +++ b/src/mpi/pt2pt/bsendutil.c @@ -54,10 +54,10 @@ static void MPIR_Bsend_dump(void); static struct BsendBuffer { void *buffer; /* Pointer to the begining of the user- * provided buffer */ - size_t buffer_size; /* Size of the user-provided buffer */ + MPI_Aint buffer_size; /* Size of the user-provided buffer */ void *origbuffer; /* Pointer to the buffer provided by * the user */ - size_t origbuffer_size; /* Size of the buffer as provided + MPI_Aint origbuffer_size; /* Size of the buffer as provided * by the user */ MPII_Bsend_data_t *avail; /* Pointer to the first available block * of space */ @@ -85,7 +85,7 @@ static void MPIR_Bsend_free_segment(MPII_Bsend_data_t *); * Attach a buffer. This checks for the error conditions and then * initialized the avail buffer. */ -int MPIR_Bsend_attach(void *buffer, int buffer_size) +int MPIR_Bsend_attach(void *buffer, MPI_Aint buffer_size) { MPII_Bsend_data_t *p; size_t offset, align_sz; @@ -159,7 +159,7 @@ int MPIR_Bsend_attach(void *buffer, int buffer_size) * argument as an "int" (the definition predates that of ssize_t as a * standard type). */ -int MPIR_Bsend_detach(void *bufferp, int *size) +int MPIR_Bsend_detach(void *bufferp, MPI_Aint * size) { int mpi_errno = MPI_SUCCESS; @@ -185,9 +185,7 @@ int MPIR_Bsend_detach(void *bufferp, int *size) /* Note that this works even when the buffer does not exist */ *(void **) bufferp = BsendBuffer.origbuffer; - /* This cast to int will work because the user must use an int to describe - * the buffer size */ - *size = (int) BsendBuffer.origbuffer_size; + *size = (MPI_Aint) BsendBuffer.origbuffer_size; BsendBuffer.origbuffer = NULL; BsendBuffer.origbuffer_size = 0; BsendBuffer.buffer = 0; @@ -604,7 +602,7 @@ static int MPIR_Bsend_finalize(void *p ATTRIBUTE((unused))) { /* No lock since this is inside MPI_Finalize */ void *b; - int s; + MPI_Aint s; MPL_UNREFERENCED_ARG(p); @@ -652,3 +650,8 @@ static void MPIR_Bsend_dump(void) MPL_DBG_MSG(MPIR_DBG_BSEND, TYPICAL, "end of list"); } #endif + +int MPIR_Buffer_detach_impl(void *buffer_addr, MPI_Aint * size) +{ + return MPIR_Bsend_detach(buffer_addr, size); +} From 068607a66bb7b4598d5a9abd3008ff2859c6fcae Mon Sep 17 00:00:00 2001 From: Hui Zhou Date: Tue, 16 Feb 2021 19:00:31 -0600 Subject: [PATCH 02/11] op: add MPIR_Op_create_c_impl --- src/binding/c/op_api.txt | 1 + src/include/mpi.h.in | 7 ++++--- src/mpi/coll/op/op_impl.c | 5 +++++ 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/binding/c/op_api.txt b/src/binding/c/op_api.txt index 1b3f6a00a6c..b64780319fe 100644 --- a/src/binding/c/op_api.txt +++ b/src/binding/c/op_api.txt @@ -4,6 +4,7 @@ MPI_Op_create: .desc: Creates a user-defined combination function handle .docnotes: collops .seealso: MPI_Op_free + .poly_impl: separate /* Notes on the user function: The calling list for the user function type is diff --git a/src/include/mpi.h.in b/src/include/mpi.h.in index d159ddbb17e..f819395dbc1 100644 --- a/src/include/mpi.h.in +++ b/src/include/mpi.h.in @@ -447,9 +447,6 @@ typedef int MPI_Message; /* Generalized requests extensions */ typedef int MPIX_Grequest_class; -/* User combination function */ -typedef void (MPI_User_function) ( void *, void *, int *, MPI_Datatype * ); - /* MPI Attribute copy and delete functions */ typedef int (MPI_Copy_function) ( MPI_Comm, int, void *, void *, void *, int * ); typedef int (MPI_Delete_function) ( MPI_Comm, int, void *, void * ); @@ -588,6 +585,10 @@ typedef struct MPI_Status { int MPI_ERROR; } MPI_Status; +/* User combination function */ +typedef void (MPI_User_function) ( void *, void *, int *, MPI_Datatype * ); +typedef void (MPI_User_function_c) ( void *, void *, MPI_Count *, MPI_Datatype * ); + /* types for the MPI_T_ interface */ struct MPIR_T_enum_s; struct MPIR_T_cvar_handle_s; diff --git a/src/mpi/coll/op/op_impl.c b/src/mpi/coll/op/op_impl.c index b87f5fa5bdf..fa8804acd15 100644 --- a/src/mpi/coll/op/op_impl.c +++ b/src/mpi/coll/op/op_impl.c @@ -76,6 +76,11 @@ int MPIR_Op_create_impl(MPI_User_function * user_fn, int commute, MPIR_Op ** p_o goto fn_exit; } +int MPIR_Op_create_c_impl(MPI_User_function_c * user_fn, int commute, MPIR_Op ** p_op_ptr) +{ + return MPIR_Op_create_impl((void *) user_fn, commute, p_op_ptr); +} + int MPIR_Op_free_impl(MPIR_Op * op_ptr) { int in_use; From d27a0e7548299cce850bae7daf43e291c7c262a3 Mon Sep 17 00:00:00 2001 From: Hui Zhou Date: Fri, 25 Dec 2020 10:43:35 -0600 Subject: [PATCH 03/11] python: remove unused dump_function_polymorph This function must be a leftover from development. It has never been used and I don't think it is complete anyway. --- maint/local_python/binding_c.py | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/maint/local_python/binding_c.py b/maint/local_python/binding_c.py index 450c93df006..9b1032aaebd 100644 --- a/maint/local_python/binding_c.py +++ b/maint/local_python/binding_c.py @@ -750,22 +750,6 @@ def dump_function(func, mapping, kind): else: push_impl_decl(func) -def dump_function_polymorph(func, mapping): - """Same as dump_function, but use `MPII_` prefix and with extra parameters.""" - func_name = get_function_name(func, mapping); - state_name = "MPID_STATE_" + func_name.upper() - - G.out.append(get_declare_function(func, mapping)) - G.out.append("{") - G.out.append("INDENT") - if 'replace' in func and 'body' not in func: - if RE.search(r'with\s+(\w+)', func['replace']): - dump_function_replace(func, state_name, "P%s" % RE.m.group(1)) - else: - dump_function_normal(func, state_name, mapping) - G.out.append("DEDENT") - G.out.append("}") - def dump_function_normal(func, state_name, mapping): G.out.append("int mpi_errno = MPI_SUCCESS;") if 'handle_ptr_list' in func: From ecb945dd69b8ee32719eb5106584e8132a39c6a8 Mon Sep 17 00:00:00 2001 From: Hui Zhou Date: Fri, 25 Dec 2020 11:28:07 -0600 Subject: [PATCH 04/11] python: add underscore to internal attribute names Need differentiate internal func attributes from the user configured attributes. --- maint/local_python/binding_c.py | 58 ++++++++++++++++----------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/maint/local_python/binding_c.py b/maint/local_python/binding_c.py index 9b1032aaebd..bcea139737e 100644 --- a/maint/local_python/binding_c.py +++ b/maint/local_python/binding_c.py @@ -564,19 +564,19 @@ def process_func_parameters(func, mapping): func['_has_comm'] = "comm" func['_comm_from_request'] = 1 - func['need_validation'] = 0 + func['_need_validation'] = 0 if len(validation_list): - func['validation_list'] = validation_list - func['need_validation'] = 1 + func['_validation_list'] = validation_list + func['_need_validation'] = 1 if len(handle_ptr_list): - func['handle_ptr_list'] = handle_ptr_list - func['need_validation'] = 1 + func['_handle_ptr_list'] = handle_ptr_list + func['_need_validation'] = 1 if 'code-error_check' in func: - func['need_validation'] = 1 - func['impl_arg_list'] = impl_arg_list - func['impl_param_list'] = impl_param_list + func['_need_validation'] = 1 + func['_impl_arg_list'] = impl_arg_list + func['_impl_param_list'] = impl_param_list if len(pointertag_list): - func['pointertag_list'] = pointertag_list + func['_pointertag_list'] = pointertag_list # ---- simple parts ---- @@ -712,8 +712,8 @@ def dump_function(func, mapping, kind): s = re.sub(r'\)$', ', '+extra_param+')', s) # prepare for the latter body of routines calling MPIR impl RE.search(r'(\w+)$', extra_param) - func['impl_arg_list'].append(RE.m.group(1)) - func['impl_param_list'].append(extra_param) + func['_impl_arg_list'].append(RE.m.group(1)) + func['_impl_param_list'].append(extra_param) dump_line_with_break(s) G.out.append("{") @@ -752,8 +752,8 @@ def dump_function(func, mapping, kind): def dump_function_normal(func, state_name, mapping): G.out.append("int mpi_errno = MPI_SUCCESS;") - if 'handle_ptr_list' in func: - for p in func['handle_ptr_list']: + if '_handle_ptr_list' in func: + for p in func['_handle_ptr_list']: dump_handle_ptr_var(func, p) if '_comm_from_request' in func: G.out.append("MPIR_Comm *comm_ptr = NULL;") @@ -778,7 +778,7 @@ def dump_function_normal(func, state_name, mapping): else: G.out.append("MPID_THREAD_CS_ENTER(GLOBAL, MPIR_THREAD_GLOBAL_ALLFUNC_MUTEX);") G.out.append("MPIR_FUNC_TERSE_ENTER(%s);" % state_name) - if 'handle_ptr_list' in func: + if '_handle_ptr_list' in func: G.out.append("") G.out.append("#ifdef HAVE_ERROR_CHECKING") G.out.append("{") @@ -786,7 +786,7 @@ def dump_function_normal(func, state_name, mapping): G.out.append(" {") G.out.append("INDENT") G.out.append("INDENT") - for p in func['handle_ptr_list']: + for p in func['_handle_ptr_list']: dump_validate_handle(func, p) G.out.append("DEDENT") G.out.append("DEDENT") @@ -795,12 +795,12 @@ def dump_function_normal(func, state_name, mapping): G.out.append("}") G.out.append("#endif \x2f* HAVE_ERROR_CHECKING */") G.out.append("") - for p in func['handle_ptr_list']: + for p in func['_handle_ptr_list']: dump_convert_handle(func, p) if 'code-handle_ptr' in func: for l in func['code-handle_ptr']: G.out.append(l) - if func['need_validation']: + if func['_need_validation']: G.out.append("") G.out.append("#ifdef HAVE_ERROR_CHECKING") G.out.append("{") @@ -808,11 +808,11 @@ def dump_function_normal(func, state_name, mapping): G.out.append(" {") G.out.append("INDENT") G.out.append("INDENT") - if 'handle_ptr_list' in func: - for p in func['handle_ptr_list']: + if '_handle_ptr_list' in func: + for p in func['_handle_ptr_list']: dump_validate_handle_ptr(func, p) - if 'validation_list' in func: - for t in func['validation_list']: + if '_validation_list' in func: + for t in func['_validation_list']: dump_validation(func, t) if 'code-error_check' in func: for l in func['code-error_check']: @@ -871,8 +871,8 @@ def dump_function_normal(func, state_name, mapping): def push_impl_decl(func, impl_name=None): if not impl_name: impl_name = re.sub(r'^MPIX?_', 'MPIR_', func['name']) + "_impl" - if func['impl_param_list']: - params = ', '.join(func['impl_param_list']) + if func['_impl_param_list']: + params = ', '.join(func['_impl_param_list']) if func['dir'] == 'coll': # All collective impl function use MPI_Aint counts params = re.sub(r' int (count|sendcount|recvcount),', r' MPI_Aint \1,', params) @@ -921,7 +921,7 @@ def swap_next(base, n, counts): G.out.append("}") def dump_v_swap(func): - args = ", ".join(func['impl_arg_list']) + args = ", ".join(func['_impl_arg_list']) if RE.match(r'mpi_i?neighbor_', func['name'], re.IGNORECASE): # neighborhood collectives G.out.append("int indegree, outdegree, weighted;") @@ -1006,7 +1006,7 @@ def dump_v_exit(func): if RE.search(r'((all)?gatherv|scatterv|alltoall[vw]|reduce_scatter\b)', func['name'], re.IGNORECASE): args = dump_v_swap(func) else: - args = ", ".join(func['impl_arg_list']) + args = ", ".join(func['_impl_arg_list']) if RE.match(r'MPI_(I.*|.*_init)$', func['name'], re.IGNORECASE): # non-blocking collectives @@ -1031,7 +1031,7 @@ def dump_body_topo_fns(func, method): comm_ptr = func['_has_comm'] + "_ptr" dump_if_open("%s->topo_fns && %s->topo_fns->%s" % (comm_ptr, comm_ptr, method)) # The extension will output `MPI_Comm *` rather than `MPIR_Comm **` - args = re.sub(r'&(\w+)_ptr', r'\1', ", ".join(func['impl_arg_list'])) + args = re.sub(r'&(\w+)_ptr', r'\1', ", ".join(func['_impl_arg_list'])) dump_line_with_break("mpi_errno = %s->topo_fns->%s(%s);" % (comm_ptr, method, args)) dump_error_check("") dump_else() @@ -1058,7 +1058,7 @@ def dump_body_impl(func, prefix='mpir'): else: impl = func['name'] + "_impl" impl = re.sub(r'^MPIX?_', 'MPIR_', impl) - args = ", ".join(func['impl_arg_list']) + args = ", ".join(func['_impl_arg_list']) dump_line_with_break("mpi_errno = %s(%s);" % (impl, args)) dump_error_check("") @@ -1861,8 +1861,8 @@ def get_declare_function(func, mapping, kind=""): s = "%s %s(%s)" % (ret, name, s_param) if kind == 'proto': - if 'pointertag_list' in func: - for t in func['pointertag_list']: + if '_pointertag_list' in func: + for t in func['_pointertag_list']: s += " MPICH_ATTR_POINTER_WITH_TYPE_TAG(%s)" % t s += " MPICH_API_PUBLIC" return s From 2f07905e6676766b520b1d929ee29e172fe81eb7 Mon Sep 17 00:00:00 2001 From: Hui Zhou Date: Fri, 25 Dec 2020 16:08:01 -0600 Subject: [PATCH 05/11] python: use lw_req in early_return routine to avoid confusion While it is technically safe, having the same temparary name within nested scope is confusing. Rename to clarity. --- maint/local_python/binding_c.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/maint/local_python/binding_c.py b/maint/local_python/binding_c.py index bcea139737e..3e93b5bfc62 100644 --- a/maint/local_python/binding_c.py +++ b/maint/local_python/binding_c.py @@ -1208,10 +1208,10 @@ def dump_early_return_pt2pt_proc_null(func): request_kind = "MPIR_REQUEST_KIND__RMA" else: raise Exception("Unexpected %s for pt2pt_proc_null" % func['name']) - G.out.append("MPIR_Request *request_ptr = MPIR_Request_create_complete(%s);" % request_kind) - G.out.append("MPIR_ERR_CHKANDSTMT(request_ptr == NULL, mpi_errno, MPIX_ERR_NOREQ, goto fn_fail,") + G.out.append("MPIR_Request *lw_req = MPIR_Request_create_complete(%s);" % request_kind) + G.out.append("MPIR_ERR_CHKANDSTMT(lw_req == NULL, mpi_errno, MPIX_ERR_NOREQ, goto fn_fail,") G.out.append(" \"**nomemreq\");") - G.out.append("*request = request_ptr->handle;") + G.out.append("*request = lw_req->handle;") if has_message: G.out.append("*message = MPI_MESSAGE_NO_PROC;") if has_status: From 12edbc01aae1573c647f79d388854fbc977cd444 Mon Sep 17 00:00:00 2001 From: Hui Zhou Date: Fri, 25 Dec 2020 17:37:16 -0600 Subject: [PATCH 06/11] errhan: add errname **too_big_for_output This will be used when user use a small function and the value returned won't fit in the output parameter. --- src/mpi/errhan/errnames.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/mpi/errhan/errnames.txt b/src/mpi/errhan/errnames.txt index a557bf82d1d..bc0aa6bdc6c 100644 --- a/src/mpi/errhan/errnames.txt +++ b/src/mpi/errhan/errnames.txt @@ -29,6 +29,10 @@ **detach_shar_mem %s %s:unable to detach shared memory - %s %s **need_get_envelope_c:use MPI_Type_get_envelope_c to query large count datatype **need_get_contents_c:use MPI_Type_get_contents_c to query large count datatype +**too_big_for_input:The input is too big for internal routines +**too_big_for_input %s:The input argument %s is too big to fit for internal routines +**too_big_for_output:The result is too big to fit in the output argument +**too_big_for_output %s:The result is too big to fit in the output argument - %s **notimpl:Function not implemented **notimpl %s:Function %s not implemented **nullptr:Null pointer From 96288f8365d47a74845c7eaa47ca802766930f15 Mon Sep 17 00:00:00 2001 From: Hui Zhou Date: Wed, 16 Dec 2020 15:37:32 -0600 Subject: [PATCH 07/11] binding: generate embiggened functions We will call dump_mpi_c twice for functions with POLY types. First we call with map_type="SMALL", then call with map_type="BIG". Functions without POLY types will just call dump_mpi_c once with map_type="SMALL". First of all, if there is a custom "large_count" block, we'll always use that in large version. If a POLY function only has scalar POLY type, we assume the implementation use MPI_Aint -- need fix any exceptions. If a POLY function has scalar output or inout POLY type, we assume internally use MPI_Aint, and python generrates temporary MPI_Aint variable to copy in and out value in the *small* version. If the function uses POLY arrays, we will use separate internal routines for datatype functions and always use MPI_Aint for collective (and other if any) functions. The array swap can be messy due to function-specific array lengths. We took the way out by only doing array swap in v-collectives. large mpir impl version with `_c_impl` suffix, and will call that. The compilation will fail if that (_c_impl) routine is missing. When we only use MPI_Aint for internal impl functions, we also check and convert when MPI_Count is bigger than MPI_Aint (such as the case in 32-bit systems). --- maint/gen_binding_c.py | 9 +- maint/local_python/binding_c.py | 528 +++++++++++++++++++++++--------- maint/local_python/mpi_api.py | 6 + src/binding/c/datatype_api.txt | 106 ++++--- src/binding/c/rma_api.txt | 15 +- src/include/mpir_datatype.h | 44 --- 6 files changed, 471 insertions(+), 237 deletions(-) diff --git a/maint/gen_binding_c.py b/maint/gen_binding_c.py index 1ac11ccc145..02923685e3f 100644 --- a/maint/gen_binding_c.py +++ b/maint/gen_binding_c.py @@ -56,10 +56,15 @@ def main(): else: G.out = [] G.err_codes = {} - mapping = G.MAPS['SMALL_C_KIND_MAP'] # dumps the code to G.out array - dump_mpi_c(func, mapping) + # Note: set func['_has_poly'] = False to skip embiggenning + func['_has_poly'] = function_has_POLY_parameters(func) + if func['_has_poly']: + dump_mpi_c(func, "SMALL") + dump_mpi_c(func, "BIG") + else: + dump_mpi_c(func, "SMALL") file_path = get_func_file_path(func, binding_dir) dump_c_file(file_path, G.out) diff --git a/maint/local_python/binding_c.py b/maint/local_python/binding_c.py index 3e93b5bfc62..be6f9d19663 100644 --- a/maint/local_python/binding_c.py +++ b/maint/local_python/binding_c.py @@ -9,15 +9,29 @@ import sys import os import re +import copy # ---- top-level routines ---- -def dump_mpi_c(func, mapping): +def dump_mpi_c(func, map_type="SMALL"): """Dumps the function's C source code to G.out array""" + + # map_type may be "SMALL", "BIG", or "SMALL-poly" + if RE.match(r'SMALL', map_type): + mapping = G.MAPS['SMALL_C_KIND_MAP'] + else: + mapping = G.MAPS['BIG_C_KIND_MAP'] + + # manpage and body-of-routines will check _map_type + func['_map_type'] = map_type + check_func_directives(func) filter_c_parameters(func) - check_params_with_large_only(func, mapping) + + # for poly functions, decide impl interface + check_large_parameters(func) + process_func_parameters(func, mapping) G.mpi_declares.append(get_declare_function(func, mapping, "proto")) @@ -26,11 +40,15 @@ def dump_mpi_c(func, mapping): if 'error' in func: for a in func['error'].split(", "): G.err_codes[a] = 1 + # -- "dump" accumulates output lines in G.out - G.out.append("#include \"mpiimpl.h\"") - if 'include' in func: - for a in func['include'].replace(',', ' ').split(): - G.out.append("#include \"%s\"" % a) + if map_type == "SMALL": + # only include once (skipping "BIG") + G.out.append("#include \"mpiimpl.h\"") + if 'include' in func: + for a in func['include'].replace(',', ' ').split(): + G.out.append("#include \"%s\"" % a) + G.out.append("") dump_profiling(func, mapping) @@ -261,6 +279,10 @@ def check_func_directives(func): if 'code-clean_up' not in func: func['code-clean_up'] = [] + # cleanup internal states + func.pop('_got_comm_size', None) + func.pop('_got_topo_size', None) + def filter_c_parameters(func): c_params = [] for p in func['parameters']: @@ -336,6 +358,9 @@ def process_func_parameters(func, mapping): validation_list, handle_ptr_list, impl_arg_list, impl_param_list = [], [], [], [] pointertag_list = [] # needed to annotate MPICH_ATTR_POINTER_WITH_TYPE_TAG + # init to empty list or we will have double entries due to being called twice (small and large) + func['_has_handle_out'] = [] + func_name = func['name'] n = len(func['c_parameters']) i = 0 @@ -352,7 +377,7 @@ def process_func_parameters(func, mapping): t += "," t += temp_p['name'] impl_arg_list.append(temp_p['name']) - impl_param_list.append(get_C_param(temp_p, mapping)) + impl_param_list.append(get_impl_param(func, temp_p, mapping)) validation_list.append({'kind': group_kind, 'name': t}) # -- pointertag_list if re.search(r'alltoallw', func_name, re.IGNORECASE): @@ -529,11 +554,9 @@ def process_func_parameters(func, mapping): impl_arg_list.append(name + "_ptr") impl_param_list.append("%s *%s_ptr" % (G.handle_mpir_types[kind], name)) elif do_handle_ptr == 2: - if '_has_handle_out' in func: - # Just MPI_Comm_idup[_with_info] have 2 handle output, but anyway... - func['_has_handle_out'].append(p) - else: - func['_has_handle_out'] = [p] + # Just MPI_Comm_idup[_with_info] have 2 handle output, but use a list anyway + func['_has_handle_out'].append(p) + impl_arg_list.append('&' + name + "_ptr") impl_param_list.append("%s **%s_ptr" % (G.handle_mpir_types[kind], name)) elif do_handle_ptr == 3: @@ -557,7 +580,7 @@ def process_func_parameters(func, mapping): impl_param_list.append("%s *%s_ptr" % (mpir_type, name)) else: impl_arg_list.append(name) - impl_param_list.append(get_C_param(p, mapping)) + impl_param_list.append(get_impl_param(func, p, mapping)) i += 1 if RE.match(r'MPI_(Wait|Test)$', func_name): @@ -612,9 +635,8 @@ def dump_profiling(func, mapping): G.out.append("#endif") def dump_manpage(func): - func_name = func['name'] G.out.append("/*@") - G.out.append(" %s - %s" % (func_name, func['desc'])) + G.out.append(" %s - %s" % (func['name'], func['desc'])) G.out.append("") lis_map = G.MAPS['LIS_KIND_MAP'] for p in func['c_parameters']: @@ -648,7 +670,7 @@ def dump_manpage(func): if RE.match(r'\s*(deprecated|removed)', func['replace'], re.IGNORECASE): G.out.append(".N %s" % RE.m.group(1).capitalize()) else: - print("Missing reasons in %s .replace" % func_name, file=sys.stderr) + print("Missing reasons in %s .replace" % func['name'], file=sys.stderr) if RE.search(r'with\s+(\w+)', func['replace']): G.out.append(" The replacement for this routine is '%s'." % RE.m.group(1)) @@ -740,15 +762,59 @@ def dump_function(func, mapping, kind): G.out.append("DEDENT") G.out.append("}") - if "decl" in func: - push_impl_decl(func, func['decl']) - elif 'impl' in func: - if RE.match(r'topo_fns->', func['impl']): - push_impl_decl(func) - elif 'body' in func: + if func['_has_poly'] and func['_poly_impl'] != "separate" and func['_map_type'] == "BIG": pass else: - push_impl_decl(func) + if "decl" in func: + push_impl_decl(func, func['decl']) + elif 'impl' in func: + if RE.match(r'topo_fns->', func['impl']): + push_impl_decl(func) + elif 'body' in func: + pass + else: + push_impl_decl(func) + +def check_large_parameters(func): + if not func['_has_poly']: + func['_poly_impl'] = "separate" + return + + # Set func['_poly_impl'] + if 'poly_impl' in func: + # always prefer explict .poly_impl directive + func['_poly_impl'] = func['poly_impl'] + elif 'code-large_count' in func: + # { -- large_count } code block exist + func['_poly_impl'] = "separate" + elif func['dir'] == 'datatype': + func['_poly_impl'] = "separate" + else: + func['_poly_impl'] = "use-aint" + + # Gather large parameters. Potentially we need copy in & out + func['_poly_in_list'] = [] + func['_poly_in_arrays'] = [] + func['_poly_out_list'] = [] + func['_poly_inout_list'] = [] + func['_poly_need_filter'] = False + for p in func['c_parameters']: + if RE.match(r'POLY', p['kind']): + if p['param_direction'] == 'out': + func['_poly_out_list'].append(p) + func['_poly_need_filter'] = True + elif p['param_direction'] == 'inout': + # MPI_{Pack,Unpack}[_external] + func['_poly_inout_list'].append(p) + func['_poly_need_filter'] = True + elif p['length']: + func['_poly_in_arrays'].append(p) + func['_poly_need_filter'] = True + elif p['kind'] == "POLYFUNCTION": + # we'll have separate versions that doesn't need cast or swap + pass + else: + func['_poly_in_list'].append(p) def dump_function_normal(func, state_name, mapping): G.out.append("int mpi_errno = MPI_SUCCESS;") @@ -830,23 +896,65 @@ def dump_function_normal(func, state_name, mapping): check_early_returns(func) G.out.append("") - G.out.append("/* ... body of routine ... */") - if 'body' in func: - for l in func['body']: - G.out.append(l) - elif 'impl' in func: - if RE.match(r'mpid', func['impl'], re.IGNORECASE): - dump_body_impl(func, "mpid") - elif RE.match(r'topo_fns->(\w+)', func['impl'], re.IGNORECASE): - dump_body_topo_fns(func, RE.m.group(1)) + + # ---- + def dump_body_of_routine(): + if 'body' in func: + if func['_map_type'] == "BIG" and func['_poly_impl'] == "separate": + if 'code-large_count' not in func: + raise Exception("%s missing large count code block." % func['name']) + for l in func['code-large_count']: + G.out.append(l) + else: + for l in func['body']: + G.out.append(l) + elif 'impl' in func: + if RE.match(r'mpid', func['impl'], re.IGNORECASE): + dump_body_impl(func, "mpid") + elif RE.match(r'topo_fns->(\w+)', func['impl'], re.IGNORECASE): + dump_body_topo_fns(func, RE.m.group(1)) + else: + print("Error: unhandled special impl: [%s]" % func['impl']) + elif func['dir'] == 'coll': + dump_body_coll(func) else: - print("Error: unhandled special impl: [%s]" % func['impl']) - elif func['dir'] == 'coll': - dump_body_coll(func) + dump_body_impl(func, "mpir") + + # ---- + G.out.append("/* ... body of routine ... */") + + if func['_map_type'] == "BIG": + # BIG but internally is using MPI_Aint + impl_args_save = copy.copy(func['_impl_arg_list']) + + dump_if_open("sizeof(MPI_Count) == sizeof(MPI_Aint)") + # Same size, just casting the _impl_arg_list + add_poly_impl_cast(func) + dump_body_of_routine() + + dump_else() + # Need filter to check limits and potentially swap args + func['_impl_arg_list'] = copy.copy(impl_args_save) + G.out.append("/* MPI_Count is bigger than MPI_Aint */") + dump_poly_pre_filter(func) + dump_body_of_routine() + dump_poly_post_filter(func) + + dump_if_close() + + elif func['_map_type'] == "SMALL" and func['_has_poly'] and func['_poly_impl'] != "separate": + # SMALL but internally is using MPI_Aint + dump_poly_pre_filter(func) + dump_body_of_routine() + dump_poly_post_filter(func) + else: - dump_body_impl(func, "mpir") + # normal + dump_body_of_routine() G.out.append("/* ... end of body of routine ... */") + + # ---- G.out.append("") G.out.append("fn_exit:") for l in func['code-clean_up']: @@ -868,15 +976,128 @@ def dump_function_normal(func, state_name, mapping): dump_mpi_fn_fail(func, mapping) G.out.append("goto fn_exit;") +def replace_impl_arg_list(arg_list, old, new): + for i in range(len(arg_list)): + if arg_list[i] == old: + arg_list[i] = new + +def check_aint_fits(map_type, val): + # only need check when swapping `MPI_Count` to `MPI_Aint` + if map_type == "BIG": + dump_if_open("%s > MPIR_AINT_MAX" % val) + dump_error("too_big_for_input", "%s", '"%s"' % val) + dump_if_close() + +def add_poly_impl_cast(func): + for p in func['_poly_in_list']: + replace_impl_arg_list(func['_impl_arg_list'], p['name'], "(MPI_Aint) " + p['name']) + for p in func['_poly_inout_list'] + func['_poly_out_list'] + func['_poly_in_arrays']: + replace_impl_arg_list(func['_impl_arg_list'], p['name'], "(MPI_Aint *) " + p['name']) + +def check_poly_is_aint(func, p): + if func['_map_type'] == "BIG": + return G.MAPS['BIG_C_KIND_MAP'][p['kind']] == "MPI_Aint" + else: + return G.MAPS['SMALL_C_KIND_MAP'][p['kind']] == "MPI_Aint" + +def dump_poly_pre_filter(func): + def filter_output(): + # internal code will use MPI_Aint + for p in func['_poly_out_list']: + if not check_poly_is_aint(func, p): + G.out.append("MPI_Aint %s_c;" % p['name']) + for p in func['_poly_inout_list']: + if not check_poly_is_aint(func, p): + G.out.append("MPI_Aint %s_c = *%s;" % (p['name'], p['name'])) + + for p in func['_poly_out_list'] + func['_poly_inout_list']: + if not check_poly_is_aint(func, p): + replace_impl_arg_list(func['_impl_arg_list'], p['name'], "&%s_c" % p['name']) + + def filter_array(): + if RE.search(r'((all)?gatherv|scatterv|alltoall[vw]|reduce_scatter\b)', func['name'], re.IGNORECASE): + dump_coll_v_swap(func) + elif RE.search(r'(h?indexed(_block)?|struct|(d|sub)array)', func['name'], re.IGNORECASE): + dump_type_create_swap(func) + else: + if func['_poly_in_arrays']: + # non-v-collectives should use separate impl + raise Exception("Unhandled POLY-array function %s" % func['name']) + # ---- + if func['_map_type'] == "BIG": + for p in func['_poly_in_list']: + if not check_poly_is_aint(func, p): + check_aint_fits("BIG", p['name']) + for p in func['_poly_inout_list']: + if not check_poly_is_aint(func, p): + check_aint_fits("BIG", '*' + p['name']) + + filter_output() + filter_array() + +def dump_poly_post_filter(func): + def filter_output(int_max): + for p in func['_poly_out_list'] + func['_poly_inout_list']: + if not check_poly_is_aint(func, p): + val = p['name'] + "_c" + if int_max: + # Seems in all cases we can return MPI_UNDEFINED rather than + # error. + if True: + dump_if_open("%s > %s" % (val, int_max)) + G.out.append("*%s = MPI_UNDEFINED;" % p['name']) + dump_else() + G.out.append("*%s = %s;" % (p['name'], val)) + dump_if_close() + else: + dump_if_open("%s > %s" % (val, int_max)) + dump_error("too_big_for_output", "%s", "\"%s\"" % val) + dump_if_close() + G.out.append("*%s = %s;" % (p['name'], val)) + else: + G.out.append("*%s = %s;" % (p['name'], val)) + + def filter_array(int_max): + if RE.search(r'((all)?gatherv|scatterv|alltoall[vw]|reduce_scatter\b)', func['name'], re.IGNORECASE): + dump_coll_v_exit(func) + elif RE.search(r'(h?indexed(_block)?|struct|(d|sub)array)', func['name'], re.IGNORECASE): + dump_type_create_exit(func) + + # ---- + int_max = None + if func['_map_type'] == "SMALL": + int_max = "INT_MAX" + filter_output(int_max) + filter_array(int_max) + +def dump_type_create_swap(func): + for p in func['_poly_in_arrays']: + n = "count" + if RE.search(r'create_(d|sub)array', func['name'], re.IGNORECASE): + n = "ndims" + new_name = p['name'] + '_c' + G.out.append("MPI_Aint *%s = MPL_malloc(%s * sizeof(MPI_Aint), MPL_MEM_OTHER);" % (new_name, n)) + dump_for_open("i", n) + check_aint_fits(func['_map_type'], "%s[i]" % p['name']) + G.out.append("%s[i] = %s[i];" % (new_name, p['name'])) + dump_for_close() + replace_impl_arg_list(func['_impl_arg_list'], p['name'], new_name) + +def dump_type_create_exit(func): + for p in func['_poly_in_arrays']: + G.out.append("MPL_free(%s_c);" % p['name']) + def push_impl_decl(func, impl_name=None): if not impl_name: impl_name = re.sub(r'^MPIX?_', 'MPIR_', func['name']) + "_impl" + + if func['_map_type'] == "BIG": + # add suffix to differentiate + impl_name = re.sub(r'_impl$', '_c_impl', impl_name) + if func['_impl_param_list']: params = ', '.join(func['_impl_param_list']) if func['dir'] == 'coll': - # All collective impl function use MPI_Aint counts - params = re.sub(r' int (count|sendcount|recvcount),', r' MPI_Aint \1,', params) - params = re.sub(r' int (sendcounts|recvcounts|[sr]?displs)\[', r' MPI_Aint \1[', params) # block collective use an extra errflag if not RE.match(r'MPI_(I.*|Neighbor.*|.*_init)$', func['name']): params = params + ", MPIR_Errflag_t *errflag" @@ -908,105 +1129,10 @@ def dump_CHECKENUM(var, errname, t, type="ENUM"): dump_if_close() def dump_body_coll(func): - # --- routines for swaping counts array due to int <-> MPI_Aint - def allocate_tmp_array(n): - G.out.append("MPI_Aint *tmp_array = MPL_malloc(%s * sizeof(MPI_Aint), MPL_MEM_OTHER);" % n) - def swap_one(n, counts): - G.out.append("for (int i = 0; i < %s; i++) {" % n) - G.out.append(" tmp_array[i] = %s[i];" % counts) - G.out.append("}") - def swap_next(base, n, counts): - G.out.append("for (int i = 0; i < %s; i++) {" % n) - G.out.append(" tmp_array[%s + i] = %s[i];" % (base, counts)) - G.out.append("}") - - def dump_v_swap(func): - args = ", ".join(func['_impl_arg_list']) - if RE.match(r'mpi_i?neighbor_', func['name'], re.IGNORECASE): - # neighborhood collectives - G.out.append("int indegree, outdegree, weighted;") - G.out.append("mpi_errno = MPIR_Topo_canon_nhb_count(comm_ptr, &indegree, &outdegree, &weighted);") - if RE.search(r'allgatherv', func['name'], re.IGNORECASE): - allocate_tmp_array("indegree * 2") - swap_one("indegree", "recvcounts") - swap_next("indegree", "indegree", "displs") - args = re.sub(r'recvcounts', 'tmp_array', args) - args = re.sub(r'displs', 'tmp_array + indegree', args) - elif RE.search(r'alltoallv', func['name'], re.IGNORECASE): - allocate_tmp_array("(outdegree + indegree) * 2") - swap_one("outdegree", "sendcounts") - swap_next("outdegree", "outdegree", "sdispls") - swap_next("outdegree * 2", "indegree", "recvcounts") - swap_next("outdegree * 2 + indegree", "indegree", "rdispls") - args = re.sub(r'sendcounts', 'tmp_array', args) - args = re.sub(r'sdispls', 'tmp_array + outdegree', args) - args = re.sub(r'recvcounts', 'tmp_array + outdegree * 2', args) - args = re.sub(r'rdispls', 'tmp_array + outdegree * 2 + indegree', args) - else: # neighbor_alltoallw - allocate_tmp_array("(outdegree + indegree)") - swap_one("indegree", "sendcounts") - swap_next("indegree", "outdegree", "recvcounts") - args = re.sub(r'sendcounts', 'tmp_array', args) - args = re.sub(r'recvcounts', 'tmp_array + indegree', args) - # classical collectives - elif RE.match(r'mpi_i?reduce_scatter\b', func['name'], re.IGNORECASE): - G.out.append("int n = comm_ptr->local_size;") - allocate_tmp_array("n") - swap_one("n", "recvcounts") - args = re.sub(r'recvcounts', 'tmp_array', args) - else: - cond = "(comm_ptr->comm_kind == MPIR_COMM_KIND__INTERCOMM)" - G.out.append("int n = %s ? comm_ptr->remote_size : comm_ptr->local_size;" % cond) - if RE.search(r'alltoall[vw]', func['name'], re.IGNORECASE): - allocate_tmp_array("n * 4") - dump_if_open("sendbuf != MPI_IN_PLACE") - swap_one("n", "sendcounts") - swap_next("n", "n", "sdispls") - dump_if_close() - swap_next("n * 2", "n", "recvcounts") - swap_next("n * 3", "n", "rdispls") - args = re.sub(r'sendcounts', 'tmp_array', args) - args = re.sub(r'sdispls', 'tmp_array + n', args) - args = re.sub(r'recvcounts', 'tmp_array + n * 2', args) - args = re.sub(r'rdispls', 'tmp_array + n * 3', args) - elif RE.search(r'allgatherv', func['name'], re.IGNORECASE): - allocate_tmp_array("n * 2") - swap_one("n", "recvcounts") - swap_next("n", "n", "displs") - args = re.sub(r'recvcounts', 'tmp_array', args) - args = re.sub(r'displs', 'tmp_array + n', args) - else: - allocate_tmp_array("n * 2") - if RE.search(r'scatterv', func['name'], re.IGNORECASE): - counts = "sendcounts" - else: # gatherv - counts = "recvcounts" - # only root need the v-array - cond_intra = "comm_ptr->comm_kind == MPIR_COMM_KIND__INTRACOMM" - cond_inter = "comm_ptr->comm_kind == MPIR_COMM_KIND__INTERCOMM" - cond_a = cond_intra + " && comm_ptr->rank == root" - cond_b = cond_inter + " && root == MPI_ROOT" - - dump_if_open("(%s) || (%s)" % (cond_a, cond_b)) - swap_one("n", counts) - swap_next("n", "n", "displs") - dump_if_close() - - args = re.sub(counts, 'tmp_array', args) - args = re.sub(r'displs', 'tmp_array + n', args) - return args - - def dump_v_exit(func): - G.out.append("MPL_free(tmp_array);") - - # ------------------------- # collectives call MPIR_Xxx mpir_name = re.sub(r'^MPIX?_', 'MPIR_', func['name']) - if RE.search(r'((all)?gatherv|scatterv|alltoall[vw]|reduce_scatter\b)', func['name'], re.IGNORECASE): - args = dump_v_swap(func) - else: - args = ", ".join(func['_impl_arg_list']) + args = ", ".join(func['_impl_arg_list']) if RE.match(r'MPI_(I.*|.*_init)$', func['name'], re.IGNORECASE): # non-blocking collectives @@ -1024,8 +1150,104 @@ def dump_v_exit(func): G.out.append("MPIR_Errflag_t errflag = MPIR_ERR_NONE;") dump_line_with_break("mpi_errno = %s(%s, &errflag);" % (mpir_name, args)) - if RE.search(r'((all)?gatherv|scatterv|alltoall[vw]|reduce_scatter\b)', func['name'], re.IGNORECASE): - dump_v_exit(func) +def dump_coll_v_swap(func): + # -- wrappers to make code cleaner + def replace_arg(old, new): + replace_impl_arg_list(func['_impl_arg_list'], old, new) + + def check_fit(val): + check_aint_fits(func['_map_type'], val) + + # -- swapping routines + def allocate_tmp_array(n): + G.out.append("MPI_Aint *tmp_array = MPL_malloc(%s * sizeof(MPI_Aint), MPL_MEM_OTHER);" % n) + def swap_one(n, counts): + dump_for_open("i", n) + check_fit("%s[i]" % counts) + G.out.append("tmp_array[i] = %s[i];" % counts) + dump_for_close() + def swap_next(base, n, counts): + dump_for_open("i", n) + check_fit("%s[i]" % counts) + G.out.append("tmp_array[%s + i] = %s[i];" % (base, counts)) + dump_for_close() + + # ------------------------- + if RE.match(r'mpi_i?neighbor_', func['name'], re.IGNORECASE): + # neighborhood collectives + G.out.append("int indegree, outdegree, weighted;") + G.out.append("mpi_errno = MPIR_Topo_canon_nhb_count(comm_ptr, &indegree, &outdegree, &weighted);") + if RE.search(r'allgatherv', func['name'], re.IGNORECASE): + allocate_tmp_array("indegree * 2") + swap_one("indegree", "recvcounts") + swap_next("indegree", "indegree", "displs") + replace_arg('recvcounts', 'tmp_array') + replace_arg('displs', 'tmp_array + indegree') + elif RE.search(r'alltoallv', func['name'], re.IGNORECASE): + allocate_tmp_array("(outdegree + indegree) * 2") + swap_one("outdegree", "sendcounts") + swap_next("outdegree", "outdegree", "sdispls") + swap_next("outdegree * 2", "indegree", "recvcounts") + swap_next("outdegree * 2 + indegree", "indegree", "rdispls") + replace_arg('sendcounts', 'tmp_array') + replace_arg('sdispls', 'tmp_array + outdegree') + replace_arg('recvcounts', 'tmp_array + outdegree * 2') + replace_arg('rdispls', 'tmp_array + outdegree * 2 + indegree') + else: # neighbor_alltoallw + allocate_tmp_array("(outdegree + indegree)") + swap_one("indegree", "sendcounts") + swap_next("indegree", "outdegree", "recvcounts") + replace_arg('sendcounts', 'tmp_array') + replace_arg('recvcounts', 'tmp_array + indegree') + # classical collectives + elif RE.match(r'mpi_i?reduce_scatter\b', func['name'], re.IGNORECASE): + G.out.append("int n = comm_ptr->local_size;") + allocate_tmp_array("n") + swap_one("n", "recvcounts") + replace_arg('recvcounts', 'tmp_array') + else: + cond = "(comm_ptr->comm_kind == MPIR_COMM_KIND__INTERCOMM)" + G.out.append("int n = %s ? comm_ptr->remote_size : comm_ptr->local_size;" % cond) + if RE.search(r'alltoall[vw]', func['name'], re.IGNORECASE): + allocate_tmp_array("n * 4") + dump_if_open("sendbuf != MPI_IN_PLACE") + swap_one("n", "sendcounts") + swap_next("n", "n", "sdispls") + dump_if_close() + swap_next("n * 2", "n", "recvcounts") + swap_next("n * 3", "n", "rdispls") + replace_arg('sendcounts', 'tmp_array') + replace_arg('sdispls', 'tmp_array + n') + replace_arg('recvcounts', 'tmp_array + n * 2') + replace_arg('rdispls', 'tmp_array + n * 3') + elif RE.search(r'allgatherv', func['name'], re.IGNORECASE): + allocate_tmp_array("n * 2") + swap_one("n", "recvcounts") + swap_next("n", "n", "displs") + replace_arg('recvcounts', 'tmp_array') + replace_arg('displs', 'tmp_array + n') + else: + allocate_tmp_array("n * 2") + if RE.search(r'scatterv', func['name'], re.IGNORECASE): + counts = "sendcounts" + else: # gatherv + counts = "recvcounts" + # only root need the v-array + cond_intra = "comm_ptr->comm_kind == MPIR_COMM_KIND__INTRACOMM" + cond_inter = "comm_ptr->comm_kind == MPIR_COMM_KIND__INTERCOMM" + cond_a = cond_intra + " && comm_ptr->rank == root" + cond_b = cond_inter + " && root == MPI_ROOT" + + dump_if_open("(%s) || (%s)" % (cond_a, cond_b)) + swap_one("n", counts) + swap_next("n", "n", "displs") + dump_if_close() + + replace_arg(counts, 'tmp_array') + replace_arg('displs', 'tmp_array + n') + +def dump_coll_v_exit(func): + G.out.append("MPL_free(tmp_array);") def dump_body_topo_fns(func, method): comm_ptr = func['_has_comm'] + "_ptr" @@ -1040,7 +1262,7 @@ def dump_body_topo_fns(func, method): def dump_body_impl(func, prefix='mpir'): # mpi_errno = MPIR_Xxx_impl(...); - if '_has_handle_out' in func: + if func['_has_handle_out']: for p in func['_has_handle_out']: (name, kind) = (p['name'], p['kind']) mpir_type = G.handle_mpir_types[kind] @@ -1052,17 +1274,19 @@ def dump_body_impl(func, prefix='mpir'): if p['kind'] == "DATATYPE" and p['param_direction'] == 'out': G.out.append("*%s = MPI_DATATYPE_NULL;" % p['name']) + impl = func['name'] + if func['_map_type'] == "BIG" and func['_poly_impl'] == "separate": + impl += '_c' if prefix == 'mpid': - impl = func['name'] impl = re.sub(r'^MPIX?_', 'MPID_', impl) else: - impl = func['name'] + "_impl" - impl = re.sub(r'^MPIX?_', 'MPIR_', impl) + impl = re.sub(r'^MPIX?_', 'MPIR_', impl) + "_impl" + args = ", ".join(func['_impl_arg_list']) dump_line_with_break("mpi_errno = %s(%s);" % (impl, args)) dump_error_check("") - if '_has_handle_out' in func: + if func['_has_handle_out']: # assuming we are creating new handle(s) for p in func['_has_handle_out']: (name, kind) = (p['name'], p['kind']) @@ -1888,6 +2112,8 @@ def get_C_param(param, mapping): if param['func_type']: param_type = param['func_type'] + if mapping['_name'].startswith("BIG_"): + param_type += "_c" if not param_type: raise Exception("Type mapping [%s] %s not found!" % (mapping, kind)) @@ -1926,6 +2152,17 @@ def get_C_param(param, mapping): return s +def get_impl_param(func, param, mapping): + s = get_C_param(param, mapping) + if RE.match(r'POLY', param['kind']): + if func['_map_type'] == "BIG": + # internally we always use MPI_Aint for poly type + s = re.sub(r'MPI_Count', r'MPI_Aint', s) + elif func['_poly_impl'] != "separate": + # SMALL but internally use MPI_Aint + s = re.sub(r'\bint\b', r'MPI_Aint', s) + return s + def get_polymorph_param_and_arg(s): # s is a polymorph spec, e.g. "MPIR_Attr_type attr_type=MPIR_ATTR_PTR" # Note: we assum limit of single extra param for now (which is sufficient) @@ -1974,6 +2211,13 @@ def dump_for_close(): G.out.append("DEDENT") G.out.append("}") +def dump_error(errname, errfmt, errargs): + G.out.append("mpi_errno = MPIR_Err_create_code(mpi_errno, MPIR_ERR_RECOVERABLE,") + G.out.append(" __func__, __LINE__, MPI_ERR_OTHER,") + G.out.append(" \"**%s\"," % errname) + G.out.append(" \"**%s %s\", %s);" % (errname, errfmt, errargs)) + G.out.append("goto fn_fail;") + def split_line_with_break(s, tail, N=100): """Breaks a long line with proper indentations. This simplistic routine splits on ", ", thus only works with function declarations diff --git a/maint/local_python/mpi_api.py b/maint/local_python/mpi_api.py index 9af1ae83ae7..a37fa9b9671 100644 --- a/maint/local_python/mpi_api.py +++ b/maint/local_python/mpi_api.py @@ -180,3 +180,9 @@ def parse_param_attributes(p): p['constant'] = True else: p['constant'] = False + +def function_has_POLY_parameters(func): + for p in func['parameters']: + if p['kind'].startswith('POLY'): + return True + return False diff --git a/src/binding/c/datatype_api.txt b/src/binding/c/datatype_api.txt index adc205f23a5..c9bb8910e48 100644 --- a/src/binding/c/datatype_api.txt +++ b/src/binding/c/datatype_api.txt @@ -56,6 +56,7 @@ MPI_Get_address: MPI_Get_count: .desc: Gets the number of "top level" elements .skip: global_cs + .poly_impl: use_aint /* Notes: If the size of the datatype is zero, this routine will return a count of @@ -64,11 +65,7 @@ MPI_Get_count: 'MPI_UNDEFINED' is returned instead. */ { - MPI_Aint count_x; - MPIR_Get_count_impl(status, datatype, &count_x); - - /* clip the value if it cannot be correctly returned to the user */ - *count = (count_x > INT_MAX) ? MPI_UNDEFINED : (int) count_x; + MPIR_Get_count_impl(status, datatype, &count_c); } MPI_Get_elements: @@ -84,11 +81,20 @@ MPI_Get_elements: MPI_Count count_x; MPI_Count byte_count = MPIR_STATUS_GET_COUNT(*status); mpi_errno = MPIR_Get_elements_x_impl(&byte_count, datatype, &count_x); - MPIR_ERR_CHECK(mpi_errno); + if (mpi_errno) { + goto fn_fail; + } /* clip the value if it cannot be correctly returned to the user */ *count = (count_x > INT_MAX) ? MPI_UNDEFINED : (int) count_x; } +{ -- large_count -- + MPI_Count byte_count = MPIR_STATUS_GET_COUNT(*status); + mpi_errno = MPIR_Get_elements_x_impl(&byte_count, datatype, count); + if (mpi_errno) { + goto fn_fail; + } +} MPI_Get_elements_x: .desc: Returns the number of basic elements @@ -103,6 +109,7 @@ MPI_Get_elements_x: MPI_Pack: .desc: Packs a datatype into contiguous memory .skip: global_cs + .poly_impl: use_aint /* Notes (from the specifications): The input value of position is the first location in the output buffer to be @@ -113,19 +120,17 @@ MPI_Pack: message. */ { - MPI_Aint position_x = *position; MPI_Aint actual_pack_bytes; - void *buf = (void *) ((char *) outbuf + position_x); + void *buf = (void *) ((char *) outbuf + position_c); mpi_errno = MPIR_Typerep_pack(inbuf, incount, datatype, 0, buf, outsize, &actual_pack_bytes); if (mpi_errno) goto fn_fail; - position_x += actual_pack_bytes; - - MPIR_Assign_trunc(*position, position_x, int); + position_c += actual_pack_bytes; } MPI_Pack_external: .desc: Packs a datatype into contiguous memory, using the external32 format + .poly_impl: use_aint { -- early_return -- if (incount == 0) { goto fn_exit; @@ -133,22 +138,23 @@ MPI_Pack_external: } { MPI_Aint actual_pack_bytes; - mpi_errno = MPIR_Typerep_pack_external(inbuf, incount, datatype, - (void *) ((char *) outbuf + *position), - &actual_pack_bytes); + void *buf = (void *) ((char *) outbuf + position_c); + mpi_errno = MPIR_Typerep_pack_external(inbuf, incount, datatype, buf, &actual_pack_bytes); if (mpi_errno) goto fn_fail; - *position += actual_pack_bytes; + position_c += actual_pack_bytes; } MPI_Pack_external_size: .desc: Returns the upper bound on the amount of space needed to pack a message using MPI_Pack_external. + .poly_impl: use_aint { - *size = (MPI_Aint) incount *(MPI_Aint) MPIR_Typerep_size_external32(datatype); + size_c = (MPI_Aint) incount *(MPI_Aint) MPIR_Typerep_size_external32(datatype); } MPI_Pack_size: .desc: Returns the upper bound on the amount of space needed to pack a message + .poly_impl: use_aint /* Notes: The MPI standard document describes this in terms of 'MPI_Pack', but it @@ -156,41 +162,38 @@ MPI_Pack_size: the maximum that is needed by either 'MPI_Pack' or 'MPI_Unpack'. */ { - MPI_Aint size_x; - MPIR_Pack_size_impl(incount, datatype, &size_x); - MPIR_Assign_trunc(*size, size_x, int); + MPIR_Pack_size_impl(incount, datatype, &size_c); } MPI_Unpack: .desc: Unpack a buffer according to a datatype into contiguous memory .seealso: MPI_Pack, MPI_Pack_size + .poly_impl: use_aint { - MPI_Aint position_x = *position; - MPI_Aint actual_unpack_bytes; - void *buf = (void *) ((char *) inbuf + position_x); - mpi_errno = - MPIR_Typerep_unpack(buf, insize, outbuf, outcount, datatype, 0, &actual_unpack_bytes); + void *buf = (void *) ((char *) inbuf + position_c); + mpi_errno = MPIR_Typerep_unpack(buf, insize, outbuf, outcount, datatype, 0, &actual_unpack_bytes); if (mpi_errno) goto fn_fail; - position_x += actual_unpack_bytes; - MPIR_Assign_trunc(*position, position_x, int); + position_c += actual_unpack_bytes; } MPI_Unpack_external: .desc: Unpack a buffer (packed with MPI_Pack_external) according to a datatype into contiguous memory -{ + .poly_impl: use_aint +{ -- early_return -- if (insize == 0) { goto fn_exit; } - +} +{ MPI_Aint actual_unpack_bytes; - mpi_errno = MPIR_Typerep_unpack_external((void *) ((char *) inbuf + *position), - outbuf, outcount, datatype, &actual_unpack_bytes); + void *buf = (void *) ((char *) inbuf + position_c); + mpi_errno = MPIR_Typerep_unpack_external(buf, outbuf, outcount, datatype, &actual_unpack_bytes); if (mpi_errno) goto fn_fail; - *position += actual_unpack_bytes; + position_c += actual_unpack_bytes; } MPI_Register_datarep: not_implemented @@ -249,7 +252,7 @@ MPI_Type_free: MPI_Type_extent: datatype: DATATYPE, [datatype to get information on] - extent: POLYDISPLACEMENT_AINT_COUNT, direction=out, [extent of datatype] + extent: DISPLACEMENT_AINT_COUNT_SMALL, direction=out, [extent of datatype] .desc: Returns the extent of a datatype .skip: global_cs .replace: removed with MPI_Type_get_extent @@ -259,7 +262,7 @@ MPI_Type_extent: MPI_Type_lb: datatype: DATATYPE, [datatype to get information on] - displacement: POLYDISPLACEMENT_AINT_COUNT, direction=out, [displacement of lower bound from origin, in bytes] + displacement: DISPLACEMENT_AINT_COUNT_SMALL, direction=out, [displacement of lower bound from origin, in bytes] .desc: Returns the lower-bound of a datatype .skip: global_cs .replace: removed with MPI_Type_Get_extent @@ -269,7 +272,7 @@ MPI_Type_lb: MPI_Type_ub: datatype: DATATYPE, [datatype to get information on] - displacement: POLYDISPLACEMENT_AINT_COUNT, direction=out, [displacement of upper bound from origin, in bytes] + displacement: DISPLACEMENT_AINT_COUNT_SMALL, direction=out, [displacement of upper bound from origin, in bytes] .desc: Returns the upper bound of a datatype .skip: global_cs .replace: removed with MPI_Type_get_extent @@ -309,6 +312,12 @@ MPI_Type_get_extent: { MPIR_Type_get_extent_impl(datatype, lb, extent); } +{ -- large_count -- + MPI_Aint lb_c, extent_c; + MPIR_Type_get_extent_impl(datatype, &lb_c, &extent_c); + *lb = lb_c; + *extent = extent_c; +} MPI_Type_get_extent_x: .desc: Get the lower bound and extent as MPI_Count values for a datatype @@ -323,6 +332,9 @@ MPI_Type_get_true_extent: { MPIR_Type_get_true_extent_impl(datatype, true_lb, true_extent); } +{ -- large_count -- + MPIR_Type_get_true_extent_x_impl(datatype, true_lb, true_extent); +} MPI_Type_get_true_extent_x: .desc: Get the true lower bound and extent as MPI_Count values for a datatype @@ -334,14 +346,12 @@ MPI_Type_get_true_extent_x: MPI_Type_size: .desc: Return the number of bytes occupied by entries in the datatype .skip: global_cs + .poly_impl: use_aint { - MPI_Count size_x; - mpi_errno = MPIR_Type_size_x_impl(datatype, &size_x); + mpi_errno = MPIR_Type_size_x_impl(datatype, &size_c); MPIR_ERR_CHECK(mpi_errno); - MPIR_Assert(size_x >= 0); - /* handle overflow: see MPI-3 p.104 */ - *size = (size_x > INT_MAX) ? MPI_UNDEFINED : (int) size_x; + MPIR_Assert(size_c >= 0); } MPI_Type_size_x: @@ -429,9 +439,9 @@ MPI_Type_dup: .desc: Duplicate a datatype MPI_Type_hindexed: - count: POLYDTYPE_NUM_ELEM_NNI, [number of blocks -- also number of entries in array_of_displacements and array_of_blocklengths] - array_of_blocklengths: POLYDTYPE_NUM_ELEM_NNI, length=count, [number of elements in each block] - array_of_displacements: POLYDISPLACEMENT_AINT_COUNT, length=count, [byte displacement of each block] + count: DTYPE_NUM_ELEM_NNI_SMALL, [number of blocks -- also number of entries in array_of_displacements and array_of_blocklengths] + array_of_blocklengths: DTYPE_NUM_ELEM_NNI_SMALL, length=count, [number of elements in each block] + array_of_displacements: DISPLACEMENT_AINT_COUNT_SMALL, length=count, [byte displacement of each block] oldtype: DATATYPE, [old datatype] newtype: DATATYPE, direction=out, [new datatype] .desc: Creates an indexed datatype with offsets in bytes @@ -463,9 +473,9 @@ MPI_Type_hindexed: */ MPI_Type_hvector: - count: POLYDTYPE_NUM_ELEM_NNI, [number of blocks] - blocklength: POLYDTYPE_NUM_ELEM_NNI, [number of elements in each block] - stride: POLYDTYPE_STRIDE_BYTES, [number of bytes between start of each block] + count: DTYPE_NUM_ELEM_NNI_SMALL, [number of blocks] + blocklength: DTYPE_NUM_ELEM_NNI_SMALL, [number of elements in each block] + stride: DTYPE_STRIDE_BYTES_SMALL, [number of bytes between start of each block] oldtype: DATATYPE, [old datatype] newtype: DATATYPE, direction=out, [new datatype] .desc: type_hvector @@ -500,9 +510,9 @@ MPI_Type_indexed: */ MPI_Type_struct: - count: POLYDTYPE_NUM_ELEM_NNI, [number of blocks also number of entries in arrays array_of_types, array_of_displacements, and array_of_blocklengths] - array_of_blocklengths: POLYDTYPE_NUM_ELEM_NNI, length=count, [number of elements in each block] - array_of_displacements: POLYDISPLACEMENT_AINT_COUNT, length=count, [byte displacement of each block] + count: DTYPE_NUM_ELEM_NNI_SMALL, [number of blocks also number of entries in arrays array_of_types, array_of_displacements, and array_of_blocklengths] + array_of_blocklengths: DTYPE_NUM_ELEM_NNI_SMALL, length=count, [number of elements in each block] + array_of_displacements: DISPLACEMENT_AINT_COUNT_SMALL, length=count, [byte displacement of each block] array_of_types: DATATYPE, length=count, [types of elements in each block] newtype: DATATYPE, direction=out, [new datatype] .desc: Creates a struct datatype diff --git a/src/binding/c/rma_api.txt b/src/binding/c/rma_api.txt index 91e0ca1e5a9..3cc31500919 100644 --- a/src/binding/c/rma_api.txt +++ b/src/binding/c/rma_api.txt @@ -533,12 +533,25 @@ MPI_Win_set_name: MPI_Win_shared_query: .desc: Query the size and base pointer for a patch of a shared memory window .seealso: MPI_Win_allocate_shared - .impl: mpid /* Notes: The returned baseptr points to the calling process' address space of the shared segment belonging to the target rank. */ +{ + mpi_errno = MPID_Win_shared_query(win_ptr, rank, size, disp_unit, baseptr); + if (mpi_errno) { + goto fn_fail; + } +} +{ -- large_count -- + int disp_unit_c; + mpi_errno = MPID_Win_shared_query(win_ptr, rank, size, &disp_unit_c, baseptr); + if (mpi_errno) { + goto fn_fail; + } + *disp_unit = disp_unit_c; +} MPI_Win_start: .desc: Start an RMA access epoch for MPI diff --git a/src/include/mpir_datatype.h b/src/include/mpir_datatype.h index 0df4daa52ee..2aa634f7725 100644 --- a/src/include/mpir_datatype.h +++ b/src/include/mpir_datatype.h @@ -619,48 +619,4 @@ MPI_Aint MPII_Datatype_blockindexed_count_contig(MPI_Aint count, const MPI_Aint disp_array[], int dispinbytes, MPI_Aint old_extent); -/* large count prototypes */ -int MPIR_Type_get_envelope_c_impl(MPI_Datatype datatype, - MPI_Aint * num_integers, MPI_Aint * num_addresses, - MPI_Aint * num_large_counts, MPI_Aint * num_datatypes, - int *combiner); -int MPIR_Type_get_contents_c_impl(MPI_Datatype datatype, MPI_Aint max_integers, - MPI_Aint max_addresses, MPI_Aint max_counts, - MPI_Aint max_datatypes, int array_of_integers[], - MPI_Aint array_of_addresses[], MPI_Count array_of_counts[], - MPI_Datatype array_of_datatypes[]); -int MPIR_Type_contiguous_c_impl(MPI_Aint count, MPI_Datatype oldtype, MPI_Datatype * newtype); -int MPIR_Type_vector_c_impl(MPI_Aint count, MPI_Aint blocklength, MPI_Aint stride, - MPI_Datatype oldtype, MPI_Datatype * newtype); -int MPIR_Type_create_hvector_c_impl(MPI_Aint count, MPI_Aint blocklength, MPI_Aint stride, - MPI_Datatype oldtype, MPI_Datatype * newtype); -int MPIR_Type_create_indexed_block_c_impl(MPI_Aint count, MPI_Aint blocklength, - const MPI_Aint array_of_displacements[], - MPI_Datatype oldtype, MPI_Datatype * newtype); -int MPIR_Type_create_hindexed_block_c_impl(MPI_Aint count, MPI_Aint blocklength, - const MPI_Aint array_of_displacements[], - MPI_Datatype oldtype, MPI_Datatype * newtype); -int MPIR_Type_indexed_c_impl(MPI_Aint count, - const MPI_Aint * array_of_blocklengths, - const MPI_Aint * array_of_displacements, - MPI_Datatype oldtype, MPI_Datatype * newtype); -int MPIR_Type_create_hindexed_c_impl(MPI_Aint count, - const MPI_Aint array_of_blocklengths[], - const MPI_Aint array_of_displacements[], - MPI_Datatype oldtype, MPI_Datatype * newtype); -int MPIR_Type_create_struct_c_impl(MPI_Aint count, - const MPI_Aint * array_of_blocklengths, - const MPI_Aint * array_of_displacements, - const MPI_Datatype * array_of_types, MPI_Datatype * newtype); -int MPIR_Type_create_resized_c_impl(MPI_Datatype oldtype, MPI_Aint lb, MPI_Aint extent, - MPI_Datatype * newtype); -int MPIR_Type_create_darray_c_impl(int size, int rank, int ndims, - const MPI_Aint array_of_gsizes[], const int array_of_distribs[], - const int array_of_dargs[], const int array_of_psizes[], - int order, MPI_Datatype oldtype, MPI_Datatype * newtype); -int MPIR_Type_create_subarray_c_impl(int ndims, const MPI_Aint array_of_sizes[], - const MPI_Aint array_of_subsizes[], - const MPI_Aint array_of_starts[], int order, - MPI_Datatype oldtype, MPI_Datatype * newtype); - #endif /* MPIR_DATATYPE_H_INCLUDED */ From 23ebfe95c912755e4d8a584de000f18f33756dff Mon Sep 17 00:00:00 2001 From: Hui Zhou Date: Tue, 16 Feb 2021 13:53:09 -0600 Subject: [PATCH 08/11] python/c: refactor the mapping parameter The parameter mapping is passed along only because a few lower level function need it. Since the mapping concept is obscure at higher level, having it in the interface makes the code obscrue. On the other hand, a simpl string parameter "map_type" is more intuitive to understand. This commit uses "map_type" or simply omits mapping whereever the mapping is not directly needed. --- maint/local_python/binding_c.py | 85 +++++++++++++++++---------------- 1 file changed, 45 insertions(+), 40 deletions(-) diff --git a/maint/local_python/binding_c.py b/maint/local_python/binding_c.py index be6f9d19663..72b25a6f598 100644 --- a/maint/local_python/binding_c.py +++ b/maint/local_python/binding_c.py @@ -16,25 +16,19 @@ def dump_mpi_c(func, map_type="SMALL"): """Dumps the function's C source code to G.out array""" - # map_type may be "SMALL", "BIG", or "SMALL-poly" - if RE.match(r'SMALL', map_type): - mapping = G.MAPS['SMALL_C_KIND_MAP'] - else: - mapping = G.MAPS['BIG_C_KIND_MAP'] - - # manpage and body-of-routines will check _map_type + # map_type may be "SMALL" or "BIG" func['_map_type'] = map_type check_func_directives(func) filter_c_parameters(func) - check_params_with_large_only(func, mapping) + check_params_with_large_only(func) # for poly functions, decide impl interface check_large_parameters(func) - process_func_parameters(func, mapping) + process_func_parameters(func) - G.mpi_declares.append(get_declare_function(func, mapping, "proto")) + G.mpi_declares.append(get_declare_function(func, map_type, "proto")) # collect error codes additional from auto generated ones if 'error' in func: @@ -50,23 +44,23 @@ def dump_mpi_c(func, map_type="SMALL"): G.out.append("#include \"%s\"" % a) G.out.append("") - dump_profiling(func, mapping) + dump_profiling(func) if 'polymorph' in func: # MPII_ function to support C/Fortran Polymorphism, eg MPI_Comm_get_attr # It needs go inside "#ifndef MPICH_MPI_FROM_PMPI" G.out.pop() # #endif from dump_profiling() - dump_function(func, mapping, kind="polymorph") + dump_function(func, kind="polymorph") G.out.append("#endif /* MPICH_MPI_FROM_PMPI */") G.out.append("") dump_manpage(func) if 'polymorph' in func: - dump_function(func, mapping, kind="call-polymorph") + dump_function(func, kind="call-polymorph") elif 'replace' in func and 'body' not in func: - dump_function(func, mapping, kind="call-replace") + dump_function(func, kind="call-replace") else: - dump_function(func, mapping, kind="normal") + dump_function(func, kind="normal") def get_func_file_path(func, root_dir): file_path = None @@ -292,7 +286,7 @@ def filter_c_parameters(func): c_params.append(p) func['c_parameters'] = c_params -def check_params_with_large_only(func, mapping): +def check_params_with_large_only(func): if '_has_large_only' not in func: func['_has_large_only'] = 0 for p in func['c_parameters']: @@ -305,7 +299,7 @@ def check_params_with_large_only(func, mapping): if not p['large_only']: func['params_small'].append(p) if func['_has_large_only']: - if mapping['_name'].startswith('SMALL'): + if func['_map_type'] == "SMALL": func['c_parameters'] = func['params_small'] else: func['c_parameters'] = func['params_large'] @@ -352,7 +346,7 @@ def get_userbuffer_group(func, i): group_kind, group_count = None, 0 return (group_kind, group_count) -def process_func_parameters(func, mapping): +def process_func_parameters(func): """ Scan parameters and populate a few lists to facilitate generation.""" # Note: we'll attach the lists to func at the end validation_list, handle_ptr_list, impl_arg_list, impl_param_list = [], [], [], [] @@ -377,7 +371,7 @@ def process_func_parameters(func, mapping): t += "," t += temp_p['name'] impl_arg_list.append(temp_p['name']) - impl_param_list.append(get_impl_param(func, temp_p, mapping)) + impl_param_list.append(get_impl_param(func, temp_p)) validation_list.append({'kind': group_kind, 'name': t}) # -- pointertag_list if re.search(r'alltoallw', func_name, re.IGNORECASE): @@ -580,7 +574,7 @@ def process_func_parameters(func, mapping): impl_param_list.append("%s *%s_ptr" % (mpir_type, name)) else: impl_arg_list.append(name) - impl_param_list.append(get_impl_param(func, p, mapping)) + impl_param_list.append(get_impl_param(func, p)) i += 1 if RE.match(r'MPI_(Wait|Test)$', func_name): @@ -610,8 +604,8 @@ def dump_copy_right(): G.out.append(" */") G.out.append("") -def dump_profiling(func, mapping): - func_name = get_function_name(func, mapping) +def dump_profiling(func): + func_name = get_function_name(func, func['_map_type']) G.out.append("/* -- Begin Profiling Symbol Block for routine %s */" % func_name) G.out.append("#if defined(HAVE_PRAGMA_WEAK)") G.out.append("#pragma weak %s = P%s" % (func_name, func_name)) @@ -620,7 +614,7 @@ def dump_profiling(func, mapping): G.out.append("#elif defined(HAVE_PRAGMA_CRI_DUP)") G.out.append("#pragma _CRI duplicate %s as P%s" % (func_name, func_name)) G.out.append("#elif defined(HAVE_WEAK_ATTRIBUTE)") - s = get_declare_function(func, mapping) + s = get_declare_function(func, func['_map_type']) dump_line_with_break(s, " __attribute__ ((weak, alias(\"P%s\")));" % (func_name)) G.out.append("#endif") G.out.append("/* -- End Profiling Symbol Block */") @@ -636,7 +630,7 @@ def dump_profiling(func, mapping): def dump_manpage(func): G.out.append("/*@") - G.out.append(" %s - %s" % (func['name'], func['desc'])) + G.out.append(" %s - %s" % (get_function_name(func, func['_map_type']), func['desc'])) G.out.append("") lis_map = G.MAPS['LIS_KIND_MAP'] for p in func['c_parameters']: @@ -722,12 +716,12 @@ def dump_manpage_list(list, header): G.out.append("") # ---- the function part ---- -def dump_function(func, mapping, kind): +def dump_function(func, kind): """Appends to G.out array the MPI function implementation.""" - func_name = get_function_name(func, mapping); + func_name = get_function_name(func, func['_map_type']); state_name = "MPID_STATE_" + func_name.upper() - s = get_declare_function(func, mapping) + s = get_declare_function(func, func['_map_type']) if kind == "polymorph": (extra_param, extra_arg) = get_polymorph_param_and_arg(func['polymorph']) s = re.sub(r'MPIX?_', 'MPII_', s, 1) @@ -757,7 +751,7 @@ def dump_function(func, mapping, kind): repl_call = "mpi_errno = %s(%s);" % (repl_name, repl_args) dump_function_replace(func, state_name, repl_call) else: - dump_function_normal(func, state_name, mapping) + dump_function_normal(func, state_name) G.out.append("DEDENT") G.out.append("}") @@ -816,7 +810,7 @@ def check_large_parameters(func): else: func['_poly_in_list'].append(p) -def dump_function_normal(func, state_name, mapping): +def dump_function_normal(func, state_name): G.out.append("int mpi_errno = MPI_SUCCESS;") if '_handle_ptr_list' in func: for p in func['_handle_ptr_list']: @@ -973,7 +967,7 @@ def dump_body_of_routine(): # MPI_T always return the mpi_errno pass else: - dump_mpi_fn_fail(func, mapping) + dump_mpi_fn_fail(func) G.out.append("goto fn_exit;") def replace_impl_arg_list(arg_list, old, new): @@ -1322,21 +1316,21 @@ def dump_function_direct(func, state_name): G.out.append(l) # -- fn_fail ---- -def dump_mpi_fn_fail(func, mapping): +def dump_mpi_fn_fail(func): G.out.append("/* --BEGIN ERROR HANDLINE-- */") if RE.match(r'mpi_(finalized|initialized)', func['name'], re.IGNORECASE): G.out.append("#ifdef HAVE_ERROR_CHECKING") cond = "MPIR_Errutil_is_initialized()" dump_if_open(cond) - s = get_fn_fail_create_code(func, mapping) + s = get_fn_fail_create_code(func) G.out.append(s) G.out.append("mpi_errno = MPIR_Err_return_comm(0, __func__, mpi_errno);") dump_if_close() G.out.append("#endif") else: G.out.append("#ifdef HAVE_ERROR_CHECKING") - s = get_fn_fail_create_code(func, mapping) + s = get_fn_fail_create_code(func) dump_line_with_break(s) G.out.append("#endif") if '_has_comm' in func: @@ -1348,11 +1342,12 @@ def dump_mpi_fn_fail(func, mapping): G.out.append("/* --END ERROR HANDLING-- */") -def get_fn_fail_create_code(func, mapping): +def get_fn_fail_create_code(func): s = "mpi_errno = MPIR_Err_create_code(mpi_errno, MPIR_ERR_RECOVERABLE, __func__, __LINE__, MPI_ERR_OTHER," - func_name = get_function_name(func, mapping) + func_name = get_function_name(func, func['_map_type']) err_name = func_name.lower() + mapping = get_mapping(func['_map_type']) (fmts, args, err_fmts) = ([], [], []) fmt_codes = {'RANK': "i", 'TAG': "t", 'COMMUNICATOR': "C", 'ASSERT': "A", 'DATATYPE': "D", 'ERRHANDLER': "E", 'FILE': "F", 'GROUP': "G", 'INFO': "I", 'OPERATION': "O", 'REQUEST': "R", 'WINDOW': "W", 'SESSION': "S", 'KEYVAL': "K", "GREQUEST_CLASS": "x"} @@ -2059,10 +2054,17 @@ def dump_validate_get_topo_size(func): G.out.append("int indegree, outdegree, weighted;") G.out.append("mpi_errno = MPIR_Topo_canon_nhb_count(comm_ptr, &indegree, &outdegree, &weighted);") func['_got_topo_size'] = 1 + # ---- supporting routines (reusable) ---- -def get_function_name(func, mapping): - if RE.search(r'BIG', mapping['_name']): +def get_mapping(map_type): + if map_type == "SMALL": + return G.MAPS['SMALL_C_KIND_MAP'] + else: + return G.MAPS['BIG_C_KIND_MAP'] + +def get_function_name(func, map_type="SMALL"): + if map_type == "BIG": return func['name'] + "_c" else: return func['name'] @@ -2073,8 +2075,9 @@ def get_function_args(func): arg_list.append(p['name']) return ', '.join(arg_list) -def get_declare_function(func, mapping, kind=""): - name = get_function_name(func, mapping) +def get_declare_function(func, map_type="SMALL", kind=""): + name = get_function_name(func, map_type) + mapping = get_mapping(map_type) ret = "int" if 'return' in func: @@ -2152,7 +2155,9 @@ def get_C_param(param, mapping): return s -def get_impl_param(func, param, mapping): +def get_impl_param(func, param): + mapping = get_mapping(func['_map_type']) + s = get_C_param(param, mapping) if RE.match(r'POLY', param['kind']): if func['_map_type'] == "BIG": From 4525265f1369235031e663c1c27e54577e71a643 Mon Sep 17 00:00:00 2001 From: Hui Zhou Date: Tue, 16 Feb 2021 18:03:46 -0600 Subject: [PATCH 09/11] datatype: use impl wrapper function for datatype API ... that has output counters, e.g. MPI_Get_count, MPI_Get_elements, MPI_Pack, MPI_Unpack, etc. We need swap pointers when the type `MPI_Count` and `MPI_Aint` are not the same size, or we may skip the swap. The swapping will require use of different variables. This become difficult to handle with inlined body-of-routines. Wrap them inside an _impl function allows both cases to be handled properly. --- src/binding/c/datatype_api.txt | 65 +---------- src/include/mpir_datatype.h | 6 +- src/mpi/coll/helper_fns.c | 2 +- src/mpi/datatype/datatype_impl.c | 106 ++++++++++++++++-- src/mpi/pt2pt/bsendutil.c | 2 +- src/mpi/pt2pt/sendrecv.c | 4 +- src/mpid/ch4/netmod/ucx/ucx_datatype.c | 4 +- .../ch4/shm/posix/posix_coll_release_gather.h | 6 +- 8 files changed, 110 insertions(+), 85 deletions(-) diff --git a/src/binding/c/datatype_api.txt b/src/binding/c/datatype_api.txt index c9bb8910e48..93d122f8b39 100644 --- a/src/binding/c/datatype_api.txt +++ b/src/binding/c/datatype_api.txt @@ -64,9 +64,6 @@ MPI_Get_count: size of 'datatype' (so that 'count' would not be integral), a 'count' of 'MPI_UNDEFINED' is returned instead. */ -{ - MPIR_Get_count_impl(status, datatype, &count_c); -} MPI_Get_elements: .desc: Returns the number of basic elements @@ -119,14 +116,6 @@ MPI_Pack: the communicator that will be subsequently used for sending the packed message. */ -{ - MPI_Aint actual_pack_bytes; - void *buf = (void *) ((char *) outbuf + position_c); - mpi_errno = MPIR_Typerep_pack(inbuf, incount, datatype, 0, buf, outsize, &actual_pack_bytes); - if (mpi_errno) - goto fn_fail; - position_c += actual_pack_bytes; -} MPI_Pack_external: .desc: Packs a datatype into contiguous memory, using the external32 format @@ -136,21 +125,10 @@ MPI_Pack_external: goto fn_exit; } } -{ - MPI_Aint actual_pack_bytes; - void *buf = (void *) ((char *) outbuf + position_c); - mpi_errno = MPIR_Typerep_pack_external(inbuf, incount, datatype, buf, &actual_pack_bytes); - if (mpi_errno) - goto fn_fail; - position_c += actual_pack_bytes; -} MPI_Pack_external_size: .desc: Returns the upper bound on the amount of space needed to pack a message using MPI_Pack_external. .poly_impl: use_aint -{ - size_c = (MPI_Aint) incount *(MPI_Aint) MPIR_Typerep_size_external32(datatype); -} MPI_Pack_size: .desc: Returns the upper bound on the amount of space needed to pack a message @@ -161,23 +139,11 @@ MPI_Pack_size: applies to both 'MPI_Pack' and 'MPI_Unpack'. That is, the value 'size' is the maximum that is needed by either 'MPI_Pack' or 'MPI_Unpack'. */ -{ - MPIR_Pack_size_impl(incount, datatype, &size_c); -} MPI_Unpack: .desc: Unpack a buffer according to a datatype into contiguous memory .seealso: MPI_Pack, MPI_Pack_size .poly_impl: use_aint -{ - MPI_Aint actual_unpack_bytes; - void *buf = (void *) ((char *) inbuf + position_c); - mpi_errno = MPIR_Typerep_unpack(buf, insize, outbuf, outcount, datatype, 0, &actual_unpack_bytes); - if (mpi_errno) - goto fn_fail; - - position_c += actual_unpack_bytes; -} MPI_Unpack_external: .desc: Unpack a buffer (packed with MPI_Pack_external) according to a datatype into contiguous memory @@ -187,14 +153,6 @@ MPI_Unpack_external: goto fn_exit; } } -{ - MPI_Aint actual_unpack_bytes; - void *buf = (void *) ((char *) inbuf + position_c); - mpi_errno = MPIR_Typerep_unpack_external(buf, outbuf, outcount, datatype, &actual_unpack_bytes); - if (mpi_errno) - goto fn_fail; - position_c += actual_unpack_bytes; -} MPI_Register_datarep: not_implemented .desc: Register a set of user-provided data conversion @@ -309,15 +267,7 @@ MPI_Type_get_envelope: MPI_Type_get_extent: .desc: Get the lower bound and extent for a Datatype .skip: global_cs -{ - MPIR_Type_get_extent_impl(datatype, lb, extent); -} -{ -- large_count -- - MPI_Aint lb_c, extent_c; - MPIR_Type_get_extent_impl(datatype, &lb_c, &extent_c); - *lb = lb_c; - *extent = extent_c; -} + .poly_impl: use_aint MPI_Type_get_extent_x: .desc: Get the lower bound and extent as MPI_Count values for a datatype @@ -329,12 +279,7 @@ MPI_Type_get_extent_x: MPI_Type_get_true_extent: .desc: Get the true lower bound and extent for a datatype .skip: global_cs -{ - MPIR_Type_get_true_extent_impl(datatype, true_lb, true_extent); -} -{ -- large_count -- - MPIR_Type_get_true_extent_x_impl(datatype, true_lb, true_extent); -} + .poly_impl: use_aint MPI_Type_get_true_extent_x: .desc: Get the true lower bound and extent as MPI_Count values for a datatype @@ -347,12 +292,6 @@ MPI_Type_size: .desc: Return the number of bytes occupied by entries in the datatype .skip: global_cs .poly_impl: use_aint -{ - mpi_errno = MPIR_Type_size_x_impl(datatype, &size_c); - MPIR_ERR_CHECK(mpi_errno); - - MPIR_Assert(size_c >= 0); -} MPI_Type_size_x: .desc: Return the number of bytes occupied by entries in the datatype diff --git a/src/include/mpir_datatype.h b/src/include/mpir_datatype.h index 2aa634f7725..335e773dd50 100644 --- a/src/include/mpir_datatype.h +++ b/src/include/mpir_datatype.h @@ -575,13 +575,9 @@ int MPIR_Get_elements_x_impl(MPI_Count * bytes, MPI_Datatype datatype, MPI_Count void MPIR_Type_get_extent_x_impl(MPI_Datatype datatype, MPI_Count * lb, MPI_Count * extent); void MPIR_Type_get_true_extent_x_impl(MPI_Datatype datatype, MPI_Count * true_lb, MPI_Count * true_extent); -void MPIR_Get_count_impl(const MPI_Status * status, MPI_Datatype datatype, MPI_Aint * count); int MPIR_Type_contiguous_x_impl(MPI_Count count, MPI_Datatype old_type, MPI_Datatype * new_type_p); -void MPIR_Type_get_extent_impl(MPI_Datatype datatype, MPI_Aint * lb, MPI_Aint * extent); -void MPIR_Type_get_true_extent_impl(MPI_Datatype datatype, MPI_Aint * true_lb, - MPI_Aint * true_extent); void MPIR_Type_free_impl(MPI_Datatype * datatype); -void MPIR_Pack_size_impl(int incount, MPI_Datatype datatype, MPI_Aint * size); +void MPIR_Pack_size(MPI_Aint incount, MPI_Datatype datatype, MPI_Aint * size); void MPIR_Type_lb_impl(MPI_Datatype datatype, MPI_Aint * displacement); /* Datatype functions */ diff --git a/src/mpi/coll/helper_fns.c b/src/mpi/coll/helper_fns.c index a84e9e4005f..db7233533c7 100644 --- a/src/mpi/coll/helper_fns.c +++ b/src/mpi/coll/helper_fns.c @@ -404,7 +404,7 @@ int MPIC_Sendrecv_replace(void *buf, MPI_Aint count, MPI_Datatype datatype, MPIR_CONTEXT_INTRA_COLL : MPIR_CONTEXT_INTER_COLL; if (count > 0 && dest != MPI_PROC_NULL) { - MPIR_Pack_size_impl(count, datatype, &tmpbuf_size); + MPIR_Pack_size(count, datatype, &tmpbuf_size); MPIR_CHKLMEM_MALLOC(tmpbuf, void *, tmpbuf_size, mpi_errno, "temporary send buffer", MPL_MEM_BUFFER); diff --git a/src/mpi/datatype/datatype_impl.c b/src/mpi/datatype/datatype_impl.c index 9e9afce7568..30d559111ad 100644 --- a/src/mpi/datatype/datatype_impl.c +++ b/src/mpi/datatype/datatype_impl.c @@ -6,7 +6,7 @@ #include "mpiimpl.h" #include "datatype.h" -void MPIR_Get_count_impl(const MPI_Status * status, MPI_Datatype datatype, MPI_Aint * count) +int MPIR_Get_count_impl(const MPI_Status * status, MPI_Datatype datatype, MPI_Aint * count) { MPI_Aint size; @@ -36,15 +36,97 @@ void MPIR_Get_count_impl(const MPI_Status * status, MPI_Datatype datatype, MPI_A (*count) = 0; } } + return MPI_SUCCESS; } -void MPIR_Pack_size_impl(int incount, MPI_Datatype datatype, MPI_Aint * size) +int MPIR_Pack_impl(const void *inbuf, MPI_Aint incount, MPI_Datatype datatype, + void *outbuf, MPI_Aint outsize, MPI_Aint * position, MPIR_Comm * comm_ptr) +{ + int mpi_errno = MPI_SUCCESS; + MPI_Aint actual_pack_bytes; + void *buf = (void *) ((char *) outbuf + *position); + mpi_errno = MPIR_Typerep_pack(inbuf, incount, datatype, 0, buf, outsize, &actual_pack_bytes); + MPIR_ERR_CHECK(mpi_errno); + *position += actual_pack_bytes; + + fn_exit: + return mpi_errno; + fn_fail: + goto fn_exit; +} + +int MPIR_Pack_external_impl(const char datarep[], + const void *inbuf, MPI_Aint incount, MPI_Datatype datatype, + void *outbuf, MPI_Aint outsize, MPI_Aint * position) +{ + int mpi_errno = MPI_SUCCESS; + MPI_Aint actual_pack_bytes; + void *buf = (void *) ((char *) outbuf + *position); + mpi_errno = MPIR_Typerep_pack_external(inbuf, incount, datatype, buf, &actual_pack_bytes); + MPIR_ERR_CHECK(mpi_errno); + *position += actual_pack_bytes; + + fn_exit: + return mpi_errno; + fn_fail: + goto fn_fail; +} + +int MPIR_Unpack_impl(const void *inbuf, MPI_Aint insize, MPI_Aint * position, + void *outbuf, MPI_Aint outcount, MPI_Datatype datatype, MPIR_Comm * comm_ptr) +{ + int mpi_errno = MPI_SUCCESS; + MPI_Aint actual_unpack_bytes; + void *buf = (void *) ((char *) inbuf + *position); + mpi_errno = + MPIR_Typerep_unpack(buf, insize, outbuf, outcount, datatype, 0, &actual_unpack_bytes); + MPIR_ERR_CHECK(mpi_errno); + *position += actual_unpack_bytes; + + fn_exit: + return mpi_errno; + fn_fail: + goto fn_fail; +} + +int MPIR_Unpack_external_impl(const char datarep[], + const void *inbuf, MPI_Aint insize, MPI_Aint * position, + void *outbuf, MPI_Aint outcount, MPI_Datatype datatype) +{ + int mpi_errno = MPI_SUCCESS; + MPI_Aint actual_unpack_bytes; + void *buf = (void *) ((char *) inbuf + *position); + mpi_errno = MPIR_Typerep_unpack_external(buf, outbuf, outcount, datatype, &actual_unpack_bytes); + MPIR_ERR_CHECK(mpi_errno); + *position += actual_unpack_bytes; + + fn_exit: + return mpi_errno; + fn_fail: + goto fn_fail; +} + +void MPIR_Pack_size(MPI_Aint incount, MPI_Datatype datatype, MPI_Aint * size) { MPI_Aint typesize; MPIR_Datatype_get_size_macro(datatype, typesize); *size = incount * typesize; } +int MPIR_Pack_size_impl(MPI_Aint incount, MPI_Datatype datatype, MPIR_Comm * comm_ptr, + MPI_Aint * size) +{ + MPIR_Pack_size(incount, datatype, size); + return MPI_SUCCESS; +} + +int MPIR_Pack_external_size_impl(const char *datarep, + MPI_Aint incount, MPI_Datatype datatype, MPI_Aint * size) +{ + *size = incount * MPIR_Typerep_size_external32(datatype); + return MPI_SUCCESS; +} + int MPIR_Status_set_elements_x_impl(MPI_Status * status, MPI_Datatype datatype, MPI_Count count) { int mpi_errno = MPI_SUCCESS; @@ -96,17 +178,16 @@ void MPIR_Type_free_impl(MPI_Datatype * datatype) *datatype = MPI_DATATYPE_NULL; } -void MPIR_Type_get_extent_impl(MPI_Datatype datatype, MPI_Aint * lb, MPI_Aint * extent) +int MPIR_Type_get_extent_impl(MPI_Datatype datatype, MPI_Aint * lb, MPI_Aint * extent) { MPI_Count lb_x, extent_x; MPIR_Type_get_extent_x_impl(datatype, &lb_x, &extent_x); *lb = (lb_x > MPIR_AINT_MAX) ? MPI_UNDEFINED : (MPI_Aint) lb_x; *extent = (extent_x > MPIR_AINT_MAX) ? MPI_UNDEFINED : (MPI_Aint) extent_x; + return MPI_SUCCESS; } -/* any non-MPI functions go here, especially non-static ones */ - void MPIR_Type_get_extent_x_impl(MPI_Datatype datatype, MPI_Count * lb, MPI_Count * extent) { MPIR_Datatype *datatype_ptr = NULL; @@ -122,14 +203,15 @@ void MPIR_Type_get_extent_x_impl(MPI_Datatype datatype, MPI_Count * lb, MPI_Coun } } -void MPIR_Type_get_true_extent_impl(MPI_Datatype datatype, MPI_Aint * true_lb, - MPI_Aint * true_extent) +int MPIR_Type_get_true_extent_impl(MPI_Datatype datatype, MPI_Aint * true_lb, + MPI_Aint * true_extent) { MPI_Count true_lb_x, true_extent_x; MPIR_Type_get_true_extent_x_impl(datatype, &true_lb_x, &true_extent_x); *true_lb = (true_lb_x > MPIR_AINT_MAX) ? MPI_UNDEFINED : (MPI_Aint) true_lb_x; *true_extent = (true_extent_x > MPIR_AINT_MAX) ? MPI_UNDEFINED : (MPI_Aint) true_extent_x; + return MPI_SUCCESS; } /* any non-MPI functions go here, especially non-static ones */ @@ -161,7 +243,15 @@ void MPIR_Type_lb_impl(MPI_Datatype datatype, MPI_Aint * displacement) } } -/* any non-MPI functions go here, especially non-static ones */ +int MPIR_Type_size_impl(MPI_Datatype datatype, MPI_Aint * size) +{ + int mpi_errno = MPI_SUCCESS; + + MPIR_Datatype_get_size_macro(datatype, *size); + MPIR_Assert(*size >= 0); + + return mpi_errno; +} int MPIR_Type_size_x_impl(MPI_Datatype datatype, MPI_Count * size) { diff --git a/src/mpi/pt2pt/bsendutil.c b/src/mpi/pt2pt/bsendutil.c index 461e60237af..cc90a57f815 100644 --- a/src/mpi/pt2pt/bsendutil.c +++ b/src/mpi/pt2pt/bsendutil.c @@ -226,7 +226,7 @@ int MPIR_Bsend_isend(const void *buf, int count, MPI_Datatype dtype, MPIR_ERR_CHECK(mpi_errno); if (dtype != MPI_PACKED) - MPIR_Pack_size_impl(count, dtype, &packsize); + MPIR_Pack_size(count, dtype, &packsize); else packsize = count; diff --git a/src/mpi/pt2pt/sendrecv.c b/src/mpi/pt2pt/sendrecv.c index 793d303a89f..c02257c1e0b 100644 --- a/src/mpi/pt2pt/sendrecv.c +++ b/src/mpi/pt2pt/sendrecv.c @@ -105,7 +105,7 @@ int MPIR_Sendrecv_replace_impl(void *buf, int count, MPI_Datatype datatype, int MPIR_FUNC_VERBOSE_ENTER(MPID_STATE_MPIR_SENDRECV_REPLACE); if (count > 0 && dest != MPI_PROC_NULL) { - MPIR_Pack_size_impl(count, datatype, &tmpbuf_size); + MPIR_Pack_size(count, datatype, &tmpbuf_size); MPIR_CHKLMEM_MALLOC_ORJUMP(tmpbuf, void *, tmpbuf_size, mpi_errno, "temporary send buffer", MPL_MEM_BUFFER); @@ -245,7 +245,7 @@ int MPIR_Isendrecv_replace_impl(void *buf, int count, MPI_Datatype datatype, int if (count > 0 && dest != MPI_PROC_NULL) { MPI_Aint tmpbuf_size = 0; MPI_Aint actual_pack_bytes; - MPIR_Pack_size_impl(count, datatype, &tmpbuf_size); + MPIR_Pack_size(count, datatype, &tmpbuf_size); tmpbuf = MPL_malloc(tmpbuf_size, MPL_MEM_BUFFER); if (!tmpbuf) { diff --git a/src/mpid/ch4/netmod/ucx/ucx_datatype.c b/src/mpid/ch4/netmod/ucx/ucx_datatype.c index b4527247621..6590dc314ee 100644 --- a/src/mpid/ch4/netmod/ucx/ucx_datatype.c +++ b/src/mpid/ch4/netmod/ucx/ucx_datatype.c @@ -56,7 +56,7 @@ static size_t pack_size(void *state) struct pack_state *pack_state = (struct pack_state *) state; MPI_Aint packsize; - MPIR_Pack_size_impl(pack_state->count, pack_state->datatype, &packsize); + MPIR_Pack_size(pack_state->count, pack_state->datatype, &packsize); return (size_t) packsize; } @@ -79,7 +79,7 @@ static ucs_status_t unpack(void *state, size_t offset, const void *src, size_t c MPI_Aint actual_unpack_bytes; MPI_Aint packsize; - MPIR_Pack_size_impl(pack_state->count, pack_state->datatype, &packsize); + MPIR_Pack_size(pack_state->count, pack_state->datatype, &packsize); max_unpack_bytes = MPL_MIN(packsize, count); MPIR_Typerep_unpack(src, max_unpack_bytes, pack_state->buffer, pack_state->count, diff --git a/src/mpid/ch4/shm/posix/posix_coll_release_gather.h b/src/mpid/ch4/shm/posix/posix_coll_release_gather.h index fdb5bfda61a..e45a9077846 100644 --- a/src/mpid/ch4/shm/posix/posix_coll_release_gather.h +++ b/src/mpid/ch4/shm/posix/posix_coll_release_gather.h @@ -81,7 +81,7 @@ MPL_STATIC_INLINE_PREFIX int MPIDI_POSIX_mpi_bcast_release_gather(void *buffer, if (is_contig) { MPIR_Datatype_get_size_macro(datatype, type_size); } else { - MPIR_Pack_size_impl(1, datatype, &type_size); + MPIR_Pack_size(1, datatype, &type_size); } if (!is_contig || type_size >= MPIDI_POSIX_RELEASE_GATHER_BCAST_CELLSIZE) { @@ -257,7 +257,7 @@ MPL_STATIC_INLINE_PREFIX int MPIDI_POSIX_mpi_reduce_release_gather(const void *s if (is_contig) { MPIR_Datatype_get_size_macro(datatype, type_size); } else { - MPIR_Pack_size_impl(1, datatype, &type_size); + MPIR_Pack_size(1, datatype, &type_size); } if (sendbuf == MPI_IN_PLACE) { @@ -382,7 +382,7 @@ MPL_STATIC_INLINE_PREFIX int MPIDI_POSIX_mpi_allreduce_release_gather(const void if (is_contig) { MPIR_Datatype_get_size_macro(datatype, type_size); } else { - MPIR_Pack_size_impl(1, datatype, &type_size); + MPIR_Pack_size(1, datatype, &type_size); } if (sendbuf == MPI_IN_PLACE) { From c04d3eaa92a1217b0e67c854eff1e892e7f0a80e Mon Sep 17 00:00:00 2001 From: Hui Zhou Date: Tue, 16 Feb 2021 23:12:11 -0600 Subject: [PATCH 10/11] binding: use _large_impl suffix for internal large interface Unfortunately our fortran bindings uses _c_impl and _c to refer to C versions of Fortran binding, causing conflicts with the large count interface. Since it is easier to change the C bindings, we use _large_impl to differentiate. I think it is more readable than _c suffix anyway. --- maint/local_python/binding_c.py | 4 +- ...lgatherv_inter_remote_gather_local_bcast.c | 2 +- ...rv_inter_sched_remote_gather_local_bcast.c | 2 +- src/mpi/coll/op/op_impl.c | 2 +- src/mpi/datatype/type_contents.c | 18 +++---- src/mpi/datatype/type_create.c | 52 +++++++++---------- src/mpi/datatype/type_create_darray.c | 9 ++-- src/mpi/datatype/type_create_subarray.c | 8 +-- .../typerep/src/typerep_dataloop_darray.c | 16 +++--- .../typerep/src/typerep_dataloop_subarray.c | 20 +++---- 10 files changed, 67 insertions(+), 66 deletions(-) diff --git a/maint/local_python/binding_c.py b/maint/local_python/binding_c.py index 72b25a6f598..d98e178f700 100644 --- a/maint/local_python/binding_c.py +++ b/maint/local_python/binding_c.py @@ -1087,7 +1087,7 @@ def push_impl_decl(func, impl_name=None): if func['_map_type'] == "BIG": # add suffix to differentiate - impl_name = re.sub(r'_impl$', '_c_impl', impl_name) + impl_name = re.sub(r'_impl$', '_large_impl', impl_name) if func['_impl_param_list']: params = ', '.join(func['_impl_param_list']) @@ -1270,7 +1270,7 @@ def dump_body_impl(func, prefix='mpir'): impl = func['name'] if func['_map_type'] == "BIG" and func['_poly_impl'] == "separate": - impl += '_c' + impl += '_large' if prefix == 'mpid': impl = re.sub(r'^MPIX?_', 'MPID_', impl) else: diff --git a/src/mpi/coll/allgatherv/allgatherv_inter_remote_gather_local_bcast.c b/src/mpi/coll/allgatherv/allgatherv_inter_remote_gather_local_bcast.c index 81e103bf096..3865a912bf0 100644 --- a/src/mpi/coll/allgatherv/allgatherv_inter_remote_gather_local_bcast.c +++ b/src/mpi/coll/allgatherv/allgatherv_inter_remote_gather_local_bcast.c @@ -94,7 +94,7 @@ int MPIR_Allgatherv_inter_remote_gather_local_bcast(const void *sendbuf, MPI_Ain newcomm_ptr = comm_ptr->local_comm; - mpi_errno = MPIR_Type_indexed_c_impl(remote_size, recvcounts, displs, recvtype, &newtype); + mpi_errno = MPIR_Type_indexed_large_impl(remote_size, recvcounts, displs, recvtype, &newtype); MPIR_ERR_CHECK(mpi_errno); mpi_errno = MPIR_Type_commit_impl(&newtype); diff --git a/src/mpi/coll/iallgatherv/iallgatherv_inter_sched_remote_gather_local_bcast.c b/src/mpi/coll/iallgatherv/iallgatherv_inter_sched_remote_gather_local_bcast.c index 361122e7795..7b5c55d7fc6 100644 --- a/src/mpi/coll/iallgatherv/iallgatherv_inter_sched_remote_gather_local_bcast.c +++ b/src/mpi/coll/iallgatherv/iallgatherv_inter_sched_remote_gather_local_bcast.c @@ -70,7 +70,7 @@ int MPIR_Iallgatherv_inter_sched_remote_gather_local_bcast(const void *sendbuf, newcomm_ptr = comm_ptr->local_comm; - mpi_errno = MPIR_Type_indexed_c_impl(remote_size, recvcounts, displs, recvtype, &newtype); + mpi_errno = MPIR_Type_indexed_large_impl(remote_size, recvcounts, displs, recvtype, &newtype); MPIR_ERR_CHECK(mpi_errno); mpi_errno = MPIR_Type_commit_impl(&newtype); diff --git a/src/mpi/coll/op/op_impl.c b/src/mpi/coll/op/op_impl.c index fa8804acd15..cee1ab58c6c 100644 --- a/src/mpi/coll/op/op_impl.c +++ b/src/mpi/coll/op/op_impl.c @@ -76,7 +76,7 @@ int MPIR_Op_create_impl(MPI_User_function * user_fn, int commute, MPIR_Op ** p_o goto fn_exit; } -int MPIR_Op_create_c_impl(MPI_User_function_c * user_fn, int commute, MPIR_Op ** p_op_ptr) +int MPIR_Op_create_large_impl(MPI_User_function_c * user_fn, int commute, MPIR_Op ** p_op_ptr) { return MPIR_Op_create_impl((void *) user_fn, commute, p_op_ptr); } diff --git a/src/mpi/datatype/type_contents.c b/src/mpi/datatype/type_contents.c index 4d311d96e6e..52ee8041afd 100644 --- a/src/mpi/datatype/type_contents.c +++ b/src/mpi/datatype/type_contents.c @@ -82,11 +82,11 @@ int MPIR_Type_get_contents_impl(MPI_Datatype datatype, int max_integers, int max return mpi_errno; } -int MPIR_Type_get_contents_c_impl(MPI_Datatype datatype, MPI_Aint max_integers, - MPI_Aint max_addresses, MPI_Aint max_counts, - MPI_Aint max_datatypes, int array_of_integers[], - MPI_Aint array_of_addresses[], MPI_Count array_of_counts[], - MPI_Datatype array_of_datatypes[]) +int MPIR_Type_get_contents_large_impl(MPI_Datatype datatype, MPI_Aint max_integers, + MPI_Aint max_addresses, MPI_Aint max_counts, + MPI_Aint max_datatypes, int array_of_integers[], + MPI_Aint array_of_addresses[], MPI_Count array_of_counts[], + MPI_Datatype array_of_datatypes[]) { int mpi_errno = MPI_SUCCESS; @@ -158,10 +158,10 @@ int MPIR_Type_get_envelope_impl(MPI_Datatype datatype, return mpi_errno; } -int MPIR_Type_get_envelope_c_impl(MPI_Datatype datatype, - MPI_Aint * num_integers, MPI_Aint * num_addresses, - MPI_Aint * num_large_counts, MPI_Aint * num_datatypes, - int *combiner) +int MPIR_Type_get_envelope_large_impl(MPI_Datatype datatype, + MPI_Aint * num_integers, MPI_Aint * num_addresses, + MPI_Aint * num_large_counts, MPI_Aint * num_datatypes, + int *combiner) { MPIR_Type_get_envelope(datatype, num_integers, num_addresses, num_large_counts, num_datatypes, combiner); diff --git a/src/mpi/datatype/type_create.c b/src/mpi/datatype/type_create.c index 1ebcdf4b79f..d399133b12f 100644 --- a/src/mpi/datatype/type_create.c +++ b/src/mpi/datatype/type_create.c @@ -370,7 +370,7 @@ int MPIR_Type_contiguous_impl(int count, MPI_Datatype oldtype, MPI_Datatype * ne goto fn_exit; } -int MPIR_Type_contiguous_c_impl(MPI_Aint count, MPI_Datatype oldtype, MPI_Datatype * newtype) +int MPIR_Type_contiguous_large_impl(MPI_Aint count, MPI_Datatype oldtype, MPI_Datatype * newtype) { int mpi_errno = MPI_SUCCESS; MPIR_Datatype *new_dtp; @@ -428,8 +428,8 @@ int MPIR_Type_vector_impl(int count, int blocklength, int stride, MPI_Datatype o goto fn_exit; } -int MPIR_Type_vector_c_impl(MPI_Aint count, MPI_Aint blocklength, MPI_Aint stride, - MPI_Datatype oldtype, MPI_Datatype * newtype) +int MPIR_Type_vector_large_impl(MPI_Aint count, MPI_Aint blocklength, MPI_Aint stride, + MPI_Datatype oldtype, MPI_Datatype * newtype) { int mpi_errno = MPI_SUCCESS; MPI_Datatype new_handle; @@ -484,8 +484,8 @@ int MPIR_Type_create_hvector_impl(int count, int blocklength, MPI_Aint stride, goto fn_exit; } -int MPIR_Type_create_hvector_c_impl(MPI_Aint count, MPI_Aint blocklength, MPI_Aint stride, - MPI_Datatype oldtype, MPI_Datatype * newtype) +int MPIR_Type_create_hvector_large_impl(MPI_Aint count, MPI_Aint blocklength, MPI_Aint stride, + MPI_Datatype oldtype, MPI_Datatype * newtype) { int mpi_errno = MPI_SUCCESS; MPI_Datatype new_handle; @@ -560,9 +560,9 @@ int MPIR_Type_create_indexed_block_impl(int count, goto fn_exit; } -int MPIR_Type_create_indexed_block_c_impl(MPI_Aint count, MPI_Aint blocklength, - const MPI_Aint array_of_displacements[], - MPI_Datatype oldtype, MPI_Datatype * newtype) +int MPIR_Type_create_indexed_block_large_impl(MPI_Aint count, MPI_Aint blocklength, + const MPI_Aint array_of_displacements[], + MPI_Datatype oldtype, MPI_Datatype * newtype) { int mpi_errno = MPI_SUCCESS; MPI_Datatype new_handle; @@ -627,9 +627,9 @@ int MPIR_Type_create_hindexed_block_impl(int count, int blocklength, goto fn_exit; } -int MPIR_Type_create_hindexed_block_c_impl(MPI_Aint count, MPI_Aint blocklength, - const MPI_Aint array_of_displacements[], - MPI_Datatype oldtype, MPI_Datatype * newtype) +int MPIR_Type_create_hindexed_block_large_impl(MPI_Aint count, MPI_Aint blocklength, + const MPI_Aint array_of_displacements[], + MPI_Datatype oldtype, MPI_Datatype * newtype) { int mpi_errno = MPI_SUCCESS; MPI_Datatype new_handle; @@ -718,10 +718,10 @@ int MPIR_Type_indexed_impl(int count, const int *array_of_blocklengths, goto fn_exit; } -int MPIR_Type_indexed_c_impl(MPI_Aint count, - const MPI_Aint * array_of_blocklengths, - const MPI_Aint * array_of_displacements, - MPI_Datatype oldtype, MPI_Datatype * newtype) +int MPIR_Type_indexed_large_impl(MPI_Aint count, + const MPI_Aint * array_of_blocklengths, + const MPI_Aint * array_of_displacements, + MPI_Datatype oldtype, MPI_Datatype * newtype) { int mpi_errno = MPI_SUCCESS; MPI_Datatype new_handle; @@ -805,10 +805,10 @@ int MPIR_Type_create_hindexed_impl(int count, const int array_of_blocklengths[], goto fn_exit; } -int MPIR_Type_create_hindexed_c_impl(MPI_Aint count, - const MPI_Aint array_of_blocklengths[], - const MPI_Aint array_of_displacements[], - MPI_Datatype oldtype, MPI_Datatype * newtype) +int MPIR_Type_create_hindexed_large_impl(MPI_Aint count, + const MPI_Aint array_of_blocklengths[], + const MPI_Aint array_of_displacements[], + MPI_Datatype oldtype, MPI_Datatype * newtype) { int mpi_errno = MPI_SUCCESS; MPI_Datatype new_handle; @@ -842,10 +842,10 @@ int MPIR_Type_create_hindexed_c_impl(MPI_Aint count, goto fn_exit; } -int MPIR_Type_create_struct_c_impl(MPI_Aint count, - const MPI_Aint * array_of_blocklengths, - const MPI_Aint * array_of_displacements, - const MPI_Datatype * array_of_types, MPI_Datatype * newtype) +int MPIR_Type_create_struct_large_impl(MPI_Aint count, + const MPI_Aint * array_of_blocklengths, + const MPI_Aint * array_of_displacements, + const MPI_Datatype * array_of_types, MPI_Datatype * newtype) { int mpi_errno = MPI_SUCCESS; MPI_Datatype new_handle; @@ -1004,8 +1004,8 @@ int MPIR_Type_create_resized_impl(MPI_Datatype oldtype, MPI_Aint lb, MPI_Aint ex goto fn_exit; } -int MPIR_Type_create_resized_c_impl(MPI_Datatype oldtype, MPI_Aint lb, MPI_Aint extent, - MPI_Datatype * newtype) +int MPIR_Type_create_resized_large_impl(MPI_Datatype oldtype, MPI_Aint lb, MPI_Aint extent, + MPI_Datatype * newtype) { int mpi_errno = MPI_SUCCESS; MPI_Datatype new_handle; @@ -1031,7 +1031,7 @@ int MPIR_Type_create_resized_c_impl(MPI_Datatype oldtype, MPI_Aint lb, MPI_Aint goto fn_exit; } -/* FIXME: replace this routine with MPIR_Type_contiguous_c_impl -- require yaksa large count support */ +/* FIXME: replace this routine with MPIR_Type_contiguous_large_impl -- require yaksa large count support */ int MPIR_Type_contiguous_x_impl(MPI_Count count, MPI_Datatype oldtype, MPI_Datatype * newtype) { /* to make 'count' fit MPI-3 type processing routines (which take integer diff --git a/src/mpi/datatype/type_create_darray.c b/src/mpi/datatype/type_create_darray.c index 7a41370b393..eca5759e5ea 100644 --- a/src/mpi/datatype/type_create_darray.c +++ b/src/mpi/datatype/type_create_darray.c @@ -504,10 +504,11 @@ int MPIR_Type_create_darray_impl(int size, int rank, int ndims, goto fn_exit; } -int MPIR_Type_create_darray_c_impl(int size, int rank, int ndims, - const MPI_Aint array_of_gsizes[], const int array_of_distribs[], - const int array_of_dargs[], const int array_of_psizes[], - int order, MPI_Datatype oldtype, MPI_Datatype * newtype) +int MPIR_Type_create_darray_large_impl(int size, int rank, int ndims, + const MPI_Aint array_of_gsizes[], + const int array_of_distribs[], const int array_of_dargs[], + const int array_of_psizes[], int order, MPI_Datatype oldtype, + MPI_Datatype * newtype) { int mpi_errno = MPI_SUCCESS; diff --git a/src/mpi/datatype/type_create_subarray.c b/src/mpi/datatype/type_create_subarray.c index 55b0fa2f24c..91ea82c3ac1 100644 --- a/src/mpi/datatype/type_create_subarray.c +++ b/src/mpi/datatype/type_create_subarray.c @@ -169,10 +169,10 @@ int MPIR_Type_create_subarray_impl(int ndims, const int array_of_sizes[], goto fn_exit; } -int MPIR_Type_create_subarray_c_impl(int ndims, const MPI_Aint array_of_sizes[], - const MPI_Aint array_of_subsizes[], - const MPI_Aint array_of_starts[], int order, - MPI_Datatype oldtype, MPI_Datatype * newtype) +int MPIR_Type_create_subarray_large_impl(int ndims, const MPI_Aint array_of_sizes[], + const MPI_Aint array_of_subsizes[], + const MPI_Aint array_of_starts[], int order, + MPI_Datatype oldtype, MPI_Datatype * newtype) { int mpi_errno = MPI_SUCCESS; diff --git a/src/mpi/datatype/typerep/src/typerep_dataloop_darray.c b/src/mpi/datatype/typerep/src/typerep_dataloop_darray.c index 523dd48c68e..af848e1eeed 100644 --- a/src/mpi/datatype/typerep/src/typerep_dataloop_darray.c +++ b/src/mpi/datatype/typerep/src/typerep_dataloop_darray.c @@ -141,7 +141,7 @@ int MPII_Typerep_convert_darray(int size, int rank, int ndims, const MPI_Aint * MPL_free(st_offsets); MPL_free(coords); - mpi_errno = MPIR_Type_create_struct_c_impl(3, blklens, disps, types, newtype); + mpi_errno = MPIR_Type_create_struct_large_impl(3, blklens, disps, types, newtype); MPIR_ERR_CHECK(mpi_errno); MPIR_Type_free_impl(&type_new); @@ -187,22 +187,22 @@ static int type_block(const MPI_Aint * array_of_gsizes, int dim, int ndims, int stride = orig_extent; if (order == MPI_ORDER_FORTRAN) { if (dim == 0) { - mpi_errno = MPIR_Type_contiguous_c_impl(mysize, type_old, type_new); + mpi_errno = MPIR_Type_contiguous_large_impl(mysize, type_old, type_new); MPIR_ERR_CHECK(mpi_errno); } else { for (int i = 0; i < dim; i++) stride *= (MPI_Aint) (array_of_gsizes[i]); - mpi_errno = MPIR_Type_create_hvector_c_impl(mysize, 1, stride, type_old, type_new); + mpi_errno = MPIR_Type_create_hvector_large_impl(mysize, 1, stride, type_old, type_new); MPIR_ERR_CHECK(mpi_errno); } } else { if (dim == ndims - 1) { - mpi_errno = MPIR_Type_contiguous_c_impl(mysize, type_old, type_new); + mpi_errno = MPIR_Type_contiguous_large_impl(mysize, type_old, type_new); MPIR_ERR_CHECK(mpi_errno); } else { for (int i = ndims - 1; i > dim; i--) stride *= (MPI_Aint) (array_of_gsizes[i]); - mpi_errno = MPIR_Type_create_hvector_c_impl(mysize, 1, stride, type_old, type_new); + mpi_errno = MPIR_Type_create_hvector_large_impl(mysize, 1, stride, type_old, type_new); MPIR_ERR_CHECK(mpi_errno); } } @@ -262,7 +262,7 @@ static int type_cyclic(const MPI_Aint * array_of_gsizes, int dim, int ndims, int for (int i = ndims - 1; i > dim; i--) stride *= (MPI_Aint) (array_of_gsizes[i]); - mpi_errno = MPIR_Type_create_hvector_c_impl(count, blksize, stride, type_old, type_new); + mpi_errno = MPIR_Type_create_hvector_large_impl(count, blksize, stride, type_old, type_new); MPIR_ERR_CHECK(mpi_errno); if (rem) { @@ -276,7 +276,7 @@ static int type_cyclic(const MPI_Aint * array_of_gsizes, int dim, int ndims, int blklens[0] = 1; blklens[1] = rem; - mpi_errno = MPIR_Type_create_struct_c_impl(2, blklens, disps, types, &type_tmp); + mpi_errno = MPIR_Type_create_struct_large_impl(2, blklens, disps, types, &type_tmp); MPIR_ERR_CHECK(mpi_errno); MPIR_Type_free_impl(type_new); @@ -295,7 +295,7 @@ static int type_cyclic(const MPI_Aint * array_of_gsizes, int dim, int ndims, int disps[2] = orig_extent * ((MPI_Aint) (array_of_gsizes[dim])); blklens[0] = blklens[1] = blklens[2] = 1; - mpi_errno = MPIR_Type_create_struct_c_impl(3, blklens, disps, types, &type_tmp); + mpi_errno = MPIR_Type_create_struct_large_impl(3, blklens, disps, types, &type_tmp); MPIR_ERR_CHECK(mpi_errno); MPIR_Type_free_impl(type_new); diff --git a/src/mpi/datatype/typerep/src/typerep_dataloop_subarray.c b/src/mpi/datatype/typerep/src/typerep_dataloop_subarray.c index 975de5be70d..843e3f84976 100644 --- a/src/mpi/datatype/typerep/src/typerep_dataloop_subarray.c +++ b/src/mpi/datatype/typerep/src/typerep_dataloop_subarray.c @@ -22,18 +22,18 @@ int MPII_Typerep_convert_subarray(int ndims, MPI_Aint * array_of_sizes, if (order == MPI_ORDER_FORTRAN) { /* dimension 0 changes fastest */ if (ndims == 1) { - mpi_errno = MPIR_Type_contiguous_c_impl(array_of_subsizes[0], oldtype, &tmp1); + mpi_errno = MPIR_Type_contiguous_large_impl(array_of_subsizes[0], oldtype, &tmp1); MPIR_ERR_CHECK(mpi_errno); } else { - mpi_errno = MPIR_Type_vector_c_impl(array_of_subsizes[1], array_of_subsizes[0], - array_of_sizes[0], oldtype, &tmp1); + mpi_errno = MPIR_Type_vector_large_impl(array_of_subsizes[1], array_of_subsizes[0], + array_of_sizes[0], oldtype, &tmp1); MPIR_ERR_CHECK(mpi_errno); size = (MPI_Aint) (array_of_sizes[0]) * extent; for (i = 2; i < ndims; i++) { size *= (MPI_Aint) (array_of_sizes[i - 1]); mpi_errno = - MPIR_Type_create_hvector_c_impl(array_of_subsizes[i], 1, size, tmp1, &tmp2); + MPIR_Type_create_hvector_large_impl(array_of_subsizes[i], 1, size, tmp1, &tmp2); MPIR_ERR_CHECK(mpi_errno); MPIR_Type_free_impl(&tmp1); tmp1 = tmp2; @@ -51,19 +51,19 @@ int MPII_Typerep_convert_subarray(int ndims, MPI_Aint * array_of_sizes, } else { /* order == MPI_ORDER_C */ /* dimension ndims-1 changes fastest */ if (ndims == 1) { - mpi_errno = MPIR_Type_contiguous_c_impl(array_of_subsizes[0], oldtype, &tmp1); + mpi_errno = MPIR_Type_contiguous_large_impl(array_of_subsizes[0], oldtype, &tmp1); MPIR_ERR_CHECK(mpi_errno); } else { - mpi_errno = MPIR_Type_vector_c_impl(array_of_subsizes[ndims - 2], - array_of_subsizes[ndims - 1], - array_of_sizes[ndims - 1], oldtype, &tmp1); + mpi_errno = MPIR_Type_vector_large_impl(array_of_subsizes[ndims - 2], + array_of_subsizes[ndims - 1], + array_of_sizes[ndims - 1], oldtype, &tmp1); MPIR_ERR_CHECK(mpi_errno); size = (MPI_Aint) (array_of_sizes[ndims - 1]) * extent; for (i = ndims - 3; i >= 0; i--) { size *= (MPI_Aint) (array_of_sizes[i + 1]); mpi_errno = - MPIR_Type_create_hvector_c_impl(array_of_subsizes[i], 1, size, tmp1, &tmp2); + MPIR_Type_create_hvector_large_impl(array_of_subsizes[i], 1, size, tmp1, &tmp2); MPIR_ERR_CHECK(mpi_errno); MPIR_Type_free_impl(&tmp1); tmp1 = tmp2; @@ -91,7 +91,7 @@ int MPII_Typerep_convert_subarray(int ndims, MPI_Aint * array_of_sizes, types[1] = tmp1; types[2] = MPI_UB; - mpi_errno = MPIR_Type_create_struct_c_impl(3, blklens, disps, types, newtype); + mpi_errno = MPIR_Type_create_struct_large_impl(3, blklens, disps, types, newtype); MPIR_ERR_CHECK(mpi_errno); MPIR_Type_free_impl(&tmp1); From deb6de41610a355ece414117a7d281a2929fcad5 Mon Sep 17 00:00:00 2001 From: Hui Zhou Date: Tue, 16 Feb 2021 21:26:11 -0600 Subject: [PATCH 11/11] test: add basic large API tests --- test/mpi/coll/Makefile.am | 1 + test/mpi/coll/coll_large.c | 67 ++++++++++++++++ test/mpi/coll/testlist.in | 2 + test/mpi/datatype/Makefile.am | 1 + test/mpi/datatype/testlist.in | 1 + test/mpi/datatype/type_large.c | 138 +++++++++++++++++++++++++++++++++ test/mpi/pt2pt/Makefile.am | 1 + test/mpi/pt2pt/pt2pt_large.c | 71 +++++++++++++++++ test/mpi/pt2pt/testlist.in | 1 + 9 files changed, 283 insertions(+) create mode 100644 test/mpi/coll/coll_large.c create mode 100644 test/mpi/datatype/type_large.c create mode 100644 test/mpi/pt2pt/pt2pt_large.c diff --git a/test/mpi/coll/Makefile.am b/test/mpi/coll/Makefile.am index e311d8a9387..9d05ad4e0df 100644 --- a/test/mpi/coll/Makefile.am +++ b/test/mpi/coll/Makefile.am @@ -126,6 +126,7 @@ noinst_PROGRAMS = \ neighb_alltoallw \ bcast \ bcast_comm_world_only \ + coll_large \ ring_neighbor_alltoall allgatherv4_LDADD = $(LDADD) -lm diff --git a/test/mpi/coll/coll_large.c b/test/mpi/coll/coll_large.c new file mode 100644 index 00000000000..fc4595b0a1c --- /dev/null +++ b/test/mpi/coll/coll_large.c @@ -0,0 +1,67 @@ +/* + * Copyright (C) by Argonne National Laboratory + * See COPYRIGHT in top-level directory + */ + +#include "mpi.h" +#include "mpitest.h" +#include +#include +#include + +/* + Basic test for collective large APIs. + It is only intended to test the API interface rather than stress testing the internals. + */ + +#define MAX_SIZE 1024 +#define MAX_PROC 20 + +MPI_Comm comm; +int rank, nprocs; +int errs; +int sendbuf[MAX_SIZE]; +int recvbuf[MAX_SIZE]; + +static void init_buf(void) +{ + for (int i = 0; i < MAX_SIZE; i++) { + sendbuf[i] = i; + } + for (int i = 0; i < MAX_SIZE; i++) { + recvbuf[i] = -1; + } +} + +static void test_alltoallv(void) +{ + MPI_Count counts[MAX_PROC]; + MPI_Aint displs[MAX_PROC]; + for (int i = 0; i < nprocs; i++) { + counts[i] = 1; + } + for (int i = 0; i < nprocs; i++) { + displs[i] = i * 3; + } + init_buf(); + MPI_Alltoallv_c(sendbuf, counts, displs, MPI_INT, recvbuf, counts, displs, MPI_INT, comm); + /* check results */ + for (int i = 0; i < nprocs; i++) { + if (recvbuf[displs[i]] != rank * 3) { + errs++; + } + } +} + +int main(int argc, char **argv) +{ + MTest_Init(&argc, &argv); + comm = MPI_COMM_WORLD; + MPI_Comm_size(comm, &nprocs); + MPI_Comm_rank(comm, &rank); + + test_alltoallv(); + + MTest_Finalize(errs); + return MTestReturnValue(errs); +} diff --git a/test/mpi/coll/testlist.in b/test/mpi/coll/testlist.in index 13b87dc896b..1719c393d55 100644 --- a/test/mpi/coll/testlist.in +++ b/test/mpi/coll/testlist.in @@ -174,3 +174,5 @@ ring_neighbor_alltoall 1 # Tests for persistent collectives p_bcast 4 strict=false p_bcast2 8 strict=false + +coll_large 8 diff --git a/test/mpi/datatype/Makefile.am b/test/mpi/datatype/Makefile.am index b2756b753c9..90d0a7db343 100644 --- a/test/mpi/datatype/Makefile.am +++ b/test/mpi/datatype/Makefile.am @@ -35,6 +35,7 @@ noinst_PROGRAMS = \ large_type \ large_type_sendrec \ large_vec \ + type_large \ lbub \ lbub_oldapi \ localpack \ diff --git a/test/mpi/datatype/testlist.in b/test/mpi/datatype/testlist.in index 2de54a6f59c..6ff5142d1ae 100644 --- a/test/mpi/datatype/testlist.in +++ b/test/mpi/datatype/testlist.in @@ -61,6 +61,7 @@ vecblklen 1 hvecblklen 1 longdouble 1 dataalign 2 +type_large 1 @largetest@large_count 1 cxx_types 1 @largetest@large_type 1 diff --git a/test/mpi/datatype/type_large.c b/test/mpi/datatype/type_large.c new file mode 100644 index 00000000000..ac6aca8bf15 --- /dev/null +++ b/test/mpi/datatype/type_large.c @@ -0,0 +1,138 @@ +/* + * Copyright (C) by Argonne National Laboratory + * See COPYRIGHT in top-level directory + */ + +#include +#include +#include +#include "mpitest.h" + +/* Basic test to test MPI 4.0 large API */ + +static MPI_Datatype make_large_contig(MPI_Count nbytes) +{ + MPI_Datatype newtype; + MPI_Type_contiguous_c(nbytes, MPI_CHAR, &newtype); + MPI_Type_commit(&newtype); + return newtype; +} + +static MPI_Datatype make_large_indexed_block(MPI_Count nbytes) +{ + MPI_Datatype newtype; + +#undef NBLK +#define NBLK 256 + MPI_Count num_blks = NBLK; + MPI_Count blklen = nbytes / num_blks / sizeof(int); + MPI_Count displs[NBLK]; + + if (num_blks * blklen * sizeof(int) != nbytes) { + return MPI_DATATYPE_NULL; + } + + for (int i = 0; i < NBLK; i++) { + displs[i] = i * blklen; + } + + MPI_Type_create_indexed_block_c(NBLK, blklen, displs, MPI_INT, &newtype); + MPI_Type_commit(&newtype); + + return newtype; +} + +static MPI_Datatype make_large_hindexed(MPI_Count nbytes) +{ + MPI_Datatype newtype; + +#undef NBLK +#define NBLK 4 + MPI_Count blkls[NBLK]; + MPI_Count displs[NBLK]; + + MPI_Count pos = 0; + for (int i = 0; i < NBLK - 1; i++) { + blkls[i] = i; + displs[i] = pos; + pos += blkls[i]; + } + blkls[NBLK - 1] = nbytes - pos; + displs[NBLK - 1] = pos; + + MPI_Type_create_hindexed_c(NBLK, blkls, displs, MPI_CHAR, &newtype); + MPI_Type_commit(&newtype); + + return newtype; +} + + +int testtype(MPI_Datatype type, MPI_Count expected) +{ + MPI_Count size, lb, extent; + int errs = 0; + MPI_Type_size_c(type, &size); + + if (size < 0) { + printf("ERROR: type size apparently overflowed integer\n"); + errs++; + } + + if (size != expected) { + printf("reported type size %lld does not match expected %lld\n", (long long) size, + (long long) expected); + errs++; + } + + MPI_Type_get_true_extent_c(type, &lb, &extent); + if (lb != 0) { + printf("ERROR: type should have lb of 0, reported %lld\n", (long long) lb); + errs++; + } + + if (extent != size) { + printf("ERROR: extent should match size, not %lld\n", (long long) extent); + errs++; + } + return errs; +} + + +int main(int argc, char **argv) +{ + + int errs = 0, i; + int rank, size; + MTest_Init(&argc, &argv); + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + MPI_Comm_size(MPI_COMM_WORLD, &size); + +#define NR_TYPES 3 + MPI_Offset expected_sizes[NR_TYPES] = { 1024UL * 1024UL * 2400UL * 2, + 2346319872 * 3, + 2346319872 * 4 + }; + MPI_Datatype types[NR_TYPES]; + + if (sizeof(MPI_Aint) == 4) { + /* 32-bit system can't work with sizes more than address int */ + for (int i = 0; i < NR_TYPES; i++) { + expected_sizes[i] /= 8; + } + } + + types[0] = make_large_contig(expected_sizes[0]); + types[1] = make_large_indexed_block(expected_sizes[1]); + types[2] = make_large_hindexed(expected_sizes[2]); + + for (i = 0; i < NR_TYPES; i++) { + if (types[i] != MPI_DATATYPE_NULL) { + errs += testtype(types[i], expected_sizes[i]); + MPI_Type_free(&(types[i])); + } + } + + MTest_Finalize(errs); + + return MTestReturnValue(errs); +} diff --git a/test/mpi/pt2pt/Makefile.am b/test/mpi/pt2pt/Makefile.am index 0fd80ce2b76..aa16c3e34ca 100644 --- a/test/mpi/pt2pt/Makefile.am +++ b/test/mpi/pt2pt/Makefile.am @@ -67,6 +67,7 @@ noinst_PROGRAMS = \ pingping_barrier \ sendrecv1 \ sendself \ + pt2pt_large \ precv_anysrc \ precv_anysrc_exp diff --git a/test/mpi/pt2pt/pt2pt_large.c b/test/mpi/pt2pt/pt2pt_large.c new file mode 100644 index 00000000000..fc5707929a1 --- /dev/null +++ b/test/mpi/pt2pt/pt2pt_large.c @@ -0,0 +1,71 @@ +/* + * Copyright (C) by Argonne National Laboratory + * See COPYRIGHT in top-level directory + */ + +#include "mpi.h" +#include +#include +#include "mpitest.h" + +/* Basic tests for large pt2pt APIs. It does not actually send large data */ + +#define SIZE 1024 + +int rank, nproc; +int errs; +int sendbuf[SIZE]; +int recvbuf[SIZE]; + +static void init_buf(void) +{ + if (rank == 0) { + for (int i = 0; i < SIZE; i++) { + sendbuf[i] = i; + } + } else if (rank == 1) { + for (int i = 0; i < SIZE; i++) { + recvbuf[i] = -1; + } + } +} + +static void check_buf(void) +{ + if (rank == 1) { + for (int i = 0; i < SIZE; i++) { + if (recvbuf[i] != i) { + errs++; + } + } + } +} + + +int main(int argc, char *argv[]) +{ + MPI_Comm comm; + MPI_Count count = SIZE; + int tag = 0; + + MTest_Init(&argc, &argv); + + comm = MPI_COMM_WORLD; + MPI_Comm_rank(comm, &rank); + MPI_Comm_size(comm, &nproc); + if (nproc != 2) { + printf("Run test with 2 procs!\n"); + return 1; + } + + init_buf(); + if (rank == 0) { + MPI_Send_c(sendbuf, count, MPI_INT, 1, tag, comm); + } else if (rank == 1) { + MPI_Recv_c(recvbuf, count, MPI_INT, 0, tag, comm, MPI_STATUS_IGNORE); + } + check_buf(); + + MTest_Finalize(errs); + return MTestReturnValue(errs); +} diff --git a/test/mpi/pt2pt/testlist.in b/test/mpi/pt2pt/testlist.in index a202643a0df..3f406709804 100644 --- a/test/mpi/pt2pt/testlist.in +++ b/test/mpi/pt2pt/testlist.in @@ -63,3 +63,4 @@ large_tag 2 precv_anysrc 2 timeLimit=60 precv_anysrc 2 timeLimit=60 env=MPIR_CVAR_CH4_OFI_AM_LONG_FORCE_PIPELINE=true precv_anysrc_exp 2 timeLimit=60 +pt2pt_large 2