Увеличение размера блока снижает производительность - PullRequest
1 голос
/ 19 февраля 2011


В моем коде cuda, если я увеличиваю blockizeizeX, blocksizeY это на самом деле занимает больше времени. [Поэтому я запускаю его с 1x1] Также часть моего времени выполнения (например, 7 из 9 с) берется только вызовом Ядро. Фактически я очень удивлен тем, что даже если я закомментирую все ядро, время почти одинаковое. Есть предложения, где и как оптимизировать?

P.S. Я отредактировал этот пост с моим реальным кодом. Я уменьшаю выборку изображения, чтобы каждые 4 соседних пикселя (например, для 1,2 из строки 1 и 1,2 из строки 2) давали выходной пиксель. Я получаю эффективное значение bw of. 5 ГБ / с по сравнению с теоретическим максимумом 86,4 ГБ / с. Время, которое я использую, заключается в разнице в вызове ядра с инструкциями и вызове пустого ядра. Сейчас это выглядит довольно плохо, но я не могу понять, что я делаю не так.

 __global__ void streamkernel(int *r_d,int *g_d,int *b_d,int height ,int width,int *f_r,int *f_g,int *f_b){


    int id=blockIdx.x * blockDim.x*blockDim.y+ threadIdx.y*blockDim.x+threadIdx.x+blockIdx.y*gridDim.x*blockDim.x*blockDim.y;
    int number=2*(id%(width/2))+(id/(width/2))*width*2;

     if (id<height*width/4)
    {

        f_r[id]=(r_d[number]+r_d[number+1];+r_d[number+width];+r_d[number+width+1];)/4;                              
        f_g[id]=(g_d[number]+g_d[number+1]+g_d[number+width]+g_d[number+width+1])/4;             
        f_b[id]=(g_d[number]+g_d[number+1]+g_d[number+width]+g_d[number+width+1];)/4;  
    }


  }

Ответы [ 2 ]

2 голосов
/ 24 февраля 2011

Попробуйте найти пример умножения матриц в примерах CUDA SDK, чтобы узнать, как использовать разделяемую память.

Проблема с вашим текущим ядром в том, что он выполняет 4 чтения глобальной памяти и 1 запись глобальной памяти для каждых 3 дополнений и 1 деления. Каждый глобальный доступ к памяти стоит примерно 400 циклов. Это означает, что вы проводите подавляющее большинство времени, обращаясь к памяти (в чем плохи графические процессоры), а не к вычислениям (в чем хорошы графические процессоры).

Фактически общая память позволяет вам кэшировать это так, чтобы амортизировалось, вы получаете примерно 1 чтение и 1 запись на каждый пиксель за 3 добавления и 1 деление. Это все еще не так уж хорошо в отношении CGMA (соотношение вычислений к глобальному доступу к памяти, святой Грааль вычислений на GPU).

В целом, я думаю, что для простого ядра, подобного этому, реализация ЦП, вероятно, будет быстрее, учитывая накладные расходы на передачу данных по шине PCI-E.

0 голосов
/ 20 февраля 2011

Вы забываете тот факт, что один мультипроцессор может выполнять до 8 блоков одновременно, и максимальная производительность достигается именно тогда.Однако существует множество факторов, которые ограничивают количество блоков, которые могут существовать параллельно (неполный список):

  • Максимальный объем разделяемой памяти на многопроцессорное устройство ограничивает количество блоков, если #blocks * разделяемая память на блокбудет> общая разделяемая память.
  • Максимальное количество потоков на многопроцессорное ограничение ограничивает количество блоков, если #blocks * #threads / block будет> max total # threads.
  • ...

Вы должны попытаться найти конфигурацию выполнения ядра, которая позволяет запускать ровно 8 блоков на одном мультипроцессоре.Это почти всегда дает наивысшую производительность, даже если занятость = / = 1.0!С этого момента вы можете попытаться итеративно вносить изменения, которые уменьшают количество исполняемых блоков на MP, но, следовательно, увеличивают занятость вашего ядра и проверяют, увеличивается ли производительность.

Калькулятор занятости nvidia (лист Excel) очень поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...