CUFFT error handling

2019-01-12 04:58发布

问题:

I'm using the following macro for CUFFT error handling:

#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);
    }
}

This macro does not return the message string from an error code. The book "CUDA Programming: a developer's guide to parallel computing with GPUs" suggests using the following macro

#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); \
} }

(note: it has been somewhat customized without altering the functionalities). The book says: "This technique works for all the CUDA calls except for the invocation of kernels." However, when using CUDA_CALL on a CUFFT routine call, the compiler returns

a value of type "cufftResult" cannot be used to initialize an entity of type "const cudaError_t". 

It seems then that cufftResult and cudaError_t are not immediately compatible.

Investigating a bit more, from this NVIDIA CUDA Library link, it seems that cudaGetErrorString requires a cudaError_t input type.

My questions are the following:

  1. Is there a way to make cufftResult and cudaError_t be compatible, so that I can use CUDA_CALL on CUFFT routines and receive the message string from an error code?
  2. Is there any technical reason why implementing a different error for the CUFFT library? :-)

Thanks.

EDIT FOLLOWING ROBERT CROVELLA'S ANSWER

I have modified the CufftSafeCall routine as

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); \
}

}

to return also the error type string.

回答1:

cufft is not part of the cuda runtime api. cufft is a separate library of functions. Since it's separate, it makes sense not to make cufft error enums dependent on the cuda runtime api library; such linkages hamper independent development of modules, codes, and libraries.

So when the book mentions CUDA calls, they are referring to the cuda runtime api, not the cufft library api.

Since the enumerated values returned from cufft library calls are independent of (and mostly orthogonal to) the enumerated values returned from the cuda runtime api, I don't think it's possible in any straightforward way to harmonize the two sets in a single macro. And since cuda calls and cufft calls may be intermingled in any piece of code, I can't think of an environmental way to do it. Someone else may come up with a clever approach, however.

If you want a cufft error enum to string parser, there is one in /usr/local/cuda/samples/common/inc/helper_cuda.h (assuming standard linux CUDA 5 install) that may be of interest. Pasting it in here for convenience:

#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


回答2:

I use the following macro in my project:

// 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); \
    } \
}