18.2.27. shmem_collect64
shmem_collect4(3), shmem_collect8(3), shmem_collect32(3), shmem_collect64(3), shmem_fcollect(3), shmem_fcollect4(3), shmem_fcollect8(3), shmem_fcollect32(3), shmem_fcollect64(3) - 将来自多个处理单元(PEs)的数据块连接至每个PE的数组中
18.2.27.1. 概述
C或C++:
#include <mpp/shmem.h>
void shmem_collect32(void *target, const void *source,
size_t nelems, int PE_start, int logPE_stride, int PE_size,
long *pSync)
void shmem_collect64(void *target, const void *source,
size_t nelems, int PE_start, int logPE_stride, int PE_size,
long *pSync)
void shmem_fcollect32(void *target, const void *source,
size_t nelems, int PE_start, int logPE_stride, int PE_size,
long *pSync)
void shmem_fcollect64(void *target, const void *source,
size_t nelems, int PE_start, int logPE_stride, int PE_size,
long *pSync)
Fortran语言:
INCLUDE "mpp/shmem.fh"
INTEGER nelems
INTEGER PE_start, logPE_stride, PE_size
INTEGER pSync(SHMEM_COLLECT_SYNC_SIZE)
CALL SHMEM_COLLECT4(target, source, nelems, PE_start,
& logPE_stride, PE_size, pSync)
CALL SHMEM_COLLECT8(target, source, nelems, PE_start,
& logPE_stride, PE_size, pSync)
CALL SHMEM_FCOLLECT4(target, source, nelems, PE_start,
& logPE_stride, PE_size, pSync)
CALL SHMEM_FCOLLECT8(target, source, nelems, PE_start,
& logPE_stride, PE_size, pSync)
18.2.27.2. 描述
共享内存(SHMEM)的collect和fcollect例程将来自源数组的nelems个64位或32位数据项,按照处理器编号顺序,在由PE_start、log2PE_stride和PE_size定义的PE集合上进行拼接,存入目标数组。生成的目标数组首先包含来自PE PE_start的贡献,其次是PE PE_start + PE_stride的贡献,依此类推。收集的结果会被写入活动集中所有PE的目标数组。
fcollect例程要求所有参与的PE中nelems的值必须相同,而collect例程则允许nelems在不同PE之间变化。
生成的目标数组如下:
----------------------------------------------------------
source(1..nelems)
from PE (PE_start + 0 * (2**logPE_stride))
----------------------------------------------------------
source(1..nelems)
from PE (PE_start + 1 * (2**logPE_stride))
----------------------------------------------------------
...
----------------------------------------------------------
source(1..nelems) from
PE (PE_start + (PE_size - 1) * (2**logPE_stride))
----------------------------------------------------------
与所有SHMEM集合例程一样,这些例程都假定只有活动集中的PE会调用该例程。如果不在活动集中的PE调用了SHMEM集合例程,将导致未定义行为。
参数如下:
- target
一个对称数组。目标参数必须足够大以容纳所有PE上源数组的拼接。数据类型如下:
- [shmem_collect8, shmem_collect64, shmem_fcollect8, and
shmem_fcollect64] 允许任何元素大小为64位的数据类型。不允许使用Fortran派生类型、Fortran字符类型以及C/C++结构体。
- [shmem_collect4, shmem_collect32, shmem_fcollect4, and
shmem_fcollect32] 任何元素大小为32位的数据类型。不允许使用Fortran派生类型、Fortran字符类型和C/C++结构体。
- source
一个对称的数据对象,可以是目标参数允许的任何类型。
- nelems
源数组中的元素数量。nelems 必须是整数类型。如果使用 Fortran,它必须是一个默认整数值。
- PE_start
活动PE集合中的最低虚拟PE编号。PE_start必须为整数类型。如果使用Fortran,则必须为默认整数值。
- logPE_stride
活动集中连续虚拟PE编号之间跨度的对数(以2为底)。logPE_stride必须是整数类型。如果使用Fortran,则必须为默认整数值。
- PE_size
活动集中的PE数量。PE_size必须为整数类型。如果使用Fortran,它必须是一个默认的整数值。
- pSync
一个对称工作数组。在C/C++中,pSync必须是int类型且大小为_SHMEM_COLLECT_SYNC_SIZE。在Fortran中,pSync必须是integer类型且大小为SHMEM_COLLECT_SYNC_SIZE。如果使用Fortran,它必须是默认整数值。在活动集中的任何PE进入shmem_barrier()之前,该数组的每个元素都必须初始化为C/C++中的_SHMEM_SYNC_VALUE或Fortran中的SHMEM_SYNC_VALUE值。
参数PE_start、logPE_stride和PE_size的值必须在活动集中的所有PE上保持一致。相同的目标数组、源数组以及相同的pSync工作数组必须传递给活动集中的所有PE。
从集体例程返回后,本地PE将满足以下条件:目标数组已更新。pSync数组中的值已恢复为原始值。
18.2.27.3. 注意事项
术语"collective"(集体)和"symmetric"(对称)在intro_shmem(3)中有定义。 所有SHMEM集体例程在返回前都会重置pSync中的值,因此特定的pSync缓冲区只需在首次使用时初始化即可。
必须确保在活动集中的任何PE参与处理SHMEM集合例程时,pSync数组不会被任何PE更新。需特别注意避免以下情况:如果pSync数组在运行时初始化,需要通过某种同步机制确保工作集中的所有PE在调用使用该pSync同步数组的SHMEM例程前,都已初始化pSync数组。只有当活动集中没有PE仍在处理先前使用相同pSync数组的SHMEM集合例程调用时,该pSync数组才能在后续SHMEM集合例程中重复使用。通常,这只能通过某种同步机制来保证。但在特殊情况下,当使用相同活动集调用SHMEM例程时,可以分配两个pSync数组并在连续调用中交替使用它们。
集合操作在非2的幂次方PE规模的活跃PE集上运行时会有一定的性能下降。当元素数量nelems为非2的幂次方值时,这些操作不会出现性能下降。
18.2.27.4. 示例
C/C++:
for (i=0; i < _SHMEM_COLLECT_SYNC_SIZE; i++) {
pSync[i] = _SHMEM_SYNC_VALUE;
}
shmem_barrier_all(); /* Wait for all PEs to initialize pSync */
shmem_collect32(target, source, 64, pe_start, logPE_stride,
pe_size, pSync);
Fortran语言:
INTEGER PSYNC(SHMEM_COLLECT_SYNC_SIZE)
DATA PSYNC /SHMEM_COLLECT_SYNC_SIZE*SHMEM_SYNC_VALUE/
CALL SHMEM_COLLECT4(TARGET, SOURCE, 64, PE_START,
& LOGPE_STRIDE, PE_SIZE, PSYNC)
另请参阅
intro_shmem(3)