我在使用 openCL C++ 时遇到了这个非常奇怪的问题。问题是我有 100 个线程正在访问一个 100 大小的数组中的每个元素。从 0 到 63,没有问题,每个线程都在正确计算和更新数组元素的值。但是当它到达线程 64 时,它会搞砸并用其他一些值更新这些值...
这是我调用内核的方式:
kernelGA(cl::EnqueueArgs(queue[iter],
cl::NDRange(200 / numberOfDevices)),
d_value,
d_doubleParameters,
buf_half_population, and so on...)
在内核端,我使用以下方式访问每个线程:
__kernel void kernelGA (__global double * value,
__global double * doubleParameters,
__global double * population,
__global double * scores, and so on...)
int idx = get_global_id(0); // This gives me 100 threads for each device. (I have two devices)
int size_a = 50;
double tempValue[size_a];
// Copying the global "value" into local array so each thread has its own copy.
for (int i = 0; i < size_a; i++) {
tempValue[i] = value[i];
}
此时,每个线程现在都有自己的具有相同值的 tempValue[] 数组。然后我对每个线程的 tempValue[] 数组的值应用一些计算和公式...
// Applying some computations on tempValue and changing the values for each copy of tempValue for each thread.
tempValue[i] = some calculations for each thread...
在此之后,我为每个线程访问 tempValue[] 数组的每个元素,并将它们连续放回到一个更大的数组中(线程数 * size_a)。请记住,数组的索引是这样的:0,1,2,3,...等等...
for (int i = 0; i < size_a; i++) {
totalArray[(idx * size_a) + i] = tempvalue[i];
}
因此,当我在内核外部获得 totalArray 的答案并打印它们时,前 64 个(从 0-63)线程已将它们的值正确地放入 totalArray[] 中。但是从 64 开始,索引就乱七八糟了。我的意思不完全是索引,因为我只打印出索引,并且所有线程都可以正确访问索引。但是这些值似乎搞砸了......
例如:线程0-63的第3、4、5、6个元素的值分别为50、60、70、80。但是对于 64 号以后的线程,第 3、4、5 和 6 个元素的值分别为 80、90、100、110。好像这些值已经向后移动了几个元素。为什么?这是怎么回事?
最佳答案
如果多个设备在同一个阵列上工作,就会出现问题,
你放
cl::NDRange(200 / numberOfDevices)
作为范围
但你没有放
cl::NDRange((200 / numberOfDevices)*deviceIndex)
作为每个设备的偏移量。
所有设备都试图写入相同的位置而不是相邻的组。
此外,您没有检查内核中的总线程数是否小于数组长度,因此某些线程可能会尝试越界写入。
关于c++ - OpenCL C++ - 线程 64 后数组的内存管理错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39873496/