0

我有以下opencl代码:

__constant SomeConstants[] = { 5, 7, 242, 74 };

long aslong(__global int * arr, int offset) {
    return ... <CalculateLong> ...;
};

void calcSomething(__global int * numArray, int * result) {
    long tempArray[] = { numArray[0], numArray[1], numArray[2], numArray[3] };

    long x0 = (result[0] = aslong(numArray, 0)) + tempArray[0];
    long x1 = (result[1] = aslong(numArray, 8)) + tempArray[1];
    long x2 = (result[2] = aslong(numArray, 16)) + tempArray[2];
    long x3 = (result[3] = aslong(numArray, 32)) + tempArray[3];
    // do some calculations here
    result[0] = x0;
    result[1] = x1;
    result[2] = x2;
    result[3] = x3;

};

__kernel void calc(__global int * numArray, __global long * sum) {
    long arr[] = { SomeConstants[0], SomeConstants[1], SomeConstants[2], SomeConstants[3] };
    calcSomething(numArray, arr);
    sum[get_global_id(0)] = arr[0];
    sum[get_global_id(0)+1] = arr[1];
    sum[get_global_id(0)+2] = arr[2];
    sum[get_global_id(0)+3] = arr[3];
};

上面的代码按预期工作,但问题是,我无法向 calcSomething 添加更多计算。当我向 calcSomethig 添加一个空循环时,如下所示:

void calcSomething(__global int * numArray, int * result) {
    long tempArray[] = { numArray[0], numArray[1], numArray[2], numArray[3] };

    long x0 = (result[0] = aslong(numArray, 0)) + tempArray[0];
    long x1 = (result[1] = aslong(numArray, 8)) + tempArray[1];
    long x2 = (result[2] = aslong(numArray, 16)) + tempArray[2];
    long x3 = (result[3] = aslong(numArray, 32)) + tempArray[3];

    for (int i = 0; i < 18; i++) {}

    result[0] = x0;
    result[1] = x1;
    result[2] = x2;
    result[3] = x3;

};

result[0] 和 result[1] 存储了正确的值,但是 result[2] 和 result[3] 是绝对错误的。通过注释掉 for 循环,结果 [2] 和 3 是正确的......知道调用 for 循环时 x0、x1、x2 和 x3 发生了什么吗?

4

1 回答 1

1

编辑答案:您的问题位于操作中:

sum[get_global_id(0)] = arr[0];
sum[get_global_id(0)+1] = arr[1];
sum[get_global_id(0)+2] = arr[2];
sum[get_global_id(0)+3] = arr[3];

您正在使用sum[]具有重叠索引的全局数组。然而,许多工作项将写入相同的内存,产生未定义的结果。您需要修复重叠,或者对全局变量执行原子操作。

例子:

 gid 0 -> Write to sum[0,1,2,3]
 gid 1 -> Write to sum[1,2,3,4]
 //....

for循环根本与问题无关。您只是看到了多线程环境中不同调度的效果。但这不是问题的根源。

进一步编辑: 代码存在与 OpenCL 无关的问题。上面已经描述了 OpenCL 的唯一问题。

有很多地方 C 变量被错误地寻址或隐式转换,然后被错误地使用。例如在aslong()8 个连续的 int 中添加一个 long,但是一个 long 是由 8bytes 组成的,而不是 8int。

于 2013-11-12T11:38:25.980 回答