【发布时间】:2015-09-06 20:41:42
【问题描述】:
我正在 GPU 上编写 Sieve of Eratosthenes (https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes) 的实现。但是没有这样的 - http://developer-resource.blogspot.com/2008/07/cuda-sieve-of-eratosthenes.html
方法:
- 创建具有默认值 0/1(0 - 素数,1 - 否)的 n 元素数组并将其传递到 GPU(我知道它可以直接在内核中完成,但目前没有问题)。李>
- 块中的每个线程检查单个数字的倍数。每个块检查总 sqrt(n) 可能性。每个块 == 不同的间隔。
- 将倍数标记为 1 并将数据传回主机。
代码:
#include <stdio.h>
#include <stdlib.h>
#define THREADS 1024
__global__ void kernel(int *global, int threads) {
extern __shared__ int cache[];
int tid = threadIdx.x + 1;
int offset = blockIdx.x * blockDim.x;
int number = offset + tid;
cache[tid - 1] = global[number];
__syncthreads();
int start = offset + 1;
int end = offset + threads;
for (int i = start; i <= end; i++) {
if ((i != tid) && (tid != 1) && (i % tid == 0)) {
cache[i - offset - 1] = 1;
}
}
__syncthreads();
global[number] = cache[tid - 1];
}
int main(int argc, char *argv[]) {
int *array, *dev_array;
int n = atol(argv[1]);
int n_sqrt = floor(sqrt((double)n));
size_t array_size = n * sizeof(int);
array = (int*) malloc(n * sizeof(int));
array[0] = 1;
array[1] = 1;
for (int i = 2; i < n; i++) {
array[i] = 0;
}
cudaMalloc((void**)&dev_array, array_size);
cudaMemcpy(dev_array, array, array_size, cudaMemcpyHostToDevice);
int threads = min(n_sqrt, THREADS);
int blocks = n / threads;
int shared = threads * sizeof(int);
kernel<<<blocks, threads, shared>>>(dev_array, threads);
cudaMemcpy(array, dev_array, array_size, cudaMemcpyDeviceToHost);
int count = 0;
for (int i = 0; i < n; i++) {
if (array[i] == 0) {
count++;
}
}
printf("Count: %d\n", count);
return 0;
}
跑步:
./筛 10240000
当 n = 16, 64, 1024, 102400 时它可以正常工作......但是对于 n = 10240000 我得到不正确的结果。问题出在哪里?
【问题讨论】:
-
任何时候您在使用 CUDA 代码时遇到问题,最好使用proper cuda error checking 并使用
cuda-memcheck运行您的代码。你真的应该在之前在这里发帖。当我使用 n=10240000 运行您的代码时,cuda-memcheck 报告来自内核的大小为 4 的无效全局读取。如果您使用该信息以及here 描述的方法,您可能能够查明问题。
标签: c cuda parallel-processing primes sieve-of-eratosthenes