Skip to content

Commit

Permalink
Merge pull request #918 from davidozog/pr/teams_spec_examples
Browse files Browse the repository at this point in the history
Add teams spec tests to "spec-example" directory
  • Loading branch information
David Ozog authored Jun 2, 2020
2 parents 98da493 + e723937 commit 27b4120
Show file tree
Hide file tree
Showing 4 changed files with 234 additions and 0 deletions.
3 changes: 3 additions & 0 deletions test/spec-example/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,13 @@ check_PROGRAMS += \
shmemx_test_any \
shmemx_test_some \
shmemx_team_split_strided \
shmem_team_split_2D \
shmemx_team_translate \
shmem_team_context \
shmemx_team_sync \
shmemx_team_broadcast \
shmemx_team_collect \
shmem_reduce_example \
shmemx_team_alltoall \
shmemx_team_alltoalls

Expand Down
55 changes: 55 additions & 0 deletions test/spec-example/shmem_reduce_example.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* This test program is derived from an example program in the
* OpenSHMEM specification.
*/

#include <shmemx.h>
#include <shmem.h>
#include <stdio.h>
#include <stdlib.h>

#define NELEMS 32

int main(void) {
shmem_init();
int mype = shmem_my_pe();
int npes = shmem_n_pes();

int *values = shmem_malloc(NELEMS * sizeof(int));

unsigned char *value_is_maximal = shmem_malloc(NELEMS * sizeof(unsigned char));
unsigned char *value_is_maximal_all = shmem_malloc(NELEMS * sizeof(unsigned char));

static int maximal_values_count = 0;
static int maximal_values_total;

srand((unsigned)mype);

for (int i = 0; i < NELEMS; i++) {
values[i] = rand() % npes;

/* Track and count instances of maximal values (i.e., values equal to (npes-1)) */
value_is_maximal[i] = (values[i] == (npes - 1)) ? 1 : 0;
maximal_values_count += value_is_maximal[i];
}

/* Wait for all PEs to initialize reductions arrays */
shmemx_sync(SHMEMX_TEAM_WORLD);

shmemx_or_reduce(SHMEMX_TEAM_WORLD, value_is_maximal_all, value_is_maximal, NELEMS);
shmemx_sum_reduce(SHMEMX_TEAM_WORLD, &maximal_values_total, &maximal_values_count, 1);

if (mype == 0) {
printf("Found %d maximal random numbers across all PEs.\n", maximal_values_total);
printf("A maximal number occured (at least once) at the following indices:\n");
for (int i = 0; i < NELEMS; i++) {
if (value_is_maximal_all[i] == 1) {
printf("%d ", i);
}
}
printf("\n");
}

shmem_finalize();
return 0;
}
107 changes: 107 additions & 0 deletions test/spec-example/shmem_team_context.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/*
* This test program is derived from an example program in the
* OpenSHMEM specification.
*/

#include <shmemx.h>
#include <shmem.h>
#include <stdio.h>


