added CUFFT errors handling into GPU module
This commit is contained in:
parent
8190837dd4
commit
a6d9cce500
@ -247,7 +247,8 @@ enum {
|
|||||||
CV_StsAssert= -215, /* assertion failed */
|
CV_StsAssert= -215, /* assertion failed */
|
||||||
CV_GpuNotSupported= -216,
|
CV_GpuNotSupported= -216,
|
||||||
CV_GpuApiCallError= -217,
|
CV_GpuApiCallError= -217,
|
||||||
CV_GpuNppCallError= -218
|
CV_GpuNppCallError= -218,
|
||||||
|
CV_GpuCufftCallError= -219
|
||||||
};
|
};
|
||||||
|
|
||||||
/****************************************************************************************\
|
/****************************************************************************************\
|
||||||
|
@ -44,13 +44,16 @@
|
|||||||
#define __OPENCV_CUDA_SAFE_CALL_HPP__
|
#define __OPENCV_CUDA_SAFE_CALL_HPP__
|
||||||
|
|
||||||
#include "cuda_runtime_api.h"
|
#include "cuda_runtime_api.h"
|
||||||
|
#include "cufft.h"
|
||||||
//#include <nppdefs.h>
|
//#include <nppdefs.h>
|
||||||
|
|
||||||
#if defined(__GNUC__)
|
#if defined(__GNUC__)
|
||||||
#define cudaSafeCall(expr) ___cudaSafeCall(expr, __FILE__, __LINE__, __func__)
|
#define cudaSafeCall(expr) ___cudaSafeCall(expr, __FILE__, __LINE__, __func__)
|
||||||
|
#define cufftSafeCall(expr) ___cufftSafeCall(expr, __FILE__, __LINE__, __func__)
|
||||||
#define nppSafeCall(expr) ___nppSafeCall(expr, __FILE__, __LINE__, __func__)
|
#define nppSafeCall(expr) ___nppSafeCall(expr, __FILE__, __LINE__, __func__)
|
||||||
#else /* defined(__CUDACC__) || defined(__MSVC__) */
|
#else /* defined(__CUDACC__) || defined(__MSVC__) */
|
||||||
#define cudaSafeCall(expr) ___cudaSafeCall(expr, __FILE__, __LINE__)
|
#define cudaSafeCall(expr) ___cudaSafeCall(expr, __FILE__, __LINE__)
|
||||||
|
#define cufftSafeCall(expr) ___cufftSafeCall(expr, __FILE__, __LINE__)
|
||||||
#define nppSafeCall(expr) ___nppSafeCall(expr, __FILE__, __LINE__)
|
#define nppSafeCall(expr) ___nppSafeCall(expr, __FILE__, __LINE__)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -58,15 +61,22 @@ namespace cv
|
|||||||
{
|
{
|
||||||
namespace gpu
|
namespace gpu
|
||||||
{
|
{
|
||||||
void error( const char *error_string, const char *file, const int line, const char *func = "");
|
void error(const char *error_string, const char *file, const int line, const char *func = "");
|
||||||
void nppError( int error, const char *file, const int line, const char *func = "");
|
void nppError(int err, const char *file, const int line, const char *func = "");
|
||||||
|
void cufftError(int err, const char *file, const int line, const char *func = "");
|
||||||
|
|
||||||
static inline void ___cudaSafeCall(cudaError_t err, const char *file, const int line, const char *func = "")
|
static inline void ___cudaSafeCall(cudaError_t err, const char *file, const int line, const char *func = "")
|
||||||
{
|
{
|
||||||
if( cudaSuccess != err)
|
if (cudaSuccess != err)
|
||||||
cv::gpu::error(cudaGetErrorString(err), file, line, func);
|
cv::gpu::error(cudaGetErrorString(err), file, line, func);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void ___cufftSafeCall(cufftResult_t err, const char *file, const int line, const char *func = "")
|
||||||
|
{
|
||||||
|
if (CUFFT_SUCCESS != err)
|
||||||
|
cv::gpu::cufftError(err, file, line, func);
|
||||||
|
}
|
||||||
|
|
||||||
static inline void ___nppSafeCall(int err, const char *file, const int line, const char *func = "")
|
static inline void ___nppSafeCall(int err, const char *file, const int line, const char *func = "")
|
||||||
{
|
{
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
|
@ -56,6 +56,9 @@ namespace
|
|||||||
{
|
{
|
||||||
#define error_entry(entry) { entry, #entry }
|
#define error_entry(entry) { entry, #entry }
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
// NPP errors
|
||||||
|
|
||||||
struct NppError
|
struct NppError
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
@ -116,6 +119,40 @@ namespace
|
|||||||
bool operator()(const NppError& e) const { return e.error == err; }
|
bool operator()(const NppError& e) const { return e.error == err; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
// CUFFT errors
|
||||||
|
|
||||||
|
struct CufftError
|
||||||
|
{
|
||||||
|
int code;
|
||||||
|
string message;
|
||||||
|
};
|
||||||
|
|
||||||
|
const CufftError cufft_errors[] =
|
||||||
|
{
|
||||||
|
error_entry(CUFFT_INVALID_PLAN),
|
||||||
|
error_entry(CUFFT_ALLOC_FAILED),
|
||||||
|
error_entry(CUFFT_INVALID_TYPE),
|
||||||
|
error_entry(CUFFT_INVALID_VALUE),
|
||||||
|
error_entry(CUFFT_INTERNAL_ERROR),
|
||||||
|
error_entry(CUFFT_EXEC_FAILED),
|
||||||
|
error_entry(CUFFT_SETUP_FAILED),
|
||||||
|
error_entry(CUFFT_INVALID_SIZE),
|
||||||
|
error_entry(CUFFT_UNALIGNED_DATA)
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CufftErrorComparer
|
||||||
|
{
|
||||||
|
CufftErrorComparer(int code_): code(code_) {}
|
||||||
|
bool operator()(const CufftError& other) const
|
||||||
|
{
|
||||||
|
return other.code == code;
|
||||||
|
}
|
||||||
|
int code;
|
||||||
|
};
|
||||||
|
|
||||||
|
const int cufft_error_num = sizeof(cufft_errors) / sizeof(cufft_errors[0]);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace cv
|
namespace cv
|
||||||
@ -138,6 +175,26 @@ namespace cv
|
|||||||
cv::error( cv::Exception(CV_GpuNppCallError, getNppErrorString(err), func, file, line) );
|
cv::error( cv::Exception(CV_GpuNppCallError, getNppErrorString(err), func, file, line) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const string getCufftErrorString(int err_code)
|
||||||
|
{
|
||||||
|
const CufftError* cufft_error = std::find_if(
|
||||||
|
cufft_errors, cufft_errors + cufft_error_num,
|
||||||
|
CufftErrorComparer(err_code));
|
||||||
|
|
||||||
|
bool found = cufft_error != cufft_errors + cufft_error_num;
|
||||||
|
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << (found ? cufft_error->message : "Unknown error code");
|
||||||
|
ss << " [Code = " << err_code << "]";
|
||||||
|
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
void cufftError(int err, const char *file, const int line, const char *func)
|
||||||
|
{
|
||||||
|
cv::error(cv::Exception(CV_GpuCufftCallError, getCufftErrorString(err), func, file, line));
|
||||||
|
}
|
||||||
|
|
||||||
void error(const char *error_string, const char *file, const int line, const char *func)
|
void error(const char *error_string, const char *file, const int line, const char *func)
|
||||||
{
|
{
|
||||||
int code = CV_GpuApiCallError;
|
int code = CV_GpuApiCallError;
|
||||||
|
@ -52,8 +52,6 @@ void cv::gpu::matchTemplate(const GpuMat&, const GpuMat&, GpuMat&, int) { throw_
|
|||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#include <cufft.h>
|
|
||||||
|
|
||||||
namespace cv { namespace gpu { namespace imgproc
|
namespace cv { namespace gpu { namespace imgproc
|
||||||
{
|
{
|
||||||
void multiplyAndNormalizeSpects(int n, float scale, const cufftComplex* a,
|
void multiplyAndNormalizeSpects(int n, float scale, const cufftComplex* a,
|
||||||
@ -271,27 +269,27 @@ namespace
|
|||||||
cufftReal* image_data;
|
cufftReal* image_data;
|
||||||
cufftReal* templ_data;
|
cufftReal* templ_data;
|
||||||
cufftReal* result_data;
|
cufftReal* result_data;
|
||||||
cudaMalloc((void**)&image_data, sizeof(cufftReal) * dft_size.area());
|
cudaSafeCall(cudaMalloc((void**)&image_data, sizeof(cufftReal) * dft_size.area()));
|
||||||
cudaMalloc((void**)&templ_data, sizeof(cufftReal) * dft_size.area());
|
cudaSafeCall(cudaMalloc((void**)&templ_data, sizeof(cufftReal) * dft_size.area()));
|
||||||
cudaMalloc((void**)&result_data, sizeof(cufftReal) * dft_size.area());
|
cudaSafeCall(cudaMalloc((void**)&result_data, sizeof(cufftReal) * dft_size.area()));
|
||||||
|
|
||||||
int spect_len = dft_size.height * (dft_size.width / 2 + 1);
|
int spect_len = dft_size.height * (dft_size.width / 2 + 1);
|
||||||
cufftComplex* image_spect;
|
cufftComplex* image_spect;
|
||||||
cufftComplex* templ_spect;
|
cufftComplex* templ_spect;
|
||||||
cufftComplex* result_spect;
|
cufftComplex* result_spect;
|
||||||
cudaMalloc((void**)&image_spect, sizeof(cufftComplex) * spect_len);
|
cudaSafeCall(cudaMalloc((void**)&image_spect, sizeof(cufftComplex) * spect_len));
|
||||||
cudaMalloc((void**)&templ_spect, sizeof(cufftComplex) * spect_len);
|
cudaSafeCall(cudaMalloc((void**)&templ_spect, sizeof(cufftComplex) * spect_len));
|
||||||
cudaMalloc((void**)&result_spect, sizeof(cufftComplex) * spect_len);
|
cudaSafeCall(cudaMalloc((void**)&result_spect, sizeof(cufftComplex) * spect_len));
|
||||||
|
|
||||||
cufftHandle planR2C, planC2R;
|
cufftHandle planR2C, planC2R;
|
||||||
CV_Assert(cufftPlan2d(&planC2R, dft_size.height, dft_size.width, CUFFT_C2R) == CUFFT_SUCCESS);
|
cufftSafeCall(cufftPlan2d(&planC2R, dft_size.height, dft_size.width, CUFFT_C2R));
|
||||||
CV_Assert(cufftPlan2d(&planR2C, dft_size.height, dft_size.width, CUFFT_R2C) == CUFFT_SUCCESS);
|
cufftSafeCall(cufftPlan2d(&planR2C, dft_size.height, dft_size.width, CUFFT_R2C));
|
||||||
|
|
||||||
GpuMat templ_roi(templ.size(), CV_32S, templ.data, templ.step);
|
GpuMat templ_roi(templ.size(), CV_32S, templ.data, templ.step);
|
||||||
GpuMat templ_block(dft_size, CV_32S, templ_data, dft_size.width * sizeof(cufftReal));
|
GpuMat templ_block(dft_size, CV_32S, templ_data, dft_size.width * sizeof(cufftReal));
|
||||||
copyMakeBorder(templ_roi, templ_block, 0, templ_block.rows - templ_roi.rows, 0,
|
copyMakeBorder(templ_roi, templ_block, 0, templ_block.rows - templ_roi.rows, 0,
|
||||||
templ_block.cols - templ_roi.cols, 0);
|
templ_block.cols - templ_roi.cols, 0);
|
||||||
CV_Assert(cufftExecR2C(planR2C, templ_data, templ_spect) == CUFFT_SUCCESS);
|
cufftSafeCall(cufftExecR2C(planR2C, templ_data, templ_spect));
|
||||||
|
|
||||||
GpuMat image_block(dft_size, CV_32S, image_data, dft_size.width * sizeof(cufftReal));
|
GpuMat image_block(dft_size, CV_32S, image_data, dft_size.width * sizeof(cufftReal));
|
||||||
|
|
||||||
@ -306,10 +304,10 @@ namespace
|
|||||||
copyMakeBorder(image_roi, image_block, 0, image_block.rows - image_roi.rows, 0,
|
copyMakeBorder(image_roi, image_block, 0, image_block.rows - image_roi.rows, 0,
|
||||||
image_block.cols - image_roi.cols, 0);
|
image_block.cols - image_roi.cols, 0);
|
||||||
|
|
||||||
CV_Assert(cufftExecR2C(planR2C, image_data, image_spect) == CUFFT_SUCCESS);
|
cufftSafeCall(cufftExecR2C(planR2C, image_data, image_spect));
|
||||||
imgproc::multiplyAndNormalizeSpects(spect_len, 1.f / dft_size.area(),
|
imgproc::multiplyAndNormalizeSpects(spect_len, 1.f / dft_size.area(),
|
||||||
image_spect, templ_spect, result_spect);
|
image_spect, templ_spect, result_spect);
|
||||||
CV_Assert(cufftExecC2R(planC2R, result_spect, result_data) == CUFFT_SUCCESS);
|
cufftSafeCall(cufftExecC2R(planC2R, result_spect, result_data));
|
||||||
|
|
||||||
Size result_roi_size;
|
Size result_roi_size;
|
||||||
result_roi_size.width = min(x + block_size.width, result.cols) - x;
|
result_roi_size.width = min(x + block_size.width, result.cols) - x;
|
||||||
@ -320,15 +318,15 @@ namespace
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cufftDestroy(planR2C);
|
cufftSafeCall(cufftDestroy(planR2C));
|
||||||
cufftDestroy(planC2R);
|
cufftSafeCall(cufftDestroy(planC2R));
|
||||||
|
|
||||||
cudaFree(image_spect);
|
cudaSafeCall(cudaFree(image_spect));
|
||||||
cudaFree(templ_spect);
|
cudaSafeCall(cudaFree(templ_spect));
|
||||||
cudaFree(result_spect);
|
cudaSafeCall(cudaFree(result_spect));
|
||||||
cudaFree(image_data);
|
cudaSafeCall(cudaFree(image_data));
|
||||||
cudaFree(templ_data);
|
cudaSafeCall(cudaFree(templ_data));
|
||||||
cudaFree(result_data);
|
cudaSafeCall(cudaFree(result_data));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -64,6 +64,7 @@
|
|||||||
|
|
||||||
#include "internal_shared.hpp"
|
#include "internal_shared.hpp"
|
||||||
#include "cuda_runtime_api.h"
|
#include "cuda_runtime_api.h"
|
||||||
|
#include "cufft.h"
|
||||||
#include "opencv2/gpu/stream_accessor.hpp"
|
#include "opencv2/gpu/stream_accessor.hpp"
|
||||||
#include "npp.h"
|
#include "npp.h"
|
||||||
#include "npp_staging.h"
|
#include "npp_staging.h"
|
||||||
|
Loading…
Reference in New Issue
Block a user