diff --git a/content/shmem_ctx_get_team.tex b/content/shmem_ctx_get_team.tex index 68a0ea8e4..0797d9349 100644 --- a/content/shmem_ctx_get_team.tex +++ b/content/shmem_ctx_get_team.tex @@ -36,15 +36,4 @@ Zero on success; otherwise, nonzero. } -\begin{apiexamples} - - \apicexample - {The following example demonstrates the use of contexts for multiple teams in a - \Cstd[11] program. This example shows contexts being used to communicate within - a team using team \ac{PE} numbers, and across teams using translated \ac{PE} numbers.} - {./example_code/shmem_team_context.c} - {} - -\end{apiexamples} - \end{apidefinition} diff --git a/content/shmem_reductions.tex b/content/shmem_reductions.tex index 7c738a0bb..bacf39fa6 100644 --- a/content/shmem_reductions.tex +++ b/content/shmem_reductions.tex @@ -315,10 +315,12 @@ \begin{apiexamples} \apicexample - {This \Cstd[11] reduction example gets integers from an external - source (random generator in this example), tests to see if the \ac{PE} got a valid - value, and outputs the sum of values for which all \acp{PE} got a valid - value.} + {In the following \Cstd[11] example, each \ac{PE} intializes an array of + random integers with values between $0$ and $npes-1$, inclusively. An OR + reduction then tracks the array indices where maximal values occur (maximal + values equal $npes - 1$), and a SUM reduction counts the total number of + maximal values across all PEs. + } {./example_code/shmem_reduce_example.c} {} diff --git a/content/shmem_team_create_ctx.tex b/content/shmem_team_create_ctx.tex index 6f626a6e6..7ebc49c69 100644 --- a/content/shmem_team_create_ctx.tex +++ b/content/shmem_team_create_ctx.tex @@ -59,7 +59,12 @@ } \begin{apiexamples} - See example in Section \ref{subsec:shmem_ctx_get_team} + \apicexample + {The following example demonstrates the use of contexts for multiple teams in a + \Cstd[11] program. This example shows contexts being used to communicate within + a team using team \ac{PE} numbers, and across teams using translated \ac{PE} numbers.} + {./example_code/shmem_team_context.c} + {} \end{apiexamples} \end{apidefinition} diff --git a/example_code/shmem_reduce_example.c b/example_code/shmem_reduce_example.c index 7d5b28b16..9e025c9d7 100644 --- a/example_code/shmem_reduce_example.c +++ b/example_code/shmem_reduce_example.c @@ -2,52 +2,46 @@ #include #include -/* As if we receive some value from external source */ -long recv_a_value(unsigned seed, int npes) { - srand(seed); - return rand() % npes; -} - -/* Validate the value we recieved */ -unsigned char is_valid(long value, int npes) { - if (value == (npes - 1)) - return 0; - return 1; -} +#define NELEMS 32 int main(void) { shmem_init(); int mype = shmem_my_pe(); int npes = shmem_n_pes(); - size_t num = 32; - long *values = shmem_malloc(num * sizeof(long)); - long *sums = shmem_malloc(num * sizeof(long)); + int *values = shmem_malloc(NELEMS * sizeof(int)); - unsigned char *valid_me = shmem_malloc(num * sizeof(unsigned char)); - unsigned char *valid_all = shmem_malloc(num * sizeof(unsigned char)); + unsigned char *value_is_maximal = shmem_malloc(NELEMS * sizeof(unsigned char)); + unsigned char *value_is_maximal_all = shmem_malloc(NELEMS * sizeof(unsigned char)); - values[0] = recv_a_value((unsigned)mype, npes); - valid_me[0] = is_valid(values[0], npes); + static int maximal_values_count = 0; + static int maximal_values_total; - for (int i = 1; i < num; i++) { - values[i] = recv_a_value((unsigned)values[i - 1], npes); - valid_me[i] = is_valid(values[i], npes); + 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 */ shmem_sync(SHMEM_TEAM_WORLD); - shmem_and_reduce(SHMEM_TEAM_WORLD, valid_all, valid_me, num); - shmem_sum_reduce(SHMEM_TEAM_WORLD, sums, values, num); + shmem_or_reduce(SHMEM_TEAM_WORLD, value_is_maximal_all, value_is_maximal, NELEMS); + shmem_sum_reduce(SHMEM_TEAM_WORLD, &maximal_values_total, &maximal_values_count, 1); - for (int i = 0; i < num; i++) { - if (valid_all[i]) { - printf("[%d] = %ld\n", i, sums[i]); - } - else { - printf("[%d] = invalid on one or more pe\n", i); + 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(); diff --git a/example_code/shmem_team_context.c b/example_code/shmem_team_context.c index 0e3559946..331b323df 100644 --- a/example_code/shmem_team_context.c +++ b/example_code/shmem_team_context.c @@ -1,106 +1,100 @@ #include #include -int isum, ival; -int my_ctx_translate_pe(shmem_ctx_t src_ctx, int src_pe, shmem_ctx_t dest_ctx) { - if (src_ctx == SHMEM_CTX_INVALID) { - return -1; - } - if (dest_ctx == SHMEM_CTX_INVALID) { - return -1; - } +int main(void) +{ + static int sum = 0, val_2, val_3; + shmem_team_t team_2, team_3; + shmem_ctx_t ctx_2, ctx_3; + shmem_team_config_t conf; - shmem_team_t src_team, dest_team; - shmem_ctx_get_team(src_ctx, &src_team); - shmem_ctx_get_team(dest_ctx, &dest_team); - return shmem_team_translate_pe(src_team, src_pe, dest_pe); -} + shmem_init(); -shmem_ctx_t my_team_create_ctx(shmem_team_t team) { - if (team == SHMEM_TEAM_INVALID) { - return SHMEM_CTX_INVALID; - } + int npes = shmem_n_pes(); + int mype = shmem_my_pe(); + conf.num_contexts = 1; + long cmask = SHMEM_TEAM_NUM_CONTEXTS; - shmem_ctx_t ctx; - if (shmem_team_create_ctx(team, 0, &ctx) != 0) { - fprintf(stderr, "Failed to create context for PE team\n"); - return SHMEM_CTX_INVALID; - } - return ctx; -} + /* Create team_2 with PEs numbered 0, 2, 4, ... */ + int ret = shmem_team_split_strided(SHMEM_TEAM_WORLD, 0, 2, (npes + 1) / 2, &conf, cmask, &team_2); -void my_send_to_neighbor(shmem_ctx_t ctx, int *val) { - if (ctx == SHMEM_CTX_INVALID) { - fprintf(stderr, "Send to neighbor fail due to invalid context\n"); - return; + if (ret != 0) { + printf("%d: Error creating team team_2 (%d)\n", mype, ret); + shmem_global_exit(ret); } - shmem_team_t team; - shmem_ctx_get_team(ctx, &team); - int team_mype = shmem_team_my_pe(team); - int team_npes = shmem_team_n_pes(team); - int rpe = (team_mype + 1) % team_npes; + /* Create team_3 with PEs numbered 0, 3, 6, ... */ + ret = shmem_team_split_strided(SHMEM_TEAM_WORLD, 0, 3, (npes + 2) / 3, &conf, cmask, &team_3); - // put my pe number in the buffer on my right hand neighbor - shmem_ctx_int_put(ctx, val, &pe, 1, rpe); -} + if (ret != 0) { + printf("%d: Error creating team team_3 (%d)\n", mype, ret); + shmem_global_exit(ret); + } -int main() { - shmem_init(); + /* Create a context on team_2. */ + ret = shmem_team_create_ctx(team_2, 0, &ctx_2); - int npes = shmem_n_pes(); - isum = 0; + if (ret != 0 && team_2 != SHMEM_TEAM_INVALID) { + printf("%d: Error creating context ctx_2 (%d)\n", mype, ret); + shmem_global_exit(ret); + } - shmem_team_t team_2s, team_3s; - shmem_ctx_t ctx_2s, ctx_3s; - shmem_team_config_t conf = {.num_contexts = 1}; - long cmask = SHMEM_TEAM_NUM_CONTEXTS; + /* Create a context on team_3. */ + ret = shmem_team_create_ctx(team_3, 0, &ctx_3); - // Create team with PEs numbered 0, 2, 4, ... - shmem_team_spit_strided(SHMEM_TEAM_WORLD, 0, 2, npes / 2, &conf, cmask, &team_2s); - // Create team with PEs numbered 0, 3, 6, ... - shmem_team_split_strided(SHMEM_TEAM_WORLD, 0, 3, npes / 3, &conf, cmask, &team_3s); + if (ret != 0 && team_3 != SHMEM_TEAM_INVALID) { + printf("%d: Error creating context ctx_3 (%d)\n", mype, ret); + shmem_global_exit(ret); + } - ctx_2s = my_team_create_ctx(team_2s); - ctx_3s = my_team_create_ctx(team_3s); + /* Within each team, put my PE number to my neighbor in a ring-based manner. */ + if (ctx_2 != SHMEM_CTX_INVALID) { + int pe = shmem_team_my_pe(team_2); + shmem_ctx_int_put(ctx_2, &val_2, &pe, 1, (pe + 1) % shmem_team_n_pes(team_2)); + } - // Send some values using the two team contexts contexts - my_send_to_neighbor(ctx_2s, &ival2); - my_send_to_neighbor(ctx_3s, &ival3); + if (ctx_3 != SHMEM_CTX_INVALID) { + int pe = shmem_team_my_pe(team_3); + shmem_ctx_int_put(ctx_3, &val_3, &pe, 1, (pe + 1) % shmem_team_n_pes(team_3)); + } - // Quiet all contexts and synchronize all PEs to complete the data transfers - shmem_ctx_quiet(ctx_2s); - shmem_ctx_quiet(ctx_3s); + /* Quiet both contexts and synchronize all PEs to complete the data transfers. */ + shmem_ctx_quiet(ctx_2); + shmem_ctx_quiet(ctx_3); shmem_team_sync(SHMEM_TEAM_WORLD); - // We will add up some results on pe 4 of team_3s using ctx_2s - if ((team_3s != SHMEM_TEAM_INVALID) && (team_2s != SHMEM_TEAM_INVALID)) { - int pe4_of_3s_in_2s = my_ctx_translate_pe(ctx_3s, 4, ctx_2s); - - if (pe4_of_3s_in_2s < 0) { - fprintf(stderr, "Fail to translate pe 4 from 3s context to 2s context\n"); - } - else { - // Add up the results on pe 4 of the 3s team, using the 2s team context - shmem_ctx_int_atomic_add(ctx_2s, &isum, ival2 + ival3, pe4_of_3s_in_2s); - } - } + /* Sum the values among PEs that are in both team_2 and team_3 on PE 0 with ctx_2. */ + if (team_3 != SHMEM_TEAM_INVALID && team_2 != SHMEM_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_2s); + /* Quiet the context and synchronize PEs to complete the operation. */ + shmem_ctx_quiet(ctx_2); shmem_team_sync(SHMEM_TEAM_WORLD); - if (shmem_team_my_pe(team_3s) == 4) { - printf("The total value on PE 4 of the 3s team is %d\n", isum); + /* 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) ? shmem_team_n_pes(team_2) - 1 : + shmem_team_translate_pe(SHMEM_TEAM_WORLD, i - 2, team_2); + vsum += ((i - 3) < 0) ? shmem_team_n_pes(team_3) - 1 : + shmem_team_translate_pe(SHMEM_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_2s); - shmem_team_destroy(team_2s); + /* Destroy contexts before teams. */ + shmem_ctx_destroy(ctx_2); + shmem_team_destroy(team_2); - shmem_ctx_destroy(ctx_3s); - shmem_team_destroy(team_3s); + shmem_ctx_destroy(ctx_3); + shmem_team_destroy(team_3); shmem_finalize(); return 0;