int main(void)
{
static int sum = 0, val_2, val_3;
shmemx_team_t team_2, team_3;
shmem_ctx_t ctx_2, ctx_3;
shmemx_team_config_t conf;

shmem_init();

int npes = shmem_n_pes();
int mype = shmem_my_pe();
conf.num_contexts = 1;
long cmask = SHMEMX_TEAM_NUM_CONTEXTS;

/* Create team_2 with PEs numbered 0, 2, 4, ... */
int ret = shmemx_team_split_strided(SHMEMX_TEAM_WORLD, 0, 2, (npes + 1) / 2, &conf, cmask, &team_2);

if (ret != 0) {
printf("%d: Error creating team team_2 (%d)\n", mype, ret);
shmem_global_exit(ret);
}

/* Create team_3 with PEs numbered 0, 3, 6, ... */
ret = shmemx_team_split_strided(SHMEMX_TEAM_WORLD, 0, 3, (npes + 2) / 3, &conf, cmask, &team_3);

if (ret != 0) {
printf("%d: Error creating team team_3 (%d)\n", mype, ret);
shmem_global_exit(ret);
}

/* Create a context on team_2. */
ret = shmemx_team_create_ctx(team_2, 0, &ctx_2);

if (ret != 0 && team_2 != SHMEMX_TEAM_INVALID) {
printf("%d: Error creating context ctx_2 (%d)\n", mype, ret);
shmem_global_exit(ret);
}

/* Create a context on team_3. */
ret = shmemx_team_create_ctx(team_3, 0, &ctx_3);

if (ret != 0 && team_3 != SHMEMX_TEAM_INVALID) {
printf("%d: Error creating context ctx_3 (%d)\n", mype, ret);
shmem_global_exit(ret);
}

/* Within each team, put my PE number to my neighbor in a ring-based manner. */
if (ctx_2 != SHMEMX_CTX_INVALID) {
int pe = shmemx_team_my_pe(team_2);
shmem_ctx_int_put(ctx_2, &val_2, &pe, 1, (pe + 1) % shmemx_team_n_pes(team_2));
}

if (ctx_3 != SHMEMX_CTX_INVALID) {
int pe = shmemx_team_my_pe(team_3);
shmem_ctx_int_put(ctx_3, &val_3, &pe, 1, (pe + 1) % shmemx_team_n_pes(team_3));
}

/* Quiet both contexts and synchronize all PEs to complete the data transfers. */
shmem_ctx_quiet(ctx_2);
shmem_ctx_quiet(ctx_3);
shmemx_team_sync(SHMEMX_TEAM_WORLD);

/* Sum the values among PEs that are in both team_2 and team_3 on PE 0 with ctx_2. */
if (team_3 != SHMEMX_TEAM_INVALID && team_2 != SHMEMX_TEAM_INVALID)
shmem_ctx_int_atomic_add(ctx_2, &sum, val_2 + val_3, 0);

/* Quiet the context and synchronize PEs to complete the operation. */
shmem_ctx_quiet(ctx_2);
shmemx_team_sync(SHMEMX_TEAM_WORLD);

/* Validate the result. */
if (mype == 0) {
int vsum = 0;
for (int i = 0; i < npes; i ++) {
if (i % 2 == 0 && i % 3 == 0) {
vsum += ((i - 2) < 0) ? shmemx_team_n_pes(team_2) - 1 :
shmemx_team_translate_pe(SHMEMX_TEAM_WORLD, i - 2, team_2);
vsum += ((i - 3) < 0) ? shmemx_team_n_pes(team_3) - 1 :
shmemx_team_translate_pe(SHMEMX_TEAM_WORLD, i - 3, team_3);
}
}
if (sum != vsum) {
fprintf(stderr, "Unexpected result, npes = %d, vsum = %d, sum = %d\n", shmem_n_pes(), vsum, sum);
shmem_global_exit(1);
}
}

/* Destroy contexts before teams. */
shmem_ctx_destroy(ctx_2);
shmemx_team_destroy(team_2);

shmem_ctx_destroy(ctx_3);
shmemx_team_destroy(team_3);

shmem_finalize();
return 0;
}
69 changes: 69 additions & 0 deletions test/spec-example/shmem_team_split_2D.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* This test program is derived from an example program in the
* OpenSHMEM specification.
*/

#include <shmemx.h>
#include <shmem.h>
#include <stdio.h>
#include <math.h>

/* Find x and y such that x * y == npes and abs(x - y) is minimized. */
static void find_xy_dims(int npes, int *x, int *y) {
for(int divider = ceil(sqrt(npes)); divider >= 1; divider--)
if (npes % divider == 0) {
*x = divider;
*y = npes / divider;
return;
}
}

/* Find x, y, and z such that x * y * z == npes and
* abs(x - y) + abs(x - z) + abs(y - z) is minimized. */
static void find_xyz_dims(int npes, int *x, int *y, int *z) {
for(int divider = ceil(cbrt(npes)); divider >= 1; divider--)
if (npes % divider == 0) {
*x = divider;
find_xy_dims(npes / divider, y, z);
return;
}
}

int main(void) {
int xdim, ydim, zdim;

shmem_init();
int mype = shmem_my_pe();
int npes = shmem_n_pes();

find_xyz_dims(npes, &xdim, &ydim, &zdim);

if (shmem_my_pe() == 0) printf("xdim = %d, ydim = %d, zdim = %d\n", xdim, ydim, zdim);

shmemx_team_t xteam, yzteam, yteam, zteam;

shmemx_team_split_2d(SHMEMX_TEAM_WORLD, xdim, NULL, 0, &xteam, NULL, 0, &yzteam);
// yzteam is immediately ready to be used in collectives
shmemx_team_split_2d(yzteam, ydim, NULL, 0, &yteam, NULL, 0, &zteam);

// We don't need the yzteam anymore
shmemx_team_destroy(yzteam);

int my_x = shmemx_team_my_pe(xteam);
int my_y = shmemx_team_my_pe(yteam);
int my_z = shmemx_team_my_pe(zteam);

for (int zdx = 0; zdx < zdim; zdx++) {
for (int ydx = 0; ydx < ydim; ydx++) {
for (int xdx = 0; xdx < xdim; xdx++) {
if ((my_x == xdx) && (my_y == ydx) && (my_z == zdx)) {
printf("(%d, %d, %d) is mype = %d\n", my_x, my_y, my_z, mype);
}
shmemx_team_sync(SHMEMX_TEAM_WORLD);
}
}
}

shmem_finalize();
return 0;
}

0 comments on commit 27b4120

Please sign in to comment.