2017-11-29 4 views
-1

나는 cuda를 처음 사용하고 있으며 Eratosthenes의 체를 수행하는 데 사용하려고합니다. 코드는 1000000 이하의 소수 (primes)에서 작동합니다. 그 위에는 알 수없는 커널 실행 오류가 발생합니다. 이제는 너무 많은 블록이있는 표를 시작하려고하기 때문에 이것이라고 생각합니다. 그러나 블록을 1000으로 설정하면 모든 소수를 얻지 못합니다. kernal에서 색인 생성에 문제가있을 수 있지만 확실하지 않을 수 있습니다.Eratosthenes의 Cuda Sieve가 1000000보다 큰 경우

#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; 
} 

답변

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입니다. 따라서 크기가 32x32x1 또는 1024x1x1 인 블록을 실행할 수 있습니다. 더 많은 데이터를 처리해야하는 경우 더 큰 격자를 사용해야합니다 (1x1x1).

희망이 도움이됩니다.