From 1b9a40e5463df0bc21be5c757d311e1f8e1acd78 Mon Sep 17 00:00:00 2001 From: Daniel Arndt Date: Thu, 1 Dec 2022 20:14:40 +0000 Subject: [PATCH] working --- include/deal.II/base/memory_space_data.h | 209 ++++++++++++------ .../lac/la_parallel_vector.templates.h | 72 +++--- source/base/kokkos.cc | 4 +- 3 files changed, 193 insertions(+), 92 deletions(-) diff --git a/include/deal.II/base/memory_space_data.h b/include/deal.II/base/memory_space_data.h index da0b809c8d..6daecffd5a 100644 --- a/include/deal.II/base/memory_space_data.h +++ b/include/deal.II/base/memory_space_data.h @@ -23,7 +23,9 @@ #include #include +DEAL_II_DISABLE_EXTRA_DIAGNOSTICS #include +DEAL_II_ENABLE_EXTRA_DIAGNOSTICS #include #include @@ -35,37 +37,47 @@ DEAL_II_NAMESPACE_OPEN namespace MemorySpace { /** - * Structure which stores data on the host or the device depending on the - * template parameter @p MemorySpace. The data is copied into the structure - * which then owns the data and will release the memory when the destructor is - * called. + * Data structure */ template struct MemorySpaceData { - MemorySpaceData(); + MemorySpaceData() + { + static_assert(std::is_same::value || + std::is_same::value, + "MemorySpace should be Host or Device"); + } /** * Copy the active data (values for Host and values_dev for Device) to @p begin. * If the data is on the device it is moved to the host. */ void - copy_to(T *begin, const std::size_t n_elements); + copy_to(T *begin, std::size_t n_elements) + { + (void)begin; + (void)n_elements; + } /** * Copy the data in @p begin to the active data of the structure (values for * Host and values_dev for Device). The pointer @p begin must be on the host. */ void - copy_from(const T *begin, const std::size_t n_elements); + copy_from(T *begin, std::size_t n_elements) + { + (void)begin; + (void)n_elements; + } /** - * Kokkos View to the data on the host + * Pointer to data on the host. */ Kokkos::View values; /** - * Kokkos View to the data on the device + * Pointer to data on the device. */ Kokkos::View values_dev; @@ -76,12 +88,12 @@ namespace MemorySpace // The pointer is shared so that MemorySpaceData can be copied and // MemorySpaceData::values can be used in Kokkos::parallel_for. This // pointer owns the data when using shared memory with MPI. In this case, - // the Kokkos::View in non-owning. When shared memory with MPI is not used, - // the pointer is not used. + // the (host) Kokkos::View is non-owning. When shared memory with MPI is not + // used, the pointer is not used. std::shared_ptr values_sm_ptr; /** - * Pointers to the data of the processes sharing the same memory. + * Pointers to the data of the processes sharing the same memory. Not used for MemorySpace::Device. */ std::vector> values_sm; }; @@ -93,77 +105,146 @@ namespace MemorySpace */ template inline void - swap(MemorySpaceData &u, MemorySpaceData &v); - + swap(MemorySpaceData &, + MemorySpaceData &) + { + static_assert(std::is_same::value || + std::is_same::value, + "MemorySpace should be Host or Device"); + } #ifndef DOXYGEN - template - MemorySpaceData::MemorySpaceData() + template + struct MemorySpaceData + { + using MemorySpace = Host; + + MemorySpaceData() : values((dealii::Impl::ensure_kokkos_initialized(), Kokkos::View("host data", 0))) - , values_dev(Kokkos::View( - "memoryspace data", - 0)) - {} + {} + void + copy_to(T *begin, std::size_t n_elements) + { + Assert(n_elements <= values.extent(0), + ExcMessage("n_elements greater than the size of values.")); + using ExecutionSpace = typename MemorySpace::kokkos_space::execution_space; + Kokkos:: + View> + begin_view(begin, n_elements); + Kokkos::deep_copy( + ExecutionSpace{}, + begin_view, + Kokkos::subview(values, Kokkos::make_pair(std::size_t(0), n_elements))); + ExecutionSpace{}.fence(); + } + void + copy_from(T *begin, std::size_t n_elements) + { + Assert(n_elements <= values.extent(0), + ExcMessage("n_elements greater than the size of values.")); + using ExecutionSpace = typename MemorySpace::kokkos_space::execution_space; + Kokkos::View> + begin_view(begin, n_elements); + Kokkos::deep_copy( + ExecutionSpace{}, + Kokkos::subview(values, Kokkos::make_pair(std::size_t(0), n_elements)), + begin_view); + ExecutionSpace{}.fence(); + } - template - void - MemorySpaceData::copy_to(T * begin, - const std::size_t n_elements) + Kokkos::View values; + + // unused + Kokkos::View values_dev; + + std::shared_ptr values_sm_ptr; + + std::vector> values_sm; + }; + + + + template + inline void + swap(MemorySpaceData &u, MemorySpaceData &v) { - Assert(n_elements <= values.extent(0), - ExcMessage("n_elements greater than the size of values.")); - using ExecutionSpace = typename MemorySpace::kokkos_space::execution_space; - Kokkos:: - View> - begin_view(begin, n_elements); - Kokkos::deep_copy( - ExecutionSpace{}, - begin_view, - Kokkos::subview(values, Kokkos::make_pair(std::size_t(0), n_elements))); - ExecutionSpace{}.fence(); + std::swap(u.values, v.values); + std::swap(u.values_sm_ptr, v.values_sm_ptr); } - template - void - MemorySpaceData::copy_from(const T * begin, - const std::size_t n_elements) + template + struct MemorySpaceData { - Assert(n_elements <= values.extent(0), - ExcMessage("n_elements greater than the size of values.")); - using ExecutionSpace = typename MemorySpace::kokkos_space::execution_space; - Kokkos::View> - begin_view(begin, n_elements); - Kokkos::deep_copy( - ExecutionSpace{}, - Kokkos::subview(values, Kokkos::make_pair(std::size_t(0), n_elements)), - begin_view); - ExecutionSpace{}.fence(); - } + using MemorySpace = Device; + MemorySpaceData() + : values((dealii::Impl::ensure_kokkos_initialized(), + Kokkos::View("host data", 0))) + , values_dev(Kokkos::View( + "memoryspace data", + 0)) + {} + void + copy_to(T *begin, std::size_t n_elements) + { + Assert(n_elements <= values_dev.extent(0), + ExcMessage("n_elements greater than the size of values.")); + using ExecutionSpace = typename MemorySpace::kokkos_space::execution_space; + Kokkos:: + View> + begin_view(begin, n_elements); + Kokkos::deep_copy( + ExecutionSpace{}, + begin_view, + Kokkos::subview(values_dev, Kokkos::make_pair(std::size_t(0), n_elements))); + ExecutionSpace{}.fence(); + } - /** - * Swap function similar to std::swap. - */ - template + void + copy_from(T *begin, std::size_t n_elements) + { + Assert(n_elements <= values_dev.extent(0), + ExcMessage("n_elements greater than the size of values.")); + using ExecutionSpace = typename MemorySpace::kokkos_space::execution_space; + Kokkos::View> + begin_view(begin, n_elements); + Kokkos::deep_copy( + ExecutionSpace{}, + Kokkos::subview(values_dev, Kokkos::make_pair(std::size_t(0), n_elements)), + begin_view); + ExecutionSpace{}.fence(); + } + + Kokkos::View values; + + Kokkos::View values_dev; + + // unused + std::shared_ptr values_sm_ptr; + + // unused + std::vector> values_sm; + }; + + + + template inline void - swap(MemorySpaceData &u, MemorySpaceData &v) + swap(MemorySpaceData &u, MemorySpaceData &v) { - auto u_copy = Kokkos::create_mirror(Kokkos::WithoutInitializing, u); - typename MemorySpace::execution_space exec_space; - // The first two calls to Kokkos::deep_copy are asynchronous. The last call - // will wait for the three deep_copy to be done before returning. - Kokkos::deep_copy(exec_space, u_copy, u); - Kokkos::deep_copy(exec_space, u, v); - Kokkos::deep_copy(v, u_copy); + std::swap(u.values, v.values); + std::swap(u.values_dev, v.values_dev); } #endif diff --git a/include/deal.II/lac/la_parallel_vector.templates.h b/include/deal.II/lac/la_parallel_vector.templates.h index 4f0375f03e..1537aef596 100644 --- a/include/deal.II/lac/la_parallel_vector.templates.h +++ b/include/deal.II/lac/la_parallel_vector.templates.h @@ -1131,7 +1131,7 @@ namespace LinearAlgebra { # if defined(DEAL_II_COMPILER_CUDA_AWARE) && \ defined(DEAL_II_MPI_WITH_CUDA_SUPPORT) - Assert( + Assert( (std::is_same::value), ExcMessage( "Using MemorySpace::CUDA only allowed if the code is compiled with a CUDA compiler!")); @@ -1148,17 +1148,40 @@ namespace LinearAlgebra # endif } + if (std::is_same_v) + std::cout << "device" << std::endl; + if (std::is_same_v) + std::cout << "host" << std::endl; + std::cout << "size_dev: " << data.values_dev.extent(0) << " " << partitioner->locally_owned_size() << std::endl; + std::cout << "size_host: " << data.values.extent(0) << " " << partitioner->locally_owned_size() << std::endl; + # if defined DEAL_II_COMPILER_CUDA_AWARE && \ !defined(DEAL_II_MPI_WITH_CUDA_SUPPORT) - // Move the data to the host and then move it back to the - // device. We use values to store the elements because the function - // uses a view of the array and thus we need the data on the host to - // outlive the scope of the function. - data.values = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace{}, data.values_dev); + if (std::is_same_v) { + // Move the data to the host and then move it back to the + // device. We use values to store the elements because the function + // uses a view of the array and thus we need the data on the host to + // outlive the scope of the function. + data.values = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace{}, data.values_dev); + } # endif -# if !(defined(DEAL_II_COMPILER_CUDA_AWARE) && \ - defined(DEAL_II_MPI_WITH_CUDA_SUPPORT)) +# if defined(DEAL_II_COMPILER_CUDA_AWARE) && \ + defined(DEAL_II_MPI_WITH_CUDA_SUPPORT) + if (std::is_same_v) { + partitioner->export_to_ghosted_array_start( + communication_channel, + ArrayView( + data.values_dev.data(), partitioner->locally_owned_size()), + ArrayView(import_data.values_dev.data(), + partitioner->n_import_indices()), + ArrayView( + data.values_dev.data() + partitioner->locally_owned_size(), + partitioner->n_ghost_indices()), + update_ghost_values_requests); + } else +#else + { partitioner->export_to_ghosted_array_start( communication_channel, ArrayView( @@ -1169,17 +1192,7 @@ namespace LinearAlgebra data.values.data() + partitioner->locally_owned_size(), partitioner->n_ghost_indices()), update_ghost_values_requests); -# else - partitioner->export_to_ghosted_array_start( - communication_channel, - ArrayView( - data.values_dev.data(), partitioner->locally_owned_size()), - ArrayView(import_data.values_dev.data(), - partitioner->n_import_indices()), - ArrayView( - data.values_dev.data() + partitioner->locally_owned_size(), - partitioner->n_ghost_indices()), - update_ghost_values_requests); + } # endif #else @@ -1204,19 +1217,24 @@ namespace LinearAlgebra // make this function thread safe std::lock_guard lock(mutex); -# if !(defined(DEAL_II_COMPILER_CUDA_AWARE) && \ - defined(DEAL_II_MPI_WITH_CUDA_SUPPORT)) +# if defined(DEAL_II_COMPILER_CUDA_AWARE) && \ + defined(DEAL_II_MPI_WITH_CUDA_SUPPORT) + if (std::is_same::value) + { + partitioner->export_to_ghosted_array_finish( + ArrayView( + data.values_dev.data() + partitioner->locally_owned_size(), + partitioner->n_ghost_indices()), + update_ghost_values_requests); + } else +#else + { partitioner->export_to_ghosted_array_finish( ArrayView( data.values.data() + partitioner->locally_owned_size(), partitioner->n_ghost_indices()), update_ghost_values_requests); -# else - partitioner->export_to_ghosted_array_finish( - ArrayView( - data.values_dev.data() + partitioner->locally_owned_size(), - partitioner->n_ghost_indices()), - update_ghost_values_requests); + } # endif } diff --git a/source/base/kokkos.cc b/source/base/kokkos.cc index 629c0063d1..77321393bd 100644 --- a/source/base/kokkos.cc +++ b/source/base/kokkos.cc @@ -28,7 +28,8 @@ namespace Impl ensure_kokkos_initialized() { if (!Kokkos::is_initialized()) - GrowingVectorMemory< + { + GrowingVectorMemory< LinearAlgebra::distributed::Vector>{}; GrowingVectorMemory< LinearAlgebra::distributed::Vector>{}; @@ -55,5 +56,6 @@ namespace Impl Kokkos::initialize(); std::atexit(Kokkos::finalize); } + } } // namespace Impl DEAL_II_NAMESPACE_CLOSE -- 2.39.5