diff --git a/src/mpi/datatype/datatype_impl.c b/src/mpi/datatype/datatype_impl.c index a3df400ec9e..44f19b7dd41 100644 --- a/src/mpi/datatype/datatype_impl.c +++ b/src/mpi/datatype/datatype_impl.c @@ -134,20 +134,168 @@ int MPIR_Pack_external_size_impl(const char *datarep, return MPI_SUCCESS; } +/* utility function for MPIR_Status_set_elements_x_impl. + * Recursively count the total number of bytes from a given number of elements, where + * we assume the datatype does not contain a single element type. + */ +static MPI_Count MPIR_Type_get_element_bytes(MPI_Count * elements_p, + MPI_Count count, MPI_Datatype datatype) +{ + if (HANDLE_IS_BUILTIN(datatype)) { + MPI_Count element_size = MPIR_Datatype_get_basic_size(datatype); + if (*elements_p > count) { + *elements_p -= count; + return count * element_size; + } else { + MPI_Count nbytes = (*elements_p) * element_size; + *elements_p = 0; + return nbytes; + } + } + + MPIR_Datatype *datatype_ptr; + MPIR_Datatype_get_ptr(datatype, datatype_ptr); + + if (datatype_ptr->builtin_element_size != -1) { + MPI_Count element_size = datatype_ptr->builtin_element_size; + count *= (datatype_ptr->size / element_size); + if (*elements_p > count) { + *elements_p -= count; + return count * element_size; + } else { + MPI_Count nbytes = (*elements_p) * element_size; + *elements_p = 0; + return nbytes; + } + } + + /* let's peel the datatype layer by layer */ + int *ints; + MPI_Aint *aints; + MPI_Aint *counts; + MPI_Datatype *types; + + MPIR_Datatype_contents *cp = datatype_ptr->contents; + MPIR_Datatype_access_contents(cp, &ints, &aints, &counts, &types); + MPIR_Assert(ints && aints && counts && types); + + switch (datatype_ptr->contents->combiner) { + case MPI_COMBINER_NAMED: + case MPI_COMBINER_DUP: + case MPI_COMBINER_RESIZED: + return MPIR_Type_get_element_bytes(elements_p, count, *types); + case MPI_COMBINER_CONTIGUOUS: + case MPI_COMBINER_VECTOR: + case MPI_COMBINER_HVECTOR: + case MPI_COMBINER_SUBARRAY: + if (cp->nr_counts == 0) { + return MPIR_Type_get_element_bytes(elements_p, count * ints[0], *types); + } else { + return MPIR_Type_get_element_bytes(elements_p, count * counts[0], *types); + } + case MPI_COMBINER_INDEXED_BLOCK: + case MPI_COMBINER_HINDEXED_BLOCK: + if (cp->nr_counts == 0) { + return MPIR_Type_get_element_bytes(elements_p, count * ints[0] * ints[1], *types); + } else { + return MPIR_Type_get_element_bytes(elements_p, count * counts[0] * counts[1], + *types); + } + case MPI_COMBINER_INDEXED: + case MPI_COMBINER_HINDEXED: + { + MPI_Aint typecount = 0; /* total number of subtypes */ + if (cp->nr_counts == 0) { + for (int i = 0; i < ints[0]; i++) { + typecount += ints[i + 1]; + } + } else { + for (MPI_Aint i = 0; i < counts[0]; i++) { + typecount += counts[i + 1]; + } + } + return MPIR_Type_get_element_bytes(elements_p, count * typecount, *types); + } + case MPI_COMBINER_STRUCT: + if (cp->nr_counts == 0) { + MPI_Count nbytes = 0; + for (MPI_Count j = 0; j < count; j++) { + for (int i = 0; i < ints[0]; i++) { + /* skip zero-count elements of the struct */ + if (ints[i + 1] == 0) + continue; + + nbytes += MPIR_Type_get_element_bytes(elements_p, ints[i + 1], types[i]); + if (*elements_p == 0) { + return nbytes; + } + } + } + return nbytes; + } else { + MPI_Count nbytes = 0; + for (MPI_Count j = 0; j < count; j++) { + for (MPI_Count i = 0; i < counts[0]; i++) { + /* skip zero-count elements of the struct */ + if (counts[i + 1] == 0) + continue; + + nbytes += MPIR_Type_get_element_bytes(elements_p, counts[i + 1], types[i]); + if (*elements_p == 0) { + return nbytes; + } + } + } + return nbytes; + } + case MPI_COMBINER_DARRAY: + case MPI_COMBINER_F90_REAL: + case MPI_COMBINER_F90_COMPLEX: + case MPI_COMBINER_F90_INTEGER: +#ifndef BUILD_MPI_ABI + case MPI_COMBINER_HVECTOR_INTEGER: + case MPI_COMBINER_HINDEXED_INTEGER: + case MPI_COMBINER_STRUCT_INTEGER: +#endif + default: + /* --BEGIN ERROR HANDLING-- */ + MPIR_Assert(0); + return 0; + /* --END ERROR HANDLING-- */ + } +} + int MPIR_Status_set_elements_x_impl(MPI_Status * status, MPI_Datatype datatype, MPI_Count count) { int mpi_errno = MPI_SUCCESS; - MPI_Count size_x; + MPI_Count nbytes; - MPIR_Datatype_get_size_macro(datatype, size_x); - - /* overflow check, should probably be a real error check? */ - if (count != 0) { - MPIR_Assert(size_x >= 0 && count > 0); - MPIR_Assert(count * size_x < MPIR_COUNT_MAX); + if (HANDLE_IS_BUILTIN(datatype)) { + nbytes = count * MPIR_Datatype_get_basic_size(datatype); + } else { + MPIR_Datatype *datatype_ptr; + MPIR_Datatype_get_ptr(datatype, datatype_ptr); + if (datatype_ptr->builtin_element_size != -1) { + nbytes = count * datatype_ptr->builtin_element_size; + } else { + if (datatype_ptr->size == 0) { + nbytes = 0; + } else { + MPI_Count orig_count = count; + nbytes = MPIR_Type_get_element_bytes(&count, 1, datatype); + /* it'll be so much easier if we store datatype_ptr->nr_elements */ + if (count > 0) { + MPI_Count nr_elements = orig_count - count; + nbytes *= (orig_count / nr_elements); + + MPI_Count remain = orig_count % nr_elements; + nbytes += MPIR_Type_get_element_bytes(&remain, 1, datatype); + } + } + } } - MPIR_STATUS_SET_COUNT(*status, size_x * count); + MPIR_STATUS_SET_COUNT(*status, nbytes); return mpi_errno; } diff --git a/src/mpl/include/mpl.h b/src/mpl/include/mpl.h index 0a836625431..0dbf7595065 100644 --- a/src/mpl/include/mpl.h +++ b/src/mpl/include/mpl.h @@ -34,6 +34,7 @@ #include "mpl_gavl.h" #include "mpl_initlock.h" #include "mpl_misc.h" +#include "mpl_hash.h" int MPL_rankmap_str_to_array(char *mapping, int sz, int *out_nodemap); int MPL_rankmap_array_to_str(int *nodemap, int sz, char **out_mapping_str); diff --git a/src/mpl/include/mpl_hash.h b/src/mpl/include/mpl_hash.h new file mode 100644 index 00000000000..f900e67d223 --- /dev/null +++ b/src/mpl/include/mpl_hash.h @@ -0,0 +1,28 @@ +#ifndef MPL_HASH_H_INCLUDED +#define MPL_HASH_H_INCLUDED + +struct strpool { + int i_str; + int i_pool; + int n_str; + size_t pool_size; + int *pn_str; + unsigned char *pc_pool; +}; + +struct MPL_hash { + int n_size; + int n_count; + char *p_exist; + int *p_key; + struct strpool pool; + int *p_val; +}; + +struct MPL_hash *MPL_hash_new(void); +int MPL_hash_has(struct MPL_hash *hv, const char *s_key); +void MPL_hash_set(struct MPL_hash *hv, const char *s_key, const char *s_value); +char *MPL_hash_get(struct MPL_hash *hv, const char *s_key); +void MPL_hash_free(struct MPL_hash *hv); + +#endif /* MPL_HASH_H_INCLUDED */ diff --git a/src/mpl/src/str/Makefile.mk b/src/mpl/src/str/Makefile.mk index 7bea9a4d38b..6e822ec0310 100644 --- a/src/mpl/src/str/Makefile.mk +++ b/src/mpl/src/str/Makefile.mk @@ -3,4 +3,8 @@ ## See COPYRIGHT in top-level directory ## -lib@MPLLIBNAME@_la_SOURCES += src/str/mpl_str.c src/str/mpl_argstr.c src/str/mpl_arg_serial.c +lib@MPLLIBNAME@_la_SOURCES += \ + src/str/mpl_str.c \ + src/str/mpl_argstr.c \ + src/str/mpl_arg_serial.c \ + src/str/mpl_hash.c diff --git a/src/mpl/src/str/mpl_hash.c b/src/mpl/src/str/mpl_hash.c new file mode 100644 index 00000000000..57812f34769 --- /dev/null +++ b/src/mpl/src/str/mpl_hash.c @@ -0,0 +1,246 @@ +/* +* Copyright (C) by Argonne National Laboratory. +* See COPYRIGHT in top-level directory. +*/ + +/** Rationale: + * An open addressing hash implementation specialized for string keys and string + * values. All strings are stored in a managed string pool in a insertion only + * manner. Deletion is achieved by simply overwrite the hash item with sentinel + * value/NULL. Deletion and reassignement will result in expired strings still + * being held in memory, which may be a concern if the application requires + * frequent deletion and modification and memory consumption is of concern. All + * memory will be released upon final free. + * + * Compared to uthash.h, the usage interface is cleaner and more intuitive -- + * hash_new, hash_set, hash_get, hash_has, and hash_free. In comparison, uthash + * requires extra data structure, does not manage string memory, and the code is + * more complex. This implementation is faster than uthash as well. + */ + +#include "mpl.h" +#include "mpl_hash.h" + +#define STRPOOL_STR(strpool, i) \ + (char *) ((strpool)->pc_pool + (strpool)->pn_str[i]) + +#define STRPOOL_STRLEN(strpool, i) \ + ((strpool)->pn_str[(i)+1] - (strpool)->pn_str[i] - 1) + +static int f_strhash_lookup(void *hash, unsigned char *key, int keylen); +static int f_strhash_lookup_left(void *hash, unsigned char *key, int keylen); +static int f_addto_strpool(struct strpool *p_strpool, const char *s, int n); +static void f_strhash_resize(void *hash, int n_size); +static void f_resize_strpool_n(struct strpool *p_strpool, int n_size, int n_avg); + +struct MPL_hash *MPL_hash_new(void) +{ + struct MPL_hash *hv; + + hv = (struct MPL_hash *) calloc(1, sizeof(struct MPL_hash)); + return hv; +} + +int MPL_hash_has(struct MPL_hash *hv, const char *s_key) +{ + int k; + + k = f_strhash_lookup(hv, (unsigned char *) s_key, strlen(s_key)); + return hv->p_exist[k]; +} + +void MPL_hash_set(struct MPL_hash *hv, const char *s_key, const char *s_value) +{ + int k; + + k = f_strhash_lookup_left(hv, (unsigned char *) s_key, strlen(s_key)); + hv->p_val[k] = f_addto_strpool(&hv->pool, s_value, strlen(s_value)); +} + +char *MPL_hash_get(struct MPL_hash *hv, const char *s_key) +{ + int k; + struct strpool *p_strpool; + + k = f_strhash_lookup(hv, (unsigned char *) s_key, strlen(s_key)); + if (hv->p_exist[k]) { + p_strpool = &hv->pool; + return STRPOOL_STR(p_strpool, hv->p_val[k]); + } else { + return NULL; + } +} + +void MPL_hash_free(struct MPL_hash *hv) +{ + MPL_free(hv->p_key); + MPL_free(hv->p_exist); + MPL_free(hv->p_val); + MPL_free(hv->pool.pn_str); + MPL_free(hv->pool.pc_pool); + MPL_free(hv); +} + +int f_strhash_lookup(void *hash, unsigned char *key, int keylen) +{ + struct MPL_hash *h = hash; + unsigned int tu_h; + int k; + struct strpool *p_strpool; + + if (keylen == 0) { + keylen = strlen((char *) key); + } + if (h->n_size == 0) { + return 0; + } + tu_h = 2166136261u; + for (int i = 0; i < keylen; i++) { + tu_h = tu_h ^ key[i]; + tu_h = tu_h * 16777619; + } + k = (int) (tu_h % h->n_size); + p_strpool = &h->pool; + + while (1) { + if (!h->p_exist[k]) { + return k; + } else { + if ((STRPOOL_STRLEN(p_strpool, h->p_key[k]) == keylen) && + (strncmp(STRPOOL_STR(p_strpool, h->p_key[k]), (char *) key, keylen) == 0)) { + return k; + } + } + + if (k == 0) { + k = h->n_size - 1; + } else { + k--; + } + } +} + +int f_strhash_lookup_left(void *hash, unsigned char *key, int keylen) +{ + struct MPL_hash *h = hash; + int k; + + if (keylen == 0) { + keylen = strlen((char *) key); + } + if (h->n_size == 0 || h->n_count + 1 >= h->n_size || + (h->n_size > 20 && h->n_count >= h->n_size * 85 / 100)) { + f_strhash_resize(h, 0); + } + k = f_strhash_lookup(h, key, keylen); + if (!h->p_exist[k]) { + h->p_key[k] = f_addto_strpool(&h->pool, (char *) key, keylen); + h->p_exist[k] = 1; + h->n_count++; + } + return k; +} + +int f_addto_strpool(struct strpool *p_strpool, const char *s, int n) +{ + int n_size; + int tn_avg_str_size; + + if (p_strpool->i_str + 2 >= p_strpool->n_str) { + n_size = p_strpool->i_str * 3 / 2 + 10; + f_resize_strpool_n(p_strpool, n_size, 0); + } + + if (n == 0) { + n = strlen(s); + } + if (p_strpool->i_pool + n >= p_strpool->pool_size) { + tn_avg_str_size = 6; + if (p_strpool->i_str > 0) { + tn_avg_str_size = p_strpool->i_pool / p_strpool->i_str + 1; + } + p_strpool->pool_size = tn_avg_str_size * p_strpool->n_str + n; + p_strpool->pc_pool = realloc(p_strpool->pc_pool, p_strpool->pool_size); + } + memcpy(p_strpool->pc_pool + p_strpool->i_pool, s, n); + p_strpool->i_str++; + p_strpool->i_pool += n; + assert(p_strpool->i_str > 0); + assert(p_strpool->i_pool > 0); + p_strpool->pc_pool[p_strpool->i_pool] = '\0'; + p_strpool->i_pool += 1; + p_strpool->pn_str[p_strpool->i_str] = p_strpool->i_pool; + + return p_strpool->i_str - 1; +} + +void f_strhash_resize(void *hash, int n_size) +{ + struct MPL_hash *h = hash; + char *tp_exist = h->p_exist; + int *tp_key = h->p_key; + int tn_old_size; + int *tp_val = h->p_val; + struct strpool *p_strpool; + int k; + + if (n_size == 0) { + if (h->n_size <= 0) { + n_size = 10; + } else { + n_size = h->n_size * 5 / 3; + } + } else if (n_size <= h->n_size) { + return; + } + + tn_old_size = h->n_size; + + h->n_size = n_size; + h->p_key = (int *) MPL_calloc(n_size, sizeof(int), MPL_MEM_OTHER); + h->p_exist = (char *) MPL_calloc(n_size, sizeof(char), MPL_MEM_OTHER); + h->p_val = (void *) MPL_calloc(n_size, sizeof(int), MPL_MEM_OTHER); + + p_strpool = &h->pool; + if (tn_old_size > 0) { + for (int i = 0; i < tn_old_size; i++) { + if (tp_exist[i]) { + + k = f_strhash_lookup(h, (unsigned char *) STRPOOL_STR(p_strpool, tp_key[i]), + STRPOOL_STRLEN(p_strpool, tp_key[i])); + h->p_exist[k] = 1; + h->p_key[k] = tp_key[i]; + h->p_val[k] = tp_val[i]; + } + } + MPL_free(tp_exist); + MPL_free(tp_key); + MPL_free(tp_val); + } +} + +void f_resize_strpool_n(struct strpool *p_strpool, int n_size, int n_avg) +{ + if (n_size <= p_strpool->n_str) { + return; + } + p_strpool->n_str = n_size; + p_strpool->pn_str = + MPL_realloc(p_strpool->pn_str, p_strpool->n_str * sizeof(int), MPL_MEM_OTHER); + + if (n_avg == 0) { + n_avg = 6; + if (p_strpool->i_str > 0) { + n_avg = p_strpool->i_pool / p_strpool->i_str + 1; + } + } + if (n_avg * p_strpool->n_str > p_strpool->pool_size) { + p_strpool->pool_size = n_avg * p_strpool->n_str; + p_strpool->pc_pool = MPL_realloc(p_strpool->pc_pool, p_strpool->pool_size, MPL_MEM_OTHER); + p_strpool->pc_pool[p_strpool->pool_size - 1] = 0; + } + + if (p_strpool->i_str == 0) { + p_strpool->pn_str[0] = 0; + } +} diff --git a/src/pm/hydra/lib/hydra.h b/src/pm/hydra/lib/hydra.h index d7d14203487..f45123d0934 100644 --- a/src/pm/hydra/lib/hydra.h +++ b/src/pm/hydra/lib/hydra.h @@ -250,8 +250,7 @@ typedef enum { } HYD_status; #define HYD_USIZE_UNSET (0) -#define HYD_USIZE_SYSTEM (-1) -#define HYD_USIZE_INFINITE (-2) +#define HYD_USIZE_INFINITE (-1) #define HYD_GPUS_PER_PROC_UNSET (-1) #define HYD_GPUS_PER_PROC_AUTO (-2) @@ -302,6 +301,7 @@ struct HYD_exec { int exec_len, exec_size; char *wdir; + int start_rank; int proc_count; struct HYD_env *user_env; char *env_prop; @@ -341,9 +341,6 @@ struct HYD_proxy { int proxy_process_count; - /* Filler processes that we are adding on this proxy */ - int filler_processes; - struct HYD_exec *exec_list; int *pid; @@ -380,6 +377,7 @@ struct HYD_user_global { int enablex; int debug; int usize; + bool usize_system; int auto_cleanup; int pmi_port; diff --git a/src/pm/hydra/lib/utils/alloc.c b/src/pm/hydra/lib/utils/alloc.c index 6ee164048dd..bda7a9cd244 100644 --- a/src/pm/hydra/lib/utils/alloc.c +++ b/src/pm/hydra/lib/utils/alloc.c @@ -21,8 +21,8 @@ void HYDU_init_user_global(struct HYD_user_global *user_global) user_global->memory_alloc_kinds = NULL; user_global->enablex = -1; - user_global->usize = HYD_USIZE_UNSET; - + user_global->usize = 0; + user_global->usize_system = false; user_global->auto_cleanup = -1; user_global->pmi_port = -1; user_global->skip_launch_node = -1; @@ -110,8 +110,7 @@ void HYDU_free_node_list(struct HYD_node *node_list) } } -static void init_proxy(struct HYD_proxy *proxy, int pgid, struct HYD_node *node, - int max_oversubscribe) +static void init_proxy(struct HYD_proxy *proxy, int pgid, struct HYD_node *node) { proxy->node = node; proxy->pgid = pgid; @@ -120,11 +119,6 @@ static void init_proxy(struct HYD_proxy *proxy, int pgid, struct HYD_node *node, proxy->exec_launch_info = NULL; proxy->proxy_process_count = 0; - if (max_oversubscribe > 0) { - proxy->filler_processes = node->core_count * max_oversubscribe - node->active_processes; - } else { - proxy->filler_processes = 0; - } proxy->pid = NULL; proxy->exit_status = NULL; @@ -168,6 +162,7 @@ HYD_status HYDU_alloc_exec(struct HYD_exec **exec) (*exec)->exec_len = 0; (*exec)->exec_size = 0; (*exec)->wdir = NULL; + (*exec)->start_rank = -1; (*exec)->proc_count = -1; (*exec)->env_prop = NULL; (*exec)->user_env = NULL; @@ -239,44 +234,35 @@ void HYDU_free_exec_list(struct HYD_exec *exec_list) HYDU_FUNC_EXIT(); } -static HYD_status add_exec_to_proxy(struct HYD_exec *exec, struct HYD_proxy *proxy, int num_procs) +static HYD_status add_exec_to_proxy(struct HYD_exec *exec, struct HYD_proxy *proxy, + int num_procs, int start_rank) { - int i; - struct HYD_exec *texec; HYD_status status = HYD_SUCCESS; - if (proxy->exec_list == NULL) { - status = HYDU_alloc_exec(&proxy->exec_list); - HYDU_ERR_POP(status, "unable to allocate proxy exec\n"); - - for (i = 0; exec->exec[i]; i++) { - status = HYDU_exec_add_arg(proxy->exec_list, exec->exec[i]); - HYDU_ERR_POP(status, "unable to add exec arg\n"); - } + struct HYD_exec *texec; + status = HYDU_alloc_exec(&texec); + HYDU_ERR_POP(status, "unable to allocate proxy exec\n"); - proxy->exec_list->wdir = exec->wdir ? MPL_strdup(exec->wdir) : NULL; - proxy->exec_list->proc_count = num_procs; - proxy->exec_list->env_prop = exec->env_prop ? MPL_strdup(exec->env_prop) : NULL; - proxy->exec_list->user_env = HYDU_env_list_dup(exec->user_env); - proxy->exec_list->appnum = exec->appnum; + if (proxy->exec_list == NULL) { + proxy->exec_list = texec; } else { - for (texec = proxy->exec_list; texec->next; texec = texec->next); - status = HYDU_alloc_exec(&texec->next); - HYDU_ERR_POP(status, "unable to allocate proxy exec\n"); + struct HYD_exec *tmp; + for (tmp = proxy->exec_list; tmp->next; tmp = tmp->next); + tmp->next = texec; + } - texec = texec->next; + for (int i = 0; exec->exec[i]; i++) { + status = HYDU_exec_add_arg(texec, exec->exec[i]); + HYDU_ERR_POP(status, "unable to add exec arg\n"); + } - for (i = 0; exec->exec[i]; i++) { - status = HYDU_exec_add_arg(texec, exec->exec[i]); - HYDU_ERR_POP(status, "unable to add exec arg\n"); - } + texec->wdir = exec->wdir ? MPL_strdup(exec->wdir) : NULL; + texec->start_rank = start_rank; + texec->proc_count = num_procs; + texec->env_prop = exec->env_prop ? MPL_strdup(exec->env_prop) : NULL; + texec->user_env = HYDU_env_list_dup(exec->user_env); + texec->appnum = exec->appnum; - texec->wdir = exec->wdir ? MPL_strdup(exec->wdir) : NULL; - texec->proc_count = num_procs; - texec->env_prop = exec->env_prop ? MPL_strdup(exec->env_prop) : NULL; - texec->user_env = HYDU_env_list_dup(exec->user_env); - texec->appnum = exec->appnum; - } proxy->proxy_process_count += num_procs; proxy->node->active_processes += num_procs; @@ -297,7 +283,7 @@ HYD_status HYDU_create_proxy_list_singleton(struct HYD_node *node, int pgid, proxy = MPL_malloc(sizeof(struct HYD_proxy), MPL_MEM_OTHER); HYDU_ASSERT(proxy, status); - init_proxy(proxy, pgid, node, 0); + init_proxy(proxy, pgid, node); proxy->proxy_id = 0; proxy->proxy_process_count = 1; @@ -313,35 +299,10 @@ HYD_status HYDU_create_proxy_list_singleton(struct HYD_node *node, int pgid, goto fn_exit; } -static int get_max_overscribe(struct HYD_node *node_list) -{ - int max_oversubscribe = 0; - for (struct HYD_node * node = node_list; node; node = node->next) { - int c = HYDU_dceil(node->active_processes, node->core_count); - if (max_oversubscribe < c) { - max_oversubscribe = c; - } - } - - bool has_spare = false; - for (struct HYD_node * node = node_list; node; node = node->next) { - if (node->core_count * max_oversubscribe - node->active_processes > 0) { - has_spare = true; - break; - } - } - if (!has_spare) { - max_oversubscribe = 0; - } - - /* NOTE: returning 0 means we can skip the filler round */ - return max_oversubscribe; -} - -HYD_status HYDU_create_proxy_list(int count, struct HYD_exec * exec_list, - struct HYD_node * node_list, int pgid, int *rankmap, +HYD_status HYDU_create_proxy_list(int count, struct HYD_exec *exec_list, + struct HYD_node *node_list, int pgid, int *rankmap, int *min_node_id_p, int *proxy_count_p, - struct HYD_proxy ** proxy_list_p) + struct HYD_proxy **proxy_list_p) { HYD_status status = HYD_SUCCESS; HYDU_FUNC_ENTER(); @@ -362,21 +323,11 @@ HYD_status HYDU_create_proxy_list(int count, struct HYD_exec * exec_list, struct HYD_proxy *proxy_list = MPL_malloc(num_nodes * sizeof(struct HYD_proxy), MPL_MEM_OTHER); HYDU_ASSERT(proxy_list, status); - int count_nonfilled = 0; - int max_oversubscribe = get_max_overscribe(node_list); for (struct HYD_node * node = node_list; node; node = node->next) { int id = node->node_id; if (id >= min_node_id && id <= max_node_id) { int i_proxy = id - min_node_id; - init_proxy(&proxy_list[i_proxy], pgid, node, max_oversubscribe); - if (proxy_list[i_proxy].filler_processes > 0) { - count_nonfilled++; - } - } - } - if (count_nonfilled == 0) { - for (int i_proxy = 0; i_proxy < num_nodes; i_proxy++) { - proxy_list[i_proxy].filler_processes += proxy_list[i_proxy].node->core_count; + init_proxy(&proxy_list[i_proxy], pgid, node); } } @@ -393,7 +344,6 @@ HYD_status HYDU_create_proxy_list(int count, struct HYD_exec * exec_list, int node_id, c; node_id = rankmap[rank]; - printf("* rankmap[%d] = %d\n", rank, node_id); c = 1; rank++; while (c < exec_rem_procs && rank < count && rankmap[rank] == node_id) { @@ -402,7 +352,7 @@ HYD_status HYDU_create_proxy_list(int count, struct HYD_exec * exec_list, } struct HYD_proxy *proxy = proxy_list + (node_id - min_node_id); - status = add_exec_to_proxy(exec, proxy, c); + status = add_exec_to_proxy(exec, proxy, c, rank - c); HYDU_ERR_POP(status, "unable to add executable to proxy\n"); exec_rem_procs -= c; diff --git a/src/pm/hydra/mpiexec/mpiexec.c b/src/pm/hydra/mpiexec/mpiexec.c index bd38d50a30e..a566f55c064 100644 --- a/src/pm/hydra/mpiexec/mpiexec.c +++ b/src/pm/hydra/mpiexec/mpiexec.c @@ -132,6 +132,15 @@ int main(int argc, char **argv) } } + /* set usize if user request for "SYSTEM" */ + if (HYD_server_info.user_global.usize_system) { + int count = 0; + for (node = HYD_server_info.node_list; node; node = node->next) { + count += node->core_count; + } + HYD_server_info.user_global.usize = count; + } + /* Reset the host list to use only the number of processes per * node as specified by the ppn option. */ if (HYD_ui_mpich_info.ppn != -1) { diff --git a/src/pm/hydra/mpiexec/options.c b/src/pm/hydra/mpiexec/options.c index 9458d74714a..f17b8bff08b 100644 --- a/src/pm/hydra/mpiexec/options.c +++ b/src/pm/hydra/mpiexec/options.c @@ -1455,11 +1455,12 @@ static HYD_status usize_fn(char *arg, char ***argv) HYDU_ERR_CHKANDJUMP(status, HYD_server_info.user_global.usize != HYD_USIZE_UNSET, HYD_INTERNAL_ERROR, "universe size already set\n"); - if (!strcmp(**argv, "SYSTEM")) - HYD_server_info.user_global.usize = HYD_USIZE_SYSTEM; - else if (!strcmp(**argv, "INFINITE")) + if (!strcmp(**argv, "SYSTEM")) { + HYD_server_info.user_global.usize_system = true; HYD_server_info.user_global.usize = HYD_USIZE_INFINITE; - else { + } else if (!strcmp(**argv, "INFINITE")) { + HYD_server_info.user_global.usize = HYD_USIZE_INFINITE; + } else { HYD_server_info.user_global.usize = atoi(**argv); HYDU_ERR_CHKANDJUMP(status, HYD_server_info.user_global.usize <= 0, HYD_INTERNAL_ERROR, "invalid universe size\n"); diff --git a/src/pm/hydra/mpiexec/pmiserv_utils.c b/src/pm/hydra/mpiexec/pmiserv_utils.c index bd7bb14d123..1049d3da3b1 100644 --- a/src/pm/hydra/mpiexec/pmiserv_utils.c +++ b/src/pm/hydra/mpiexec/pmiserv_utils.c @@ -177,13 +177,11 @@ static HYD_status add_env_to_exec_stash(struct HYD_string_stash *exec_stash, con HYD_status HYD_pmcd_pmi_fill_in_exec_launch_info(struct HYD_pg *pg) { int inherited_env_count, user_env_count, system_env_count; - int total_core_count; - int pmi_id, *filler_pmi_ids = NULL, *nonfiller_pmi_ids = NULL; struct HYD_env *env; struct HYD_exec *exec; struct HYD_pmcd_pmi_pg_scratch *pg_scratch; - char *mapping = NULL, *map; - struct HYD_string_stash stash, exec_stash; + char *mapping = NULL; + struct HYD_string_stash exec_stash; HYD_status status = HYD_SUCCESS; int mpl_err = MPL_rankmap_array_to_str(pg->rankmap, pg->pg_process_count, &mapping); @@ -195,30 +193,6 @@ HYD_status HYD_pmcd_pmi_fill_in_exec_launch_info(struct HYD_pg *pg) mapping = NULL; } - /* FIXME: The following code is still assigning ranks according to round-robin PPN. - * For now it works because we don't provide explicit rankmap option. The - * rankmap is always generated from round-robin PPN. The code need be changed - * if we ever offer user custom rankmap. - */ - - total_core_count = 0; - for (int i = 0; i < pg->proxy_count; i++) { - total_core_count += pg->proxy_list[i].node->core_count; - } - - HYDU_MALLOC_OR_JUMP(filler_pmi_ids, int *, pg->proxy_count * sizeof(int), status); - HYDU_MALLOC_OR_JUMP(nonfiller_pmi_ids, int *, pg->proxy_count * sizeof(int), status); - - pmi_id = 0; - for (int i = 0; i < pg->proxy_count; i++) { - filler_pmi_ids[i] = pmi_id; - pmi_id += pg->proxy_list[i].filler_processes; - } - for (int i = 0; i < pg->proxy_count; i++) { - nonfiller_pmi_ids[i] = pmi_id; - pmi_id += pg->proxy_list[i].node->core_count; - } - for (int i = 0; i < pg->proxy_count; i++) { struct HYD_proxy *proxy = &pg->proxy_list[i]; for (inherited_env_count = 0, env = HYD_server_info.user_global.global_env.inherited; @@ -241,32 +215,6 @@ HYD_status HYD_pmcd_pmi_fill_in_exec_launch_info(struct HYD_pg *pg) HYD_STRING_STASH(exec_stash, MPL_strdup("--hostname"), status); HYD_STRING_STASH(exec_stash, MPL_strdup(proxy->node->hostname), status); - /* This map has three fields: filler cores on this node, - * remaining cores on this node, total cores in the system */ - HYD_STRING_STASH(exec_stash, MPL_strdup("--global-core-map"), status); - - HYD_STRING_STASH_INIT(stash); - HYD_STRING_STASH(stash, HYDU_int_to_str(proxy->filler_processes), status); - HYD_STRING_STASH(stash, MPL_strdup(","), status); - HYD_STRING_STASH(stash, HYDU_int_to_str(proxy->node->core_count), status); - HYD_STRING_STASH(stash, MPL_strdup(","), status); - HYD_STRING_STASH(stash, HYDU_int_to_str(total_core_count), status); - HYD_STRING_SPIT(stash, map, status); - - HYD_STRING_STASH(exec_stash, map, status); - - /* This map has two fields: start PMI ID during the filler - * phase, start PMI ID for the remaining phase */ - HYD_STRING_STASH(exec_stash, MPL_strdup("--pmi-id-map"), status); - - HYD_STRING_STASH_INIT(stash); - HYD_STRING_STASH(stash, HYDU_int_to_str(filler_pmi_ids[i]), status); - HYD_STRING_STASH(stash, MPL_strdup(","), status); - HYD_STRING_STASH(stash, HYDU_int_to_str(nonfiller_pmi_ids[i]), status); - HYD_STRING_SPIT(stash, map, status); - - HYD_STRING_STASH(exec_stash, map, status); - HYD_STRING_STASH(exec_stash, MPL_strdup("--global-process-count"), status); HYD_STRING_STASH(exec_stash, HYDU_int_to_str(pg->pg_process_count), status); @@ -334,6 +282,9 @@ HYD_status HYD_pmcd_pmi_fill_in_exec_launch_info(struct HYD_pg *pg) HYD_STRING_STASH(exec_stash, MPL_strdup("--exec-appnum"), status); HYD_STRING_STASH(exec_stash, HYDU_int_to_str(exec->appnum), status); + HYD_STRING_STASH(exec_stash, MPL_strdup("--exec-rank"), status); + HYD_STRING_STASH(exec_stash, HYDU_int_to_str(exec->start_rank), status); + HYD_STRING_STASH(exec_stash, MPL_strdup("--exec-proc-count"), status); HYD_STRING_STASH(exec_stash, HYDU_int_to_str(exec->proc_count), status); @@ -374,8 +325,6 @@ HYD_status HYD_pmcd_pmi_fill_in_exec_launch_info(struct HYD_pg *pg) fn_exit: MPL_free(mapping); - MPL_free(filler_pmi_ids); - MPL_free(nonfiller_pmi_ids); return status; fn_fail: diff --git a/src/pm/hydra/proxy/pmip.h b/src/pm/hydra/proxy/pmip.h index 146d91b0324..b54ca1a83d0 100644 --- a/src/pm/hydra/proxy/pmip.h +++ b/src/pm/hydra/proxy/pmip.h @@ -83,17 +83,6 @@ struct pmip_pg { int num_procs; struct pmip_downstream *downstreams; - struct { - int local_filler; - int local_count; - int global_count; - } global_core_map; - - struct { - int filler_start; - int non_filler_start; - } pmi_id_map; - int global_process_count; char *pmi_process_mapping; char *spawner_kvsname; @@ -140,9 +129,6 @@ HYD_status PMIP_foreach_pg_do(HYD_status(*callback) (struct pmip_pg * pg)); HYD_status PMIP_pg_alloc_downstreams(struct pmip_pg *pg, int num_procs); struct pmip_pg *PMIP_find_pg(int pgid, int proxy_id); -int PMIP_pg_local_to_global_id(struct pmip_pg *pg, int local_id); -int PMIP_pg_global_to_local_id(struct pmip_pg *pg, int global_id); - bool PMIP_pg_has_open_stdoe(struct pmip_pg *pg); int *PMIP_pg_get_pid_list(struct pmip_pg *pg); diff --git a/src/pm/hydra/proxy/pmip_cb.c b/src/pm/hydra/proxy/pmip_cb.c index ac772a7ba45..32d5a43d087 100644 --- a/src/pm/hydra/proxy/pmip_cb.c +++ b/src/pm/hydra/proxy/pmip_cb.c @@ -740,7 +740,7 @@ static HYD_status singleton_init(struct pmip_pg *pg, int singleton_pid, int sing static HYD_status launch_procs(struct pmip_pg *pg) { - int j, process_id, dummy; + int process_id, dummy; char *str, *envstr, *list, *pmi_port = NULL; struct HYD_string_stash stash; struct HYD_env *env, *force_env = NULL; @@ -773,7 +773,17 @@ static HYD_status launch_procs(struct pmip_pg *pg) * PORT. */ p->pmi_fd = HYD_FD_UNSET; p->pmi_fd_active = 0; - p->pmi_rank = PMIP_pg_local_to_global_id(pg, i); + } + + /* set pmi_rank */ + { + int i = 0; + for (exec = pg->exec_list; exec; exec = exec->next) { + for (int j = 0; j < exec->proc_count; j++) { + pg->downstreams[i].pmi_rank = exec->start_rank + j; + i++; + } + } } if (HYD_pmcd_pmip.user_global.pmi_port) { @@ -992,7 +1002,7 @@ static HYD_status launch_procs(struct pmip_pg *pg) } HYD_STRING_STASH_INIT(stash); - for (j = 0; exec->exec[j]; j++) + for (int j = 0; exec->exec[j]; j++) HYD_STRING_STASH(stash, MPL_strdup(exec->exec[j]), status); /* For non rank-0 processes, store the stdin socket in a @@ -1056,35 +1066,14 @@ static HYD_status launch_procs(struct pmip_pg *pg) goto fn_exit; } -/* global_core_map and pmi_id_map */ static void init_pg_params(struct pmip_pg *pg) { - pg->global_core_map.local_filler = -1; - pg->global_core_map.local_count = -1; - pg->global_core_map.global_count = -1; - pg->pmi_id_map.filler_start = -1; - pg->pmi_id_map.non_filler_start = -1; - pg->global_process_count = -1; } static HYD_status verify_pg_params(struct pmip_pg *pg) { HYD_status status = HYD_SUCCESS; - if (pg->global_core_map.local_filler == -1 || - pg->global_core_map.local_count == -1 || pg->global_core_map.global_count == -1) { - HYDU_ERR_SETANDJUMP(status, HYD_INTERNAL_ERROR, - "cannot find global core map (%d,%d,%d)\n", - pg->global_core_map.local_filler, - pg->global_core_map.local_count, pg->global_core_map.global_count); - } - - if (pg->pmi_id_map.filler_start == -1 || pg->pmi_id_map.non_filler_start == -1) { - HYDU_ERR_SETANDJUMP(status, HYD_INTERNAL_ERROR, - "cannot find pmi id map (%d,%d)\n", - pg->pmi_id_map.filler_start, pg->pmi_id_map.non_filler_start); - } - if (pg->global_process_count == -1) { HYDU_ERR_SETANDJUMP(status, HYD_INTERNAL_ERROR, "cannot find global_process_count\n"); } diff --git a/src/pm/hydra/proxy/pmip_pg.c b/src/pm/hydra/proxy/pmip_pg.c index 1c13115be5e..cffdd54a783 100644 --- a/src/pm/hydra/proxy/pmip_pg.c +++ b/src/pm/hydra/proxy/pmip_pg.c @@ -265,45 +265,3 @@ void PMIP_bcast_signal(int sig) } } } - -int PMIP_pg_local_to_global_id(struct pmip_pg *pg, int local_id) -{ - int rem1, rem2, layer, ret; - - if (local_id < pg->global_core_map.local_filler) - ret = pg->pmi_id_map.filler_start + local_id; - else { - rem1 = local_id - pg->global_core_map.local_filler; - layer = rem1 / pg->global_core_map.local_count; - rem2 = rem1 - (layer * pg->global_core_map.local_count); - - ret = pg->pmi_id_map.non_filler_start + (layer * pg->global_core_map.global_count) + rem2; - } - - return ret; -} - -int PMIP_pg_global_to_local_id(struct pmip_pg *pg, int global_id) -{ - if (global_id < pg->pmi_id_map.filler_start) { - return -1; - } else if (global_id < pg->pmi_id_map.non_filler_start) { - int rem1 = global_id - pg->pmi_id_map.filler_start; - if (rem1 < pg->global_core_map.local_filler) { - return rem1; - } else { - return -1; - } - } else { - int rem1 = global_id - pg->pmi_id_map.non_filler_start; - int layer = rem1 / pg->global_core_map.global_count; - int rem2 = rem1 - layer * pg->global_core_map.global_count; - - if (rem2 < pg->global_core_map.local_count) { - return pg->global_core_map.local_filler + (layer * pg->global_core_map.local_count) - + rem2; - } else { - return -1; - } - } -} diff --git a/src/pm/hydra/proxy/pmip_pmi.c b/src/pm/hydra/proxy/pmip_pmi.c index 2c541d52d8f..8b947c7eb3b 100644 --- a/src/pm/hydra/proxy/pmip_pmi.c +++ b/src/pm/hydra/proxy/pmip_pmi.c @@ -369,15 +369,7 @@ HYD_status fn_get_my_kvsname(struct pmip_downstream *p, struct PMIU_cmd *pmi) static int get_universe_size(struct pmip_downstream *p) { - int universe_size; - if (HYD_pmcd_pmip.user_global.usize == HYD_USIZE_SYSTEM) { - universe_size = PMIP_pg_from_downstream(p)->global_core_map.global_count; - } else if (HYD_pmcd_pmip.user_global.usize == HYD_USIZE_INFINITE) { - universe_size = -1; - } else { - universe_size = HYD_pmcd_pmip.user_global.usize; - } - return universe_size; + return HYD_pmcd_pmip.user_global.usize; } HYD_status fn_get_usize(struct pmip_downstream * p, struct PMIU_cmd * pmi) diff --git a/src/pm/hydra/proxy/pmip_utils.c b/src/pm/hydra/proxy/pmip_utils.c index 39a10deffc3..739ccd030e0 100644 --- a/src/pm/hydra/proxy/pmip_utils.c +++ b/src/pm/hydra/proxy/pmip_utils.c @@ -364,70 +364,6 @@ static HYD_status genv_prop_fn(char *arg, char ***argv) return status; } -static HYD_status global_core_map_fn(char *arg, char ***argv) -{ - char *map, *tmp; - HYD_status status = HYD_SUCCESS; - - /* Split the core map into three different segments */ - map = MPL_strdup(**argv); - HYDU_ASSERT(map, status); - - tmp = strtok(map, ","); - HYDU_ASSERT(tmp, status); - cur_pg->global_core_map.local_filler = atoi(tmp); - - tmp = strtok(NULL, ","); - HYDU_ASSERT(tmp, status); - cur_pg->global_core_map.local_count = atoi(tmp); - - tmp = strtok(NULL, ","); - HYDU_ASSERT(tmp, status); - cur_pg->global_core_map.global_count = atoi(tmp); - - MPL_free(map); - - (*argv)++; - - fn_exit: - HYDU_FUNC_EXIT(); - return status; - - fn_fail: - goto fn_exit; -} - -static HYD_status pmi_id_map_fn(char *arg, char ***argv) -{ - char *map, *tmp; - HYD_status status = HYD_SUCCESS; - - HYDU_ASSERT(cur_pg, status); - - /* Split the core map into three different segments */ - map = MPL_strdup(**argv); - HYDU_ASSERT(map, status); - - tmp = strtok(map, ","); - HYDU_ASSERT(tmp, status); - cur_pg->pmi_id_map.filler_start = atoi(tmp); - - tmp = strtok(NULL, ","); - HYDU_ASSERT(tmp, status); - cur_pg->pmi_id_map.non_filler_start = atoi(tmp); - - MPL_free(map); - - (*argv)++; - - fn_exit: - HYDU_FUNC_EXIT(); - return status; - - fn_fail: - goto fn_exit; -} - static HYD_status global_process_count_fn(char *arg, char ***argv) { HYD_status status = HYD_SUCCESS; @@ -514,6 +450,19 @@ static HYD_status exec_appnum_fn(char *arg, char ***argv) return status; } +static HYD_status exec_rank_fn(char *arg, char ***argv) +{ + struct HYD_exec *exec = NULL; + HYD_status status = HYD_SUCCESS; + + for (exec = cur_pg->exec_list; exec->next; exec = exec->next); + status = HYDU_set_int(arg, &exec->start_rank, atoi(**argv)); + + (*argv)++; + + return status; +} + static HYD_status exec_proc_count_fn(char *arg, char ***argv) { struct HYD_exec *exec = NULL; @@ -656,8 +605,6 @@ struct HYD_arg_match_table HYD_pmip_procinfo_match_table[] = { {"global-system-env", global_env_fn, NULL}, {"global-user-env", global_env_fn, NULL}, {"genv-prop", genv_prop_fn, NULL}, - {"global-core-map", global_core_map_fn, NULL}, - {"pmi-id-map", pmi_id_map_fn, NULL}, {"global-process-count", global_process_count_fn, NULL}, {"version", version_fn, NULL}, {"iface-ip-env-name", iface_ip_env_name_fn, NULL}, @@ -665,6 +612,7 @@ struct HYD_arg_match_table HYD_pmip_procinfo_match_table[] = { {"proxy-core-count", dummy1_fn, NULL}, {"exec", exec_fn, NULL}, {"exec-appnum", exec_appnum_fn, NULL}, + {"exec-rank", exec_rank_fn, NULL}, {"exec-proc-count", exec_proc_count_fn, NULL}, {"exec-local-env", exec_local_env_fn, NULL}, {"exec-env-prop", exec_env_prop_fn, NULL}, diff --git a/test/mpi/datatype/large_count.c b/test/mpi/datatype/large_count.c index 1ca4f1ba6d6..6355b008bf0 100644 --- a/test/mpi/datatype/large_count.c +++ b/test/mpi/datatype/large_count.c @@ -39,7 +39,7 @@ static void check_set_elements(MPI_Status status, MPI_Datatype type, MPI_Count e elements = elements_x = count = 0xfeedface; /* can't use legacy "set" for large element counts */ if (expected <= INT_MAX) { - MPI_Status_set_elements(&status, type, 1); + MPI_Status_set_elements(&status, type, expected); MPI_Get_elements(&status, type, &elements); MPI_Get_elements_x(&status, type, &elements_x); MPI_Get_count(&status, type, &count); @@ -49,7 +49,7 @@ static void check_set_elements(MPI_Status status, MPI_Datatype type, MPI_Count e } elements = elements_x = count = 0xfeedface; - MPI_Status_set_elements_x(&status, type, 1); + MPI_Status_set_elements_x(&status, type, expected); MPI_Get_elements(&status, type, &elements); MPI_Get_elements_x(&status, type, &elements_x); MPI_Get_count(&status, type, &count); @@ -63,7 +63,7 @@ static void check_set_elements(MPI_Status status, MPI_Datatype type, MPI_Count e #if MTEST_HAVE_MIN_MPI_VERSION(4,0) elements = elements_x = count = 0xfeedface; - MPI_Status_set_elements_c(&status, type, 1); + MPI_Status_set_elements_c(&status, type, expected); MPI_Get_elements(&status, type, &elements); MPI_Get_elements_c(&status, type, &elements_x); MPI_Get_count(&status, type, &count); @@ -88,6 +88,7 @@ int main(int argc, char *argv[]) MPI_Datatype four_ints = MPI_DATATYPE_NULL; MPI_Datatype imx4i = MPI_DATATYPE_NULL; MPI_Datatype imx4i_rsz = MPI_DATATYPE_NULL; + MPI_Datatype four_struct = MPI_DATATYPE_NULL; MPI_Status status; MTest_Init(&argc, &argv); @@ -135,6 +136,17 @@ int main(int argc, char *argv[]) MPI_Type_create_resized(imx4i, /*lb= */ INT_MAX, /*extent= */ -1024, &imx4i_rsz); MPI_Type_commit(&imx4i_rsz); + /* four_struct: a struct with four elements */ + int blklens[4] = { 1, 1, 1, 1 }; + MPI_Aint displs[4] = { 0, 8, 16, 24 }; + MPI_Datatype types[4] = { MPI_CHAR, MPI_INT, MPI_DOUBLE, MPI_SHORT }; + MPI_Type_create_struct(4, blklens, displs, types, &four_struct); + MPI_Type_commit(&four_struct); + + MPI_Aint four_struct_extent = displs[3] + sizeof(double); + MPI_Aint four_struct_true_extent = displs[3] + sizeof(short); + MPI_Aint four_struct_size = sizeof(char) + sizeof(int) + sizeof(double) + sizeof(short); + /* MPI_Type_size */ MPI_Type_size(imax_contig, &size); check(size == INT_MAX); @@ -144,6 +156,8 @@ int main(int argc, char *argv[]) check(size == MPI_UNDEFINED); /* should overflow an int */ MPI_Type_size(imx4i_rsz, &size); check(size == MPI_UNDEFINED); /* should overflow an int */ + MPI_Type_size(four_struct, &size); + check(size == four_struct_size); /* MPI_Type_size_x */ MPI_Type_size_x(imax_contig, &size_x); @@ -154,6 +168,8 @@ int main(int argc, char *argv[]) check(size_x == 4LL * sizeof(int) * (INT_MAX / 2)); /* should overflow an int */ MPI_Type_size_x(imx4i_rsz, &size_x); check(size_x == 4LL * sizeof(int) * (INT_MAX / 2)); /* should overflow an int */ + MPI_Type_size_x(four_struct, &size_x); + check(size_x == four_struct_size); /* MPI_Type_get_extent */ MPI_Type_get_extent(imax_contig, &lb, &extent); @@ -172,6 +188,9 @@ int main(int argc, char *argv[]) MPI_Type_get_extent(imx4i_rsz, &lb, &extent); check(lb == INT_MAX); check(extent == -1024); + MPI_Type_get_extent(four_struct, &lb, &extent); + check(lb == 0); + check(extent == four_struct_extent); /* MPI_Type_get_extent_x */ MPI_Type_get_extent_x(imax_contig, &lb_x, &extent_x); @@ -186,6 +205,9 @@ int main(int argc, char *argv[]) MPI_Type_get_extent_x(imx4i_rsz, &lb_x, &extent_x); check(lb_x == INT_MAX); check(extent_x == -1024); + MPI_Type_get_extent_x(four_struct, &lb_x, &extent_x); + check(lb_x == 0); + check(extent_x == four_struct_extent); /* MPI_Type_get_true_extent */ MPI_Type_get_true_extent(imax_contig, &lb, &extent); @@ -206,6 +228,9 @@ int main(int argc, char *argv[]) check(extent == MPI_UNDEFINED); else check(extent == imx4i_true_extent); + MPI_Type_get_true_extent(four_struct, &lb, &extent); + check(lb == 0); + check(extent == four_struct_true_extent); /* MPI_Type_get_true_extent_x */ MPI_Type_get_true_extent_x(imax_contig, &lb_x, &extent_x); @@ -220,6 +245,9 @@ int main(int argc, char *argv[]) MPI_Type_get_true_extent_x(imx4i_rsz, &lb_x, &extent_x); check(lb_x == 0); check(extent_x == imx4i_true_extent); + MPI_Type_get_true_extent_x(four_struct, &lb_x, &extent_x); + check(lb_x == 0); + check(extent == four_struct_true_extent); /* MPI_{Status_set_elements,Get_elements}{,_x} */ @@ -246,6 +274,7 @@ int main(int argc, char *argv[]) check_set_elements(status, four_ints, 4); check_set_elements(status, imx4i, 4LL * (INT_MAX / 2)); check_set_elements(status, imx4i_rsz, 4LL * (INT_MAX / 2)); + check_set_elements(status, four_struct, 4); epilogue: if (imax_contig != MPI_DATATYPE_NULL) @@ -256,6 +285,8 @@ int main(int argc, char *argv[]) MPI_Type_free(&imx4i); if (imx4i_rsz != MPI_DATATYPE_NULL) MPI_Type_free(&imx4i_rsz); + if (four_struct != MPI_DATATYPE_NULL) + MPI_Type_free(&four_struct); MTest_Finalize(errs);