проблема программирования CUDA - PullRequest
0 голосов
/ 16 мая 2011

Я очень новичок в cuda. ​​Я использую cuda на своей Ubuntu 10.04 в режиме эмуляции устройства. Я пишу код для вычисления квадрата массива, который выглядит следующим образом:

#include <stdio.h>
#include <cuda.h>
__global__ void square_array(float *a, int N)
    {
      int idx = blockIdx.x + threadIdx.x;
      if (idx<=N) 
       a[idx] = a[idx] * a[idx];
    }
int main(void)
    {
      float *a_h, *a_d; 
      const int N = 10;  
      size_t size = N * sizeof(float);
      a_h = (float *)malloc(size);        
      cudaMalloc((void **) &a_d, size);   
          for (int i=0; i<N; i++) a_h[i] = (float)i;
      cudaMemcpy(a_d, a_h, size, cudaMemcpyHostToDevice);
           square_array <<< 1,10>>> (a_d, N);

 cudaMemcpy(a_h, a_d, sizeof(float)*N, cudaMemcpyDeviceToHost);
      // Print results
      for (int i=0; i<N; i++) printf(" %f\n",  a_h[i]);

      free(a_h); 
cudaFree(a_d);
  return 0;
    } 

Когда я запускаю этот код, он не показывает никаких проблем, он дает мне правильный вывод.

Теперь моя проблема в том, что когда я использую <<< 2,5 >>> или <<< 5,2 >>>, результат остается тем же. что происходит на GPU? Все, что я понимаю, это то, что я просто запускаю ядро ​​cuda с 5 блоками, содержащими 2 потока. Может кто-нибудь объяснить мне, как Gpu справляется с этим или осуществляет запуск (вызов ядра)?

Теперь моя настоящая проблема в том, что когда я вызываю ядро ​​с <<< 1,10 >>> Это нормально. Это показывает идеальный результат. но когда я вызываю ядро ​​с <<< 1,5 >>, результат будет следующим:

 0.000000
 1.000000
 4.000000
 9.000000
 16.000000
 5.000000
 6.000000
 7.000000
 8.000000
 9.000000

аналогично, когда я уменьшаю или увеличиваю второй параметр в вызове ядра, он показывает другой результат, например, когда я изменяю его на << 1,4 >>, он показывает следующий результат:

 0.000000
 1.000000
 4.000000
 9.000000
 4.000000
 5.000000
 6.000000
 7.000000
 8.000000
 9.000000

Почему этот результат приходит? Может ли кто-нибудь объяснить, как работает запуск ядра?

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

Ответы [ 3 ]

5 голосов
/ 16 мая 2011

Вычисление idx в коде вашего ядра неверно.Если вы измените его на:

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

Вы можете найти результаты немного проще для понимания.

РЕДАКТИРОВАТЬ: Для любого данного запуска ядра

square_array<<<gridDim,blockDim>>>(...)

вGPU, автоматическая переменная blockDim будет содержать компоненты x, y и z аргумента blockDim, переданного при запуске ядра на стороне хоста.Аналогично, gridDim будет содержать компоненты x и y аргумента gridDim, переданного при запуске.

0 голосов
/ 11 февраля 2013

То, как ядра запускаются в CUDA, выглядит примерно так:

kernel<<<numBlocks,numThreads>>>(Kernel arguments);

Это означает, что в каждом блоке будут работать блоки numBlocks с потоками numThreads. Например, если вы позвоните

 kernel<<<1,5>>>(Kernel args);

тогда 1 блок будет работать с 5 параллельными потоками. и если вы позвоните

 kernel<<<2,5>>>(Kernel args);

тогда будет 2 блока по 5 потоков в каждом. Если вы не измените код своего устройства, максимальный размер массива, который вы «возводите в квадрат», равен продукту numBlocks * numThreads. Это объясняет, почему не все значения в исходном массиве были в квадрате.

Я предлагаю вам прочитать CUDA_C_Programming_Guide.pdf, который поставляется с инструментарием CUDA.

0 голосов
/ 16 мая 2011

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

if (idx < N) {
tmp = a[idx];
a[idx] = tmp * tmp;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...