2013-04-23 2 views
-2

Исходная задача запускали больше потоков, что можно так:CUDA больше, чем максимальные потоки без ошибок?

someKernel<<<1 , 1025>>> (...); 

и не обнаруживает ошибку, так как я не знаю, как для обнаружения ошибок вызовов ядра. Это объясняется также в talonmies ответить на этот вопрос:

What is the canonical way to check for errors using the CUDA runtime API?

Вместо того, чтобы изменить код я представил я написал свой собственный для лаконичности:

#include "cuda_runtime.h" 
#include "device_launch_parameters.h" 

#include <stdio.h> 

#define gpuErrchk(ans) { gpuAssert((ans), __FILE__, __LINE__); } 
inline void gpuAssert(cudaError_t cudaError, char *file, int line, bool abort=true) 
{ 
    if (cudaError != cudaSuccess) 
    { 
     fprintf(stderr,"GPUassert: %s %s %d\n", cudaGetErrorString(cudaError), file, line); 
    } 
} 

__global__ void addKernel(const int *dev_a, const int *dev_b, int *dev_c) 
{ 
    int i = threadIdx.x; 
    if (i < 5) 
     dev_c[i] = dev_a[i] + dev_b[i]; 
} 

int main() 
{ 
    const int arraySize = 5; 
    const int a[arraySize] = { 1, 2, 3, 4, 5 }; 
    const int b[arraySize] = { 10, 20, 30, 40, 50 }; 
    int c[arraySize] = { 0 }; 

    int *dev_a(nullptr), *dev_b(nullptr), *dev_c(nullptr); 

    gpuErrchk(cudaMalloc((void**)&dev_a, arraySize * sizeof(int))); 
    gpuErrchk(cudaMalloc((void**)&dev_b, arraySize * sizeof(int))); 
    gpuErrchk(cudaMalloc((void**)&dev_c, arraySize * sizeof(int))); 

    gpuErrchk(cudaMemcpy(dev_a, a, arraySize * sizeof(int), cudaMemcpyHostToDevice)); 
    gpuErrchk(cudaMemcpy(dev_b, b, arraySize * sizeof(int), cudaMemcpyHostToDevice)); 

    const int testMax1D = 1025; 
    dim3 testMax2D (32, 33); 

    addKernel<<<1, testMax2D>>> (dev_a , dev_b, dev_c); 
    gpuErrchk(cudaPeekAtLastError()); 
    gpuErrchk(cudaDeviceSynchronize()); 

    gpuErrchk( cudaMemcpy(c, dev_c, arraySize * sizeof(int), cudaMemcpyDeviceToHost)); 

    printf("{1,2,3,4,5} + {10,20,30,40,50} = {%d,%d,%d,%d,%d}\n", 
     c[0], c[1], c[2], c[3], c[4]); 

    cudaFree(dev_a); 
    cudaFree(dev_b); 
    cudaFree(dev_c); 

    return 0; 
} 

я теперь получить правильные отчеты об ошибках. Спасибо за терпеливость.

Я не понимаю, этот вызов в функции gpuAssert, так что я его: опущен

if (abort) exit(code); 

ли выйти из пользовательского написал функцию или что-то я пропустил?

+2

Вам необходимо [проверить ошибку CUDA] (http://stackoverflow.com/questions/14038589/what-is-the-canonical-way-to-check-for-errors-using-the-cuda-runtime -api) после запуска каждого ядра. Когда вы превысите максимальное количество блоков или потоков в конфигурации запуска, вы получите «CUDA неуказанную ошибку запуска» или что-то подобное. –

+0

@JaredHoberock Я добавил весь код. Я (или, скорее, разработчики примера nVidia), похоже, проверяет ошибки на каждом возможном этапе. Я скучаю по одному? –

+2

Да. Вы не понимаете, как проверить ошибки запуска ядра. Прочтите ссылку, которую Джаред предложил тщательно. –

ответ

3

Существует два класса ошибок, которые могут возникать при запуске ядра, и их необходимо проверять отдельными шагами, следуя определенному порядку.

Первый класс ошибок сообщается синхронно при вызове ядра и перед запуском ядра на устройстве, то есть это ошибки «перед запуском». Эти ошибки обычно связаны с запросом большего количества определенного ресурса, чем доступно (например, слишком много разделяемой памяти, слишком много потоков). Проверьте их, вызвав cudaGetLastError() сразу после вызова ядра.

Второй класс ошибок - это те, которые происходят в некоторый момент времени после запуска ядра на устройстве (например, нарушение доступа к памяти, тайм-аут сторожевого таймера). Это ошибки после запуска. Причина, по которой они сообщаются через некоторое время после вызова ядра, является естественным следствием запуска ядра асинхронно. Они сообщаются при следующей возможности, которая обычно является следующим синхронным вызовом API. Проверьте их, вызвав cudaDeviceSynchronize() и рассмотрев его возврат статуса.

В опубликованном коде отсутствует проверка ошибок первого класса.