-
-
Save markalle/56f739c3c907e53960d22d5de2fe4bc9 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
#include <sys/time.h> | |
#include <unistd.h> | |
#include <sys/types.h> | |
#include <string.h> | |
#include <errno.h> | |
#include <mpi.h> | |
static MPI_Comm dup_of_comm_world; // for this thread | |
static void | |
randomseed() | |
{ | |
FILE *fp; | |
struct timeval tv; | |
int seed, mygrank; | |
MPI_Comm_rank(dup_of_comm_world, &mygrank); | |
if (mygrank == 0) { | |
fp = fopen("SEED.VALUE", "r"); | |
if (fp) { | |
fscanf(fp, "%d", &seed); | |
fclose(fp); | |
} else { | |
seed = -1; | |
} | |
if (seed == -1) { | |
gettimeofday(&tv, 0); | |
seed = 1000000 * tv.tv_sec + tv.tv_usec; | |
fp = fopen("SEED.VALUE", "w"); | |
fprintf(fp, "%d\n", seed); | |
fclose(fp); | |
} | |
} | |
MPI_Bcast(&seed, 1, MPI_INT, 0, dup_of_comm_world); | |
if (mygrank == 0) { | |
printf("seed value: %d\n", seed); | |
} | |
srandom(seed + mygrank); | |
} | |
static int | |
randomint(int from, int to) | |
{ | |
return random() % (to - from + 1) + from; | |
} | |
static void | |
checkerr(int status, int expected, int line, char *string) | |
{ | |
if (status != expected) { | |
printf("checkerr line %d [%d!=%d] %s\n", line, | |
status, expected, string); | |
fflush(stdout); | |
MPI_Abort(dup_of_comm_world, MPI_ERR_OTHER); | |
} | |
} | |
#ifdef NO_MAIN_JUST_THREADS | |
#define ITERTIME 1 | |
#else | |
#define ITERTIME 3 | |
#endif | |
static int myrank, nranks; | |
static MPI_Datatype ncint; /* int space */ | |
static int *winbuf; | |
static MPI_Win win; | |
static int from, to; | |
static int mesgsize; /* in bytes */ | |
static int *send_buffer; | |
static int *recv_buffer; | |
static char string[1024]; | |
static double t1; | |
static void | |
setup() { | |
int j; | |
j = randomint(1,4); | |
switch (j) { | |
case 1: | |
mesgsize = 2*sizeof(int)*randomint(1,10); | |
break; | |
case 2: | |
mesgsize = 2*sizeof(int)*randomint(1,1000); | |
break; | |
case 3: | |
mesgsize = 2*sizeof(int)*randomint(1,25000); | |
break; | |
case 4: | |
mesgsize = 2*sizeof(int)*randomint(1,125000); | |
break; | |
} | |
MPI_Bcast(&mesgsize, 1, MPI_INT, 0, dup_of_comm_world); | |
send_buffer = malloc(mesgsize); | |
recv_buffer = malloc(mesgsize); | |
if (!send_buffer || !recv_buffer) { | |
checkerr(0,1,__LINE__, "malloc failed"); | |
} | |
if (myrank == 0) { | |
printf("[mesgsize %d]\n", mesgsize); | |
fflush(stdout); | |
} | |
} | |
/* | |
* fill_buf(buf, iter, size_bytes, noncontig, accum) | |
* - iter changes the data (-1 means fill with 0's) | |
* - accum argument is there since we use a different data pattern for that | |
* check_buf(buf, from, iter, size_bytes, noncontig, accum, naccum, | |
* int synctype int line) | |
* - from is included since the data depends on who the sender was | |
* - synctype is only needed to aid in the print stmt | |
* do_get(noncontig) | |
* do_put(noncontig) | |
* do_accum(noncontig) | |
*/ | |
static void | |
fill_buf(int *buf, int iter, int size_bytes, int noncontig, int accum) { | |
int i; | |
for (i=0; i<size_bytes/sizeof(int); ++i) { | |
if (!accum) { | |
if (noncontig && i%2) { | |
buf[i] = -1; | |
} else { | |
buf[i] = myrank+iter+i; | |
} | |
} else { | |
if (noncontig && i%2) { | |
buf[i] = -1; | |
} else { | |
buf[i] = myrank; | |
} | |
} | |
if (iter == -1) { | |
buf[i] = 0; | |
} | |
} | |
} | |
// Adding an extended printout for the wrong-data case: | |
// i = index (in int *buf) where first wrong data was seen | |
// size_bytes = buffer size, not amount of data | |
// iter, noncontig, and *accum are needed to determine the expected value | |
static void | |
showbuf(int *buf, int i, | |
int iter, int size_bytes, int noncontig, int accum, int naccum) | |
{ | |
int j, expected, n, line_index; | |
n = size_bytes/sizeof(int); | |
char line[80]; // 16b | 16b | |
#define MAX_BYTES_DISPLAY 300 | |
line_index = 0; | |
strcpy(line, "-------- -------- -------- -------- | -------- -------- -------- -------- "); | |
for (j=i; j<n && j<i+MAX_BYTES_DISPLAY; ++j) { | |
if (!accum) { | |
if (!noncontig) { | |
expected = from + iter + j; | |
} else { | |
expected = (1-noncontig*(j%2))*(from+iter+j); | |
} | |
} else { | |
if (!noncontig) { | |
expected = from * naccum; | |
} else { | |
expected = (1-noncontig*(j%2))*(from*naccum); | |
} | |
} | |
sprintf(&line[line_index], "%08x", buf[j]); | |
line[line_index + 8] = ' '; | |
sprintf(&line[line_index + 38], "%08x", expected); | |
line[line_index + 38 + 8] = ' '; | |
line_index += 9; | |
if (line_index > 32) { | |
printf("%s\n", line); | |
line_index = 0; | |
strcpy(line, "-------- -------- -------- -------- | -------- -------- -------- -------- "); | |
} | |
} | |
if (line_index) { | |
printf("%s\n", line); | |
} | |
} | |
static void | |
check_buf(int *buf, int from, int iter, int size_bytes, | |
int noncontig, int accum, int naccum, int synctype, | |
int line | |
) { | |
int i, expected, n; | |
n = size_bytes/sizeof(int); | |
if (!accum) { | |
if (!noncontig) { | |
for (i=0; i<n; ++i) { | |
expected = from + iter + i; | |
if (buf[i] != expected) { | |
showbuf(buf, i, iter, size_bytes, | |
noncontig, accum, naccum); | |
sprintf(string, "wrong data, " | |
"i=%d myrank=%d " | |
"iter=%d " | |
"from=%d to=%d " | |
"synctype=%d " | |
"len-bytes=%d noncontig=%d", | |
i, myrank, iter, | |
from, to, | |
synctype, | |
mesgsize, noncontig); | |
checkerr(buf[i], expected, | |
line, string); | |
checkerr(0, 123, | |
line, string); | |
} | |
} | |
} else { | |
for (i=0; i<n; ++i) { | |
expected = (1-noncontig*(i%2))*(from+iter+i); | |
if (buf[i] != expected) { | |
showbuf(buf, i, iter, size_bytes, | |
noncontig, accum, naccum); | |
sprintf(string, "wrong data, " | |
"i=%d myrank=%d " | |
"iter=%d " | |
"from=%d to=%d " | |
"synctype=%d " | |
"len-bytes=%d noncontig=%d", | |
i, myrank, iter, | |
from, to, | |
synctype, | |
mesgsize, noncontig); | |
checkerr(buf[i], expected, | |
line, string); | |
checkerr(0, 123, | |
line, string); | |
} | |
} | |
} | |
} else { | |
if (!noncontig) { | |
for (i=0; i<n; ++i) { | |
expected = from * naccum; | |
if (buf[i] != expected) { | |
showbuf(buf, i, iter, size_bytes, | |
noncontig, accum, naccum); | |
sprintf(string, "wrong data, " | |
"i=%d myrank=%d " | |
"iter=%d " | |
"from=%d to=%d " | |
"synctype=%d " | |
"len-bytes=%d noncontig=%d", | |
i, myrank, iter, | |
from, to, | |
synctype, | |
mesgsize, noncontig); | |
checkerr(buf[i], expected, | |
line, string); | |
checkerr(0, 123, | |
line, string); | |
} | |
} | |
} else { | |
for (i=0; i<n; ++i) { | |
expected = (1-noncontig*(i%2))*(from*naccum); | |
if (buf[i] != expected) { | |
showbuf(buf, i, iter, size_bytes, | |
noncontig, accum, naccum); | |
sprintf(string, "wrong data, " | |
"i=%d myrank=%d " | |
"iter=%d " | |
"from=%d to=%d " | |
"synctype=%d " | |
"len-bytes=%d noncontig=%d", | |
i, myrank, iter, | |
from, to, | |
synctype, | |
mesgsize, noncontig); | |
checkerr(buf[i], expected, | |
line, string); | |
checkerr(0, 123, | |
line, string); | |
} | |
} | |
} | |
} | |
} | |
#define SYNC_FENCE 1 | |
#define SYNC_POST 2 | |
#define SYNC_TEST 3 | |
#define SYNC_LOCKALL 4 | |
#define SYNC_LOCK 5 | |
static void | |
report(int phase, int part, char *mesg, int noncontig, int check, | |
int iter, int synctype) | |
{ | |
char *stype; | |
MPI_Barrier(dup_of_comm_world); | |
if (t1 > 0 && myrank==0) { | |
/* for previous work */ | |
printf(" iter: %d, time: %f sec\n", iter, MPI_Wtime() - t1); | |
fflush(stdout); | |
} | |
t1 = MPI_Wtime(); | |
stype="n/a"; | |
if (synctype==SYNC_FENCE) { stype="fence"; } | |
if (synctype==SYNC_POST) { stype="post"; } | |
if (synctype==SYNC_TEST) { stype="test"; } | |
if (synctype==SYNC_LOCKALL) { stype="lockall"; } | |
if (synctype==SYNC_LOCK) { stype="lock"; } | |
if (myrank == 0) { | |
printf("phase %d part %d (%s) %s %s [st:%s]\n", | |
phase, part, mesg, | |
noncontig?"nc-int":"c-int", | |
check?"chk":"nochk", | |
stype); | |
fflush(stdout); | |
} | |
} | |
static void | |
do_get(int noncontig) | |
{ | |
int ierr, i, chunk; | |
MPI_Datatype dt; | |
int nitem, sizeitem; | |
if (noncontig) { | |
dt = ncint; | |
nitem = mesgsize / sizeof(int) / 2; | |
sizeitem = 2; | |
} else { | |
dt = MPI_INT; | |
nitem = mesgsize / sizeof(int); | |
sizeitem = 1; | |
} | |
ierr = MPI_Get(recv_buffer, nitem, dt, | |
from, 0, nitem, dt, win); | |
checkerr(ierr,MPI_SUCCESS, __LINE__, "recv failed"); | |
} | |
static void | |
do_put(int noncontig) | |
{ | |
int ierr, i, chunk; | |
MPI_Datatype dt; | |
int nitem, sizeitem; | |
if (noncontig) { | |
dt = ncint; | |
nitem = mesgsize / sizeof(int) / 2; | |
sizeitem = 2; | |
} else { | |
dt = MPI_INT; | |
nitem = mesgsize / sizeof(int); | |
sizeitem = 1; | |
} | |
ierr = MPI_Put(send_buffer, nitem, dt, | |
to, 0, nitem, dt, win); | |
checkerr(ierr,MPI_SUCCESS, __LINE__, "recv failed"); | |
} | |
static void | |
do_accum(int noncontig) | |
{ | |
int ierr, i, chunk; | |
MPI_Datatype dt; | |
int nitem, sizeitem; | |
if (noncontig) { | |
dt = ncint; | |
nitem = mesgsize / sizeof(int) / 2; | |
sizeitem = 2; | |
} else { | |
dt = MPI_INT; | |
nitem = mesgsize / sizeof(int); | |
sizeitem = 1; | |
} | |
ierr = MPI_Accumulate(send_buffer, nitem, dt, | |
to, 0, nitem, dt, MPI_SUM, win); | |
checkerr(ierr,MPI_SUCCESS, __LINE__, "recv failed"); | |
} | |
static int | |
main_test_fn(MPI_Comm comm, int tid) { | |
int i, k, nocheck, noncontig; | |
MPI_Group group_from; /* left neighbor */ | |
MPI_Group group_to; /* right neighbor */ | |
MPI_Group group_world; | |
int them; /* tmp var while creating the groups above */ | |
int synctype; /* 1 = fence, 2 = post/start, 3 = lock/unlock */ | |
double tstart, tnow, ttmp; | |
int niter; | |
int naccum_tome; | |
MPI_Type_create_resized(MPI_INT, 0, 2*sizeof(int), &ncint); | |
MPI_Type_commit(&ncint); | |
MPI_Alloc_mem(250000*sizeof(int), MPI_INFO_NULL, &winbuf); | |
MPI_Win_create(winbuf, 250000*sizeof(int), 4, | |
MPI_INFO_NULL, dup_of_comm_world, &win); | |
to = (myrank + 1) % nranks; | |
from = (myrank - 1 + nranks) % nranks; | |
setup(); | |
t1 = -1; | |
MPI_Comm_group(dup_of_comm_world, &group_world); | |
MPI_Group_incl(group_world, 1, &from, &group_from); | |
MPI_Group_incl(group_world, 1, &to, &group_to); | |
MPI_Group_free(&group_world); | |
/* | |
* Each phase below will have four parts. Each phase will contain | |
* part 1: contig ints with datachecking | |
* part 2: more iterations, contig ints no datachecking | |
* part 3: non-contig, with datachecking | |
* part 4: more iterations non-contig no datachecking | |
* Each phase is described in a comment preceeding it. | |
*/ | |
niter = 0; | |
/* | |
* Phase 5: | |
* | |
* loop iterations | |
* write to window | |
* fence | |
* get | |
* fence | |
*/ | |
for (noncontig=0; noncontig<=1; ++noncontig) { | |
for (nocheck=0; nocheck<=1; ++nocheck) { | |
for (synctype=1; synctype<=5; ++synctype) { | |
report(5, 2*noncontig+nocheck+1, | |
"loop(i){fence;get;fence}", | |
noncontig, nocheck?0:1, niter, synctype); | |
niter = 0; | |
tstart = MPI_Wtime(); | |
MPI_Bcast(&tstart, 1, MPI_DOUBLE, 0, dup_of_comm_world); | |
tnow = tstart; | |
for (i=0; tnow-tstart<=ITERTIME; ++i) { | |
++niter; | |
if (!nocheck) { | |
fill_buf(winbuf, i, mesgsize, | |
noncontig, 0); | |
fill_buf(recv_buffer, -1, mesgsize, | |
noncontig, 0); | |
} | |
if (synctype == SYNC_FENCE) { | |
MPI_Win_fence(0,win); | |
} else if (synctype == SYNC_POST) { | |
MPI_Win_post(group_to, 0, win); | |
MPI_Win_start(group_from, 0, win); | |
} else if (synctype == SYNC_TEST) { | |
MPI_Win_post(group_to, 0, win); | |
MPI_Win_start(group_from, 0, win); | |
} else if (synctype == SYNC_LOCKALL) { | |
MPI_Barrier(dup_of_comm_world); | |
MPI_Win_lock_all(0, win); | |
} else /* synctype == SYNC_LOCK */ { | |
MPI_Barrier(dup_of_comm_world); | |
MPI_Win_lock(MPI_LOCK_EXCLUSIVE,from,0,win); | |
} | |
do_get(noncontig); | |
if (synctype == SYNC_FENCE) { | |
MPI_Win_fence(0,win); | |
} else if (synctype == SYNC_POST) { | |
MPI_Win_complete(win); | |
MPI_Win_wait(win); | |
} else if (synctype == SYNC_TEST) { | |
int flag = 0; | |
MPI_Win_complete(win); | |
while (!flag) { | |
MPI_Win_test(win, &flag); | |
} | |
} else if (synctype == SYNC_LOCKALL) { | |
MPI_Win_unlock_all(win); | |
} else /* synctype == SYNC_LOCK */ { | |
MPI_Win_unlock(from,win); | |
} | |
if (!nocheck) { | |
check_buf(recv_buffer, from, i, | |
mesgsize, noncontig, 0, 0, | |
synctype, | |
__LINE__); | |
} | |
if (synctype == SYNC_LOCK || synctype == SYNC_LOCKALL) { | |
MPI_Barrier(dup_of_comm_world); | |
} | |
tnow = MPI_Wtime(); | |
MPI_Bcast(&tnow, 1, MPI_DOUBLE, 0, dup_of_comm_world); | |
} | |
}}} | |
/* | |
* Phase 6: | |
* (wanted somewhere to have a more rapidfire sequence of gets without | |
* a fence in between) | |
* | |
* write to window | |
* fence | |
* loop iterations | |
* get | |
* fence | |
*/ | |
for (noncontig=0; noncontig<=1; ++noncontig) { | |
for (nocheck=0; nocheck<=1; ++nocheck) { | |
for (synctype=1; synctype<=5; ++synctype) { | |
report(6, 2*noncontig+nocheck+1, | |
"loop(i){fence;loop(j){get};fence}", | |
noncontig, nocheck?0:1, niter, synctype); | |
niter = 0; | |
tstart = MPI_Wtime(); | |
MPI_Bcast(&tstart, 1, MPI_DOUBLE, 0, dup_of_comm_world); | |
tnow = tstart; | |
int nloops = 10; | |
for (i=0; tnow-tstart<=ITERTIME; ++i) { | |
while (tnow-tstart<=ITERTIME) { | |
if (!nocheck) { | |
fill_buf(winbuf, i, mesgsize, | |
noncontig, 0); | |
fill_buf(recv_buffer, -1, mesgsize, | |
noncontig, 0); | |
} | |
if (synctype == SYNC_FENCE) { | |
MPI_Win_fence(0,win); | |
} else if (synctype == SYNC_POST) { | |
MPI_Win_post(group_to, 0, win); | |
MPI_Win_start(group_from, 0, win); | |
} else if (synctype == SYNC_TEST) { | |
MPI_Win_post(group_to, 0, win); | |
MPI_Win_start(group_from, 0, win); | |
} else if (synctype == SYNC_LOCKALL) { | |
MPI_Barrier(dup_of_comm_world); | |
MPI_Win_lock_all(0, win); | |
} else /* synctype == SYNC_LOCK */ { | |
MPI_Barrier(dup_of_comm_world); | |
MPI_Win_lock(MPI_LOCK_EXCLUSIVE,from,0,win); | |
} | |
for (k=0; k<nloops; ++k) { | |
++niter; | |
do_get(noncontig); | |
} | |
if (synctype == SYNC_FENCE) { | |
MPI_Win_fence(0,win); | |
} else if (synctype == SYNC_POST) { | |
MPI_Win_complete(win); | |
MPI_Win_wait(win); | |
} else if (synctype == SYNC_TEST) { | |
int flag = 0; | |
MPI_Win_complete(win); | |
while (!flag) { | |
MPI_Win_test(win, &flag); | |
} | |
} else if (synctype == SYNC_LOCKALL) { | |
MPI_Win_unlock_all(win); | |
} else /* synctype == SYNC_LOCK */ { | |
MPI_Win_unlock(from,win); | |
} | |
if (!nocheck) { | |
check_buf(recv_buffer, from, i, | |
mesgsize, noncontig, 0, 0, | |
synctype, | |
__LINE__); | |
} | |
if (synctype == SYNC_LOCK || synctype == SYNC_LOCKALL) { | |
MPI_Barrier(dup_of_comm_world); | |
} | |
tnow = MPI_Wtime(); | |
MPI_Bcast(&tnow, 1, MPI_DOUBLE, 0, dup_of_comm_world); | |
} | |
if (tnow - tstart < ITERTIME/2.0) { nloops *= 2; } | |
} | |
}}} | |
/* | |
* Phase 7: | |
* | |
* loop iterations | |
* initialize window | |
* fence | |
* put | |
* fence | |
*/ | |
for (noncontig=0; noncontig<=1; ++noncontig) { | |
for (nocheck=0; nocheck<=1; ++nocheck) { | |
for (synctype=1; synctype<=5; ++synctype) { | |
report(7, 2*noncontig+nocheck+1, | |
"loop(i){fence;put;fence}", | |
noncontig, nocheck?0:1, niter, synctype); | |
niter = 0; | |
tstart = MPI_Wtime(); | |
MPI_Bcast(&tstart, 1, MPI_DOUBLE, 0, dup_of_comm_world); | |
tnow = tstart; | |
for (i=0; tnow-tstart<=ITERTIME; ++i) { | |
++niter; | |
if (!nocheck) { | |
fill_buf(winbuf, -1, mesgsize, | |
noncontig, 0); | |
fill_buf(send_buffer, i, mesgsize, | |
noncontig, 0); | |
} | |
if (synctype == SYNC_FENCE) { | |
MPI_Win_fence(0,win); | |
} else if (synctype == SYNC_POST) { | |
MPI_Win_post(group_from, 0, win); | |
MPI_Win_start(group_to, 0, win); | |
} else if (synctype == SYNC_TEST) { | |
MPI_Win_post(group_from, 0, win); | |
MPI_Win_start(group_to, 0, win); | |
} else if (synctype == SYNC_LOCKALL) { | |
MPI_Barrier(dup_of_comm_world); | |
MPI_Win_lock_all(0, win); | |
} else /* synctype == SYNC_LOCK */ { | |
MPI_Barrier(dup_of_comm_world); | |
MPI_Win_lock(MPI_LOCK_EXCLUSIVE,to,0,win); | |
} | |
do_put(noncontig); | |
if (synctype == SYNC_FENCE) { | |
MPI_Win_fence(0,win); | |
} else if (synctype == SYNC_POST) { | |
MPI_Win_complete(win); | |
MPI_Win_wait(win); | |
} else if (synctype == SYNC_TEST) { | |
int flag = 0; | |
MPI_Win_complete(win); | |
while (!flag) { | |
MPI_Win_test(win, &flag); | |
} | |
} else if (synctype == SYNC_LOCKALL) { | |
MPI_Win_unlock_all(win); | |
MPI_Barrier(dup_of_comm_world); | |
} else /* synctype == SYNC_LOCK */ { | |
MPI_Win_unlock(to,win); | |
MPI_Barrier(dup_of_comm_world); | |
} | |
if (!nocheck) { | |
check_buf(winbuf, from, i, | |
mesgsize, noncontig, 0, 0, | |
synctype, | |
__LINE__); | |
} | |
tnow = MPI_Wtime(); | |
MPI_Bcast(&tnow, 1, MPI_DOUBLE, 0, dup_of_comm_world); | |
} | |
}}} | |
/* | |
* Phase 8: | |
* | |
* initialize window | |
* fence | |
* loop iterations | |
* accum | |
* fence | |
*/ | |
for (noncontig=0; noncontig<=1; ++noncontig) { | |
for (nocheck=0; nocheck<=1; ++nocheck) { | |
for (synctype=1; synctype<=5; ++synctype) { | |
report(8, 2*noncontig+nocheck+1, | |
"fence;loop(i){accum};fence", | |
noncontig, nocheck?0:1, niter, synctype); | |
niter = 0; | |
tstart = MPI_Wtime(); | |
MPI_Bcast(&tstart, 1, MPI_DOUBLE, 0, dup_of_comm_world); | |
tnow = tstart; | |
fill_buf(winbuf, -1, mesgsize, noncontig, 1); | |
if (synctype == SYNC_FENCE) { | |
MPI_Win_fence(0,win); | |
} else if (synctype == SYNC_POST) { | |
MPI_Win_post(group_from, 0, win); | |
MPI_Win_start(group_to, 0, win); | |
} else if (synctype == SYNC_TEST) { | |
MPI_Win_post(group_from, 0, win); | |
MPI_Win_start(group_to, 0, win); | |
} else if (synctype == SYNC_LOCKALL) { | |
MPI_Barrier(dup_of_comm_world); | |
MPI_Win_lock_all(0, win); | |
} else /* synctype == SYNC_LOCK */ { | |
MPI_Barrier(dup_of_comm_world); | |
MPI_Win_lock(MPI_LOCK_EXCLUSIVE,to,0,win); | |
} | |
ttmp = MPI_Wtime(); | |
for (i=0; i==0 || (tnow-ttmp<=ITERTIME && i<1000); ++i) { | |
++niter; | |
if (!nocheck) { | |
fill_buf(send_buffer, i, mesgsize, noncontig, 1); | |
} | |
do_accum(noncontig); | |
tnow = MPI_Wtime(); | |
} | |
MPI_Send(&i, 1, MPI_INT, to, 99, dup_of_comm_world); | |
MPI_Recv(&naccum_tome, 1, MPI_INT, MPI_ANY_SOURCE, | |
MPI_ANY_TAG, dup_of_comm_world, MPI_STATUS_IGNORE); | |
if (synctype == SYNC_FENCE) { | |
MPI_Win_fence(0,win); | |
} else if (synctype == SYNC_POST) { | |
MPI_Win_complete(win); | |
MPI_Win_wait(win); | |
} else if (synctype == SYNC_TEST) { | |
int flag = 0; | |
MPI_Win_complete(win); | |
while (!flag) { | |
MPI_Win_test(win, &flag); | |
} | |
} else if (synctype == SYNC_LOCKALL) { | |
MPI_Win_unlock_all(win); | |
MPI_Barrier(dup_of_comm_world); | |
} else /* synctype == SYNC_LOCK */ { | |
MPI_Win_unlock(to,win); | |
MPI_Barrier(dup_of_comm_world); | |
} | |
if (!nocheck) { | |
check_buf(winbuf, from, i, | |
mesgsize, noncontig, 1, | |
naccum_tome, | |
synctype, | |
__LINE__); | |
} | |
tnow = MPI_Wtime(); | |
MPI_Bcast(&tnow, 1, MPI_DOUBLE, 0, dup_of_comm_world); | |
}}} | |
if (myrank==0) { | |
printf(" iter: %d, time: %f sec\n", niter, MPI_Wtime() - t1); | |
fflush(stdout); | |
} | |
if (send_buffer) { free(send_buffer); } | |
if (recv_buffer) { free(recv_buffer); } | |
MPI_Win_free(&win); | |
MPI_Free_mem(winbuf); | |
MPI_Group_free(&group_from); | |
MPI_Group_free(&group_to); | |
MPI_Type_free(&ncint); | |
return 0; | |
} | |
#ifdef NO_MAIN_JUST_THREADS | |
#define NLOOPS 10 | |
#else | |
#define NAME_OF_TEST_FN runtest | |
#define NLOOPS 2 | |
#endif | |
void | |
NAME_OF_TEST_FN(MPI_Comm comm, int tid) { | |
int i; | |
dup_of_comm_world = comm; | |
MPI_Comm_size(dup_of_comm_world, &nranks); | |
MPI_Comm_rank(dup_of_comm_world, &myrank); | |
if (tid == 0) { randomseed(); } | |
for (i=0; i<NLOOPS; ++i) { | |
main_test_fn(comm, tid); | |
} | |
} | |
#ifdef NO_MAIN_JUST_THREADS | |
#else | |
int | |
main() { | |
MPI_Init(0,0); // for single threaded version | |
NAME_OF_TEST_FN(MPI_COMM_WORLD, 0); | |
MPI_Finalize(); | |
return(0); | |
} | |
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <pthread.h> | |
#include <mpi.h> | |
MPI_Comm td1_comm, td2_comm; | |
void runtest_td1(MPI_Comm comm, int tid); | |
void runtest_td2(MPI_Comm comm, int tid); | |
void* | |
tdfunc1(void *args) { | |
runtest_td1(td1_comm, 1); | |
} | |
void* | |
tdfunc2(void *args) { | |
runtest_td2(td2_comm, 2); | |
} | |
int | |
main() { | |
int provided, myrank, nranks; | |
pthread_t tids[10]; | |
MPI_Init_thread(0,0, MPI_THREAD_MULTIPLE, &provided); | |
MPI_Comm_rank(MPI_COMM_WORLD, &myrank); | |
MPI_Comm_size(MPI_COMM_WORLD, &nranks); | |
MPI_Comm_dup(MPI_COMM_WORLD, &td1_comm); | |
MPI_Comm_dup(MPI_COMM_WORLD, &td2_comm); | |
pthread_create(&tids[0], 0, &tdfunc2, 0); | |
tdfunc1(0); | |
pthread_join(tids[0], (void**)0); | |
MPI_Comm_free(&td1_comm); | |
MPI_Comm_free(&td2_comm); | |
MPI_Finalize(); | |
printf("R%d: all tids done, exiting\n", myrank); | |
return(0); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define NO_MAIN_JUST_THREADS | |
#define NAME_OF_TEST_FN runtest_td1 | |
#include "1sided.c" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define NO_MAIN_JUST_THREADS | |
#define NAME_OF_TEST_FN runtest_td2 | |
#include "1sided.c" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment