Skip to content

Instantly share code, notes, and snippets.

@markalle
Created December 7, 2016 23:19
Show Gist options
  • Save markalle/56f739c3c907e53960d22d5de2fe4bc9 to your computer and use it in GitHub Desktop.
Save markalle/56f739c3c907e53960d22d5de2fe4bc9 to your computer and use it in GitHub Desktop.
#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
#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);
}
#define NO_MAIN_JUST_THREADS
#define NAME_OF_TEST_FN runtest_td1
#include "1sided.c"
#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