API устройства Cublas выводит странный результат

0

Все: Недавно я попытался использовать последнее свойство cuda 5.5 для программы, то есть динамический параллелизм. Но у меня есть очень запутанная проблема. Мой код здесь:

    /* Includes, system */
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <iostream>
    using namespace std;
    /* Includes, cuda */
    #include <cuda_runtime.h>
    #include <cublas_v2.h>

    /* Includes, cuda helper functions */
    #include <helper_cuda.h>

    #include "kernels.cu"
    /* Matrix size */
    #define N  (275)

    #define LengthSignal (64)

    #define AmountSignal (255025)

    #define NBLOCKX (32768)

    #define NTHREADS_PER_BLOCK (128)
    /* Declaration of the function that computes sgemm using CUBLAS device API */

    __global__ void invokeDeviceCublasSgemm(float *d_A, float *Test);

    /* Main */
    int main(int argc, char **argv)
    {
      float *h_A;
      float *d_A = 0;
      int n2 = N * N;

      h_A = (float *)malloc(n2 * sizeof(h_A[0]));
  /* Fill the matrices with test data */
  for (int i = 0; i < n2; i++)
    {
      h_A[i] = rand() / (float)RAND_MAX;
    }

      cudaMalloc((void **)&d_A, n2 * sizeof(h_A[0]));

      /* Initialize the device matrices with the host matrices */
      //  cudaMemcpy(d_A, h_A, sizeof(float) * LengthSignal * AmountSignal, cudaMemcpyHostToDevice);
      cudaMemcpy(d_A, h_A, n2 * sizeof(h_A[0]), cudaMemcpyHostToDevice);

      int Length = 100;
      float *h_Test = (float *) malloc(sizeof(float) * Length);
      float *d_Test;
      cudaMalloc((void **) &d_Test, sizeof(float) * Length);
      cudaMemset(d_Test, 0, sizeof(float) * Length);

  invokeDeviceCublasSgemm<<<NBLOCKX, NTHREADS_PER_BLOCK>>>(d_A, d_Test);
  cudaMemcpy(h_Test, d_Test, sizeof(float) * Length, cudaMemcpyDeviceToHost);

  printf("\n The first 10 elements of d_A in location 1 are: \n");
  for (int j = 0; j < 10; j ++)
    {
      printf("%f ", h_Test[j]);
    }

  printf("\n The first 10 elements of d_A in location 2 are: \n");
  for (int j = 10; j < 20; j ++)
    {
      printf("%f ", h_Test[j]);
    }
  printf("\n");

  free(h_Test);
  cudaFree(d_Test);

  /* Memory clean up */
  free(h_A);
  cudaFree(d_A);
}

#ifndef __GLOBAL__CU__
#define __GLOBAL__CU__

__global__ void invokeDeviceCublasSgemm(float *d_A, float *Test)
{
  // save the first 10 elements of d_A in location 1
  for (int j = 0; j < 10; j ++)
    {
      Test[j] = d_A[j];
    }
  cublasHandle_t cnpHandle;
  cublasCreate(&cnpHandle);

    // save the first 10 elements of d_A in location 2
    for (int j = 10; j < 20; j ++)
      {
        Test[j] = d_A[j - 10];
      }
  cublasDestroy(cnpHandle);
}

#endif

Если я установил параметры конфигурации как <<< 1, 1 >>>, все будет хорошо. И результат такой:

Первые 10 элементов d_A в местоположении 1:

0,840188 0,394383 0,783099 0,798440 0,911647 0,197551 0,335223 0,768230 0,27775 0,553970

Первые 10 элементов d_A в местоположении 2:

0,840188 0,394383 0,783099 0,798440 0,911647 0,197551 0,335223 0,768230 0,27775 0,553970

Однако, если я установил параметры конфигурации как <<< 32768, 128 >>>, вывод довольно странный. И результат такой:

Первые 10 элементов d_A в местоположении 1:

-0.000000 0,000000 0,000000 0,000000 0,000000 0,000000 0,000000 0,000000 0,000000 0,000000

Первые 10 элементов d_A в местоположении 2:

0,000000 0,000000 0,000000 0,000000 0,000000 0,000000 0,000000 0,000000 0,000000 0,000000

Я действительно не знаю, почему! Мой код только что пришел из "образцов" с небольшим изменением.


И тогда я просто удаляю последний код "cublasDestroy (cnpHandle)", тогда он становится нормальным. И выход:

Первые 10 элементов d_A в местоположении 1:

0,840188 0,394383 0,783099 0,798440 0,911647 0,197551 0,335223 0,768230 0,27775 0,553970

Первые 10 элементов d_A в местоположении 2:

0,840188 0,394383 0,783099 0,798440 0,911647 0,197551 0,335223 0,768230 0,27775 0,553970


У кого-то была такая же проблема?

Благодарю!

Теги:
cuda
cublas

1 ответ

2
Лучший ответ

Соблюдайте правильную проверку ошибок cuda. Вы можете сделать это на вызовах API хоста, а также на вызовы API вашего устройства, а также на вызовы API CUBLAS (и вызовы ядра). Если вы не уверены, читать динамический параллелизм документации.

Вероятно, вы превысили количество запусков ядра, которые могут быть выдающимися в любое время. Существует (настраиваемый) предел 2048 запусков ядра, которые могут быть выдающимися. Так как ваш код выходит из строя с параметрами запуска ядра ядра <<<32768, 128>>>, это означает, что вы пытаетесь запустить потоки 32768x128, каждый из которых может попытаться запустить дочернее ядро. Если количество запусков ядра превысит лимит, оставшиеся запуски ядра будут терпеть неудачу.

"Но я не запускаю какие-либо дочерние ядра?" Фактически, использование устройства CUBLAS API предполагает, что ядра могут запускаться. Так работает система CUBLAS.

Чтобы действительно получить ясность, я снова настоятельно советую вам тщательно проверять ошибки.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню