SHMEM_COMPLEXF_SUM_TO_ALL(3)

πŸ“¦
version 5.0.10 Β· 4 versions
, in ubuntu stonking

✨ SHMEM_COMPLEXF_SUM_TO_ALL(3) ✨

okay so this is from the Open MPI manual, section 3, and bestie, it's a big one. we're doing sum reductions across PEs and it's giving parallel computing main character energy πŸ’…

🌸 the whole squad (NAME) 🌸

this one page covers a WHOLE friend group of routines, all (3):

  • shmem_comp4_sum_to_all
  • shmem_comp8_sum_to_all
  • shmem_complexd_sum_to_all
  • shmem_complexf_sum_to_all
  • shmem_double_sum_to_all
  • shmem_float_sum_to_all
  • shmem_int_sum_to_all
  • shmem_int4_sum_to_all
  • shmem_int8_sum_to_all
  • shmem_long_sum_to_all
  • shmem_longdouble_sum_to_all
  • shmem_longlong_sum_to_all
  • shmem_real4_sum_to_all
  • shmem_real8_sum_to_all
  • shmem_real16_sum_to_all
  • shmem_short_sum_to_all

and what do they all do?? they perform a sum reduction across a set of processing elements (PEs). iconic. no cap. 🫢


πŸŽ€ SYNOPSIS πŸŽ€

C or C++

#include <mpp/shmem.h>

void shmem_complexd_sum_to_all(double complex *target,
  const double complex *source, int nreduce, int PE_start,
  int logPE_stride, int PE_size, double complex *pWrk,
  long *pSync)

void shmem_complexf_sum_to_all(float complex *target,
  const float complex *source, int nreduce, int PE_start,
  int logPE_stride, int PE_size, float complex *pWrk,
  long *pSync)

void shmem_double_sum_to_all(double *target,
  const double *source, int nreduce, int PE_start, int logPE_stride,
  int PE_size, double *pWrk, long *pSync)

void shmem_float_sum_to_all(float *target, const float *source,
  int nreduce, int PE_start, int logPE_stride, int PE_size,
  float *pWrk, long *pSync)

void shmem_int_sum_to_all(int *target, const int *source,
  int nreduce, int PE_start, int logPE_stride, int PE_size,
  int *pWrk, long *pSync)

void shmem_long_sum_to_all(long *target, const long *source,
  int nreduce, int PE_start, int logPE_stride, int PE_size,
  long *pWrk, long *pSync)

void shmem_longdouble_sum_to_all(long double *target,
  const long double *source, int nreduce, int PE_start, int
  logPE_stride, int PE_size, long double *pWrk, long *pSync)

void shmem_longlong_sum_to_all(long long *target,
  const long long *source, int nreduce, int PE_start,
  int logPE_stride, int PE_size, long long *pWrk,
  long *pSync)

void shmem_short_sum_to_all(short *target, const short *source,
  int nreduce, int PE_start, int logPE_stride, int PE_size,
  short *pWrk, long *pSync)

Fortran

INCLUDE "mpp/shmem.fh"

INTEGER pSync(SHMEM_REDUCE_SYNC_SIZE)
INTEGER nreduce, PE_start, logPE_stride, PE_size

CALL SHMEM_COMP4_SUM_TO_ALL(target, source, nreduce,
& PE_start, logPE_stride, PE_size, pWrk, pSync)

CALL SHMEM_COMP8_SUM_TO_ALL(target, source, nreduce,
& PE_start, logPE_stride, PE_size, pWrk, pSync)

CALL SHMEM_INT4_SUM_TO_ALL(target, source, nreduce,
& PE_start, logPE_stride, PE_size, pWrk, pSync)

CALL SHMEM_INT8_SUM_TO_ALL(target, source, nreduce,
& PE_start, logPE_stride, PE_size, pWrk, pSync)

CALL SHMEM_REAL4_SUM_TO_ALL(target, source, nreduce,
& PE_start, logPE_stride, PE_size, pWrk, pSync)

CALL SHMEM_REAL8_SUM_TO_ALL(target, source, nreduce,
& PE_start, logPE_stride, PE_size, pWrk, pSync)

CALL SHMEM_REAL16_SUM_TO_ALL(target, source, nreduce,
& PE_start, logPE_stride, PE_size, pWrk, pSync)

