0

我在这里遇到了麻烦。我启动了两个内核,检查某个值是否是预期的值(memcpy 到主机),如果是,我停止,如果不是,我再次启动这两个内核。

第一个内核:

__global__  void aco_step(const KPDeviceData* data)
{
int obj = threadIdx.x;
int ant = blockIdx.x;
int id = threadIdx.x + blockIdx.x * blockDim.x;

*(data->added) = 1;

while(*(data->added) == 1)
{
    *(data->added) = 0;

    //check if obj fits
    int fits = (data->obj_weights[obj] + data->weight[ant] <= data->max_weight);
    fits = fits * !(getElement(data->selections, data->selections_pitch, ant, obj));

    if(obj == 0)
        printf("ant %d going..\n", ant);
    __syncthreads();

...

代码在此之后继续。但是那个 printf 永远不会被打印出来,那个 syncthreads 只是为了调试目的。

“添加”变量是共享的,但由于共享内存是 PITA 并且通常会在代码中引发错误,所以我现在只是将其删除。这个“添加”变量不是最聪明的做法,但它比替代方法更快,后者检查数组中的任何变量是否是主机上的某个值并决定是否继续迭代。

getElement 只需使用音高进行矩阵内存计算以访问正确的位置并返回那里的元素:

int* el = (int*) ((char*)mat + row * pitch) + col;
return *el;

obj_weights 数组具有正确的大小,n*sizeof(int)。权重数组 ants*sizeof(float) 也是如此。所以他们并没有越界。

这个之后的内核在开始时有一个 printf ,它也没有被打印,并且在 printf 之后它在设备内存上设置一个变量,并且在内核完成后这个内存被复制到 CPU,它是当我在 CPU 代码中打印它时,它不是正确的值。所以我认为这个内核正在做一些非法的事情,而第二个内核甚至没有启动。

我正在测试一些实例,当我启动 8 个块和 512 个线程时,它运行正常。32 个块,512 个线程,OK。但是 8 个块和 1024 个线程,发生这种情况,内核不起作用,32 个块和 1024 个线程都不起作用。

难道我做错了什么?内存访问?我是否启动了太多线程?

编辑:尝试删除“添加”变量和 while 循环,所以它应该只执行一次。仍然不起作用,没有打印任何内容,即使 printf 就在三个初始行之后并且下一个内核也没有打印任何内容。

编辑:另一件事,我使用的是 GTX 570,因此根据http://en.wikipedia.org/wiki/CUDA ,“每个块的最大线程数”为 1024 。也许我会坚持最大 512 或检查我能把这个值放多高。

4

1 回答 1

2

__syncthreads()仅当条件在块的所有线程上的评估相同时,才允许使用内部条件代码。

在您的情况下,该条件遭受竞争条件并且是不确定的,因此它很可能会针对不同线程评估不同的结果。

printf()只有在内核成功完成后才会显示输出。在这种情况下,它不是由于上面提到的问题,所以输出永远不会出现。您可以通过测试所有 CUDA 函数调用的错误返回码来解决这个问题。

于 2012-09-12T22:50:27.250 回答