Cuda 全局写入中的内存合并

Cuda 全局写入中的内存合并,cuda,gpu,gpgpu,kepler,Cuda,Gpu,Gpgpu,Kepler,在CUDA设备中,全局内存写入中的合并是否与全局内存读取中的合并一样重要?如果是,如何解释?早期的CUDA设备与最新的CUDA设备在这个问题上是否存在差异?合并写入(或缺少写入)会影响性能,就像合并读取(或缺少写入)会影响性能一样 当warp指令触发读取请求时,会发生合并读取,例如: int i = my_int_data[threadIdx.x+blockDim.x*blockIdx.x]; my_int_data[threadIdx.x+blockDim.x*blockIdx.x] = i

在CUDA设备中,全局内存写入中的合并是否与全局内存读取中的合并一样重要?如果是,如何解释?早期的CUDA设备与最新的CUDA设备在这个问题上是否存在差异?

合并写入(或缺少写入)会影响性能,就像合并读取(或缺少写入)会影响性能一样

当warp指令触发读取请求时,会发生合并读取,例如:

int i = my_int_data[threadIdx.x+blockDim.x*blockIdx.x];
my_int_data[threadIdx.x+blockDim.x*blockIdx.x] = i; 
可以通过内存控制器中的单个读取事务来满足(本质上说,所有单个线程读取都来自单个缓存线)

当warp指令触发写入请求时,会发生合并写入,例如:

int i = my_int_data[threadIdx.x+blockDim.x*blockIdx.x];
my_int_data[threadIdx.x+blockDim.x*blockIdx.x] = i; 
可以通过内存控制器中的单个写入事务来满足

对于我所展示的上述例子,在不同的世代之间没有差异

但是,还有其他类型的读或写操作可以在以后的设备中合并(即,崩溃为单个内存控制器事务),但在以前的设备中不会。一个例子是“广播读取”:

在上面的示例中,所有线程都从相同的全局位置读取。在较新的设备中,这种读取将在单个事务中“广播”到所有线程。在一些早期的设备中,这将导致线程的序列化服务。这样的例子在写操作中可能没有必然结果,因为多个线程向一个位置写操作会产生未定义的行为。但是,“加扰”写入可能会在较新的设备上合并,但不会在较旧的设备上合并:

my_int_data[(threadIdx.x+5)%32] = i;
请注意,上面的所有写操作都是唯一的(在warp中),并且属于单个缓存线,但它们不满足1.0或1.1设备上的合并要求,但应该在较新的设备上满足


如果您阅读,并与以后的设备进行比较,您将看到在早期设备上进行聚合的一些要求,这些要求在以后的设备上已经放宽了。

我们在我主持的一门课程中做了这个实验。合并在写操作中比在读操作中更为重要,这可能是因为L1和L2缓存存储了一些未使用的数据供以后使用。

合并问题在《CUDA C编程指南》(第5.3.2节)和《CUDA C最佳实践指南》(第9.2.1节)中进行了广泛讨论。这两个指南还涵盖了不同体系结构的合并问题。为了避免复制材料,如果你看一下这些文件,并张贴一些模糊的、需要澄清的要点,那会更有建设性。谢谢。您能详细解释一下写操作时缓存是如何涉及的吗?您已经指出,在联合读取事务中,“所有单个线程读取都来自单个缓存线。”因此,在写入的情况下,非联合写入占用多个二级缓存线,对吗?是的,非联合内存事务跨越多个缓存线,无论是读取还是写入。缓存本身在这里没有问题。缓存线是由内存控制器强制执行的基本交换量。