我想做一个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;
}
感谢您的帮助:)
答案 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;
如您所见,网格是二维的,并且二维被方便地称为x
和y
。考虑行和列。 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;
}