【问题标题】:Cuda Sieve of Eratosthenes Error when larger than 1000000大于 1000000 时 Eratosthenes 错误的 Cuda Sieve
【发布时间】:2017-11-29 20:20:33
【问题描述】:

我是 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;
}

【问题讨论】:

    标签: c++ cuda sieve-of-eratosthenes


    【解决方案1】:

    我发现您的代码存在一些问题。首先,double sieve_size = 4000000 / sizeof(long); 行没有意义,因为这会导致在 GPU 上分配的内存量不足。

    举个例子,有 8 个数字,每个 8 字节长(这是 long 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 更大的网格。

    希望这会有所帮助!

    【讨论】:

      猜你喜欢
      • 2018-08-10
      • 2012-02-21
      • 2012-02-21
      • 1970-01-01
      • 1970-01-01
      • 2016-04-05
      • 1970-01-01
      • 2015-09-06
      • 1970-01-01
      相关资源
      最近更新 更多