Ошибка ядра CUDA при увеличении номера потока - PullRequest
1 голос
/ 01 декабря 2011

Я разрабатываю ядро ​​пересечения плоскости луча CUDA.

Предположим, моя структура плоскости (лица):

typedef struct _Face {
    int ID;
    int matID;

    int V1ID;
    int V2ID;
    int V3ID;

    float V1[3];
    float V2[3];
    float V3[3];

    float reflect[3];

    float emmision[3];
    float in[3];
    float out[3];

    int intersects[RAYS];

} Face;

Я вставил всю структуру, чтобы вы могли получитьИдея его размера. RAYS равно 625 в текущей конфигурации.В следующем коде предположим, что размер массива Faces составляет, например, 1270 (обычно - тысячи).

Теперь до сегодняшнего дня я очень наивно запускал свое ядро:

const int tpb = 64; //threads per block
dim3 grid = (n +tpb-1)/tpb; // n - face count in array
dim3 block = tpb;
//.. some memory allocation etc.
theKernel<<<grid,block>>>(dev_ptr, n);

внутри ядра у меня был цикл:

__global__ void theKernel(Face* faces, int faceCount) {
    int offset = threadIdx.x + blockIdx.x*blockDim.x;
    if(offset >= faceCount)
        return;
    Face f = faces[offset];
    //..some initialization
    int RAY = -1;
    for(float alpha=0.0f; alpha<=PI; alpha+= alpha_step ){ 
        for(float beta=0.0f; beta<=PI; beta+= beta_step ){ 
            RAY++;
            //..calculation per ray in (alpha,beta) direction ...
            faces[offset].intersects[RAY] = ...; //some assignment

Это об этом.Я перебрал все направления и обновил массив face .Я работал правильно, но вряд ли был быстрее, чем код процессора.

Поэтому сегодня я попытался оптимизировать код и запустить ядро ​​с гораздо большим количеством потоков.Вместо 1 нити на лицо я хочу 1 нить на луч лица (то есть 625 нитей работают на 1 лицо).Модификации были просты:

dim3 grid = (n*RAYS +tpb-1)/tpb;  //before launching . RAYS = 625, n = face count

и само ядро:

__global__ void theKernel(Face *faces, int faceCount){

int threadNum = threadIdx.x + blockIdx.x*blockDim.x;

int offset = threadNum/RAYS; //RAYS is a global #define
int rayNum = threadNum - offset*RAYS;

if(offset >= faceCount || rayNum != 0)
    return;

Face f = faces[offset];
//initialization and the rest.. again ..

И этот код не работает вообще.Зачем?Теоретически, должен работать только 1-й поток (из 625 на одну грань), так почему же это приводит к плохим (почти никаким) вычислениям?

С уважением, например.

Ответы [ 2 ]

0 голосов
/ 02 декабря 2011

Как указал Heatsink, вы, вероятно, превышаете доступные ресурсы. Хорошая идея - проверить после выполнения ядра, не было ли ошибки.

Вот код C ++, который я использую:

#include <cutil_inline.h>

void
check_error(const char* str, cudaError_t err_code) {
    if (err_code != ::cudaSuccess)
        std::cerr << str << " -- " << cudaGetErrorString(err_code) << "\n";
}

Затем, когда я запускаю ядро:

my_kernel <<<block_grid, thread_grid >>>(args);
check_error("my_kernel", cudaGetLastError());
0 голосов
/ 02 декабря 2011

Максимальный размер сетки в любом измерении составляет 65535 ( Руководство по программированию CUDA , Приложение F). Если ваш размер сетки был до изменения 1000, вы увеличили его до 625000. Это больше, чем предел, поэтому ядро ​​не будет работать правильно.

Если вы определите размер сетки как

dim3 grid((n + tpb - 1) / tpb, RAYS);

тогда все размеры сетки будут меньше предела. Вам также придется изменить способ использования blockIdx в ядре.

...