From 7cf2f8c26882aee4cd3e95fe22967f04318b6bf7 Mon Sep 17 00:00:00 2001 From: Cedric Nugteren Date: Sat, 2 Jul 2016 15:34:55 +0200 Subject: Fixed some memory leaks related to events not properly cleaned-up --- CHANGELOG | 1 + samples/cache.c | 1 + samples/dgemv.c | 1 + samples/haxpy.c | 1 + samples/sasum.c | 1 + samples/sgemm.c | 1 + samples/sgemm.cpp | 1 + src/clpp11.hpp | 33 +++++++++++++++++++++------------ 8 files changed, 28 insertions(+), 12 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index fe8f7221..725eb116 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -2,6 +2,7 @@ Development version (next release) - Updated to version 6.0 of the CLCudaAPI C++11 OpenCL header - Fixed proper MSVC dllimport and dllexport declarations +- Fixed memory leaks related to events not being released Version 0.8.0 - Added support for half-precision floating-point (fp16) in the library diff --git a/samples/cache.c b/samples/cache.c index 7f876be1..a592824d 100644 --- a/samples/cache.c +++ b/samples/cache.c @@ -113,6 +113,7 @@ void run_example_routine(const cl_device_id device) { // Wait for completion clWaitForEvents(1, &event); + clReleaseEvent(event); // Retrieves the execution time clock_t diff = clock() - start; diff --git a/samples/dgemv.c b/samples/dgemv.c index 6ea0deb0..c22c9f37 100644 --- a/samples/dgemv.c +++ b/samples/dgemv.c @@ -85,6 +85,7 @@ int main(void) { // Wait for completion clWaitForEvents(1, &event); + clReleaseEvent(event); // Example completed. See "clblast_c.h" for status codes (0 -> success). printf("Completed DGEMV with status %d\n", status); diff --git a/samples/haxpy.c b/samples/haxpy.c index 3c7bb33a..d5b98e12 100644 --- a/samples/haxpy.c +++ b/samples/haxpy.c @@ -78,6 +78,7 @@ int main(void) { // Wait for completion clWaitForEvents(1, &event); + clReleaseEvent(event); // Copies the result back to the host clEnqueueReadBuffer(queue, device_b, CL_TRUE, 0, n*sizeof(cl_half), host_b, 0, NULL, NULL); diff --git a/samples/sasum.c b/samples/sasum.c index 3fdbb0eb..1518cc13 100644 --- a/samples/sasum.c +++ b/samples/sasum.c @@ -74,6 +74,7 @@ int main(void) { // Wait for completion clWaitForEvents(1, &event); + clReleaseEvent(event); // Copies the result back to the host clEnqueueReadBuffer(queue, device_output, CL_TRUE, 0, 1*sizeof(float), host_output, 0, NULL, NULL); diff --git a/samples/sgemm.c b/samples/sgemm.c index 79f30c83..b4827777 100644 --- a/samples/sgemm.c +++ b/samples/sgemm.c @@ -88,6 +88,7 @@ int main(void) { // Wait for completion clWaitForEvents(1, &event); + clReleaseEvent(event); // Example completed. See "clblast_c.h" for status codes (0 -> success). printf("Completed SGEMM with status %d\n", status); diff --git a/samples/sgemm.cpp b/samples/sgemm.cpp index 5fe7490a..a4b89968 100644 --- a/samples/sgemm.cpp +++ b/samples/sgemm.cpp @@ -96,6 +96,7 @@ int main() { // Record the execution time clWaitForEvents(1, &event); + clReleaseEvent(event); auto elapsed_time = std::chrono::steady_clock::now() - start_time; auto time_ms = std::chrono::duration(elapsed_time).count(); diff --git a/src/clpp11.hpp b/src/clpp11.hpp index f8bc2b02..1eeaf702 100644 --- a/src/clpp11.hpp +++ b/src/clpp11.hpp @@ -72,15 +72,24 @@ inline void CheckError(const cl_int status) { class Event { public: - // Constructor based on the regular OpenCL data-type - explicit Event(const cl_event event): event_(event) { } + // Constructor based on the regular OpenCL data-type: memory management is handled elsewhere + explicit Event(const cl_event event): + event_(new cl_event) { + *event_ = event; + } - // Regular constructor - explicit Event(): event_(nullptr) { } + // Regular constructor with memory management + explicit Event(): + event_(new cl_event, [](cl_event* e) { + if (*e) { CheckError(clReleaseEvent(*e)); } + delete e; + }) { + *event_ = nullptr; + } // Waits for completion of this event void WaitForCompletion() const { - CheckError(clWaitForEvents(1, &event_)); + CheckError(clWaitForEvents(1, &(*event_))); } // Retrieves the elapsed time of the last recorded event. Note that no error checking is done on @@ -89,20 +98,20 @@ class Event { float GetElapsedTime() const { WaitForCompletion(); auto bytes = size_t{0}; - clGetEventProfilingInfo(event_, CL_PROFILING_COMMAND_START, 0, nullptr, &bytes); + clGetEventProfilingInfo(*event_, CL_PROFILING_COMMAND_START, 0, nullptr, &bytes); auto time_start = size_t{0}; - clGetEventProfilingInfo(event_, CL_PROFILING_COMMAND_START, bytes, &time_start, nullptr); - clGetEventProfilingInfo(event_, CL_PROFILING_COMMAND_END, 0, nullptr, &bytes); + clGetEventProfilingInfo(*event_, CL_PROFILING_COMMAND_START, bytes, &time_start, nullptr); + clGetEventProfilingInfo(*event_, CL_PROFILING_COMMAND_END, 0, nullptr, &bytes); auto time_end = size_t{0}; - clGetEventProfilingInfo(event_, CL_PROFILING_COMMAND_END, bytes, &time_end, nullptr); + clGetEventProfilingInfo(*event_, CL_PROFILING_COMMAND_END, bytes, &time_end, nullptr); return (time_end - time_start) * 1.0e-6f; } // Accessor to the private data-member - cl_event& operator()() { return event_; } - cl_event* pointer() { return &event_; } + cl_event& operator()() { return *event_; } + cl_event* pointer() { return &(*event_); } private: - cl_event event_; + std::shared_ptr event_; }; // Pointer to an OpenCL event -- cgit v1.2.3