Destroying CUDA and CudaDeviceReset Streams

I implemented the following class using CUDA threads

class CudaStreams { private: int nStreams_; cudaStream_t* streams_; cudaStream_t active_stream_; public: // default constructor CudaStreams() { } // streams initialization void InitStreams(const int nStreams = 1) { nStreams_ = nStreams; // allocate and initialize an array of stream handles streams_ = (cudaStream_t*) malloc(nStreams_*sizeof(cudaStream_t)); for(int i = 0; i < nStreams_; i++) CudaSafeCall(cudaStreamCreate(&(streams_[i]))); active_stream_ = streams_[0];} // default destructor ~CudaStreams() { for(int i = 0; i<nStreams_; i++) CudaSafeCall(cudaStreamDestroy(streams_[i])); } }; 

If I run this simple code now

 void main( int argc, char** argv) { streams.InitStreams(1); streams.~CudaStreams(); cudaDeviceReset(); } 

after calling cudaDeviceReset() , I get the following message:

Unhandled exception 0x772f15de in test.exe file: 0x00000000.

What to do before calling the destructor to avoid this problem when using cudaDeviceReset() ?

EDIT

If I add free(streams_); to the destructor, namely

 ~CudaStreams() { for(int i = 0; i<nStreams_; i++) CudaSafeCall(cudaStreamDestroy(streams_[i])); // * free(streams_); } 

The following error message appears

 cudaSafeCall() failed at C:\Users\Documents\Project\Library\CudaStreams.cuh:79 : unknown error 

where line 79 indicated by the * in the destructor.

Also, if I use the same constructor and destructor instructions directly inside the code, namely

 void main( int argc, char** argv) { int nStreams_ = 3; cudaStream_t* streams_ = (cudaStream_t*) malloc(nStreams_*sizeof(cudaStream_t)); for(int i = 0; i < nStreams_; i++) CudaSafeCall(cudaStreamCreate(&(streams_[i]))); for(int i = 0; i<nStreams_; i++) CudaSafeCall(cudaStreamDestroy(streams_[i])); free(streams_); cudaDeviceReset(); } 

everything works well. Are defects related to poor class usage?

+1
source share
1 answer

There are two problems associated with the destructor of your class and scope.

First, let's start with a version of your main() that will work correctly:

 int main( int argc, char** argv) { { CudaStreams streams; streams.InitStreams(1); } cudaDeviceReset(); return 0; } 

This works correctly because the destructor for streams is called exactly once (when streams falls out of scope) and before the cudaDeviceReset call.

The original main() (or its compiled version, but more on that later ...) fails for two reasons. Take another look:

 int main( int argc, char** argv) { CudaStreams streams; streams.InitStreams(1); streams.~CudaStreams(); cudaDeviceReset(); return 0; } 

Here you explicitly call the destructor for streams (which you should almost never do), then cudaDeviceReset , then the destructor is called again in the return statement when streams falls out of scope. An automatic call to the destructor after the context is destroyed is the source of segfault / exception. The cudaStreamDestroy call tries to work with streams without a valid CUDA context. Thus, the solution should not contain any classes that cause CUDA API calls to go out of scope (or explicitly call their destructors) when there is no context.

If we made the third version as follows:

 int main( int argc, char** argv) { { CudaStreams streams; streams.InitStreams(1); streams.~CudaStreams(); } cudaDeviceReset(); return 0; } 

You will get a CUDA runtime error. Because the destructor receives the call twice. The first time (explicit) it will work. The second (implict, out of scope) will result in a runtime error: you have a valid context, but now it is trying to destroy non-existent threads.

As a final comment / question: how difficult would it be to publish a current compiled version of the code that you indicated in your original question? He literally demanded 5 extra lines to turn it into a proper play that someone could really compile and run. It seemed a little unreasonable for me to expect others to do their best to answer that they mainly debug questions, if you do not want to make similar efforts to provide useful code and information, which makes life much easier. I'm thinking about it. [end of rant]

+7
source

All Articles