C++ CUDA循环中的空间局部性

C++ CUDA循环中的空间局部性,c++,performance,cuda,unified-memory,C++,Performance,Cuda,Unified Memory,我在读CUDA更简单的介绍,我在想这样的例子: __global__ void add(int n, float *x, float *y) { int index = threadIdx.x; int stride = blockDim.x; for (int i = index; i < n; i += stride) y[i] = x[i] + y[i]; } \u全局__ 无效添加(整数n,浮点*x,浮点*y) { int index=threadIdx.

我在读CUDA更简单的介绍,我在想这样的例子:

__global__
void add(int n, float *x, float *y)
{
  int index = threadIdx.x;
  int stride = blockDim.x;
  for (int i = index; i < n; i += stride)
      y[i] = x[i] + y[i];
}
\u全局__
无效添加(整数n,浮点*x,浮点*y)
{
int index=threadIdx.x;
int-stride=blockDim.x;
for(int i=指数;i
其中每个线程在数组中移动。在普通的CPU计算中,人们更愿意将阵列分割成连续的子阵列,这些子阵列在线程之间进行分割,以便它们能够更好地利用空间局部性

这个概念也适用于CUDA的统一内存吗?我想了解在这种情况下最有效的方法是什么。

a有利于内存访问的原因是它促进了内存访问。简言之,合并访问意味着在任何给定的读或写周期/操作上(被认为是扭曲范围),中的相邻线程正在访问内存中的相邻位置

“栅格跨步循环”(grid stride loop)跨扭曲排列索引以提升此图案

这与内存是使用“普通”设备分配器(例如
cudamaloc
)还是“统一”分配器(例如
cudamalocmanaged
)分配的是正交的。在这两种情况下,设备代码访问此类分配的最佳方式是使用联合访问

您没有询问它,但它也有一个“最佳访问模式”,其中包括warp中的相邻线程访问(共享)内存中的相邻位置。

a有利于内存访问的原因是它促进了。简言之,合并访问意味着在任何给定的读或写周期/操作上(被认为是扭曲范围),中的相邻线程正在访问内存中的相邻位置

“栅格跨步循环”(grid stride loop)跨扭曲排列索引以提升此图案

这与内存是使用“普通”设备分配器(例如
cudamaloc
)还是“统一”分配器(例如
cudamalocmanaged
)分配的是正交的。在这两种情况下,设备代码访问此类分配的最佳方式是使用联合访问


您没有问过它,但它也有一个“最佳访问模式”,其中包括warp中的相邻线程访问(共享)内存中的相邻位置。

虽然NVIDIA称它们为“线程”,但这是一个误称。您应该将CUDA线程视为SIMD向量处理单元的通道。那么这个模式就更有意义了。这就是说,这种类比并不适用于所有级别,因此他们称之为SIMT。CUDA支持SIMD类型,如每个线程内的float4,作为较小的并行化方法(这可以减少内存密集型内核的内存事务数)。虽然NVIDIA称之为“线程”,但这是一种误称。您应该将CUDA线程视为SIMD向量处理单元的通道。那么这个模式就更有意义了。这就是说,这种类比并不适用于所有级别,因此他们称之为SIMT。CUDA也支持SIMD类型,如每个线程内的float4,作为较小的并行化方法(这可以减少内存密集型内核的内存事务数)。这个答案中的一个非常重要的概念是32个线程的扭曲,这个答案中的一个非常重要的概念是32条线程的扭曲,它可以被认为是同时执行的。