我有一个以下形式的CUDA内核:
Void launch_kernel(..Arguments...)
{
int i = threadIdx.x
//Load required data
int temp1 = A[i];
int temp2 = A[i+1];
int temp3= A[i+2];
// compute step
int output1 = temp1 + temp2 + temp3;
int output2 = temp1 + temp3;
// Store the result
B[i] = output1;
C[i] = output2;
}
正如CUDA手册中所讨论的,GPU全局内存的一致性模型不顺序。结果,存储器操作可能看起来按照与原始程序顺序不同的顺序执行。为了强制执行内存排序,CUDA提供了__threadfence()函数。但是,根据手册,此类函数强制执行跨读取的相对排序和跨写入的相对排序。从手册中引用一行:
在调用线程的块中的所有线程都会观察到调用线程在调用__threadfence_block()之前对共享和全局内存所做的所有写操作都发生在调用线程对共享内存和全局内存的所有写入之前在调用__threadfence_block();
之后
很明显,__threadfence()不足以强制执行读写顺序。
如何跨读取和写入全局内存强制执行排序。或者,如何在执行上述内核的计算和存储部分之前确保完成所有读取保证。
答案 0 :(得分:1)
像Crovella在评论中所说,你的代码可以正常工作。
temp1,temp2和temp3是本地的(它将使用寄存器或本地存储器{每线程全局存储器})。这些不在线程之间共享,因此没有任何并发问题。它们将像普通的C / C ++一样工作。
A,B和C是全球性的。这些将受到同步问题的影响。 A仅作为只读使用,因此访问顺序并不重要。写入B和C,但每个线程只写入它自己的索引,因此它们写入的顺序并不重要。您对保证全局内存读取完成的担忧是不必要的。 在一个线程中,您的代码将按照写入的顺序执行,并具有适当的全局内存访问停顿。出于性能原因,你不会想要,但你可以做B [i] = 0; B [i] = 5; temp1 = B [i];并且temp1保证为5。
在此示例中,您不使用共享内存,但它是线程块的本地内存,您可以使用__syncthreads();
在线程块内进行同步跨不同线程块同步全局内存需要结束一个内核并开始另一个内核。 NVidia声称他们正在为youtube上的未来方向视频中的一个更好的方式工作。