2011-01-22 2 views
4

У меня есть код, который я хочу сделать в ядре cuda. Вот:CUDA: встроенный для ядра цикла

for (r = Y; r < Y + H; r+=2) 
    { 
     ch1RowSum = ch2RowSum = ch3RowSum = 0; 
     for (c = X; c < X + W; c+=2) 
     { 
      chan1Value = //some calc'd value 
          chan3Value = //some calc'd value 
      chan2Value = //some calc'd value 
      ch2RowSum += chan2Value; 
      ch3RowSum += chan3Value; 
      ch1RowSum += chan1Value; 
     } 
     ch1Mean += ch1RowSum/W; 
     ch2Mean += ch2RowSum/W; 
     ch3Mean += ch3RowSum/W; 
    } 

Если это разделить на два ядра, один, чтобы вычислить RowSums и высчитывать средства, и как я должен справиться с тем, что мои показатели цикла не начинает с нуля и заканчиваются на N?

+0

попытайтесь выбрать один из вопросов, это затрудняет выбор правильного ответа. но, что касается вашего второго вопроса ... сложно ответить конкретно, но я думаю, вы увидите, как только вы углубитесь в развитие своего ядра. – jmilloy

+0

вы должны запустить свое ядро ​​с конфигурацией, такой как H-блоки и W-потоки на каждый блок. Затем вы вычисляете r и c из значений blockIdx и threadIdx внутри ядра. вычисляем r и c, но вы хотите ... я попытался поместить это в свой ответ ниже ... – jmilloy

+0

Это выглядело как два вопроса, но я не был уверен, что контекст будет там, если я попытаюсь написать его как два вопроса: – Derek

ответ

1

Предположим, у вас есть ядро, которое вычисляет три значения. Каждый поток в вашей конфигурации будет вычислять три значения для каждой пары (r, c).

__global__ value_kernel(Y, H, X, W) 
{ 
    r = blockIdx.x + Y; 
    c = threadIdx.x + W; 

    chan1value = ... 
    chan2value = ... 
    chan3value = ... 
} 

Я не верю, что вы можете рассчитать сумму (полностью параллельно, по крайней мере) в указанном выше ядре. Вы не сможете использовать + = как вы уже выше. Вы можете поместить все это в одном ядре, если у вас есть только один поток в каждом блоке (строке) сделать сумму и сказать, как это ...

__global__ both_kernel(Y, H, X, W) 
{ 
    r = blockIdx.x + Y; 
    c = threadIdx.x + W; 

    chan1value = ... 
    chan2value = ... 
    chan3value = ... 

    if(threadIdx.x == 0) 
    { 
     ch1RowSum = 0; 
     ch2RowSum = 0; 
     ch3RowSum = 0; 

     for(i=0; i<blockDim.x; i++) 
     { 
      ch1RowSum += chan1value; 
      ch2RowSum += chan2value; 
      ch3RowSum += chan3value; 
     } 

     ch1Mean = ch1RowSum/blockDim.x; 
     ch2Mean = ch2RowSum/blockDim.x; 
     ch3Mean = ch3RowSum/blockDim.x; 
    } 
} 

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

__global__ sum_kernel(Y,W) 
{ 
    r = blockIdx.x + Y; 

    ch1RowSum = 0; 
    ch2RowSum = 0; 
    ch3RowSum = 0; 

    for(i=0; i<W; i++) 
    { 
     ch1RowSum += chan1value; 
     ch2RowSum += chan2value; 
     ch3RowSum += chan3value; 
    } 

    ch1Mean = ch1RowSum/W; 
    ch2Mean = ch2RowSum/W; 
    ch3Mean = ch3RowSum/W; 
} 
+0

i что вы можете распараллелить сумму/значение ... то, что вы хотите, - это сокращение. (один из многих доступных примеров: http://supercomputingblog.com/cuda/cuda-tutorial-3-thread-communication/) – jmilloy

+0

Я заметил, что вы фактически не использовали значения R или C здесь. Должна ли какая-то проверка делать No Op, если вроде blockIdx.x * threadIdx.x больше, чем blockIdx.x + Y? что бы это выглядело точно? – Derek

+0

вы также не использовали r или c в своем коде. У вас есть три значения, которые рассчитываются для каждого местоположения сетки (r, c). Вероятно, вы захотите, чтобы один поток вычислил один набор значений. Когда вы запускаете ядро, запустите с r блоками и c потоками на каждый блок. Затем в каждом потоке вы можете рассчитать r и c из идентификатора блока и идентификатора потока. Я полагаю, что r и c используются для доступа к вводу для вычисления значений и/или они используются напрямую. (если вы можете запустить ядро ​​с большим количеством потоков или блоков, чем вам нужно, тогда обязательно проверьте свои границы ... что-то вроде if (r> = #rows || c> = #cols) return;) – jmilloy

Смежные вопросы