#include "BSprivate.h" /* routines for manipulating the bulletin board structures */ /*+ BSinit_bb_d - initialize a DP bulletin board Input Parameters: . length - the length of the data in the BB . map - pointer to the mapping to use Returns: the new BB +*/ BSbb_d *BSinit_bb_d(int length, BSmapping *map) { BSbb_d *bb; MY_MALLOCN(bb,(BSbb_d *),sizeof(BSbb_d),1); MY_MALLOCN(bb->info,(FLOAT *),sizeof(FLOAT)*length,2); bb->length = length; bb->map = map; return(bb); } /*+ BSfree_bb_d - free a DP bulletin board Input Parameters: . bb - the BB to free Returns: void +*/ void BSfree_bb_d(BSbb_d *bb) { MY_FREE(bb->info); MY_FREE(bb); } /*+ BSpost_bb_d - post information with addresses into the DP BB Input Parameters: . bb - the BB . length - the length of the data to be posted . address - the address into the BB to post to . info - the array of information to post Returns: void +*/ void BSpost_bb_d(BSbb_d *bb, int length, int *address, FLOAT *info) { int i; for (i=0;iinfo[address[i]] = info[i]; } } /*+ BSpost_noaddr_bb_d - post information w/o addresses into the DP BB Input Parameters: . bb - the BB . length - the length of the data to be posted . info - the array of information to post Returns: void +*/ void BSpost_noaddr_bb_d(BSbb_d *bb, int length, FLOAT *info) { int i; for (i=0;iinfo[i] = info[i]; } } /*+ BSquery_match_bb_d - Mutual DP BB query Input Parameters: . bb - the BB . length - the length of the query . address - the array of global addresses to query . procinfo - the usual processor info Output Parameters: . info - on exit, this array contains the query answers Returns: void Notes: The queries are symmetric in nature. If one processor queries another, it assumed that that other processor will also be querying the first processor. +*/ void BSquery_match_bb_d(BSbb_d *bb, int length, int *address, FLOAT *info, BSprocinfo *procinfo) { int i, j; BSpermutation *perm; int *proc_id; int *p_address; FLOAT *p_info; int from, size; int cur_len, cur_addr, cur_proc; int num_msg_sent; int *in_msg, *out_msg; FLOAT *in_info_msg, *out_info_msg; BSmsg_list *msg_list = NULL; MPI_Status mpi_status; void *msg_buf; GSYNC(procinfo->procset); if (length == 0) return; /* build query list */ /* these NEED to be sorted by processor, such that each processor */ /* gets only ONE list */ MY_MALLOC(proc_id,(int *),sizeof(int)*length,1); /* get processor numbers */ (*bb->map->fglobal2proc)(length,address,proc_id, procinfo,bb->map); CHKERR(0); /* allocate a permutation vector and copies of other vectors */ perm = BSalloc_permutation(length); CHKERR(0); MY_MALLOC(p_address,(int *),sizeof(int)*length,2); MY_MALLOC(p_info,(FLOAT *),sizeof(FLOAT)*length,3); /* initialize the perm. to 1 thru length and copy vectors */ for (i=0;iperm[i] = i; p_address[i] = address[i]; } /* sort vectors by address */ BSheap_sort2(length,proc_id,p_address,perm->perm); CHKERR(0); /* send query lists */ cur_addr = 0; cur_proc = proc_id[0]; cur_len = 0; num_msg_sent = 0; for (i=0;imap->fglobal2local)(size,in_msg,out_msg,procinfo,bb->map); CHKERR(0); /* free up message */ MSGFREERECV(msg_buf);CHKERR(0); /* get requested info at local addresses */ MY_MALLOC(out_info_msg,(FLOAT *),sizeof(FLOAT)*size,4+i); for (j=0;jinfo[out_msg[j]]; } MY_FREE(out_msg); /* send back info */ MY_SEND_SYNC(msg_list,BB_SA_MSG,out_info_msg,size,from, MY_MPI_FLT,procinfo); /* free up message */ MY_FREE(out_info_msg); } /* receive answers */ for (i=0;iprocset); /* build query list */ /* these NEED to be sorted by processor, such that each processor */ /* gets only ONE list */ if (length > 0) { MY_MALLOC(proc_id,(int *),sizeof(int)*length,1); /* get processor numbers */ (*bb->map->fglobal2proc)(length,address,proc_id, procinfo,bb->map); CHKERR(0); /* allocate a permutation vector and copies of other vectors */ perm = BSalloc_permutation(length); CHKERR(0); MY_MALLOC(p_address,(int *),sizeof(int)*length,2); MY_MALLOC(p_info,(FLOAT *),sizeof(FLOAT)*length,3); /* initialize the perm. to 1 thru length and copy vectors */ for (i=0;iperm[i] = i; p_address[i] = address[i]; } /* sort vectors by address */ BSheap_sort2(length,proc_id,p_address,perm->perm); CHKERR(0); /* send query lists */ cur_addr = 0; cur_proc = proc_id[0]; cur_len = 0; num_msg_sent = 0; for (i=0;iprocset); PSNbrTree(PS_LCHILD,l_child,procinfo->procset); PSNbrTree(PS_RCHILD,r_child,procinfo->procset); num_children = 0; if (l_child >= 0) num_children++; if (r_child >= 0) num_children++; num_term_msg = 0; num_real_msg = 0; sent_parent_term = FALSE; done = FALSE; while (! done ) { /* if we have all our answers and we haven't done so, tell everyone */ if ((num_real_msg == num_msg_sent) && (num_children == num_term_msg) && (sent_parent_term == FALSE)) { if (PSISROOT(procinfo)) { /* tell children */ if (l_child >= 0) { MY_SEND_SYNC(msg_list,BB_SQ_MSG,&dummy,0,l_child,MPI_INT, procinfo); } if (r_child >= 0) { MY_SEND_SYNC(msg_list,BB_SQ_MSG,&dummy,0,r_child,MPI_INT, procinfo); } done = TRUE; break; } else { /* tell parent */ MY_SEND_SYNC(msg_list,BB_SQ_MSG,&dummy,0,parent,MPI_INT, procinfo); } sent_parent_term = TRUE; } /* get either a request or an answer */ msg_avail = FALSE; while (TRUE) { type = BB_SQ_MSG; MPI_Iprobe(MPI_ANY_SOURCE,type,procinfo->procset, &msg_avail,&mpi_status); if (msg_avail) break; type = BB_SA_MSG; MPI_Iprobe(MPI_ANY_SOURCE,type,procinfo->procset, &msg_avail,&mpi_status); if (msg_avail) break; CHECK_SEND_LIST(msg_list); } if (type == BB_SQ_MSG) { /* receive a request */ RECVSYNCUNSZ(BB_SQ_MSG,msg_buf,size,MPI_INT,procinfo,mpi_status); CHKERR(0); in_msg = (int *)msg_buf; from = mpi_status.MPI_SOURCE; CHECK_SEND_LIST(msg_list); /* if empty message, then it is a termination message */ if (size == 0) { if (from == l_child) { num_term_msg++; } else if (from == r_child) { num_term_msg++; } else { /* tell children */ if (l_child >= 0) { MY_SEND_SYNC(msg_list,BB_SQ_MSG,&dummy,0,l_child, MPI_INT,procinfo); } if (r_child >= 0) { MY_SEND_SYNC(msg_list,BB_SQ_MSG,&dummy,0,r_child, MPI_INT,procinfo); } done = TRUE; } MSGFREERECV(msg_buf);CHKERR(0); } else { /* translate into local addrs */ MY_MALLOC(out_msg,(int *),sizeof(int)*size,4+i); (*bb->map->fglobal2local)(size,in_msg,out_msg,procinfo,bb->map); CHKERR(0); /* free up message */ MSGFREERECV(msg_buf);CHKERR(0); /* get requested info at local addresses */ MY_MALLOC(out_info_msg,(FLOAT *),sizeof(FLOAT)*size,4+i); for (j=0;jinfo[out_msg[j]]; } MY_FREE(out_msg); /* send back info */ MY_SEND_SYNC(msg_list,BB_SA_MSG,out_info_msg,size, from,MY_MPI_FLT,procinfo); /* free up message */ MY_FREE(out_info_msg); } } else { /* receive an answer */ RECVSYNCUNSZ(BB_SA_MSG,msg_buf,size,MY_MPI_FLT,procinfo, mpi_status); CHKERR(0); in_info_msg = (FLOAT *)msg_buf; from = mpi_status.MPI_SOURCE; CHECK_SEND_LIST(msg_list); /* find place to receive in */ for (j=0;j 0) { /* now sort the information according to the permutation */ BSperm_dvec(p_info,info,perm); CHKERR(0); /* free up work vectors */ MY_FREE(p_info); MY_FREE(p_address); MY_FREE(proc_id); BSfree_permutation(perm); CHKERR(0); } FINISH_SEND_LIST(msg_list); GSYNC(procinfo->procset); }