¿Cuál es la forma canónica de verificar los errores usando la API de tiempo de ejecución de CUDA?



Answers

La respuesta de talonmies anterior es una buena forma de abortar una aplicación de una manera de estilo assert .

Ocasionalmente, es posible que deseemos informarnos y recuperarnos de una condición de error en un contexto de C ++ como parte de una aplicación más grande.

Esta es una forma razonable de hacerlo lanzando una excepción de C ++ derivada de std::runtime_error utilizando thrust::system_error :

#include <thrust/system_error.h>
#include <thrust/system/cuda/error.h>
#include <sstream>

void throw_on_cuda_error(cudaError_t code, const char *file, int line)
{
  if(code != cudaSuccess)
  {
    std::stringstream ss;
    ss << file << "(" << line << ")";
    std::string file_and_line;
    ss >> file_and_line;
    throw thrust::system_error(code, thrust::cuda_category(), file_and_line);
  }
}

Esto incorporará el nombre de archivo, el número de línea y una descripción en idioma inglés de cudaError_t en el miembro cudaError_t .what() la excepción lanzada:

#include <iostream>

int main()
{
  try
  {
    // do something crazy
    throw_on_cuda_error(cudaSetDevice(-1), __FILE__, __LINE__);
  }
  catch(thrust::system_error &e)
  {
    std::cerr << "CUDA error after cudaSetDevice: " << e.what() << std::endl;

    // oops, recover
    cudaSetDevice(0);
  }

  return 0;
}

La salida:

$ nvcc exception.cu -run
CUDA error after cudaSetDevice: exception.cu(23): invalid device ordinal

Un cliente de some_function puede distinguir los errores de CUDA de otros tipos de errores si lo desea:

try
{
  // call some_function which may throw something
  some_function();
}
catch(thrust::system_error &e)
{
  std::cerr << "CUDA error during some_function: " << e.what() << std::endl;
}
catch(std::bad_alloc &e)
{
  std::cerr << "Bad memory allocation during some_function: " << e.what() << std::endl;
}
catch(std::runtime_error &e)
{
  std::cerr << "Runtime error during some_function: " << e.what() << std::endl;
}
catch(...)
{
  std::cerr << "Some other kind of error during some_function" << std::endl;

  // no idea what to do, so just rethrow the exception
  throw;
}

Debido a que thrust::system_error es std::runtime_error , alternativamente podemos manejarlo de la misma manera que una clase amplia de errores si no requerimos la precisión del ejemplo anterior:

try
{
  // call some_function which may throw something
  some_function();
}
catch(std::runtime_error &e)
{
  std::cerr << "Runtime error during some_function: " << e.what() << std::endl;
}
Question

Repasando las respuestas y los comentarios sobre las preguntas de CUDA, y en la wiki de la etiqueta de CUDA , veo que a menudo se sugiere que el estado de devolución de cada llamada API se revise para detectar errores. La documentación de la API contiene funciones como cudaGetLastError , cudaPeekAtLastError y cudaGetErrorString , pero ¿cuál es la mejor manera de juntarlas para detectar e informar errores de manera confiable sin requerir muchos códigos adicionales?




La solución discutida here funcionó bien para mí. Esta solución usa funciones de cuda integradas y es muy simple de implementar.

El código relevante se copia a continuación:

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

__global__ void foo(int *ptr)
{
  *ptr = 7;
}

int main(void)
{
  foo<<<1,1>>>(0);

  // make the host block until the device is finished with foo
  cudaDeviceSynchronize();

  // check for error
  cudaError_t error = cudaGetLastError();
  if(error != cudaSuccess)
  {
    // print the CUDA error message and exit
    printf("CUDA error: %s\n", cudaGetErrorString(error));
    exit(-1);
  }

  return 0;
}



Links