From 5908aeeaba8f768bcce467849d1d41be5ac96599 Mon Sep 17 00:00:00 2001 From: Antonio Sanchez Date: Wed, 17 Feb 2021 15:09:37 -0800 Subject: [PATCH] Fix CUDA device new and delete, and add test. HIP does not support new/delete on device, so test is skipped. --- Eigen/src/Core/util/Memory.h | 15 ++++++++++++++- test/gpu_basic.cu | 21 +++++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/Eigen/src/Core/util/Memory.h b/Eigen/src/Core/util/Memory.h index 14713aaa7..7cbe8a672 100644 --- a/Eigen/src/Core/util/Memory.h +++ b/Eigen/src/Core/util/Memory.h @@ -780,32 +780,45 @@ template void swap(scoped_array &a,scoped_array &b) #else -#if EIGEN_MAX_ALIGN_BYTES!=0 +// HIP does not support new/delete on device. +#if EIGEN_MAX_ALIGN_BYTES!=0 && !defined(EIGEN_HIP_DEVICE_COMPILE) #define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_NOTHROW(NeedsToAlign) \ + EIGEN_DEVICE_FUNC \ void* operator new(std::size_t size, const std::nothrow_t&) EIGEN_NO_THROW { \ EIGEN_TRY { return Eigen::internal::conditional_aligned_malloc(size); } \ EIGEN_CATCH (...) { return 0; } \ } #define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(NeedsToAlign) \ + EIGEN_DEVICE_FUNC \ void *operator new(std::size_t size) { \ return Eigen::internal::conditional_aligned_malloc(size); \ } \ + EIGEN_DEVICE_FUNC \ void *operator new[](std::size_t size) { \ return Eigen::internal::conditional_aligned_malloc(size); \ } \ + EIGEN_DEVICE_FUNC \ void operator delete(void * ptr) EIGEN_NO_THROW { Eigen::internal::conditional_aligned_free(ptr); } \ + EIGEN_DEVICE_FUNC \ void operator delete[](void * ptr) EIGEN_NO_THROW { Eigen::internal::conditional_aligned_free(ptr); } \ + EIGEN_DEVICE_FUNC \ void operator delete(void * ptr, std::size_t /* sz */) EIGEN_NO_THROW { Eigen::internal::conditional_aligned_free(ptr); } \ + EIGEN_DEVICE_FUNC \ void operator delete[](void * ptr, std::size_t /* sz */) EIGEN_NO_THROW { Eigen::internal::conditional_aligned_free(ptr); } \ /* in-place new and delete. since (at least afaik) there is no actual */ \ /* memory allocated we can safely let the default implementation handle */ \ /* this particular case. */ \ + EIGEN_DEVICE_FUNC \ static void *operator new(std::size_t size, void *ptr) { return ::operator new(size,ptr); } \ + EIGEN_DEVICE_FUNC \ static void *operator new[](std::size_t size, void* ptr) { return ::operator new[](size,ptr); } \ + EIGEN_DEVICE_FUNC \ void operator delete(void * memory, void *ptr) EIGEN_NO_THROW { return ::operator delete(memory,ptr); } \ + EIGEN_DEVICE_FUNC \ void operator delete[](void * memory, void *ptr) EIGEN_NO_THROW { return ::operator delete[](memory,ptr); } \ /* nothrow-new (returns zero instead of std::bad_alloc) */ \ EIGEN_MAKE_ALIGNED_OPERATOR_NEW_NOTHROW(NeedsToAlign) \ + EIGEN_DEVICE_FUNC \ void operator delete(void *ptr, const std::nothrow_t&) EIGEN_NO_THROW { \ Eigen::internal::conditional_aligned_free(ptr); \ } \ diff --git a/test/gpu_basic.cu b/test/gpu_basic.cu index 46e4a436f..1935f0bc6 100644 --- a/test/gpu_basic.cu +++ b/test/gpu_basic.cu @@ -233,6 +233,26 @@ struct replicate { } }; +template +struct alloc_new_delete { + EIGEN_DEVICE_FUNC + void operator()(int i, const typename T::Scalar* in, typename T::Scalar* out) const + { + int offset = 2*i*T::MaxSizeAtCompileTime; + T* x = new T(in + offset); + Eigen::Map u(out + offset); + u = *x; + delete x; + + offset += T::MaxSizeAtCompileTime; + T* y = new T[1]; + y[0] = T(in + offset); + Eigen::Map v(out + offset); + v = y[0]; + delete[] y; + } +}; + template struct redux { EIGEN_DEVICE_FUNC @@ -418,4 +438,5 @@ EIGEN_DECLARE_TEST(gpu_basic) typedef Matrix Matrix6f; CALL_SUBTEST( run_and_compare_to_gpu(eigenvalues(), nthreads, in, out) ); #endif + CALL_SUBTEST( run_and_compare_to_gpu(alloc_new_delete(), nthreads, in, out) ); }