πŸ’« DESCRIPTION πŸ’«

so the SHMEM reduction routines compute one or more reductions across symmetric arrays on multiple virtual PEs. a reduction performs an associative binary operation across a set of values. wanna see the other SHMEM reduction routines? go look at intro_shmem(3). iykyk. πŸ“š

like literally every SHMEM collective routine, each of these assumes that only PEs in the active set call the routine. if a PE that is not in the active set calls a SHMEM collective routine?? undefined behavior, bestie. we do not do that. 🚫

the nreduce argument tells you how many separate reductions to perform. the source array on all PEs in the active set hands over one element for each reduction. then the results land in the target array on all PEs in the active set. and that active set?? it's defined by the PE_start, logPE_stride, PE_size triplet. that trio is the moment. πŸ‘‘

source and target may be the same array, but they may not be overlapping arrays. periodt.

the arguments, one by one 🧚

  • target β€” the remotely accessible integer data object to be updated on the remote PE. if you're doing C/C++, the type of target should match what the SYNOPSIS says. if you're on the Fortran compiler, it must be of type integer with an element size of 4 bytes for SHMEM_INT4_ADD and 8 bytes for SHMEM_INT8_ADD.
  • value β€” the value to be atomically added to target. if you're in C/C++, the type of value should match what the SYNOPSIS says. if you're in Fortran, it must be of type integer with an element size of target.
  • pe β€” an integer that shows which PE number target gets updated on. if you're in Fortran, it must be a default integer value.
ngl bestie those last three lowkey read like they wandered in from an atomic-add page πŸ™ˆ but they're in the original, so they stay. we keep every crumb. πŸ’…
  • target β€” a symmetric array of length nreduce elements that receives the results of the reduction operations. the data type of target changes with the version of the reduction routine you call and the language you're in. calling from C/C++? check the SYNOPSIS section for data type info. calling from Fortran? the target data types go like this:
    • shmem_comp4_sum_to_all: COMPLEX(KIND=4).
    • shmem_comp8_sum_to_all: Complex. if you are using Fortran, it must be a default complex value.
    • shmem_int4_sum_to_all: INTEGER(KIND=4).
    • shmem_int8_sum_to_all: Integer. if you are using Fortran, it must be a default integer value.
    • shmem_real4_sum_to_all: REAL(KIND=4).
    • shmem_real8_sum_to_all: Real. if you are using Fortran, it must be a default real value.
    • shmem_real16_sum_to_all: Real. if you are using Fortran, it must be a default real value.
  • source β€” a symmetric array, length nreduce elements, holding one element for each separate reduction operation. source must have the same data type as target. fr fr, they gotta match. 🫢
  • nreduce β€” the number of elements in the target and source arrays. nreduce must be of type integer. if you're in Fortran, it must be a default integer value.
  • PE_start β€” the lowest virtual PE number of the active set of PEs. PE_start must be of type integer. if you're in Fortran, it must be a default integer value.
  • logPE_stride β€” the log (base 2) of the stride between consecutive virtual PE numbers in the active set. logPE_stride must be of type integer. if you're in Fortran, it must be a default integer value.
  • PE_size β€” the number of PEs in the active set. PE_size must be of type integer. if you're in Fortran, it must be a default integer value.
  • pWrk β€” a symmetric work array. pWrk must have the same data type as target. in C/C++ it contains max(nreduce/2 + 1, _SHMEM_REDUCE_MIN_WRKDATA_SIZE) elements. in Fortran it contains max(nreduce/2 + 1, SHMEM_REDUCE_MIN_WRKDATA_SIZE) elements.
  • pSync β€” a symmetric work array. in C/C++, pSync is of type long and size _SHMEM_REDUCE_SYNC_SIZE. in Fortran, pSync is of type integer and size SHMEM_REDUCE_SYNC_SIZE. it must be a default integer value. every single element of this array must be initialized with the value _SHMEM_SYNC_VALUE (in C/C++) or SHMEM_SYNC_VALUE (in Fortran) before any of the PEs in the active set enter the reduction routine. don't skip this step bestie, it's not optional. 😭

the rules of the group chat πŸ“‹

the values of nreduce, PE_start, logPE_stride, and PE_size must be equal on all PEs in the active set. and the same target and source arrays, plus the same pWrk and pSync work arrays, must be passed to all PEs in the active set. everybody on the same page or nobody moves. βœ‹

