我正在使用AMD Radeon HD 7700 GPU。我想使用以下内核来验证波前大小是否为64。
__kernel
void kernel__test_warpsize(
__global T* dataSet,
uint size
)
{
size_t idx = get_global_id(0);
T value = dataSet[idx];
if (idx<size-1)
dataSet[idx+1] = value;
}
在主程序中,我传递一个包含128个元素的数组。初始值是dataSet [i] = i。在内核之后,我期望以下值: 数据集[0] = 0 数据集[1] = 0 数据集[2] = 1 ... 数据集[63] = 62 数据集[64] = 63 数据集[65] = 63 数据集[66] = 65 ... 数据集[127] = 126
但是,我发现dataSet [65]是64,而不是63,这不是我的期望。
我的理解是第一个wavefront(64个线程)应该将dataSet [64]更改为63.因此,当执行第二个wavefront时,线程#64应该得到63并将其写入dataSet [65]。但是我看到dataSet [65]仍然是64.为什么?
答案 0 :(得分:1)
您正在调用未定义的行为。如果你想访问内存,工作组中的另一个线程正在编写,你必须使用障碍。
另外假设GPU一次运行2个波前。然后dataSet [65]确实包含正确的值,第一个波前尚未完成。
根据规范,所有项目的输出也是0的有效结果。这是因为一切都可以完全连续进行。这就是你需要障碍的原因。
根据您的评论我编辑了这部分:
安装http://developer.amd.com/tools-and-sdks/heterogeneous-computing/codexl/ 阅读:http://developer.amd.com/download/AMD_Accelerated_Parallel_Processing_OpenCL_Programming_Guide.pdf
在一定数量的线程内优化分支只是优化的一小部分。您应该了解AMD HW如何在工作组中调度波前以及如何通过交错执行波前(在工作组内)来隐藏内存延迟。分支也影响整个工作组的执行,因为运行它的有效时间与执行单个最长运行波前的时间基本相同(它不能释放本地内存等,直到组中的所有内容都完成,因此无法安排另一个工作组)。但这也取决于您的本地内存和寄存器使用情况等。要了解实际发生的情况,请抓住CodeXL并运行GPU分析运行。这将准确显示设备上发生的事情。
即使这只适用于当前一代的硬件。这就是为什么这个概念不在OpenCL规范本身。这些属性变化很大,并且很大程度上取决于硬件。
但是如果你真的想知道什么是AMD波前大小,那么答案几乎就是64(请参阅http://devgurus.amd.com/thread/159153以获取他们的OpenCL编程指南)。对于构成其整个当前阵容的所有GCN设备来说,它是64。也许一些较旧的设备有16或32,但现在一切都只有64(对于nvidia,一般只有32)。
答案 1 :(得分:0)
CUDA model - what is warp size? 我认为这是一个很好的答案,可以简单地解释这种扭曲。
但我对Sharpneli所说的有点困惑 “[如果你将它设置为512几乎肯定会失败,规范不要求实现支持任意本地大小。在AMD HW中,本地大小正好是波前大小。同样适用于Nvidia。一般情况下你不会真的需要关心实现如何处理它。]“。
我认为本地大小意味着组大小由程序员设置。但是当工具发生时,细分的组由像warp这样的硬件设置。