2016-10-05 51 views
2

我在使用openCL C++时遇到了这个非常奇怪的问题。问题是我有100个线程访问100个大小数组中的每个元素。从0到63,没有问题,每个线程都正确地计算和更新数组元素的值。但是,当它到达线程64,它搅乱了,并与一些其他值更新值...OpenCL C++ - 线程后数组的内存管理错误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。就好像这些值已经向后移动了一些元素。为什么?这里发生了什么?

回答

0

所以我发现我的问题的解决方案:

的问题是,即使每个线程有存储在tempValue[]阵列自行value[]阵列的复制:在阵列中

// 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]; 
} 

值在线程64之后被搞乱了。所以我做的是我在主机代码(sizeOf(value) * 100)外部创建了一个更大的数值数组,然后将数组的第一部分复制到其余的99个部分,然后将其发送到设备。然后我使用索引使每个线程访问它自己的值[]数组的一部分。

它解决了这个问题!

0

有,如果工作同一阵列上的多台设备出了问题,

你把

cl::NDRange(200/numberOfDevices) 

的范围

,但你不把

cl::NDRange((200/numberOfDevices)*deviceIndex) 

为偏移每个设备。

所有试图写入相同位置而不是相邻组的设备。

另外,您并未检查内核中的总线程数是否小于数组长度,因此有些线程可能会尝试写出超出范围。

+0

如何检查总线程数是否小于数组长度? –