Cuda заменяет двойной для 2D блок - PullRequest
2 голосов
/ 18 мая 2011

Я действительно новичок в CUDA и пытаюсь пройти 2D-массив. У меня есть следующий код, который работает, как и ожидалось, на простом C:

for (ty=0;ty<s;ty++){
        if (ty+pixY < s && ty+pixY>=0){
            for(tx=0;tx<r;tx++){
                T[ty/3][tx/3] += (tx+pixX<s && tx+pixX>=0) ? 
                *(image +M*(ty+pixY)+tx+pixX) * *(filter+fw*(ty%3)+tx%3) : 0;
            }
        }
    }  

Может быть, я что-то не так, но разве этот код не будет переведен в CUDA следующим образом?

tx = threadIdx.x;
ty = threadIdy.y;

T[ty/3][tx/3] += (tx+pixX<s && tx+pixX>=0) ?
                *(image +M*(ty+pixY)+tx+pixX) * *(filter+fw*(ty%3)+tx%3) : 0; 

при условии, что я определил параметры моего ядра как dimGrid(1,1,1) и blockDim(r,s,1)

Я спрашиваю, потому что получаю неожиданные результаты. Также, если я правильно объявлю и выделю свои массивы как двумерные массивы cuda, а не просто как большой одномерный массив, это поможет?

Спасибо за вашу помощь.

1 Ответ

4 голосов
/ 18 мая 2011

Если оставить в стороне правильность схем размещения и индексации массивов (я не уверен, что в посте достаточно информации, чтобы подтвердить это), а также тот факт, что целочисленное деление и по модулю медленные и их следует избегать, у вас естьболее фундаментальная проблема - гонка памяти.

Несколько потоков в одном используемом вами блоке будут пытаться читать и записывать в одну и ту же запись T одновременно.CUDA не дает никаких гарантий относительно правильности такого рода операций, и это почти наверняка не сработает.Самая простая альтернатива - использовать только один поток для вычисления каждой записи T[][], а не три потока.Это устраняет гонку памяти.

...