我正在寫一個「錯誤檢查」功能,每當遇到錯誤時都會拋出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
不要尷尬,你不知道,但現在你做... –