Обработка ошибок CUFFT
Я использую следующий макрос для обработки ошибок CUFFT:
#define cufftSafeCall(err) __cufftSafeCall(err, __FILE__, __LINE__)
inline void __cufftSafeCall(cufftResult err, const char *file, const int line)
{
if( CUFFT_SUCCESS != err) {
fprintf(stderr, "cufftSafeCall() CUFFT error in file <%s>, line %i.\n",
file, line);
getch(); exit(-1);
}
}
Этот макрос не возвращает строку сообщения из кода ошибки. В книге "Программирование CUDA: руководство разработчика по параллельным вычислениям с графическими процессорами" предлагается использовать следующий макрос
#define CUDA_CALL(call) { const cudaError_t err = (call); \
if(err != cudaSuccess) \
{ \
fprintf(stderr, "CUDA error in file '%s', line %d\n %s\nerror %d: %s\nterminating!\n",__FILE__, __LINE__,err, \
cudaGetErrorString(err)); \
cudaDeviceReset(); assert(0); \
} }
(примечание: он был несколько настроен без изменения функциональности). В книге сказано: "Этот метод работает для всех вызовов CUDA, за исключением вызова ядер". Однако при использовании CUDA_CALL
при вызове процедуры CUFFT компилятор возвращает
a value of type "cufftResult" cannot be used to initialize an entity of type "const cudaError_t".
Кажется, что cufftResult
а также cudaError_t
не сразу совместимы.
Из этой ссылки на Библиотеку NVIDIA CUDA можно узнать немного больше. cudaGetErrorString
требует cudaError_t
тип ввода.
Мои вопросы следующие:
- Есть ли способ сделать
cufftResult
а такжеcudaError_t
быть совместимым, чтобы я мог использоватьCUDA_CALL
на подпрограммах CUFFT и получить строку сообщения из кода ошибки? - Есть ли какая-либо техническая причина, по которой следует реализовывать другую ошибку для библиотеки CUFFT? :-)
Благодарю.
ИЗМЕНИТЬ СЛЕДУЮЩИЙ ОТВЕТ РОБЕРТА КРОВЕЛЛЫ
Я изменил процедуру CufftSafeCall как
inline void __cufftSafeCall(cufftResult err, const char *file, const int line)
{
if( CUFFT_SUCCESS != err) {
fprintf(stderr, "CUFFT error in file '%s', line %d\n %s\nerror %d: %s\nterminating!\n",__FILE__, __LINE__,err, \
_cudaGetErrorEnum(err)); \
cudaDeviceReset(); assert(0); \
}
}
вернуть также строку типа ошибки.
2 ответа
Cufft не является частью API CUDA Runtime. cufft - это отдельная библиотека функций. Поскольку он разделен, имеет смысл не делать перечисления ошибок cufft зависимыми от библиотеки API времени выполнения cuda; такие связи затрудняют самостоятельную разработку модулей, кодов и библиотек.
Поэтому, когда в книге упоминаются вызовы CUDA, они ссылаются на API времени выполнения cuda, а не API библиотеки cufft.
Поскольку перечисляемые значения, возвращаемые из вызовов библиотеки cufft, не зависят (и в основном ортогональны) от перечисляемых значений, возвращаемых из API времени выполнения cuda, я не думаю, что можно каким-либо простым способом согласовать два набора в одном макросе. А так как вызовы cuda и вызовы cufft могут смешиваться в любом фрагменте кода, я не могу придумать экологического способа сделать это. Кто-то другой может придумать умный подход, однако.
Если вы хотите, чтобы перечисление ошибок с помощью cufft было обработчиком строк, есть один в /usr/local/cuda/samples/common/inc/helper_cuda.h
(при условии стандартной установки Linux CUDA 5), которая может представлять интерес. Вставьте его здесь для удобства:
#ifdef _CUFFT_H_
// cuFFT API errors
static const char *_cudaGetErrorEnum(cufftResult error)
{
switch (error)
{
case CUFFT_SUCCESS:
return "CUFFT_SUCCESS";
case CUFFT_INVALID_PLAN:
return "CUFFT_INVALID_PLAN";
case CUFFT_ALLOC_FAILED:
return "CUFFT_ALLOC_FAILED";
case CUFFT_INVALID_TYPE:
return "CUFFT_INVALID_TYPE";
case CUFFT_INVALID_VALUE:
return "CUFFT_INVALID_VALUE";
case CUFFT_INTERNAL_ERROR:
return "CUFFT_INTERNAL_ERROR";
case CUFFT_EXEC_FAILED:
return "CUFFT_EXEC_FAILED";
case CUFFT_SETUP_FAILED:
return "CUFFT_SETUP_FAILED";
case CUFFT_INVALID_SIZE:
return "CUFFT_INVALID_SIZE";
case CUFFT_UNALIGNED_DATA:
return "CUFFT_UNALIGNED_DATA";
}
return "<unknown>";
}
#endif
Я использую следующий макрос в моем проекте:
// NOTE: include cufft to import '_cudaGetErrorEnum(cufftResult error)'
#include <cufft.h>
#include <helper_cuda.h>
#define CHECK_CUFFT_ERRORS(call) { \
cufftResult_t err; \
if ((err = (call)) != CUFFT_SUCCESS) { \
fprintf(stderr, "cuFFT error %d:%s at %s:%d\n", err, _cudaGetErrorEnum(err), \
__FILE__, __LINE__); \
exit(1); \
} \
}