我正在写一个“错误检查”功能,每当遇到错误时都会抛出std::runtime_error
(下面的代码示例)。
现状:
比方说,在foo
构造函数(文件:下面fooClass.h
样本)我是能够成功地设置CUDA设备和分配GPU内存,但我对cudaMemcpy(***)
调用返回的任何错误原因。这意味着我的errchk(***)
函数正在抛出异常并将控制权转移到main()
函数(文件中:Start.cpp
)。
因为foo
构造并没有完成它的工作,没有创建foo
对象和~foo()
析构函数不叫,因此以前分配GPU资源一直没有公布。
我知道try
块main()
应该以相反的顺序取消分配所有资源到它们的初始化(每当抛出异常时)。
问题1:
这是否意味着我经历了GPU的内存泄漏?或以某种方式throw
, try
和catch
可以处理这种情况?
问题#2(?意见基础?):
我学习C++异常体系和为此,我想知道这是否是一个好主意,抛出异常无处不在,抓住他们只在main()
功能?
我认为这是值得考虑的,因为那时我可以结束我的程序在“自然”的方式 - return EXIT_FAILURE;
反对exit(EXIT_FAILURE);
如果我的类抛出一个被捕获的异常,是否会分配GPU内存泄漏?
ErrorCheck.h:(整个文件)
#pragma once
#ifndef __ERROR_CHECK_H__
#define __ERROR_CHECK_H__
#include <stdexcept>
// The function:
template <typename T>
bool errchk(const T check, const char* file, unsigned int line, const char* from, const char* func);
// How To call it:
#define ERRCHK(_check) \
errchk(_check, __FILE__, __LINE__, __FUNC__, #_check)
#endif // !__ERROR_CHECK_H__
ErrorCheck.cpp:(简化版)
// Include:
#include <cuda.h> // cudaError_t
#include <cuda_runtime_api.h>
#include <cufft.h> // cufftResult_t
#include <cublas.h> // cublasStatus_t
#include <curand_kernel.h> // curandStatus_t
#include <cusolver_common.h> // cusolverStatus_t
#include <cusparse.h> // cusparseStatus_t
#include <stdexcept>
#include "ErrorCheck.h"
// Functions bellow are overloaded 7 times for every error type from headers included above
inline const bool testForError(const Type & check) { return check != SuccessValue; };
inline const char * getErrorName(const Type & error) { /* ... */ };
inline const char * getErrorString(const Type & error) { /* ... */ };
// The function:
template <typename T, T successValue>
void errchk(const T check, const char* file, unsigned int line, const char* from, const char* func)
{
if (testForError(check)) {
// generate error description in form of a string.
throw std::runtime_error(errorDescription);
}
}
// Instantiations:
template void errchk <bool > (const bool check, const char * file, unsigned int line, const char * from, const char * func);
template void errchk <cudaError_t > (const cudaError_t check, const char * file, unsigned int line, const char * from, const char * func);
template void errchk <cufftResult_t > (const cufftResult_t check, const char * file, unsigned int line, const char * from, const char * func);
template void errchk <cublasStatus_t > (const cublasStatus_t check, const char * file, unsigned int line, const char * from, const char * func);
template void errchk <curandStatus_t > (const curandStatus_t check, const char * file, unsigned int line, const char * from, const char * func);
template void errchk <cusolverStatus_t> (const cusolverStatus_t check, const char * file, unsigned int line, const char * from, const char * func);
template void errchk <cusparseStatus_t> (const cusparseStatus_t check, const char * file, unsigned int line, const char * from, const char * func);
fooClass.h:
#include "ErrorCheck.h"
class foo
{
private:
float * dev_floatArray;
float * host_floatArray;
public:
foo() {
// Do something...
ERRCHK(cudaSetDevice(0));
ERRCHK(cudaMalloc(&dev_floatArray, 10000 * sizeof(float)));
// Do something...
ERRCHK(cudaMemcpy(host_floatArray, dev_floatArray, 10000 * sizeof(float), cudaMemcpyDeviceToHost));
// Do something...
}
~foo() {
// Do something...
ERRCHK(cudaFree(dev_floatArray));
ERRCHK(cudaDeviceReset());
}
}
Start.cpp:
#include <iostream>
#include "fooClass.h"
using namespace std;
int main() {
try {
foo bar; // constructor of "foo" Class is called.
}
catch (std::runtime_error error) {
cout << error.what() << endl;
getchar();
return EXIT_FAILURE;
}
}
你有没有听说过RAII?处理这种问题是一种非常常见的模式。 –
@让BaptisteYunès 有点不好意思承认,但从来没有听说过...但好我们学习生活的全部。 :) 谢谢。我认为你的回答解决了我的两个问题。 – cukier9a7b5
不要尴尬,你不知道,但现在你做... –