-
Notifications
You must be signed in to change notification settings - Fork 53
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #918 from davidozog/pr/teams_spec_examples
Add teams spec tests to "spec-example" directory
- Loading branch information
Showing
4 changed files
with
234 additions
and
0 deletions.
There are no files selected for viewing
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
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
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; | ||
} |
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
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; | ||
} |
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
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; | ||
} |