before any PE calls a reduction routine, you must make sure the following conditions exist (synchronization via a barrier or some other method is often needed to guarantee this):

  • the pWrk and pSync arrays on all PEs in the active set are not still in use from a prior call to a collective SHMEM routine.
  • the target array on all PEs in the active set is ready to accept the results of the reduction.

upon return from a reduction routine, the following are true for the local PE:

  • the target array is updated. πŸŽ‰
  • the values in the pSync array are restored to the original values. ✨

πŸ”₯ NOTES πŸ”₯

the terms collective, symmetric, and cache aligned are defined in intro_shmem(3). go read it, it's giving lore. πŸ“–

all SHMEM reduction routines reset the values in pSync before they return, so a particular pSync buffer only needs to be initialized the first time it's used. slay, one less thing.

you must ensure that the pSync array is not being updated on any PE in the active set while any of the PEs are participating in processing of a SHMEM reduction routine. be careful of these situations, bestie:

  • if the pSync array is initialized at run time, some type of synchronization is needed to ensure that all PEs in the working set have initialized pSync before any of them enter a SHMEM routine called with the pSync synchronization array.
  • a pSync or pWrk array can be reused in a subsequent reduction routine call only if none of the PEs in the active set are still processing a prior reduction routine call that used the same pSync or pWrk arrays.

in general, this can be assured only by doing some type of synchronization. however, in the special case of reduction routines being called with the same active set, you can allocate two pSync and pWrk arrays and alternate between them on successive calls. double-buffering?? we love a workaround that eats. πŸ’–


okay that's part 1 bestie, and no we are NOT done β€” there's more of this page coming, so don't go anywhere 🌈

✨ EXAMPLES ✨

okay bestie, time for the fun part β€” actual code you can stare at πŸ’–

🌸 Example 1

This Fortran example statically initializes the pSync array and finds the sum of the real variable FOO across all even PEs. (only the even ones, we're being ✨selective✨)

          INCLUDE "mpp/shmem.fh"

          INTEGER PSYNC(SHMEM_REDUCE_SYNC_SIZE)
          DATA PSYNC /SHMEM_REDUCE_SYNC_SIZE*SHMEM_SYNC_VALUE/
          PARAMETER (NR=1)
          REAL FOO, FOOSUM, PWRK(MAX(NR/2+1,SHMEM_REDUCE_MIN_WRKDATA_SIZE))
          COMMON /COM/ FOO, FOOSUM, PWRK
          INTRINSIC MY_PE

          IF ( MOD(MY_PE(),2) .EQ. 0) THEN
            CALL SHMEM_INT4_SUM_TO_ALL(FOOSUM, FOO, NR, 0, 1, N$PES/2,
            & PWRK, PSYNC)
            PRINT *, 'Result on PE ', MY_PE(), ' is ', FOOSUM
          ENDIF
notice the MOD(MY_PE(),2) .EQ. 0 vibe check β€” that's the even-PE filter, no cap 🫢

πŸ¦‹ Example 2

Now consider this C/C++ call:

          shmem_int_sum_to_all( target, source, 3, 0, 0, 8, pwrk, psync );

The preceding call is more efficient, but semantically equivalent to, the combination of the following calls:

          shmem_int_sum_to_all(&(target[0]), &(source[0]), 1, 0, 0, 8,
            pwrk1, psync1);
          shmem_int_sum_to_all(&(target[1]), &(source[1]), 1, 0, 0, 8,
            pwrk2, psync2);
          shmem_int_sum_to_all(&(target[2]), &(source[2]), 1, 0, 0, 8,
            pwrk1, psync1);
Note that two sets of pWrk and pSync arrays are used alternately because no synchronization is done between calls. like, no handshake, no "hey are you done yet", they just go πŸƒπŸ’¨ so you gotta keep them from stepping on each other's toes.

πŸ’… See also


2003-2026, The Open MPI Community


and that's a wrap, bestie πŸŽ€ this page came to you from the SHMEM_COMPLEXF_SUM_TO_ALL(3) manual, dated Sep 10, 2026, and it lives in the Open MPI collection β€” go forth and reduce, you absolute icon πŸ’–βœ¨

πŸ“¦ where this page comes from