【发布时间】:2017-07-13 06:03:04
【问题描述】:
我仍然是 CUDA 的初学者,我一直在尝试编写一个简单的内核来在 GPU 上执行并行素筛。最初我用 C 编写了我的代码,但我想研究 GPU 上的加速,所以我重写了它:
41.cu
#include <stdio.h>
#include <stdlib.h>
#include <cuda.h>
#include <cuda_runtime.h>
#define B 1024
#define T 256
#define N (B*T)
#define checkCudaErrors(error) {\
if (error != cudaSuccess) {\
printf("CUDA Error - %s:%d: '%s'\n",__FILE__,__LINE__,cudaGetErrorString(error));\
exit(1);\
}\
}\
__global__ void prime_sieve(int *primes) {
unsigned int i = threadIdx.x + blockIdx.x * blockDim.x;
primes[i] = i;
primes[0] = primes[1] = 0;
if (i > 1 && i<N) {
for (int j=2; j<N/2; j++) {
if (i*j < N) {
primes[i*j] = 0;
}
}
}
}
int main() {
int *h_primes=(int*)malloc(N * sizeof(int));
int *d_primes;
checkCudaErrors(cudaMalloc( (void**)&d_primes, N*sizeof(int)));
checkCudaErrors(cudaMemcpy(d_primes,h_primes,N*sizeof(int),cudaMemcpyHostToDevice));
prime_sieve<<<B,T>>>(d_primes);
checkCudaErrors(cudaMemcpy(h_primes,d_primes,N*sizeof(int),cudaMemcpyDeviceToHost));
checkCudaErrors(cudaFree(d_primes));
int size = 0;
int total = 0;
for (int i=2; i<N; i++) {
if (h_primes[i]) {
size++;
}
total++;
}
printf("\n");
printf("Length = %d\tPrimes = %d\n",total,size);
free(h_primes);
return 0;
}
我在 Ubuntu 16.04 (4.4.0-83-generic) 上运行该程序,并在 8.0.61 版本下使用 nvcc 41.cu -o 41.o -arch=sm_30 进行编译。该程序在 GeForce GTX 780 Ti 上运行,但每次运行时,总是会产生不确定的结果:
Length = 262142 Primes = 49477
Length = 262142 Primes = 49486
Length = 262142 Primes = 49596
Length = 262142 Primes = 49589
没有错误报告。起初我认为这是一个竞争条件,但cuda-memcheck 没有报告racecheck、initcheck 或synccheck 的任何危险,我想不出我的假设有任何问题。我在想这可能是一个同步问题?
这种非确定性行为仅在我增加代码中看到的块大小和线程大小时才会发生。当我尝试块大小和线程大小为 16 时,没有问题(据我所知)。似乎并非所有线程都有机会执行?我计划在非常大的数组大小(
我在这里做错了什么?
【问题讨论】: