Обработка ошибок 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 тип ввода.

Мои вопросы следующие:

  1. Есть ли способ сделать cufftResult а также cudaError_t быть совместимым, чтобы я мог использовать CUDA_CALL на подпрограммах CUFFT и получить строку сообщения из кода ошибки?
  2. Есть ли какая-либо техническая причина, по которой следует реализовывать другую ошибку для библиотеки 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); \
    } \
}
Другие вопросы по тегам