大于1000000时,Eratosthenes错误的CUDA筛子

Cuda Sieve of Eratosthenes Error when larger than 1000000

本文关键字:CUDA 筛子 错误 Eratosthenes 1000000时 大于      更新时间:2023-10-16

我是Cuda的新手,并试图使用它来执行Eratosthenes的筛子。该代码适用于低于1000000的素数。在其上方,我遇到了一个未知的内核启动错误。现在,我知道这是因为我试图启动一个带有太多块的网格。但是,如果我将块设置为1000,则不会获得所有质数。我认为内核中的索引可能存在问题,但不确定。

#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include <iostream>
#include <fstream>
#include <stdio.h>
using namespace std;
__global__ static void Sieve(long * sieve, long sieve_size)
{
int idx = blockIdx.x * blockDim.x + threadIdx.x;
if (idx > 1) {
    for (int i = idx+idx; i < sieve_size; i += idx) {
        sieve[i] = 1;
    }
}
}
int main()
{
long  *device_sieve;
long *host_sieve = new long[4000000];
ofstream data("data.csv", ofstream::out);
double sieve_size = 4000000 / sizeof(long);
cudaSetDevice(0);
cudaDeviceSynchronize();
cudaThreadSynchronize();
cudaMalloc((void**)&device_sieve, sizeof(long) * sieve_size);
cudaError_t error1 = cudaGetLastError();
cout << "1" << cudaGetErrorString(error1) << endl;
int block = sqrt(sieve_size);
Sieve << <1, block >> >(device_sieve, sieve_size);
cudaThreadSynchronize();
cudaMemcpy(host_sieve, device_sieve, sizeof(long) * sieve_size, cudaMemcpyDeviceToHost);
cudaError_t error = cudaGetLastError();
cout << "2" << cudaGetErrorString(error) << endl;
cudaFree(device_sieve);
for (int i = 2; i < sieve_size; ++i)
    if (host_sieve[i] == 0)
        data << i << endl;
getchar();
cout << "DONE" << endl;
return 0;
}

我看到了您的代码几个问题。首先,该行double sieve_size = 4000000 / sizeof(long);没有意义,因为这导致在GPU上分配不足的内存。

以8个数字,每个8个字节长(这是长AFAIK的标准大小)的示例,因此将它们放入数组中占64个字节的内存。这意味着您的double sieve_size = 8/sizeof(long)将保持值1。然后,您将在GPU上分配内存的sieve_size*sizeof(long)字节,在这种情况下,这意味着您要分配8个字节,而在初始数组中则需要64个字节。因此,放下划分。

另一件事是,我认为使用 double表示某种内存并不是一个好主意一对字节太少了,因此调用了分割故障(如果您需要表示离散实体,例如内存的大小或数组长度的大小,则整数类型是逻辑上的选择)。因此,我会将行更改为:

long sieve_size = 4000000;

现在的另一件事是,您可以执行的块的大小有限制。它因架构而异,您可以找到使用命令cudaGetDeviceProperties的细节。据我所知,在大多数现代卡上,限制是1024 max threads per block。因此,您可以执行大小32x32x11024x1x1等。如果需要处理更多数据,则必须使用更大的网格,而不仅仅是1x1x1

希望这会有所帮助!