"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "src/mpi2.c" between
NetPIPE_4.x.tar.gz and NetPIPE-3.7.2.tar.gz

About: NetPIPE - a Network Protocol Independent Performance Evaluator

mpi2.c  (NetPIPE_4.x):mpi2.c  (NetPIPE-3.7.2)
/* Netpipe module for mpi-2 one-sided communications by Adam Oline */ /* Netpipe module for mpi-2 one-sided communications by Adam Oline */
#define USE_VOLATILE_RPTR
#include "netpipe.h" #include "netpipe.h"
#include <mpi.h> #include <mpi.h>
MPI_Win* send_win; MPI_Win win;
MPI_Win* recv_win;
void Init(ArgStruct *p, int* pargc, char*** pargv) void Init(ArgStruct *p, int* pargc, char*** pargv)
{ {
p->prot.use_get = 0; /* Default to put */ p->prot.use_get = 0; /* Default to put */
p->prot.no_fence = 0; /* Default to fence */ p->prot.no_fence = 0; /* Default to fence */
MPI_Init(pargc, pargv); MPI_Init(pargc, pargv);
} }
void Setup(ArgStruct *p) void Setup(ArgStruct *p)
skipping to change at line 51 skipping to change at line 51
/* TODO: Finish changing netpipe such that it can run with > 2 procs */ /* TODO: Finish changing netpipe such that it can run with > 2 procs */
/* 0 <--> (nprocs - 1) /* 0 <--> (nprocs - 1)
* 1 <--> (nprocs - 2) * 1 <--> (nprocs - 2)
* ... * ...
*/ */
p->tr = p->rcv = 0; p->tr = p->rcv = 0;
if (p->prot.iproc == 0) { if (p->prot.iproc == 0) {
p->tr = 1; p->tr = 1;
p->prot.nbor = nprocs-1; p->prot.nbor = nprocs-1;
p->myproc = 0;
} else if( p->prot.iproc == nprocs-1 ) { } else if( p->prot.iproc == nprocs-1 ) {
p->rcv = 1; p->rcv = 1;
p->prot.nbor = 0; p->prot.nbor = 0;
p->myproc = 1;
} }
} }
void Sync(ArgStruct *p) void Sync(ArgStruct *p)
{ {
MPI_Barrier(MPI_COMM_WORLD); MPI_Win_fence(0, win);
}
void Fence(ArgStruct *p)
{
MPI_Win_fence(0, *recv_win);
if( p->cache && p->bidir )
MPI_Win_fence(0, *send_win);
} }
void PrepareToReceive(ArgStruct *p) void PrepareToReceive(ArgStruct *p)
{ {
} }
void SendData(ArgStruct *p) void SendData(ArgStruct *p)
{ {
int buf_offset = ((p->s_ptr - p->soffset) - p->s_buff) + p->roffset; int buf_offset = 0;
if( p->prot.use_get ) {
/* First call to fence signals other proc to start get. Second call
* to fence waits for get to complete. */
MPI_Win_fence(0, *send_win); /* If we're limiting cache effects, then we need to calculate the offset
* from the beginning of the memory pool
if( !p->bidir && !p->prot.no_fence ) MPI_Win_fence(0, *send_win); */
if( !p->cache )
} else { buf_offset = p->s_ptr - p->s_buff;
if( p->prot.use_get )
MPI_Get(p->s_ptr, p->bufflen, MPI_BYTE, p->prot.nbor, buf_offset,
p->bufflen, MPI_BYTE, win);
else
MPI_Put(p->s_ptr, p->bufflen, MPI_BYTE, p->prot.nbor, buf_offset, MPI_Put(p->s_ptr, p->bufflen, MPI_BYTE, p->prot.nbor, buf_offset,
p->bufflen, MPI_BYTE, *recv_win); p->bufflen, MPI_BYTE, win);
/* If bi-directional mode, we don't need this fence, it will be if (p->prot.no_fence == 0)
* called in RecvData */ MPI_Win_fence(0, win);
if ( !p->bidir && !p->prot.no_fence ) MPI_Win_fence(0, *recv_win);
}
} }
/* MPI implementations are not required to guarantee message progress
* without a sync call so this may not work with all implementations.
*/
int TestForCompletion(ArgStruct *p)
{
if( p->r_ptr[p->bufflen-1] == (p->tr ? p->expected+1 : p->expected-1) ) {
return 1;
} else return 0;
}
void RecvData(ArgStruct *p) void RecvData(ArgStruct *p)
{ {
volatile unsigned char *cbuf = (unsigned char *) p->r_ptr; /* If user specified 'no fence' option on cmd line, then we try to bypass
* the fence call by waiting for the last byte to arrive. The MPI-2
int buf_offset = ((p->r_ptr - p->roffset) - p->r_buff) + p->soffset; * standard does not require any data to be written locally until a
* synchronization call (such as fence) occurs, however, so this may
if( p->prot.use_get ) { * hang, depending on the MPI-2 implementation. Currently works with
* MP_Lite .
/* If bi-directional or no-cache mode, we have separate windows for the */
* send and receive buffers, and for gets we need to use the send window
* (if neither mode, then send_win == recv_win) */
if( !p->bidir ) MPI_Win_fence(0, *send_win); if( p->prot.no_fence ) {
MPI_Get(p->r_ptr, p->bufflen, MPI_BYTE, p->prot.nbor, buf_offset, /* The conditional in the comparison below is necessary because we are
p->bufflen, MPI_BYTE, *send_win); * always waiting for a 'b' to arrive if in no-cache mode, but in cache
* mode the character we are waiting for depends on whether we are the
* transmitter or receiver. Adding a little complexity here helps
* us avoid more complexity elsewhere with regard to the no-cache code.
* We cannot use the same character all the time with cache mode due
* to timing issues.
*/
while(p->r_ptr[p->bufflen-1] != 'a' + (p->cache ? 1 - p->tr : 1) )
sched_yield(); /* Since we made r_ptr volatile, we don't necessarily
* need to call a function here encourage the compiler
* to reload it */
if( !p->prot.no_fence ) MPI_Win_fence(0, *send_win); p->r_ptr[p->bufflen-1] = 'a' + (p->cache ? p->tr : 0);
} else { } else {
/* Waiting for incoming MPI_Put */ MPI_Win_fence(0, win);
if( !p->prot.no_fence ) MPI_Win_fence(0, *recv_win);
}
/* If no_fence, then we forego the second call to MPI_Win_fence and instead
* try to poll on the last byte of the buffer. Since MPI implementations are
* not required to guarantee message progress without a synchronization call,
* this may stall with some implementations. */
if( p->prot.no_fence ) {
while(cbuf[p->bufflen-1] != (p->tr ? p->expected+1 : p->expected-1))
sched_yield();
} }
} }
/* Gather the times from all procs to proc 0 for output */ void SendTime(ArgStruct *p, double *t)
void Gather(ArgStruct *p, double *buf)
{ {
MPI_Gather( &buf[p->myproc], 1, MPI_DOUBLE, MPI_Send(t, 1, MPI_DOUBLE, p->prot.nbor, 2, MPI_COMM_WORLD);
buf, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
} }
/* Proc 0 sets nrepeats then broadcasts it to all procs */ void RecvTime(ArgStruct *p, double *t)
void Broadcast(ArgStruct *p, unsigned int *nrepeat)
{ {
MPI_Bcast(nrepeat, 1, MPI_INT, 0, MPI_COMM_WORLD); MPI_Status status;
}
void CleanUp(ArgStruct *p) MPI_Recv(t, 1, MPI_DOUBLE, p->prot.nbor, 2, MPI_COMM_WORLD, &status);
{
MPI_Finalize();
} }
void Reset(ArgStruct *p) void SendRepeat(ArgStruct *p, int rpt)
{ {
MPI_Send(&rpt, 1, MPI_INT, p->prot.nbor, 2, MPI_COMM_WORLD);
} }
void MyMalloc(ArgStruct *p, int bufflen) void RecvRepeat(ArgStruct *p, int *rpt)
{ {
if((p->r_buff=(char *)malloc(bufflen+MAX(p->soffset,p->roffset)))==(char *)N MPI_Status status;
ULL)
{
fprintf(stderr,"couldn't allocate memory for receive buffer\n");
exit(-1);
}
/* Allocate second buffer if flushing cache or doing bidirectional mode * MPI_Recv(rpt, 1, MPI_INT, p->prot.nbor, 2, MPI_COMM_WORLD, &status);
/
if(!p->cache || p->bidir)
if((p->s_buff=(char *)malloc(bufflen+MAX(p->soffset,p->roffset)))==(char *
)NULL)
{
fprintf(stderr,"couldn't allocate memory for send buffer\n");
exit(-1);
}
} }
void AfterAlignmentInit(ArgStruct *p) void CleanUp(ArgStruct *p)
{ {
/* After mallocs and alignment, we need to create MPI Windows */ MPI_Finalize();
recv_win = (MPI_Win*)malloc(sizeof(MPI_Win));
MPI_Win_create(p->r_buff, p->bufflen+MAX(p->soffset,p->roffset), 1, NULL,
MPI_COMM_WORLD, recv_win);
if( !p->cache || p->bidir ) {
send_win = (MPI_Win*)malloc(sizeof(MPI_Win));
MPI_Win_create(p->s_buff, p->bufflen+MAX(p->soffset,p->roffset), 1, NULL,
MPI_COMM_WORLD, send_win);
} else {
send_win = recv_win;
}
} }
void FreeBuff(char *buff1, char *buff2) void Reset(ArgStruct *p)
{ {
/* Free MPI windows */
if( recv_win != send_win ) free(send_win);
free(recv_win);
/* Free buffers */
if(buff1 != NULL)
free(buff1);
if(buff2 != NULL)
free(buff2);
} }
void ModuleSwapPtrs(ArgStruct *p) void AfterAlignmentInit(ArgStruct *p)
{ {
void* tmp; /* After mallocs and alignment, we need to create MPI Window */
tmp = send_win; MPI_Win_create(p->r_buff, p->bufflen, 1, NULL, MPI_COMM_WORLD, &win);
send_win = recv_win;
recv_win = tmp;
} }
 End of changes. 34 change blocks. 
145 lines changed or deleted 54 lines changed or added

Home  |  About  |  All  |  Newest  |  Fossies Dox  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTPS