/** mpi_wait(+Handle,-Status,-Data * * Completes a non-blocking operation. IF the operation was a send, the * function waits until the message is buffered or sent by the runtime * system. At this point the send buffer is released. If the operation * was a receive, it waits until the message is copied to the receive * buffer. * . */ static YAP_Bool mpi_wait_recv(term_t YAP_ARG1,...) { YAP_Term t1 = YAP_Deref(YAP_ARG1); // data MPI_Status status; MPI_Request *handle; char *s; int ret; size_t len; YAP_Term out; // The first argument (handle) must be an integer if(!YAP_IsIntTerm(t1)) { return false; } CONT_TIMER(); handle=INT2HANDLE(YAP_IntOfTerm(t1)); s=(char*)get_request(handle); // wait for communication completion if( MPI_CALL(MPI_Wait( handle , &status )) != MPI_SUCCESS) { PAUSE_TIMER(); return false; } len=YAP_SizeOfExportedTerm(s); // make sure we only fetch ARG3 after constructing the term out = string2term(s,(size_t*)&len); MSG_RECV(len); free_request(handle); PAUSE_TIMER(); ret=YAP_Unify(YAP_ARG3,out); return(ret & YAP_Unify(YAP_ARG2,YAP_MkIntTerm(status.MPI_ERROR))); }
/* * Broadcasts a message from the process with rank "root" to * all other processes of the group. * Note: Collective communication means all processes within a communicator call the same routine. * To be able to use a regular MPI_Recv to recv the messages, one should use mpi_bcast2 * * mpi_bcast(+Root,+Data). */ static YAP_Bool mpi_bcast(term_t YAP_ARG1,...) { YAP_Term t1 = YAP_Deref(YAP_ARG1), t2 = YAP_Deref(YAP_ARG2); int root,val; size_t len=0; char *str; int rank; //The arguments should be bound if(!YAP_IsIntTerm(t1)) { return false; } MPI_CALL(MPI_Comm_rank(MPI_COMM_WORLD, &rank)); CONT_TIMER(); root = YAP_IntOfTerm(t1); if (root == rank) { str=term2string(NULL,&len,t2); #ifdef DEBUG write_msg(__FUNCTION__,__FILE__,__LINE__,"mpi_bcast(%s,%u, MPI_CHAR,%d)\n",str,len,root); #endif } else { RESET_BUFFER(); str = BUFFER_PTR; len = BLOCK_SIZE; } // send the data val=(MPI_CALL(MPI_Bcast( str, len, MPI_CHAR, root, MPI_COMM_WORLD))==MPI_SUCCESS?true:false); #ifdef MPISTATS { int size; MPI_CALL(MPI_Comm_size(MPI_COMM_WORLD, &size)); MSG_SENT(len*size); } #endif PAUSE_TIMER(); if (root != rank) { YAP_Term out; len=YAP_SizeOfExportedTerm(str); // make sure we only fetch ARG3 after constructing the term out = string2term(str,(size_t*)&len); MSG_RECV(len); if (!YAP_Unify(YAP_ARG2, out)) return false; } return(val); }
int cut_trame_in_msg(t_client *client, char *msg, int result) { int tmp; int got_one; got_one = 0; while (result > 0) { tmp = sizeof(TAG_RECV(client)) + sizeof(LEN_RECV(client)) - POS_RECV(client); if (tmp > 0) { if (result < tmp) tmp = result; memcpy(&TAG_RECV(client) + POS_RECV(client), msg, tmp); POS_RECV(client) += tmp; msg += tmp; result -= tmp; } if (result > 0 && LEN_RECV(client) > 0) { tmp = (LEN_RECV(client) * sizeof(*MSG_RECV(client))) + ((tmp < 0) ? (tmp) : (0)); if (result < tmp) tmp = result; if (!MSG_RECV(client)) MSG_RECV(client) = (char*)_net_xmalloc(sizeof(*MSG_RECV(client)) * LEN_RECV(client)); memcpy(MSG_RECV(client) + POS_RECV(client) - sizeof(TAG_RECV(client)) - sizeof(LEN_RECV(client)), msg, tmp); POS_RECV(client) += tmp; msg += tmp; result -= tmp; } if (result > 0 || (!result && POS_RECV(client) == sizeof(TAG_RECV(client)) + sizeof(LEN_RECV(client)) + (LEN_RECV(client) * sizeof(*MSG_RECV(client))))) { // message complet #ifdef NETWORK_DEBUG printf("DEBUG: GOT %d\n", TAG_RECV(client)); #endif got_one = 1; if (++client->pos_recv >= NET_MAX_MSG) client->pos_recv = 0; } } return (got_one); }
/* * Implements a blocking receive operation. * mpi_recv(?Source,?Tag,-Data). */ static YAP_Bool mpi_recv(term_t YAP_ARG1,...) { YAP_Term t1 = YAP_Deref(YAP_ARG1), t2 = YAP_Deref(YAP_ARG2), t3 = YAP_Deref(YAP_ARG3), t4; int tag, orig; int len=0; MPI_Status status; //The third argument (data) must be unbound if(!YAP_IsVarTerm(t3)) { return false; } /* The first argument (Source) must be bound to an integer (the rank of the source) or left unbound (i.e. any source is OK) */ if (YAP_IsVarTerm(t1)) orig = MPI_ANY_SOURCE; else if( !YAP_IsIntTerm(t1) ) return false; else orig = YAP_IntOfTerm(t1); /* The second argument must be bound to an integer (the tag) or left unbound (i.e. any tag is OK) */ if (YAP_IsVarTerm(t2)) tag = MPI_ANY_TAG; else if( !YAP_IsIntTerm(t2) ) return false; else tag = YAP_IntOfTerm( t2 ); CONT_TIMER(); // probe for term' size if( MPI_CALL(MPI_Probe( orig, tag, MPI_COMM_WORLD, &status )) != MPI_SUCCESS) { PAUSE_TIMER(); return false; } if( MPI_CALL(MPI_Get_count( &status, MPI_CHAR, &len )) != MPI_SUCCESS || status.MPI_TAG==MPI_UNDEFINED || status.MPI_SOURCE==MPI_UNDEFINED) { PAUSE_TIMER(); return false; } //realloc memory buffer change_buffer_size((size_t)(len+1)); BUFFER_LEN=len; // Already know the source from MPI_Probe() if( orig == MPI_ANY_SOURCE ) { orig = status.MPI_SOURCE; if( !YAP_Unify(t1, YAP_MkIntTerm(orig))) { PAUSE_TIMER(); return false; } } // Already know the tag from MPI_Probe() if( tag == MPI_ANY_TAG ) { tag = status.MPI_TAG; if( !YAP_Unify(t2, YAP_MkIntTerm(status.MPI_TAG))) { PAUSE_TIMER(); return false; } } // Receive the message as a string if( MPI_CALL(MPI_Recv( BUFFER_PTR, BUFFER_LEN, MPI_CHAR, orig, tag, MPI_COMM_WORLD, &status )) != MPI_SUCCESS ) { /* Getting in here should never happen; it means that the first package (containing size) was sent properly, but there was a glitch with the actual content! */ PAUSE_TIMER(); return false; } #ifdef DEBUG write_msg(__FUNCTION__,__FILE__,__LINE__,"%s(%s,%u, MPI_CHAR,%d,%d)\n",__FUNCTION__,BUFFER_PTR, BUFFER_LEN, orig, tag); #endif MSG_RECV(BUFFER_LEN); t4=string2term(BUFFER_PTR,&BUFFER_LEN); PAUSE_TIMER(); return(YAP_Unify(YAP_ARG3,t4)); }