extern gex_TI_t gasnetc_Token_Info( gex_Token_t token, gex_Token_Info_t *info, gex_TI_t mask) { gasneti_assert(token); gasneti_assert(info); if (gasnetc_token_in_nbrhd(token)) { return gasnetc_nbrhd_Token_Info(token, info, mask); } gex_TI_t result = 0; info->gex_srcrank = gasnetc_msgsource(token); result |= GEX_TI_SRCRANK; info->gex_ep = gasneti_THUNK_EP; result |= GEX_TI_EP; #if 0 // TODO-EX: need to implement this /* (###) add code here to write the address of the handle entry into info->gex_entry (optional) */ info->gex_entry = ###; result |= GEX_TI_ENTRY; #endif return GASNETI_TOKEN_INFO_RETURN(result, info, mask); }
void gasnete_fh_request_put(void *_pop, const firehose_request_t *req, int allLocalHit) { gasnete_eop_t *pop = (gasnete_eop_t *) _pop; gasnet_node_t node; gasneti_assert(pop != NULL); gasneti_assert(pop->src > 0 && pop->dest > 0); node = pop->node; gasneti_assert(node != gasneti_mynode && node < gasneti_nodes); gasneti_assert(pop->len > 0); gasneti_assert(req == &(pop->req_remote)); gasneti_mutex_lock(&gasnetc_lock_gm); gasnetc_token_lo_poll(); GASNETI_TRACE_PRINTF(C, ("Firehose directed send(%p): (%d,%p) <- (%p,%d)", (void *) pop, (unsigned) node, (void *) pop->dest, (void *) pop->src, pop->len)); #if GASNETI_STATS_OR_TRACE if (!allLocalHit) pop->fh_stats = pop->len > 4096 ? fh_many : fh_one; #endif GASNETC_GM_PUT( _gmc.port, (void *) pop->src, (gm_remote_ptr_t) pop->dest, (unsigned long) pop->len, GM_LOW_PRIORITY, gasnetc_nodeid(node), gasnetc_portid(node), gasnete_fh_callback_put, (void *) pop); gasneti_mutex_unlock(&gasnetc_lock_gm); return; }
/* ------------------------------------------------------------------------------------ */ static int gasnetc_attach_segment(gex_Segment_t *segment_p, gex_TM_t tm, uintptr_t segsize, gasneti_bootstrapExchangefn_t exchangefn, gex_Flags_t flags) { int retval = GASNET_OK; // TODO-EX: crude detection of multiple calls until we support them gasneti_assert(NULL == gasneti_seginfo[0].addr); /* ------------------------------------------------------------------------------------ */ /* register segment */ gasneti_segmentAttach(segsize, gasneti_seginfo, exchangefn, flags); void *segbase = gasneti_seginfo[gasneti_mynode].addr; segsize = gasneti_seginfo[gasneti_mynode].size; gasneti_assert(((uintptr_t)segbase) % GASNET_PAGESIZE == 0); gasneti_assert(segsize % GASNET_PAGESIZE == 0); gasneti_EP_t ep = gasneti_import_tm(tm)->_ep; ep->_segment = gasneti_alloc_segment(ep->_client, segbase, segsize, flags, 0); gasneti_legacy_segment_attach_hook(ep); *segment_p = gasneti_export_segment(ep->_segment); /* After local segment is attached, call optional client-provided hook (###) should call BEFORE any conduit-specific pinning/registration of the segment */ if (gasnet_client_attach_hook) { gasnet_client_attach_hook(segbase, segsize); } #if !GASNETC_MOCK_EVERYTHING /* AMUDP allows arbitrary registration with no further action */ if (segsize) { retval = AM_SetSeg(gasnetc_endpoint, segbase, segsize); if (retval != AM_OK) INITERR(RESOURCE, "AM_SetSeg() failed"); } #endif /* ------------------------------------------------------------------------------------ */ /* gather segment information */ /* (###) add code here to gather the segment assignment info into gasneti_seginfo on each node (may be possible to use AMShortRequest here) If gasneti_segmentAttach() was used above, this is already done. Done in gasneti_segmentAttach(), above. */ gasneti_assert(gasneti_seginfo[gasneti_mynode].addr == segbase && gasneti_seginfo[gasneti_mynode].size == segsize); done: GASNETI_RETURN(retval); }
void do_kvs_put(void *value, size_t sz) { int rc; do_encode(value, sz); #if USE_PMI2_API rc = PMI2_KVS_Put(kvs_key, kvs_value); gasneti_assert(PMI2_SUCCESS == rc); #else rc = PMI_KVS_Put(kvs_name, kvs_key, kvs_value); gasneti_assert(PMI_SUCCESS == rc); #endif }
void do_kvs_get(void *value, size_t sz) { int rc; #if USE_PMI2_API int len; rc = PMI2_KVS_Get(kvs_name, PMI2_ID_NULL, kvs_key, kvs_value, max_val_len, &len); gasneti_assert(PMI2_SUCCESS == rc); #else rc = PMI_KVS_Get(kvs_name, kvs_key, kvs_value, max_val_len); gasneti_assert(PMI_SUCCESS == rc); #endif do_decode(value, sz); }
void gasnete_coll_bcast_set_default_proto(gasnet_team_handle_t team) { gasnete_coll_team_dcmf_t *dcmf_tp; gasneti_assert(team != NULL); dcmf_tp = (gasnete_coll_team_dcmf_t *)team->dcmf_tp; gasneti_assert(dcmf_tp != NULL); if (gasnete_coll_bcast_set_proto(team, TORUS_RECTANGLE_BROADCAST)) if (gasnete_coll_bcast_set_proto(team, TORUS_BINOMIAL_BROADCAST)) dcmf_tp->bcast_proto = NULL; }
gex_Rank_t gasnetc_msgsource(gex_Token_t token) { #if GASNET_PSHM gasneti_assert(! gasnetc_token_in_nbrhd(token)); #endif gasneti_assert(token); int tmp; /* AMUDP wants an int, but gex_Rank_t is uint32_t */ gasneti_assert_zeroret(AMUDP_GetSourceId(token, &tmp)); gasneti_assert(tmp >= 0); gex_Rank_t sourceid = tmp; gasneti_assert(sourceid < gasneti_nodes); return sourceid; }
extern int firehose_move_callback(gasnet_node_t node, const firehose_region_t *unpin_list, size_t unpin_num, firehose_region_t *pin_list, size_t pin_num) { GASNETC_TRACE_WAIT_BEGIN(); int rc; int h, i; const enum ibv_access_flags access = (enum ibv_access_flags) (IBV_ACCESS_LOCAL_WRITE | IBV_ACCESS_REMOTE_WRITE | IBV_ACCESS_REMOTE_READ); /* Take care of any unpins first */ for (i = 0; i < unpin_num; i++) { GASNETC_FOR_ALL_HCA_INDEX(h) { rc = ibv_dereg_mr(unpin_list[i].client.handle[h]); GASNETC_IBV_CHECK(rc, "from ibv_dereg_mr"); } GASNETC_TRACE_UNPIN(&unpin_list[i]); } /* Take care of any pins */ for (i = 0; i < pin_num; i++) { firehose_region_t *region = pin_list + i; firehose_client_t *client = ®ion->client; gasneti_assert(region->addr % GASNET_PAGESIZE == 0); gasneti_assert(region->len % GASNET_PAGESIZE == 0); GASNETC_FOR_ALL_HCA_INDEX(h) { client->handle[h] = ibv_reg_mr(gasnetc_hca[h].pd, (void*)(uintptr_t)region->addr, region->len, access); if_pf (client->handle[h] == NULL) gasneti_fatalerror("ibv_reg_mr failed in firehose_move_callback errno=%d (%s)", errno, strerror(errno)); client->lkey[h] = client->handle[h]->lkey; client->rkey[h] = client->handle[h]->rkey; } GASNETC_TRACE_PIN(&pin_list[i]); } GASNETC_TRACE_WAIT_END(FIREHOSE_MOVE); return 0; }
char* gasnete_coll_tree_type_to_str(char *buffer, gasnete_coll_tree_type_t tree_type) { int i; if(!tree_type) {memset(buffer, 0, 10); return buffer;} switch (tree_type->tree_class) { case GASNETE_COLL_NARY_TREE: strcpy(buffer, "NARY_TREE"); break; case GASNETE_COLL_KNOMIAL_TREE: strcpy(buffer, "KNOMIAL_TREE"); break; case GASNETE_COLL_RECURSIVE_TREE: strcpy(buffer, "RECURSIVE_TREE"); break; case GASNETE_COLL_FORK_TREE: strcpy(buffer, "FORK_TREE"); break; case GASNETE_COLL_FLAT_TREE: strcpy(buffer, "FLAT_TREE"); break; default: gasneti_fatalerror("Unknown tree class: %d", tree_type->tree_class); } for(i=0; i<tree_type->num_params; i++ ) { gasneti_assert(strlen(buffer) < GASNETE_COLL_MAX_TREE_TYPE_STRLEN); sprintf(buffer, "%s,%d", buffer, tree_type->params[i]); } return buffer; }
/* get a new iop */ static gasnete_iop_t *gasnete_iop_new(gasneti_threaddata_t * const thread) { gasnete_iop_t *iop = thread->iop_free; if_pt (iop) { thread->iop_free = iop->next; gasneti_memcheck(iop); gasneti_assert(OPTYPE(iop) == OPTYPE_IMPLICIT); gasneti_assert(iop->threadidx == thread->threadidx); /* If using trace or stats, want meaningful counts when tracing NBI access regions */ #if GASNETI_STATS_OR_TRACE iop->initiated_get_cnt = 0; iop->initiated_put_cnt = 0; gasnetc_atomic_set(&(iop->completed_get_cnt), 0, 0); gasnetc_atomic_set(&(iop->completed_put_cnt), 0, 0); #endif } else {
void gasnetc_bootstrapBroadcast(void *src, size_t len, void *dest, int rootnode) { int retval; gasneti_assert(gasneti_nodes > 0 && gasneti_mynode < gasneti_nodes); if (gasneti_mynode == rootnode) memcpy(dest, src, len); GASNETI_AM_SAFE_NORETURN(retval,AMMPI_SPMDBroadcast(dest, len, rootnode)); if_pf (retval) gasneti_fatalerror("failure in gasnetc_bootstrapBroadcast()"); }
/* Naive (poorly scaling) "reference" implementation via gasnetc_bootstrapExchange() */ static void gasnetc_bootstrapSNodeBroadcast(void *src, size_t len, void *dest, int rootnode) { void *tmp = gasneti_malloc(len * gasneti_nodes); gasneti_assert(NULL != src); gasnetc_bootstrapExchange(src, len, tmp); memcpy(dest, (void*)((uintptr_t)tmp + (len * rootnode)), len); gasneti_free(tmp); }
extern void gasnete_VIS_SetPeerCompletionHandler(gex_AM_Index_t handler, const void *source_addr, size_t nbytes, gex_Flags_t flags GASNETI_THREAD_FARG) { GASNETI_TRACE_PRINTF(A,("VIS_SetPeerCompletionHandler: handler=%i, source_addr="GASNETI_LADDRFMT", nbytes=%"PRIuSZ, (int)handler, GASNETI_LADDRSTR(source_addr),nbytes)); gasnete_vis_threaddata_t * const td = GASNETE_VIS_MYTHREAD; gasnete_vis_pcinfo_t * const pcinfo = &(td->pcinfo); if (!handler) { // disarm pcinfo->_handler = 0; } else { // arm gasneti_assert(nbytes <= GEX_VIS_MAX_PEERCOMPLETION); gasneti_assert(!nbytes || source_addr); pcinfo->_handler = handler; pcinfo->_nbytes = nbytes; pcinfo->_srcaddr = source_addr; } }
/* ------------------------------------------------------------------------------------ */ static int gasnetc_attach_primary(void) { int retval = GASNET_OK; AMLOCK(); /* pause to make sure all nodes have called attach if a node calls gasnet_exit() between init/attach, then this allows us to process the AMUDP_SPMD control messages required for job shutdown */ gasnetc_bootstrapBarrier(); /* ------------------------------------------------------------------------------------ */ /* register fatal signal handlers */ /* catch fatal signals and convert to SIGQUIT */ gasneti_registerSignalHandlers(gasneti_defaultSignalHandler); #if HAVE_ON_EXIT on_exit(gasnetc_on_exit, NULL); #else atexit(gasnetc_atexit); #endif #if GASNET_TRACE || GASNET_DEBUG #if !GASNET_DEBUG if (GASNETI_TRACE_ENABLED(A)) #endif GASNETI_AM_SAFE(AMUDP_SetHandlerCallbacks(gasnetc_endpoint, gasnetc_enteringHandler_hook, gasnetc_leavingHandler_hook)); #endif #if GASNETC_MOCK_EVERYTHING retval = AM_SetSeg(gasnetc_endpoint, NULL, (uintptr_t)-1); if (retval != AM_OK) INITERR(RESOURCE, "AM_SetSeg() failed"); #endif /* ------------------------------------------------------------------------------------ */ /* primary attach complete */ gasneti_attach_done = 1; gasnetc_bootstrapBarrier(); AMUNLOCK(); GASNETI_TRACE_PRINTF(C,("gasnetc_attach_primary(): primary attach complete\n")); gasnete_init(); /* init the extended API */ gasneti_nodemapFini(); /* ensure extended API is initialized across nodes */ AMLOCK(); gasnetc_bootstrapBarrier(); AMUNLOCK(); gasneti_assert(retval == GASNET_OK); return retval; done: /* error return while locked */ AMUNLOCK(); GASNETI_RETURN(retval); }
static tree_node_t make_hiearchical_tree_helper(gasnete_coll_tree_type_t tree_type, int level, int final_level, tree_node_t *allnodes, int num_nodes, int *node_counts) { tree_node_t rootnode; tree_node_t *temp; gasneti_assert(tree_type !=NULL); if(level == final_level) { switch (tree_type->tree_class) { case GASNETE_COLL_NARY_TREE: rootnode = make_nary_tree(allnodes, num_nodes, tree_type->params[0]); break; case GASNETE_COLL_FLAT_TREE: rootnode = make_flat_tree(allnodes, num_nodes); break; case GASNETE_COLL_KNOMIAL_TREE: rootnode = make_knomial_tree(allnodes, num_nodes, tree_type->params[0]); break; case GASNETE_COLL_RECURSIVE_TREE: rootnode = make_recursive_tree(allnodes, num_nodes, tree_type->params[0]); break; case GASNETE_COLL_FORK_TREE: rootnode = make_fork_tree(allnodes, num_nodes, tree_type->params, tree_type->num_params); break; default: gasneti_fatalerror("unknown tree type"); } } else { int i,j=0,num_processed=0; int level_nodes = MYCEIL(num_nodes, node_counts[0]); temp = gasneti_malloc(sizeof(tree_node_t) * level_nodes); for(i=0; i<level_nodes-1; i++) { temp[j]=make_hiearchical_tree_helper(tree_type->subtree, level+1, final_level, allnodes+i*node_counts[0], node_counts[0], node_counts+1); j++; num_processed += node_counts[0]; } temp[j]=make_hiearchical_tree_helper(tree_type->subtree, level+1, final_level, allnodes+i*node_counts[0], num_nodes - num_processed, node_counts+1); j++; switch (tree_type->tree_class) { case GASNETE_COLL_NARY_TREE: rootnode = make_nary_tree(temp, j, tree_type->params[0]); break; case GASNETE_COLL_FLAT_TREE: rootnode = make_flat_tree(temp,j); break; case GASNETE_COLL_KNOMIAL_TREE: rootnode = make_knomial_tree(temp, j, tree_type->params[0]); break; case GASNETE_COLL_RECURSIVE_TREE: rootnode = make_recursive_tree(temp, j, tree_type->params[0]); break; case GASNETE_COLL_FORK_TREE: rootnode = make_fork_tree(temp, j, tree_type->params, tree_type->num_params); break; default: gasneti_fatalerror("unknown tree type"); } gasneti_free(temp); } return rootnode; }
void gasnete_amref_get_reqh_inner(gasnet_token_t token, gasnet_handlerarg_t nbytes, void *dest, void *src, void *done) { gasneti_assert(nbytes <= gasnet_AMMaxMedium()); GASNETI_SAFE( MEDIUM_REP(2,4,(token, gasneti_handleridx(gasnete_amref_get_reph), src, nbytes, PACK(dest), PACK(done)))); }
extern gasnet_mxm_recv_req_t * gasnetc_alloc_recv_req(void) { gasnet_mxm_recv_req_t * r; size_t size = GASNETI_PAGE_ALIGNUP(gasneti_AMMaxMedium()); void * buf; r = gasneti_malloc(sizeof(*r)); gasneti_assert(r && "Out of memory"); buf = gasneti_mmap(size); gasneti_assert(buf && "Out of memory"); r->mxm_rreq.base.data.buffer.ptr = buf; r->mxm_rreq.base.data.buffer.length = size; return r; }
int gasnete_coll_bcast_set_proto(gasnet_team_handle_t team, gasnete_dcmf_bcast_kind_t kind) { gasnete_coll_team_dcmf_t *dcmf_tp; gasneti_assert(team != NULL); dcmf_tp = (gasnete_coll_team_dcmf_t *)team->dcmf_tp; gasneti_assert(dcmf_tp != NULL); if (kind < G_DCMF_BCAST_PROTO_NUM && DCMF_Geometry_analyze(&dcmf_tp->geometry, &gasnete_dcmf_bcast_proto[kind]) && gasnete_dcmf_bcast_enabled[kind]) { dcmf_tp->bcast_proto = &gasnete_dcmf_bcast_proto[kind]; return 0; /* SUCCESS */ } return 1; /* FAILED */ }
static tree_node_t make_hiearchical_tree(gasnete_coll_tree_type_t tree_type, tree_node_t *allnodes, int num_nodes) { /*first param tells us how many tree levels there are going to be*/ /*the second contains the number at teh lowest level grouping*/ /*each tree level contains a triple (tree shape, <tree args>*/ /*so a 64 node run with 8 flat trees grouped into a binomial tree w/ 8 ndoes would have 2, 8*/ int num_levels = tree_type->params[0]; gasneti_assert(tree_type->num_params >= 2); return make_hiearchical_tree_helper(tree_type->subtree, 0, num_levels-1, allnodes, num_nodes, tree_type->params+1); }
extern int firehose_remote_callback(gasnet_node_t node, const firehose_region_t *pin_list, size_t num_pinned, firehose_remotecallback_args_t *args) { #if GASNETC_PIN_SEGMENT /* DO NOTHING. IF WE GET CALLED WE COMPLAIN. */ gasneti_fatalerror("invalid attempted to call firehose_remote_callback()"); return -1; #else /* Memcpy payload into place */ gasneti_assert(args != NULL); gasneti_assert(args->addr != NULL); gasneti_assert(args->len > 0); gasneti_assert(args->len <= gasnetc_putinmove_limit); memcpy(args->addr, args->data, args->len); gasneti_sync_writes(); return 0; #endif }
gasnet_mxm_send_req_t * gasnetc_alloc_send_req(void) { gasnet_mxm_send_req_t * sreq = (gasnet_mxm_send_req_t *) #if GASNET_DEBUG gasneti_calloc(1, sizeof(gasnet_mxm_send_req_t)); #else gasneti_malloc(sizeof(gasnet_mxm_send_req_t)); #endif gasneti_assert(sreq && "Out of memory"); return sreq; }
void gasnetc_free_send_req(void * p_sreq) { gasnet_mxm_send_req_t * sreq = (gasnet_mxm_send_req_t *) p_sreq; gasneti_assert(sreq && "bad sreq to free"); #if GASNET_DEBUG /* clear object's data before freeing it - might catch use after free */ memset(sreq, 0, sizeof(gasnet_mxm_send_req_t)); #endif gasneti_free(sreq); }
extern int gasnetc_EP_Create(gex_EP_t *ep_p, gex_Client_t client, gex_Flags_t flags) { /* (###) add code here to create an endpoint belonging to the given client */ #if 1 // TODO-EX: This is a stub, which assumes 1 implicit call from ClientCreate static gasneti_mutex_t lock = GASNETI_MUTEX_INITIALIZER; gasneti_mutex_lock(&lock); static int once = 0; int prev = once; once = 1; gasneti_mutex_unlock(&lock); if (prev) gasneti_fatalerror("Multiple endpoints are not yet implemented"); #endif gasneti_EP_t ep = gasneti_alloc_ep(gasneti_import_client(client), flags, 0); *ep_p = gasneti_export_ep(ep); { /* core API handlers */ gex_AM_Entry_t *ctable = (gex_AM_Entry_t *)gasnetc_get_handlertable(); int len = 0; int numreg = 0; gasneti_assert(ctable); while (ctable[len].gex_fnptr) len++; /* calc len */ if (gasneti_amregister(ep->_amtbl, ctable, len, GASNETC_HANDLER_BASE, GASNETE_HANDLER_BASE, 0, &numreg) != GASNET_OK) GASNETI_RETURN_ERRR(RESOURCE,"Error registering core API handlers"); gasneti_assert(numreg == len); } { /* extended API handlers */ gex_AM_Entry_t *etable = (gex_AM_Entry_t *)gasnete_get_handlertable(); int len = 0; int numreg = 0; gasneti_assert(etable); while (etable[len].gex_fnptr) len++; /* calc len */ if (gasneti_amregister(ep->_amtbl, etable, len, GASNETE_HANDLER_BASE, GASNETI_CLIENT_HANDLER_BASE, 0, &numreg) != GASNET_OK) GASNETI_RETURN_ERRR(RESOURCE,"Error registering extended API handlers"); gasneti_assert(numreg == len); } return GASNET_OK; }
/* called at startup to check configuration sanity */ static void gasnetc_check_config(void) { gasneti_check_config_preinit(); gasneti_assert(GASNET_MAXNODES <= AMMPI_MAX_SPMDPROCS); gasneti_assert(AMMPI_MAX_NUMHANDLERS >= 256); gasneti_assert(AMMPI_MAX_SEGLENGTH == (uintptr_t)-1); gasneti_assert(GASNET_ERR_NOT_INIT == AM_ERR_NOT_INIT); gasneti_assert(GASNET_ERR_RESOURCE == AM_ERR_RESOURCE); gasneti_assert(GASNET_ERR_BAD_ARG == AM_ERR_BAD_ARG); #if GASNET_PSHM gasneti_assert(gasnetc_Short == (gasnetc_category_t) ammpi_Short); gasneti_assert(gasnetc_Medium == (gasnetc_category_t) ammpi_Medium); gasneti_assert(gasnetc_Long == (gasnetc_category_t) ammpi_Long); #endif }
/* get a new op */ static gasnete_eop_t *_gasnete_eop_new(gasneti_threaddata_t * const thread) { gasnete_eopaddr_t head = thread->eop_free; if_pf (gasnete_eopaddr_isnil(head)) { gasnete_eop_alloc(thread); head = thread->eop_free; } { gasnete_eop_t *eop = GASNETE_EOPADDR_TO_PTR(thread, head); thread->eop_free = eop->addr; eop->addr = head; gasneti_assert(!gasnete_eopaddr_equal(thread->eop_free,head)); gasneti_assert(eop->threadidx == thread->threadidx); gasneti_assert(OPTYPE(eop) == OPTYPE_EXPLICIT); gasneti_assert(OPSTATE(eop) == OPSTATE_FREE); #if GASNET_DEBUG || !GASNETE_EOP_COUNTED SET_OPSTATE(eop, OPSTATE_INFLIGHT); #endif return eop; } }
/* Misc. Active Message Functions ============================== */ extern int gasnetc_AMGetMsgSource(gasnet_token_t token, gasnet_node_t *srcindex) { int retval; gasnet_node_t sourceid; GASNETI_CHECKATTACH(); GASNETI_CHECK_ERRR((!token),BAD_ARG,"bad token"); GASNETI_CHECK_ERRR((!srcindex),BAD_ARG,"bad src ptr"); #if GASNET_PSHM if (gasneti_AMPSHMGetMsgSource(token, &sourceid) != GASNET_OK) #endif { int tmp; /* AMUDP wants an int, but gasnet_node_t is uint16_t */ GASNETI_AM_SAFE_NORETURN(retval,AMUDP_GetSourceId(token, &tmp)); if_pf (retval) GASNETI_RETURN_ERR(RESOURCE); gasneti_assert(tmp >= 0); sourceid = tmp; } gasneti_assert(sourceid < gasneti_nodes); *srcindex = sourceid; return GASNET_OK; }
void gasnete_coll_tree_type_to_str(char *outbuf, gasnete_coll_tree_type_t in) { gasneti_assert(in->subtree == NULL); gasneti_assert(in->num_params <= 1); switch(in->tree_class) { case GASNETE_COLL_NARY_TREE: sprintf(outbuf, "NARY_TREE,%d", in->params[0]); break; case GASNETE_COLL_FLAT_TREE: strcpy(outbuf, "FLAT_TREE"); break; case GASNETE_COLL_KNOMIAL_TREE: sprintf(outbuf, "KNOMIAL_TREE,%d", in->params[0]); break; case GASNETE_COLL_RECURSIVE_TREE: sprintf(outbuf, "RECURSIVE_TREE,%d", in->params[0]); break; default: gasneti_fatalerror("unknown tree type"); } }
static tree_node_t make_knomial_tree(tree_node_t *nodes, int num_nodes, int radix) { int i; int num_children=0; gasneti_assert(radix>1); if(num_nodes > 1) { int r; int stride = 1; int num_proc = 1; tree_node_t *children; while(num_proc < num_nodes) { for(r=stride; r<stride*radix; r+=stride) { num_proc += MIN(stride, num_nodes - num_proc); num_children++; if(num_proc == num_nodes) break; } stride*=radix; } children = (tree_node_t*) gasneti_malloc(num_children*sizeof(tree_node_t)); num_proc = 1; i=1; stride = 1; while(num_proc<num_nodes) { for(r=stride; r<stride*radix; r+=stride) { gasneti_assert(i<=num_children); children[num_children-i] = make_knomial_tree(nodes+r,MIN(stride, num_nodes - num_proc), radix); num_proc += MIN(stride, num_nodes - num_proc); if(num_proc == num_nodes) break; i++; } stride*=radix; } nodes[0]->children_reversed=1; preappend_children(nodes[0], children, num_children); gasneti_free(children); } return nodes[0]; }
/*need to worry about corner cases*/ static tree_node_t make_fork_tree(tree_node_t *nodes, int num_nodes, int *dims, int ndims) { int i; int stride; tree_node_t *temp_nodes; gasneti_assert(ndims > 0); gasneti_assert(multarr(dims, ndims)==num_nodes); if(ndims > 1) { temp_nodes = gasneti_malloc(sizeof(tree_node_t)*dims[0]); stride = multarr(dims+1,ndims-1); for(i=dims[0]-1; i>=0; i--) { temp_nodes[i] = make_fork_tree(nodes+stride*i, stride, dims+1, ndims-1); } make_chain_tree(temp_nodes, dims[0]); gasneti_free(temp_nodes); } else { make_chain_tree(nodes, dims[0]); } nodes[0]->children_reversed=1; return nodes[0]; }
void gasneti_bootstrapFini_mpi(void) { int err; err = MPI_Comm_free(&gasnetc_mpi_comm); gasneti_assert(err == MPI_SUCCESS); /* In most cases it appears that calling MPI_Finalize() will * prevent us from propagating the exit code to the spawner. * However, as seen w/ mpich-1.2.5, the alternative is to * hang on exit, which is no alternative at all. */ if (!gasnetc_mpi_preinitialized) { (void) MPI_Finalize(); } }