Ошибки CUDA Matrix Addition Seg - PullRequest
       3

Ошибки CUDA Matrix Addition Seg

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

У меня просто вопрос о моей программе cuda, которую я написал. Это позволяет мне вводить размер матрицы, столбцов и строк. Допустим, я ввожу ~ 1124, и он прекрасно вычисляется. Однако, скажем, я ввожу 1149, это происходит сбой сегмента ПОСЛЕ вычислений в устройстве (я думаю, что это сбой сегмента во время копирования). Но, скажем, я ввожу 2000, это вызывает ошибки ДО вычислений в устройстве (я думаю, что это вызывает ошибки во время копирования). Я думаю, что моя проблема все с управлением памятью. Если бы вы, ребята, могли указать мне правильное направление, я был бы признателен.

Я обновил код тем, как он называется. В новом редакторе (внизу) он содержит: sumMatrix (пустая матрица с размером eleCount1, который является размером всей матрицы), matrixOne (первая матрица), matrixTwo (вторая матрица, расположенная таким же образом, как выполняется matrix1) , eleCount1 (весь размер матрицы). MatrixOne и два считываются из файла.

Не был уверен, нужно ли кому-то видеть это о моем графическом процессоре:

  • Общий объем постоянной памяти: 65536 байт
  • Общий объем разделяемой памяти на блок: 49152 байта
  • Общее количество регистров, доступных на блок: 32768
  • Размер основы: 32
  • Максимальное количество потоков в блоке: 1024
  • Максимальные размеры каждого измерения блока: 1024 x 1024 x 64
  • Максимальные размеры каждого измерения сетки: 65535 x 65535 x 65535

Код:

void addKernel(float *c, float *a, float *b)
{
    int i = threadIdx.x;
    int idx = blockDim.x * blockIdx.x + threadIdx.x;
    c[idx] = a[idx] + b[idx];
}
cudaError_t addWithCuda(float *c, float *a, float *b, size_t size)
{
  float *dev_a = 0;
  float *dev_b = 0;
  float *dev_c = 0;
  cudaError_t cudaStatus;
  blocksNeeded=(size/MAXTHREADS)+1;
  int threadsPerBlock = MAXTHREADS/blocksNeeded+1;
  cudaStatus = cudaMalloc((void**)&dev_c, size * sizeof(float));
  if (cudaStatus != cudaSuccess) {
      fprintf(stderr, "cudaMalloc failed!");
      goto Error;
  }

  cudaStatus = cudaMalloc((void**)&dev_a, size * sizeof(float));
  if (cudaStatus != cudaSuccess) {
      fprintf(stderr, "cudaMalloc failed!");
      goto Error;
  }

  cudaStatus = cudaMalloc((void**)&dev_b, size * sizeof(float));
  if (cudaStatus != cudaSuccess) {
      fprintf(stderr, "cudaMalloc failed!");
      goto Error;
  }

  cudaStatus = cudaMemcpy(dev_a, a, size * sizeof(float), cudaMemcpyHostToDevice);
  if (cudaStatus != cudaSuccess) {
      fprintf(stderr, "cudaMemcpy failed!");
      goto Error;
  }

  cudaStatus = cudaMemcpy(dev_b, b, size * sizeof(float), cudaMemcpyHostToDevice);
  if (cudaStatus != cudaSuccess) {
      fprintf(stderr, "cudaMemcpy failed!");
      goto Error;
  }

  addKernel<<<blocksNeeded, size>>>(dev_c, dev_a, dev_b);
  cudaStatus = cudaDeviceSynchronize();

  if (cudaStatus != cudaSuccess) {
      fprintf(stderr, "cudaDeviceSynchronize returned error code %d after launching addKernel!\n", cudaStatus);
      goto Error;
  }
  cudaStatus = cudaMemcpy(c, dev_c, size * sizeof(float), cudaMemcpyDeviceToHost);
  if (cudaStatus != cudaSuccess) {
      fprintf(stderr, "cudaMemcpy failed!");
      goto Error;
  }

Error:
  cudaFree(dev_c);
  cudaFree(dev_a);
  cudaFree(dev_b);

  return cudaStatus;
}
//edit: added how the matrix are allocated
    float* matrixOne = (float*)malloc(sizeof(float)*file1size);
int matrixIndex = 0;
readFromFile(fd,byte, matrixOneWidth, matrixOneHeight,  matrixOne);

//matrixOneHeight--;
eleCount1 = matrixOneHeight*matrixOneWidth;
matrixOne= (float*)realloc(matrixOne,eleCount1*sizeof(float));
//Edit: Added how the addWithCuda is called.
cudaStatus = addWithCuda(sumMatrix, matrixOne,matrixTwo,eleCount1);
//sumMatrix is created after we know how large the matrices are. 
float sumMatrix[eleCount1];

Ответы [ 2 ]

0 голосов
/ 08 декабря 2011

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

0 голосов
/ 08 декабря 2011

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

__global__ void addKernel(float *c, float *a, float *b, int size)
{
    int i = threadIdx.x;
    int idx = blockDim.x * blockIdx.x + threadIdx.x;
    if(idx < size) c[idx] = a[idx] + b[idx];
}
...