cuda的多线程循环

时间:2018-10-13 13:28:05

标签: parallel-processing cuda

我想做一个for循环,用cuda测试2 ^ 41的值。 我编写了这段代码,但是它多次测试相同的密钥,但是我只想测试一次,所以不知道为什么。

__global__ void kernel(int fileSize, unsigned char * buffer)
{
   for(mot64 i3 = 0L; i3 < (1L << 41); i3++){
     deCipher(buffer, i3, fileSize);
   }
   return;
}

感谢您的帮助:)

1 个答案:

答案 0 :(得分:1)

您似乎并不真正了解大规模并行GPU计算的工作原理,因此我将尽力为您提供有关发生情况的“快速”解释。但是,实际上,您会想读一本不错的书,因为这是一个庞大而复杂的主题。

在CUDA中启动内核时,您正在启动它以在特定数量的线程上运行,如下所示:

kernel<<<blocks, threads>>>(fileSize, buffer);

这意味着该函数将在指定数量的blocks上运行,并且每个块具有一定数量的threads,总共blocks*threads个线程。

要真正理解这意味着什么,您需要阅读一些有关CUDA的书以及什么是网格,块和线程。一个简单的解释是在“ grid”上启动了一个函数。此“ grid”分为“ blocks”。将这些块视为CPU中的虚拟“核心”。不太正确,但足够接近,对我们所说的内容含糊不清。每个“ block”本身被分为“ threads”。这些“ threads”中的每一个都独立地运行您的函数。因此,您现在可以让函数并行运行大量实例。您希望每个实例访问缓冲区的不同部分。

在内核中,您想像这样计算正在处理的线程:

int index = blockIdx.x * blockDim.x + threadIdx.x;
int stride = blockDim.x * gridDim.x;

This image is very important.

如您所见,网格是二维的,并且二维被方便地称为xy。考虑行和列。 index告诉您的是您在网格上的水平位置。 stride告诉您每行有多长,请将其视为偏移量。

因此在您的内核中,您将有一个像这样的循环:

for (int i = index; i < sizeOfYourData; i += stride)
{
    // [...]
}

这可以准确告诉您正在使用什么线程。其余的都是微不足道的。变量i现在是您的“线程ID”,您可以将其用作缓冲区的偏移量,以允许每个线程访问其不同部分。

因此,您需要这样的东西:

__global__ void kernel(int fileSize, unsigned char * buffer)
{
    int index = blockIdx.x * blockDim.x + threadIdx.x;
    int stride = blockDim.x * gridDim.x;

    for (int i3 = index; i3 < (1L << 41); i3 += stride)
    {
        deCipher(buffer, i3, fileSize);
    }

    return;
}