我试图了解合并全局内存。
假设我想将一组奇数的浮点数加载到全局内存中。每个线程将处理一组 3 个浮点数。假设这些浮点数是 A、B 和 C。
A0, B0, C0
A1, B1, C1
A2, B2, C2
..
A19, B19, C19
所以线程会像这样抓取数据:
Thread 0: A0, B0, C0
Thread 1: A1, B1, C1
Thread 2: A2, B2, C2
..
Thread 19: A19, B19, C19
第一种方法:
我可以加载 3 个数组:float A[20]; float B[20]; floatC[20];
我必须 cudaMemcpy() 三个不同的时间才能将数据加载到全局内存中。这种方法可能不会很好地结合起来。
第二种方法:
更好的方法是:
struct {float A, float B, float C} dataPt;
dataPt data[20];
我可以用一个 cudaMemcpy() 加载数据,但我不确定内存访问是否会很好地合并。
第三种方法:
struct {float A, float B, float C, float padding} dataPt2;
dataPt2 data2[20];
或者
struct __align__(16){float A, float B, float C} dataPt3;
dataPt3 data3[20];
我可以使用单个 cudaMemcpy() 将数据加载到全局内存,并且线程对数据的访问将被合并。(以浪费全局内存为代价。)
1)第一种方法不会合并,因为每个线程可能需要 3 个总线周期来加载输入数据。
2) 第二种方法将合并许多线程,但会有一些线程需要两个总线周期来获取输入数据。
3)第三种方法将合并所有线程。
这是准确的吗?第二种和第三种方法之间有显着差异吗?是否有使用 3 个线程维度(threadIdx.x、threadIdx.y、threadIdx.z)的方法?