From a6ac3149c014418b261ed2dcc0084cfcae75b2ee Mon Sep 17 00:00:00 2001 From: Marcel Koch Date: Tue, 12 Dec 2023 16:59:38 +0000 Subject: [PATCH] review updates: - formatting - enable uncommented test - add static_assert to warn on mismatching alignment - check ginkgo build config matches kokkos - increase types test - remove unnecessary if-def guard - use memory space type for mapping instead of variable - set cxx standard to 17 for kokkos extension - documentation - move implementation out of class - add install doc Co-authored-by: Pratik Nayak Co-authored-by: Yu-Hsiang M. Tsai --- INSTALL.md | 5 + dev_tools/scripts/regroup | 2 +- examples/kokkos-assembly/kokkos-assembly.cpp | 11 +- extensions/CMakeLists.txt | 20 +- extensions/test/kokkos/CMakeLists.txt | 34 +-- extensions/test/kokkos/spaces.cpp | 3 + extensions/test/kokkos/types.cpp | 80 ++++++- include/ginkgo/config.hpp.in | 12 - include/ginkgo/extensions/kokkos.hpp | 3 +- .../ginkgo/extensions/kokkos/config.hpp.in | 15 ++ include/ginkgo/extensions/kokkos/spaces.hpp | 69 +++--- include/ginkgo/extensions/kokkos/types.hpp | 221 ++++++++++-------- 12 files changed, 295 insertions(+), 180 deletions(-) create mode 100644 include/ginkgo/extensions/kokkos/config.hpp.in diff --git a/INSTALL.md b/INSTALL.md index 9719bdfb920..db846f66c82 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -118,6 +118,11 @@ Ginkgo adds the following additional switches to control what is being built: this option see the [`ARCHITECTURES` specification list](https://github.com/ginkgo-project/CudaArchitectureSelector/blob/master/CudaArchitectureSelector.cmake#L58) section in the documentation of the CudaArchitectureSelector CMake module. +* `-DGINKGO_EXTENSION_KOKKOS={ON, OFF}` enables an extension that can map simple Ginkgo + types (`gko::array`, `gko::matrix::Dense`) to equivalent native Kokkos types. `OFF` by + default. Requires Kokkos to be installed if set to `ON`. To use the mapping it is + required to additionally link against `Ginkgo::ext::kokkos` (or `Ginkgo::ext` for short). + More details on the usage of this extension can be found in the example `kokkos-assembly`. Additionally, the following CMake options have effect on the build process: diff --git a/dev_tools/scripts/regroup b/dev_tools/scripts/regroup index e35bd37efee..b10570f4982 100644 --- a/dev_tools/scripts/regroup +++ b/dev_tools/scripts/regroup @@ -2,7 +2,7 @@ IncludeBlocks: Regroup IncludeCategories: - Regex: '^<(nlohmann|gflags|gtest|papi).*' Priority: 3 - - Regex: '^<(omp|cu|hip|thrust|CL/|cooperative|oneapi|mpi|nvToolsExt).*' + - Regex: '^<(omp|cu|hip|thrust|CL/|cooperative|oneapi|mpi|nvToolsExt|Kokkos_Core).*' Priority: 2 - Regex: '^ -#include #include +#include + + #include #include @@ -47,8 +49,9 @@ struct mapper, MemorySpace> { * @param row_idxs Pointer to the row indices * @param col_idxs Pointer to the column indices * @param values Pointer to the values + * * @return An object which has each gko::array of the - * devive_matrix_data mapped to a Kokkos view + * device_matrix_data mapped to a Kokkos view */ static type map(size_type size, IndexType_c* row_idxs, IndexType_c* col_idxs, ValueType_c* values) @@ -66,7 +69,7 @@ struct mapper, MemorySpace> { static type map( device_matrix_data& md) { - assert_compatibility(md, MemorySpace{}); + assert_compatibility(md); return type::map( md.get_num_stored_elements(), md.get_row_idxs(), md.get_col_idxs(), md.get_values()); @@ -75,7 +78,7 @@ struct mapper, MemorySpace> { static type map( const device_matrix_data& md) { - assert_compatibility(md, MemorySpace{}); + assert_compatibility(md); return type::map( md.get_num_stored_elements(), md.get_const_row_idxs(), md.get_const_col_idxs(), md.get_const_values()); diff --git a/extensions/CMakeLists.txt b/extensions/CMakeLists.txt index 1e6054e9b9e..986b9216f6f 100644 --- a/extensions/CMakeLists.txt +++ b/extensions/CMakeLists.txt @@ -1,8 +1,4 @@ -add_library(ginkgo_ext INTERFACE) -add_library(Ginkgo::ext ALIAS ginkgo_ext) -set_property(TARGET ginkgo_ext PROPERTY EXPORT_NAME ext) - -if(GINKGO_EXTENSION_KOKKOS) +if (GINKGO_EXTENSION_KOKKOS) find_package(Kokkos 4.1 REQUIRED) set(GINKGO_Kokkos_VERSION ${Kokkos_VERSION} PARENT_SCOPE) @@ -13,19 +9,25 @@ if(GINKGO_EXTENSION_KOKKOS) set_property(TARGET ginkgo_ext_kokkos PROPERTY EXPORT_NAME ext::kokkos) target_link_libraries(ginkgo_ext_kokkos INTERFACE Kokkos::kokkos) + target_compile_features(ginkgo_ext_kokkos INTERFACE cxx_std_17) - target_link_libraries(ginkgo_ext INTERFACE ginkgo_ext_kokkos) + configure_file("${Ginkgo_SOURCE_DIR}/include/ginkgo/extensions/kokkos/config.hpp.in" + "${Ginkgo_BINARY_DIR}/include/ginkgo/extensions/kokkos/config.hpp" + @ONLY + ) ginkgo_install_library(ginkgo_ext_kokkos) + install(FILES "${Ginkgo_BINARY_DIR}/include/ginkgo/extensions/kokkos/config.hpp" + DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/ginkgo/extensions/kokkos" + ) install(DIRECTORY "${Ginkgo_SOURCE_DIR}/include/ginkgo/extensions/kokkos" DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/ginkgo/extensions" + FILES_MATCHING PATTERN "*.hpp" ) install(FILES "${Ginkgo_SOURCE_DIR}/include/ginkgo/extensions/kokkos.hpp" DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/ginkgo/extensions" ) -endif() - -ginkgo_install_library(ginkgo_ext) +endif () if (GINKGO_BUILD_TESTS) add_subdirectory(test) diff --git a/extensions/test/kokkos/CMakeLists.txt b/extensions/test/kokkos/CMakeLists.txt index 9c7b806fdc7..9f40b991c3e 100644 --- a/extensions/test/kokkos/CMakeLists.txt +++ b/extensions/test/kokkos/CMakeLists.txt @@ -11,31 +11,35 @@ function(_ginkgo_check_build_config _build) endfunction() if(Kokkos_ENABLE_CUDA) - set(resource_type "cudagpu") - set(definitions "GKO_COMPILING_CUDA") + _ginkgo_check_build_config(cuda) + set(resource_type "cudagpu") + set(definitions "GKO_COMPILING_CUDA") elseif(Kokkos_ENABLE_HIP) - set(resource_type "hipgpu") - set(definitions "GKO_COMPILING_HIP") + _ginkgo_check_build_config(hip) + set(resource_type "hipgpu") + set(definitions "GKO_COMPILING_HIP") elseif(Kokkos_ENABLE_SYCL) - set(resource_type "sycl") - set(definitions "GKO_COMPILING_DPCPP") + _ginkgo_check_build_config(sycl) + set(resource_type "sycl") + set(definitions "GKO_COMPILING_DPCPP") else() - set(resource_type "cpu") - if(Kokkos_ENABLE_OMP) - set(definitions "GKO_COMPILING_OMP") - endif() + set(resource_type "cpu") + if(Kokkos_ENABLE_OPENMP) + _ginkgo_check_build_config(omp) + set(definitions "GKO_COMPILING_OMP") + endif() endif() function(create_gtest_main_kokkos) - add_library(ginkgo_gtest_main_kokkos STATIC kokkos_main.cpp ${PROJECT_SOURCE_DIR}/core/test/gtest/resources.cpp) - target_link_libraries(ginkgo_gtest_main_kokkos PUBLIC Ginkgo::ginkgo GTest::GTest Ginkgo::ext::kokkos) - target_compile_definitions(ginkgo_gtest_main_kokkos PRIVATE ${definitions}) - ginkgo_compile_features(ginkgo_gtest_main_kokkos) + add_library(ginkgo_gtest_main_kokkos STATIC kokkos_main.cpp ${PROJECT_SOURCE_DIR}/core/test/gtest/resources.cpp) + target_link_libraries(ginkgo_gtest_main_kokkos PUBLIC Ginkgo::ginkgo GTest::GTest Ginkgo::ext::kokkos) + target_compile_definitions(ginkgo_gtest_main_kokkos PRIVATE ${definitions}) + ginkgo_compile_features(ginkgo_gtest_main_kokkos) endfunction() create_gtest_main_kokkos() function(ginkgo_create_test_kokkos test_name) - ginkgo_create_test(${test_name} NO_GTEST_MAIN RESOURCE_TYPE ${resource_type} ADDITIONAL_LIBRARIES Ginkgo::ext::kokkos ginkgo_gtest_main_kokkos ${ARGN}) + ginkgo_create_test(${test_name} NO_GTEST_MAIN RESOURCE_TYPE ${resource_type} ADDITIONAL_LIBRARIES Ginkgo::ext::kokkos ginkgo_gtest_main_kokkos ${ARGN}) endfunction() ginkgo_create_test_kokkos(types) diff --git a/extensions/test/kokkos/spaces.cpp b/extensions/test/kokkos/spaces.cpp index a9315096477..47e24aac93e 100644 --- a/extensions/test/kokkos/spaces.cpp +++ b/extensions/test/kokkos/spaces.cpp @@ -2,6 +2,9 @@ // // SPDX-License-Identifier: BSD-3-Clause +#include + + #include diff --git a/extensions/test/kokkos/types.cpp b/extensions/test/kokkos/types.cpp index c049dab36e9..4bff41499e9 100644 --- a/extensions/test/kokkos/types.cpp +++ b/extensions/test/kokkos/types.cpp @@ -6,6 +6,9 @@ #include +#include + + #include @@ -19,6 +22,7 @@ using DefaultMemorySpace = Kokkos::DefaultExecutionSpace::memory_space; + template class ArrayMapper : public ::testing::Test { protected: @@ -40,14 +44,20 @@ TYPED_TEST(ArrayMapper, CanMapDefault) auto mapped_array = gko::ext::kokkos::map_data(this->array); - using array_type = + using mapped_type = std::remove_cv_t>; static_assert( - std::is_same_v>>); + ASSERT_EQ(reinterpret_cast(mapped_array.data()), + reinterpret_cast(this->array.get_data())); + ASSERT_EQ(mapped_array.extent(0), this->array.get_size()); + ASSERT_EQ(mapped_array.size(), this->array.get_size()); + ASSERT_EQ(mapped_array.stride(0), 1); } + TYPED_TEST(ArrayMapper, CanMapConst) { using value_type = typename TestFixture::value_type; @@ -57,12 +67,17 @@ TYPED_TEST(ArrayMapper, CanMapConst) auto mapped_array = gko::ext::kokkos::map_data( const_cast&>(this->array)); - using array_type = + using mapped_type = std::remove_cv_t>; static_assert(std::is_same_v< - array_type, + mapped_type, Kokkos::View>>); + ASSERT_EQ(reinterpret_cast(mapped_array.data()), + reinterpret_cast(this->array.get_data())); + ASSERT_EQ(mapped_array.extent(0), this->array.get_size()); + ASSERT_EQ(mapped_array.size(), this->array.get_size()); + ASSERT_EQ(mapped_array.stride(0), 1); } @@ -89,15 +104,25 @@ TYPED_TEST(DenseMapper, CanMapDefault) auto mapped_mtx = gko::ext::kokkos::map_data(this->mtx); - using mtx_type = + using mapped_type = std::remove_cv_t>; static_assert( - std::is_same_v>>); + ASSERT_EQ(reinterpret_cast(mapped_mtx.data()), + reinterpret_cast(this->mtx->get_values())); + ASSERT_EQ(mapped_mtx.extent(0), this->mtx->get_size()[0]); + ASSERT_EQ(mapped_mtx.extent(1), this->mtx->get_size()[1]); + ASSERT_EQ(mapped_mtx.size(), + this->mtx->get_size()[0] * this->mtx->get_size()[1]); + ASSERT_EQ(mapped_mtx.span(), this->mtx->get_num_stored_elements()); + ASSERT_EQ(mapped_mtx.stride(0), this->mtx->get_stride()); + ASSERT_EQ(mapped_mtx.stride(1), 1); } + TYPED_TEST(DenseMapper, CanMapConst) { using value_type = typename TestFixture::value_type; @@ -107,11 +132,50 @@ TYPED_TEST(DenseMapper, CanMapConst) auto mapped_mtx = gko::ext::kokkos::map_data( const_cast*>(this->mtx.get())); - using mtx_type = + using mapped_type = std::remove_cv_t>; static_assert( - std::is_same_v>>); + ASSERT_EQ(reinterpret_cast(mapped_mtx.data()), + reinterpret_cast(this->mtx->get_values())); + ASSERT_EQ(mapped_mtx.extent(0), this->mtx->get_size()[0]); + ASSERT_EQ(mapped_mtx.extent(1), this->mtx->get_size()[1]); + ASSERT_EQ(mapped_mtx.size(), + this->mtx->get_size()[0] * this->mtx->get_size()[1]); + ASSERT_EQ(mapped_mtx.span(), this->mtx->get_num_stored_elements()); + ASSERT_EQ(mapped_mtx.stride(0), this->mtx->get_stride()); + ASSERT_EQ(mapped_mtx.stride(1), 1); +} + + +TYPED_TEST(DenseMapper, CanMapStrided) +{ + using mtx_type = typename TestFixture::mtx_type; + using value_type = typename TestFixture::value_type; + using kokkos_value_type = + typename gko::ext::kokkos::detail::value_type::type; + std::unique_ptr mtx = mtx_type ::create( + this->exec, gko::dim<2>{2, 2}, + gko::array{this->exec, {1, 2, -1, 3, 4, -10}}, 3); + + auto mapped_mtx = gko::ext::kokkos::map_data(mtx); + + using mapped_type = + std::remove_cv_t>; + static_assert( + std::is_same_v>>); + ASSERT_EQ(reinterpret_cast(mapped_mtx.data()), + reinterpret_cast(mtx->get_values())); + ASSERT_EQ(mapped_mtx.extent(0), mtx->get_size()[0]); + ASSERT_EQ(mapped_mtx.extent(1), mtx->get_size()[1]); + ASSERT_EQ(mapped_mtx.size(), mtx->get_size()[0] * mtx->get_size()[1]); + ASSERT_EQ(mapped_mtx.span(), mtx->get_num_stored_elements()); + ASSERT_EQ(mapped_mtx.stride(0), mtx->get_stride()); + ASSERT_EQ(mapped_mtx.stride(1), 1); } diff --git a/include/ginkgo/config.hpp.in b/include/ginkgo/config.hpp.in index b8c22c65438..329918399d6 100644 --- a/include/ginkgo/config.hpp.in +++ b/include/ginkgo/config.hpp.in @@ -112,16 +112,4 @@ // clang-format on -/* Is the Kokkos extension enabled? */ -// clang-format off -#cmakedefine01 GINKGO_EXTENSION_KOKKOS -// clang-format on - - -/* Do we need to check the type alignment in the Kokkos type maps? */ -// clang-format off -#cmakedefine01 GINKGO_EXTENSION_KOKKOS_CHECK_TYPE_ALIGNMENT -// clang-format on - - #endif // GKO_INCLUDE_CONFIG_H diff --git a/include/ginkgo/extensions/kokkos.hpp b/include/ginkgo/extensions/kokkos.hpp index 2a16cffacc6..d3f1c46dcf2 100644 --- a/include/ginkgo/extensions/kokkos.hpp +++ b/include/ginkgo/extensions/kokkos.hpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2017-2023 The Ginkgo authors +// SPDX-FileCopyrightText: 2017 - 2024 The Ginkgo authors // // SPDX-License-Identifier: BSD-3-Clause @@ -6,6 +6,7 @@ #define GKO_PUBLIC_EXTENSIONS_KOKKOS_HPP_ +#include #include #include diff --git a/include/ginkgo/extensions/kokkos/config.hpp.in b/include/ginkgo/extensions/kokkos/config.hpp.in new file mode 100644 index 00000000000..9e635ef76bd --- /dev/null +++ b/include/ginkgo/extensions/kokkos/config.hpp.in @@ -0,0 +1,15 @@ +// SPDX-FileCopyrightText: 2024 The Ginkgo authors +// +// SPDX-License-Identifier: BSD-3-Clause + +#ifndef GINKGO_INCLUDE_GINKGO_EXTENSIONS_KOKKOS_CONFIG_HPP_IN +#define GINKGO_INCLUDE_GINKGO_EXTENSIONS_KOKKOS_CONFIG_HPP_IN + + +/* Do we need to check the type alignment in the Kokkos type maps? */ +// clang-format off +#cmakedefine01 GINKGO_EXTENSION_KOKKOS_CHECK_TYPE_ALIGNMENT +// clang-format on + + +#endif // GINKGO_INCLUDE_GINKGO_EXTENSIONS_KOKKOS_CONFIG_HPP_IN diff --git a/include/ginkgo/extensions/kokkos/spaces.hpp b/include/ginkgo/extensions/kokkos/spaces.hpp index b087fc8cc5b..6875f931152 100644 --- a/include/ginkgo/extensions/kokkos/spaces.hpp +++ b/include/ginkgo/extensions/kokkos/spaces.hpp @@ -1,19 +1,16 @@ -// SPDX-FileCopyrightText: 2017-2023 The Ginkgo authors +// SPDX-FileCopyrightText: 2017 - 2024 The Ginkgo authors // // SPDX-License-Identifier: BSD-3-Clause -#ifndef GINKGO_SPACES_HPP -#define GINKGO_SPACES_HPP - -#include - - -#if GINKGO_EXTENSION_KOKKOS - +#ifndef GINKGO_EXTENSIONS_KOKKOS_SPACES_HPP +#define GINKGO_EXTENSIONS_KOKKOS_SPACES_HPP #include +#include +#include +#include #include @@ -35,25 +32,26 @@ struct compatible_space Kokkos::has_shared_host_pinned_space> {}; template <> -struct compatible_space - : std::true_type {}; +struct compatible_space : std::true_type { +}; template -struct compatible_space { +struct compatible_space { // need manual implementation of std::integral_constant because, // while compiling for cuda, somehow bool is replaced by __nv_bool static constexpr bool value = Kokkos::SpaceAccessibility::accessible; }; + #ifdef KOKKOS_ENABLE_OPENMP template -struct compatible_space - : compatible_space {}; +struct compatible_space + : compatible_space {}; #endif #ifdef KOKKOS_ENABLE_CUDA template -struct compatible_space { +struct compatible_space { static constexpr bool value = Kokkos::SpaceAccessibility::accessible; }; @@ -61,7 +59,7 @@ struct compatible_space { #ifdef KOKKOS_ENABLE_HIP template -struct compatible_space { +struct compatible_space { static constexpr bool value = Kokkos::SpaceAccessibility::accessible; }; @@ -69,7 +67,7 @@ struct compatible_space { #ifdef KOKKOS_ENABLE_SYCL template -struct compatible_space { +struct compatible_space { static constexpr bool value = Kokkos::SpaceAccessibility::accessible; @@ -88,7 +86,7 @@ struct compatible_space { template inline bool check_compatibility(std::shared_ptr) { - return detail::compatible_space::value; + return compatible_space::value; } @@ -127,15 +125,14 @@ inline bool check_compatibility(std::shared_ptr exec) * Throws if the memory space is ~not~ accessible by the executor associated * with the passed in Ginkgo object. * - * @tparam MemorySpace A Kokkos memory space type.. + * @tparam MemorySpace A Kokkos memory space type. * @tparam T A Ginkgo type that has the member function `get_executor`. * * @param obj Object which executor is used to check the access to the memory * space. - * @param space The Kokkos memory space to compare agains. */ template -inline void assert_compatibility(T&& obj, MemorySpace space) +inline void assert_compatibility(T&& obj) { GKO_THROW_IF_INVALID(check_compatibility(obj.get_executor()), "Executor type and memory space are incompatible"); @@ -154,20 +151,16 @@ inline void assert_compatibility(T&& obj, MemorySpace space) */ inline std::shared_ptr create_default_host_executor() { - static std::mutex mutex{}; - std::lock_guard guard(mutex); #ifdef KOKKOS_ENABLE_SERIAL if constexpr (std::is_same_v) { - static auto exec = ReferenceExecutor::create(); - return exec; + return ReferenceExecutor::create(); } #endif #ifdef KOKKOS_ENABLE_OPENMP if constexpr (std::is_same_v) { - static auto exec = OmpExecutor::create(); - return exec; + return OmpExecutor::create(); } #endif GKO_NOT_IMPLEMENTED; @@ -188,6 +181,10 @@ inline std::shared_ptr create_default_host_executor() * constructor. * * @tparam ExecSpace A supported Kokkos ExecutionSpace. + * @tparam MemorySpace A supported Kokkos MemorySpace. Defaults to the one + * defined in the ExecSpace. + * + * @param ex the execution space * * @return An executor matching the type of the ExecSpace. */ @@ -197,8 +194,6 @@ inline std::shared_ptr create_executor(ExecSpace ex, MemorySpace = {}) { static_assert( Kokkos::SpaceAccessibility::accessible); - static std::mutex mutex{}; - std::lock_guard guard(mutex); #ifdef KOKKOS_ENABLE_SERIAL if constexpr (std::is_same_v) { return ReferenceExecutor::create(); @@ -214,20 +209,19 @@ inline std::shared_ptr create_executor(ExecSpace ex, MemorySpace = {}) if constexpr (std::is_same_v) { return CudaExecutor::create( Kokkos::device_id(), create_default_host_executor(), - std::make_shared(), ex.cuda_stream()); + std::make_shared(), ex.cuda_stream()); } if constexpr (std::is_same_v) { return CudaExecutor::create( Kokkos::device_id(), create_default_host_executor(), - std::make_shared( - Kokkos::device_id()), + std::make_shared(Kokkos::device_id()), ex.cuda_stream()); } if constexpr (std::is_same_v) { return CudaExecutor::create( Kokkos::device_id(), create_default_host_executor(), - std::make_shared(Kokkos::device_id()), + std::make_shared(Kokkos::device_id()), ex.cuda_stream()); } } @@ -237,18 +231,18 @@ inline std::shared_ptr create_executor(ExecSpace ex, MemorySpace = {}) if constexpr (std::is_same_v) { return HipExecutor::create( Kokkos::device_id(), create_default_host_executor(), - std::make_shared(), ex.hip_stream()); + std::make_shared(), ex.hip_stream()); } if constexpr (std::is_same_v) { return HipExecutor::create( Kokkos::device_id(), create_default_host_executor(), - std::make_shared(Kokkos::device_id()), + std::make_shared(Kokkos::device_id()), ex.hip_stream()); } if constexpr (std::is_same_v) { return HipExecutor::create( Kokkos::device_id(), create_default_host_executor(), - std::make_shared(Kokkos::device_id()), + std::make_shared(Kokkos::device_id()), ex.hip_stream()); } } @@ -283,5 +277,4 @@ inline std::shared_ptr create_default_executor( } // namespace gko -#endif // GINKGO_EXTENSION_KOKKOS -#endif // GINKGO_SPACES_HPP +#endif // GINKGO_EXTENSIONS_KOKKOS_SPACES_HPP diff --git a/include/ginkgo/extensions/kokkos/types.hpp b/include/ginkgo/extensions/kokkos/types.hpp index 270258f3b72..88362f317b1 100644 --- a/include/ginkgo/extensions/kokkos/types.hpp +++ b/include/ginkgo/extensions/kokkos/types.hpp @@ -5,16 +5,16 @@ #ifndef GINKGO_EXTENSIONS_KOKKOS_TYPES_HPP #define GINKGO_EXTENSIONS_KOKKOS_TYPES_HPP -#include +#include -#if GINKGO_EXTENSION_KOKKOS -#include #include +#include #include #include +#include namespace gko { @@ -66,12 +66,25 @@ template using value_type_t = typename value_type::type; +/** + * Maps ginkgo types to the corresponding kokkos type + * + * @tparam T A ginkgo type to map + * @tparam MemorySpace A kokkos MemorySpace which the resulting type will use + * + * @warning The MemorySpace has to match the internally used executor of T. + * + * @note This only describes the interface of the mapper class. The actual + * implementation is done via specialization of this class. + */ template struct mapper { static auto map(T&); + static auto map(const T&); }; + /** * Type that maps a Ginkgo array to an unmanaged 1D Kokkos::View. * @@ -87,36 +100,74 @@ struct mapper, MemorySpace> { Kokkos::View::type*, MemorySpace, Kokkos::MemoryTraits>; + /** + * Constructor based on size and raw pointer + * + * @tparam ValueType_c The same type as ValueType, but possible + * const-qualified + * @param data The pointer to the data + * @param size The size of the array + * @return A Kokkos 1D-view to the data + */ template - static type map(ValueType_c* data, size_type size) - { - return type{ - reinterpret_cast*>(data), size}; - } + static type map(ValueType_c* data, size_type size); - static type map(array& arr) - { - assert_compatibility(arr, MemorySpace{}); + /** + * Maps a mutable array. + */ + static type map(array& arr); - return map(arr.get_data(), arr.get_size()); - } + /** + * Maps a const array. + */ + static type map(const array& arr); - static type map(const array& arr) - { - assert_compatibility(arr, MemorySpace{}); + /** + * Maps a const_array_view (same as mapping a const array). + */ + static type map( + const ::gko::detail::const_array_view& arr); +}; - return map(arr.get_const_data(), arr.get_size()); - } +template +template +typename mapper, MemorySpace>::template type +mapper, MemorySpace>::map(ValueType_c* data, size_type size) +{ + return type{reinterpret_cast*>(data), + size}; +} - static type map( - const ::gko::detail::const_array_view& arr) - { - assert_compatibility(arr, MemorySpace{}); +template +typename mapper, MemorySpace>::template type +mapper, MemorySpace>::map(array& arr) +{ + assert_compatibility(arr); - return map(arr.get_const_data(), arr.get_size()); - } -}; + return map(arr.get_data(), arr.get_size()); +} + + +template +typename mapper, MemorySpace>::template type +mapper, MemorySpace>::map(const array& arr) +{ + assert_compatibility(arr); + + return map(arr.get_const_data(), arr.get_size()); +} + + +template +typename mapper, MemorySpace>::template type +mapper, MemorySpace>::map( + const ::gko::detail::const_array_view& arr) +{ + assert_compatibility(arr); + + return map(arr.get_const_data(), arr.get_size()); +} /** @@ -134,62 +185,48 @@ struct mapper, MemorySpace> { Kokkos::LayoutStride, MemorySpace, Kokkos::MemoryTraits>; - static type map(matrix::Dense& m) - { - assert_compatibility(m, MemorySpace{}); + /** + * Maps a mutable dense matrix. + */ + static type map(matrix::Dense& m); + + /** + * Maps a const dense matrix. + */ + static type map(const matrix::Dense& m); +}; - auto size = m.get_size(); +template +typename mapper, MemorySpace>::template type +mapper, MemorySpace>::map(matrix::Dense& m) +{ + assert_compatibility(m); - return type{ - reinterpret_cast*>(m.get_values()), - Kokkos::LayoutStride{size[0], m.get_stride(), size[1], 1}}; - } + auto size = m.get_size(); - static type map(const matrix::Dense& m) - { - assert_compatibility(m, MemorySpace{}); + return type{ + reinterpret_cast*>(m.get_values()), + Kokkos::LayoutStride{size[0], m.get_stride(), size[1], 1}}; +} - auto size = m.get_size(); - return type{ - reinterpret_cast*>( - m.get_const_values()), - Kokkos::LayoutStride{size[0], m.get_stride(), size[1], 1}}; - } -}; +template +typename mapper, + MemorySpace>::template type +mapper, MemorySpace>::map( + const matrix::Dense& m) +{ + assert_compatibility(m); + auto size = m.get_size(); -} // namespace detail + return type{ + reinterpret_cast*>(m.get_const_values()), + Kokkos::LayoutStride{size[0], m.get_stride(), size[1], 1}}; +} -//!< specialization of gko::native for Kokkos -template -struct kokkos_type { - template - static auto map(T* data) - { - return map(*data); - } - - template - static auto map(const std::unique_ptr& data) - { - return map(*data); - } - - template - static auto map(const std::shared_ptr& data) - { - return map(*data); - } - - template - static auto map(T&& data) - { - return detail::mapper, MemorySpace>::map( - std::forward(data)); - } -}; +} // namespace detail /** @@ -202,41 +239,42 @@ struct kokkos_type { * * @return A wrapper for the Ginkgo object that is compatible with Kokkos */ -template -inline auto map_data(T* data, MemorySpace = {}) +template +inline auto map_data(T&& data) { - return kokkos_type::map(*data); + return detail::mapper, MemorySpace>::map( + std::forward(data)); } /** - * @copydoc map_data(T*, MemorySpace) + * @copydoc map_data(T&&, MemorySpace) */ -template -inline auto map_data(std::unique_ptr& data, MemorySpace = {}) +template +inline auto map_data(T* data) { - return kokkos_type::map(*data); + return map_data(*data); } /** - * @copydoc map_data(T*, MemorySpace) + * @copydoc map_data(T&&, MemorySpace) */ -template -inline auto map_data(std::shared_ptr& data, MemorySpace = {}) +template +inline auto map_data(std::unique_ptr& data) { - return kokkos_type::map(*data); + return map_data(*data); } /** - * @copydoc map_data(T*, MemorySpace) + * @copydoc map_data(T&&, MemorySpace) */ -template -inline auto map_data(T&& data, MemorySpace = {}) +template +inline auto map_data(std::shared_ptr& data) { - return kokkos_type::map(data); + return map_data(*data); } @@ -245,5 +283,4 @@ inline auto map_data(T&& data, MemorySpace = {}) } // namespace gko -#endif // GINKGO_EXTENSION_KOKKOS #endif // GINKGO_EXTENSIONS_KOKKOS_TYPES_HPP