CUDA - вызов ядра несколько раз - PullRequest
1 голос
/ 30 ноября 2011

У меня проблемы с программой CUDA, которую я пытаюсь написать.У меня есть массив около 524 тыс. Значений с плавающей точкой (1,0), и я использую технику сокращения, чтобы добавить все значения.Проблема работает нормально, если я хочу запустить ее только один раз, но я действительно хочу запустить ядро ​​несколько раз, чтобы в итоге я мог собрать более 1 миллиарда значений.

Причина, по которой я делаю это кусками по 524 КБ, заключается в том, что я всегда получаю нули обратно, когда перебираю около 1 миллиона на GPU.Это не должно превышать объем памяти на карте, но в этот момент она всегда дает сбой.

В любом случае, когда я зацикливаю ядро ​​только один раз, все работает нормально.То есть без циклов это нормально.Когда я бегу с петлями, он возвращается с нулями.Я подозреваю, что выхожу за пределы какого-то места, но я не могу понять это.Это сводит меня с ума.

Любая помощь приветствуется,

Спасибо,

Al

Вот код:

#include <stdio.h>
#include <stdlib.h>
#include "cutil.h"

#define TILE_WIDTH     512
#define WIDTH          524288 
//#define WIDTH          1048576
#define MAX_WIDTH      524288

#define BLOCKS         WIDTH/TILE_WIDTH

__global__ void PartSum(float * V_d)
{
   int tx = threadIdx.x;
   int bx = blockIdx.x;

   __shared__ float partialSum[TILE_WIDTH];

   for(int i = 0; i < WIDTH/TILE_WIDTH; ++i)
   {
      partialSum[tx] = V_d[bx * TILE_WIDTH + tx];
      __syncthreads();


      for(unsigned int stride = 1; stride < blockDim.x; stride *= 2)
      {
         __syncthreads();
         if(tx % (2 * stride) == 0)
            partialSum[tx] += partialSum[tx + stride];
      }
   }

   if(tx % TILE_WIDTH == 0)
      V_d[bx * TILE_WIDTH + tx] = partialSum[tx];
}

int main(int argc, char * argv[])
{
   float * V_d;
   float * V_h;
   float * R_h;
   float * Result;
   float * ptr;

   dim3 dimBlock(TILE_WIDTH,1,1);
   dim3 dimGrid(BLOCKS,1,1);

   // Allocate memory on Host
   if((V_h = (float *)malloc(sizeof(float) * WIDTH)) == NULL)
   {
      printf("Error allocating memory on host\n");
      exit(-1);
   }

   if((R_h = (float *)malloc(sizeof(float) * MAX_WIDTH)) == NULL)
   {
      printf("Error allocating memory on host\n");
      exit(-1);
   }

   // If MAX_WIDTH is not a multiple of WIDTH, this won't work
   if(WIDTH % MAX_WIDTH != 0)
   {
      printf("The width of the vector must be a multiple of the maximum width\n");
      exit(-3);
   }

   // Initialize memory on host with 1.0f
   ptr = V_h;
   for(long long i = 0; i < WIDTH; ++i)
   {
      *ptr = 1.0f;
      ptr = &ptr[1];
   }

   ptr = V_h;

   // Allocate memory on device in global memory
   cudaMalloc((void**) &V_d, MAX_WIDTH*(sizeof(float)));
   float Pvalue = 0.0f;
   for(int i = 0; i < WIDTH/MAX_WIDTH; ++i)
   {


   if((Result = (float *) malloc(sizeof(float) * WIDTH)) == NULL)
   {
      printf("Error allocating memory on host\n");
      exit(-4);
   }

   for(int j = 0; j < MAX_WIDTH; ++j)
   {
      Result[j] = *ptr;
      ptr = &ptr[1];
   }

      ptr = &V_h[i*MAX_WIDTH];
      // Copy portion of data to device
      cudaMemcpy(V_d, Result, MAX_WIDTH*(sizeof(float)), cudaMemcpyHostToDevice);

      // Execute Kernel
      PartSum<<<dimGrid, dimBlock>>>(V_d);

      // Copy data back down to host
      cudaMemcpy(R_h, V_d, MAX_WIDTH*(sizeof(float)), cudaMemcpyDeviceToHost);

      for(int i = 0; i < MAX_WIDTH; i += TILE_WIDTH)
      {
         Pvalue += R_h[i];
      }
printf("Pvalue == %f\n", Pvalue);

  free(Result);


   }

//   printf("WIDTH == %d items\n", WIDTH);
//   printf("Value: %f\n", Pvalue);

   cudaFree(V_d);
   free(V_h);
   free(R_h);
   return(1);
}

Хорошо, я думаю, что я сузил проблему с V_d на устройстве.Я подозреваю, что я превышаю границы массива как-то.Если я выделю 2 раза объем памяти, который мне действительно нужен, программа завершит работу с ожидаемыми результатами.Проблема в том, что я не могу понять, что вызывает проблемы.

Al

Ответы [ 2 ]

2 голосов
/ 01 декабря 2011

Во-первых, спасибо всем, кто посмотрел на это и помог.

Во-вторых, я наконец понял, что я делаю неправильно. BLOCKS должен был быть определен как MAX_WIDTH/TILE_WIDTH, а не WIDTH/TILE_WIDTH. Глупая, глупая ошибка с моей стороны.

Еще раз спасибо.

2 голосов
/ 30 ноября 2011

Я думаю, что я заметил первую ошибку здесь:

  if(tx % TILE_WIDTH == 0)
      V_d[bx * TILE_WIDTH + tx] = partialSum[tx];

Диапазон tx составляет 0-511, и он никогда не достигал 512. Так что , если условие никогда не будет верным.Вы можете написать это как if (tx% (TILE_WIDTH-1) == 0) .

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