diff --git a/test/cuda/beta_double.cu b/test/cuda/beta_double.cu index 85abeb536..bf5722759 100644 --- a/test/cuda/beta_double.cu +++ b/test/cuda/beta_double.cu @@ -117,21 +117,6 @@ int main(void) } std::cout << "Test PASSED with calculation time: " << t << "s" << std::endl; - - // Reset the device and exit - // cudaDeviceReset causes the driver to clean up all state. While - // not mandatory in normal operation, it is good practice. It is also - // needed to ensure correct operation when the application is being - // profiled. Calling cudaDeviceReset causes all profile data to be - // flushed before the application exits - err = cudaDeviceReset(); - - if (err != cudaSuccess) - { - std::cerr << "Failed to deinitialize the device! error=" << cudaGetErrorString(err) << std::endl; - return EXIT_FAILURE; - } - std::cout << "Done\n"; } catch(const std::exception& e) diff --git a/test/cuda/beta_float.cu b/test/cuda/beta_float.cu index 098cf1d0f..a37254e3d 100644 --- a/test/cuda/beta_float.cu +++ b/test/cuda/beta_float.cu @@ -117,21 +117,6 @@ int main(void) } std::cout << "Test PASSED with calculation time: " << t << "s" << std::endl; - - // Reset the device and exit - // cudaDeviceReset causes the driver to clean up all state. While - // not mandatory in normal operation, it is good practice. It is also - // needed to ensure correct operation when the application is being - // profiled. Calling cudaDeviceReset causes all profile data to be - // flushed before the application exits - err = cudaDeviceReset(); - - if (err != cudaSuccess) - { - std::cerr << "Failed to deinitialize the device! error=" << cudaGetErrorString(err) << std::endl; - return EXIT_FAILURE; - } - std::cout << "Done\n"; } catch(const std::exception& e) diff --git a/test/cuda/cbrt_double.cu b/test/cuda/cbrt_double.cu index 71ce20728..e2179c393 100644 --- a/test/cuda/cbrt_double.cu +++ b/test/cuda/cbrt_double.cu @@ -90,21 +90,6 @@ int main(void) } std::cout << "Test PASSED, normal calculation time: " << t << "s" << std::endl; - - // Reset the device and exit - // cudaDeviceReset causes the driver to clean up all state. While - // not mandatory in normal operation, it is good practice. It is also - // needed to ensure correct operation when the application is being - // profiled. Calling cudaDeviceReset causes all profile data to be - // flushed before the application exits - err = cudaDeviceReset(); - - if (err != cudaSuccess) - { - std::cerr << "Failed to deinitialize the device! error=" << cudaGetErrorString(err) << std::endl; - return EXIT_FAILURE; - } - std::cout << "Done\n"; return 0; diff --git a/test/cuda/cbrt_float.cu b/test/cuda/cbrt_float.cu index 9104f9b80..b57446337 100644 --- a/test/cuda/cbrt_float.cu +++ b/test/cuda/cbrt_float.cu @@ -89,21 +89,6 @@ int main(void) } std::cout << "Test PASSED in " << t << "s" << std::endl; - - // Reset the device and exit - // cudaDeviceReset causes the driver to clean up all state. While - // not mandatory in normal operation, it is good practice. It is also - // needed to ensure correct operation when the application is being - // profiled. Calling cudaDeviceReset causes all profile data to be - // flushed before the application exits - err = cudaDeviceReset(); - - if (err != cudaSuccess) - { - std::cerr << "Failed to deinitialize the device! error=" << cudaGetErrorString(err) << std::endl; - return EXIT_FAILURE; - } - std::cout << "Done\n"; return 0; diff --git a/test/cuda/cuda_managed_ptr.hpp b/test/cuda/cuda_managed_ptr.hpp index ad40da297..6ec7f3f7f 100644 --- a/test/cuda/cuda_managed_ptr.hpp +++ b/test/cuda/cuda_managed_ptr.hpp @@ -24,10 +24,44 @@ protected: int managed_holder_base::count = 0; +// +// Reset the device and exit: +// cudaDeviceReset causes the driver to clean up all state. While +// not mandatory in normal operation, it is good practice. It is also +// needed to ensure correct operation when the application is being +// profiled. Calling cudaDeviceReset causes all profile data to be +// flushed before the application exits. +// +// We have a global instance of this class, plus instances for each +// managed pointer. Last one out the door switches the lights off. +// +class cudaResetter +{ + static int count; +public: + cudaResetter() { ++count; } + ~cudaResetter() + { + if(--count == 0) + { + cudaError_t err = cudaDeviceReset(); + if(err != cudaSuccess) + { + std::cerr << "Failed to deinitialize the device! error=" << cudaGetErrorString(err) << std::endl; + } + } + } +}; + +int cudaResetter::count = 0; + +cudaResetter global_resetter; + template class cuda_managed_ptr { T* data; + static const cudaResetter resetter; cuda_managed_ptr(const cuda_managed_ptr&) = delete; cuda_managed_ptr& operator=(cuda_managed_ptr const&) = delete; void free() @@ -35,7 +69,11 @@ class cuda_managed_ptr if(data) { cudaDeviceSynchronize(); - cudaFree(data); + cudaError_t err = cudaFree(data); + if(err != cudaSuccess) + { + std::cerr << "Failed to deinitialize the device! error=" << cudaGetErrorString(err) << std::endl; + } } } public: @@ -92,6 +130,9 @@ public: const T& operator[](std::size_t n)const { return data[n]; } }; +template +cudaResetter const cuda_managed_ptr::resetter; + #endif diff --git a/test/cuda/erf_double.cu b/test/cuda/erf_double.cu index ee570e5bd..ebece0bea 100644 --- a/test/cuda/erf_double.cu +++ b/test/cuda/erf_double.cu @@ -89,21 +89,6 @@ int main(void) } std::cout << "Test PASSED with calculation time: " << t << "s" << std::endl; - - // Reset the device and exit - // cudaDeviceReset causes the driver to clean up all state. While - // not mandatory in normal operation, it is good practice. It is also - // needed to ensure correct operation when the application is being - // profiled. Calling cudaDeviceReset causes all profile data to be - // flushed before the application exits - err = cudaDeviceReset(); - - if (err != cudaSuccess) - { - std::cerr << "Failed to deinitialize the device! error=" << cudaGetErrorString(err) << std::endl; - return EXIT_FAILURE; - } - std::cout << "Done\n"; return 0; diff --git a/test/cuda/erf_float.cu b/test/cuda/erf_float.cu index 41420a055..8e1b36799 100644 --- a/test/cuda/erf_float.cu +++ b/test/cuda/erf_float.cu @@ -90,21 +90,6 @@ int main(void) } std::cout << "Test PASSED in " << t << "s" << std::endl; - - // Reset the device and exit - // cudaDeviceReset causes the driver to clean up all state. While - // not mandatory in normal operation, it is good practice. It is also - // needed to ensure correct operation when the application is being - // profiled. Calling cudaDeviceReset causes all profile data to be - // flushed before the application exits - err = cudaDeviceReset(); - - if (err != cudaSuccess) - { - std::cerr << "Failed to deinitialize the device! error=" << cudaGetErrorString(err) << std::endl; - return EXIT_FAILURE; - } - std::cout << "Done\n"; return 0; diff --git a/test/cuda/erf_inv_double.cu b/test/cuda/erf_inv_double.cu index 151563ac6..4c2415f1a 100644 --- a/test/cuda/erf_inv_double.cu +++ b/test/cuda/erf_inv_double.cu @@ -96,21 +96,6 @@ int main(void) } std::cout << "Test PASSED with calculation time: " << t << "s" << std::endl; - - // Reset the device and exit - // cudaDeviceReset causes the driver to clean up all state. While - // not mandatory in normal operation, it is good practice. It is also - // needed to ensure correct operation when the application is being - // profiled. Calling cudaDeviceReset causes all profile data to be - // flushed before the application exits - err = cudaDeviceReset(); - - if (err != cudaSuccess) - { - std::cerr << "Failed to deinitialize the device! error=" << cudaGetErrorString(err) << std::endl; - return EXIT_FAILURE; - } - std::cout << "Done\n"; return 0; diff --git a/test/cuda/erf_inv_float.cu b/test/cuda/erf_inv_float.cu index 1404c8630..0afb32e82 100644 --- a/test/cuda/erf_inv_float.cu +++ b/test/cuda/erf_inv_float.cu @@ -96,21 +96,6 @@ int main(void) } std::cout << "Test PASSED with calculation time: " << t << "s" << std::endl; - - // Reset the device and exit - // cudaDeviceReset causes the driver to clean up all state. While - // not mandatory in normal operation, it is good practice. It is also - // needed to ensure correct operation when the application is being - // profiled. Calling cudaDeviceReset causes all profile data to be - // flushed before the application exits - err = cudaDeviceReset(); - - if (err != cudaSuccess) - { - std::cerr << "Failed to deinitialize the device! error=" << cudaGetErrorString(err) << std::endl; - return EXIT_FAILURE; - } - std::cout << "Done\n"; return 0; diff --git a/test/cuda/gamma_p_deriv_double.cu b/test/cuda/gamma_p_deriv_double.cu index 938202f68..834318f17 100644 --- a/test/cuda/gamma_p_deriv_double.cu +++ b/test/cuda/gamma_p_deriv_double.cu @@ -111,21 +111,6 @@ int main(void) } std::cout << "Test PASSED with calculation time: " << t << "s" << std::endl; - - // Reset the device and exit - // cudaDeviceReset causes the driver to clean up all state. While - // not mandatory in normal operation, it is good practice. It is also - // needed to ensure correct operation when the application is being - // profiled. Calling cudaDeviceReset causes all profile data to be - // flushed before the application exits - err = cudaDeviceReset(); - - if (err != cudaSuccess) - { - std::cerr << "Failed to deinitialize the device! error=" << cudaGetErrorString(err) << std::endl; - return EXIT_FAILURE; - } - std::cout << "Done\n"; } catch(const std::exception& e) diff --git a/test/cuda/gamma_p_deriv_float.cu b/test/cuda/gamma_p_deriv_float.cu index acb95dc8c..53b8daa8d 100644 --- a/test/cuda/gamma_p_deriv_float.cu +++ b/test/cuda/gamma_p_deriv_float.cu @@ -123,21 +123,6 @@ int main(void) } std::cout << "Test PASSED with calculation time: " << t << "s" << std::endl; - - // Reset the device and exit - // cudaDeviceReset causes the driver to clean up all state. While - // not mandatory in normal operation, it is good practice. It is also - // needed to ensure correct operation when the application is being - // profiled. Calling cudaDeviceReset causes all profile data to be - // flushed before the application exits - err = cudaDeviceReset(); - - if (err != cudaSuccess) - { - std::cerr << "Failed to deinitialize the device! error=" << cudaGetErrorString(err) << std::endl; - return EXIT_FAILURE; - } - std::cout << "Done\n"; } catch(const std::exception& e) diff --git a/test/cuda/gamma_p_double.cu b/test/cuda/gamma_p_double.cu index ff5a7eb8c..2d0f6ca5f 100644 --- a/test/cuda/gamma_p_double.cu +++ b/test/cuda/gamma_p_double.cu @@ -123,21 +123,6 @@ int main(void) } std::cout << "Test PASSED with calculation time: " << t << "s" << std::endl; - - // Reset the device and exit - // cudaDeviceReset causes the driver to clean up all state. While - // not mandatory in normal operation, it is good practice. It is also - // needed to ensure correct operation when the application is being - // profiled. Calling cudaDeviceReset causes all profile data to be - // flushed before the application exits - err = cudaDeviceReset(); - - if (err != cudaSuccess) - { - std::cerr << "Failed to deinitialize the device! error=" << cudaGetErrorString(err) << std::endl; - return EXIT_FAILURE; - } - std::cout << "Done\n"; } catch(const std::exception& e) diff --git a/test/cuda/gamma_p_float.cu b/test/cuda/gamma_p_float.cu index 12cb75258..4ae08e0d5 100644 --- a/test/cuda/gamma_p_float.cu +++ b/test/cuda/gamma_p_float.cu @@ -123,21 +123,6 @@ int main(void) } std::cout << "Test PASSED with calculation time: " << t << "s" << std::endl; - - // Reset the device and exit - // cudaDeviceReset causes the driver to clean up all state. While - // not mandatory in normal operation, it is good practice. It is also - // needed to ensure correct operation when the application is being - // profiled. Calling cudaDeviceReset causes all profile data to be - // flushed before the application exits - err = cudaDeviceReset(); - - if (err != cudaSuccess) - { - std::cerr << "Failed to deinitialize the device! error=" << cudaGetErrorString(err) << std::endl; - return EXIT_FAILURE; - } - std::cout << "Done\n"; } catch(const std::exception& e) diff --git a/test/cuda/ibeta_derivative_double.cu b/test/cuda/ibeta_derivative_double.cu index c27889dde..040b1cb95 100644 --- a/test/cuda/ibeta_derivative_double.cu +++ b/test/cuda/ibeta_derivative_double.cu @@ -135,21 +135,6 @@ int main(void) } std::cout << "Test PASSED with calculation time: " << t << "s" << std::endl; - - // Reset the device and exit - // cudaDeviceReset causes the driver to clean up all state. While - // not mandatory in normal operation, it is good practice. It is also - // needed to ensure correct operation when the application is being - // profiled. Calling cudaDeviceReset causes all profile data to be - // flushed before the application exits - err = cudaDeviceReset(); - - if (err != cudaSuccess) - { - std::cerr << "Failed to deinitialize the device! error=" << cudaGetErrorString(err) << std::endl; - return EXIT_FAILURE; - } - std::cout << "Done\n"; } catch(const std::exception& e) diff --git a/test/cuda/ibeta_derivative_float.cu b/test/cuda/ibeta_derivative_float.cu index d89625357..389e3ff65 100644 --- a/test/cuda/ibeta_derivative_float.cu +++ b/test/cuda/ibeta_derivative_float.cu @@ -138,21 +138,6 @@ int main(void) } std::cout << "Test PASSED with calculation time: " << t << "s" << std::endl; - - // Reset the device and exit - // cudaDeviceReset causes the driver to clean up all state. While - // not mandatory in normal operation, it is good practice. It is also - // needed to ensure correct operation when the application is being - // profiled. Calling cudaDeviceReset causes all profile data to be - // flushed before the application exits - err = cudaDeviceReset(); - - if (err != cudaSuccess) - { - std::cerr << "Failed to deinitialize the device! error=" << cudaGetErrorString(err) << std::endl; - return EXIT_FAILURE; - } - std::cout << "Done\n"; } catch(const std::exception& e) diff --git a/test/cuda/lgamma_double.cu b/test/cuda/lgamma_double.cu index e323386f2..195d6738c 100644 --- a/test/cuda/lgamma_double.cu +++ b/test/cuda/lgamma_double.cu @@ -115,21 +115,6 @@ int main(void) } std::cout << "Test PASSED with calculation time: " << t << "s" << std::endl; - - // Reset the device and exit - // cudaDeviceReset causes the driver to clean up all state. While - // not mandatory in normal operation, it is good practice. It is also - // needed to ensure correct operation when the application is being - // profiled. Calling cudaDeviceReset causes all profile data to be - // flushed before the application exits - err = cudaDeviceReset(); - - if (err != cudaSuccess) - { - std::cerr << "Failed to deinitialize the device! error=" << cudaGetErrorString(err) << std::endl; - return EXIT_FAILURE; - } - std::cout << "Done\n"; } catch(const std::exception& e) diff --git a/test/cuda/lgamma_float.cu b/test/cuda/lgamma_float.cu index ea73a9015..c1ba0bb22 100644 --- a/test/cuda/lgamma_float.cu +++ b/test/cuda/lgamma_float.cu @@ -115,21 +115,6 @@ int main(void) } std::cout << "Test PASSED with calculation time: " << t << "s" << std::endl; - - // Reset the device and exit - // cudaDeviceReset causes the driver to clean up all state. While - // not mandatory in normal operation, it is good practice. It is also - // needed to ensure correct operation when the application is being - // profiled. Calling cudaDeviceReset causes all profile data to be - // flushed before the application exits - err = cudaDeviceReset(); - - if (err != cudaSuccess) - { - std::cerr << "Failed to deinitialize the device! error=" << cudaGetErrorString(err) << std::endl; - return EXIT_FAILURE; - } - std::cout << "Done\n"; } catch(const std::exception& e) diff --git a/test/cuda/tgamma_double.cu b/test/cuda/tgamma_double.cu index 3921a071a..9fb94a93a 100644 --- a/test/cuda/tgamma_double.cu +++ b/test/cuda/tgamma_double.cu @@ -115,21 +115,6 @@ int main(void) } std::cout << "Test PASSED with calculation time: " << t << "s" << std::endl; - - // Reset the device and exit - // cudaDeviceReset causes the driver to clean up all state. While - // not mandatory in normal operation, it is good practice. It is also - // needed to ensure correct operation when the application is being - // profiled. Calling cudaDeviceReset causes all profile data to be - // flushed before the application exits - err = cudaDeviceReset(); - - if (err != cudaSuccess) - { - std::cerr << "Failed to deinitialize the device! error=" << cudaGetErrorString(err) << std::endl; - return EXIT_FAILURE; - } - std::cout << "Done\n"; } catch(const std::exception& e) diff --git a/test/cuda/tgamma_float.cu b/test/cuda/tgamma_float.cu index 34930b9f7..25469041b 100644 --- a/test/cuda/tgamma_float.cu +++ b/test/cuda/tgamma_float.cu @@ -115,21 +115,6 @@ int main(void) } std::cout << "Test PASSED with calculation time: " << t << "s" << std::endl; - - // Reset the device and exit - // cudaDeviceReset causes the driver to clean up all state. While - // not mandatory in normal operation, it is good practice. It is also - // needed to ensure correct operation when the application is being - // profiled. Calling cudaDeviceReset causes all profile data to be - // flushed before the application exits - err = cudaDeviceReset(); - - if (err != cudaSuccess) - { - std::cerr << "Failed to deinitialize the device! error=" << cudaGetErrorString(err) << std::endl; - return EXIT_FAILURE; - } - std::cout << "Done\n"; } catch(const std::exception& e)