From 86abc1941cbfd5c26b004d6ccb70f66cfcdf2c26 Mon Sep 17 00:00:00 2001 From: Nicolas Morales Date: Mon, 15 Apr 2024 16:28:45 -0700 Subject: [PATCH 1/2] initial work on mdspan copy impl --- include/experimental/p3242_bits/copy.hpp | 131 +++++++++++++++++++++++ include/mdspan/mdspan.hpp | 1 + tests/CMakeLists.txt | 1 + tests/test_mdspan_copy_and_fill.cpp | 65 +++++++++++ 4 files changed, 198 insertions(+) create mode 100644 include/experimental/p3242_bits/copy.hpp create mode 100644 tests/test_mdspan_copy_and_fill.cpp diff --git a/include/experimental/p3242_bits/copy.hpp b/include/experimental/p3242_bits/copy.hpp new file mode 100644 index 00000000..cd027f72 --- /dev/null +++ b/include/experimental/p3242_bits/copy.hpp @@ -0,0 +1,131 @@ +//@HEADER +// ************************************************************************ +// +// Kokkos v. 4.0 +// Copyright (2022) National Technology & Engineering +// Solutions of Sandia, LLC (NTESS). +// +// Under the terms of Contract DE-NA0003525 with NTESS, +// the U.S. Government retains certain rights in this software. +// +// Part of Kokkos, under the Apache License v2.0 with LLVM Exceptions. +// See https://kokkos.org/LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//@HEADER +#pragma once + +#include "../__p0009_bits/default_accessor.hpp" +#include "../__p0009_bits/extents.hpp" +#include "../__p0009_bits/layout_left.hpp" +#include "../__p0009_bits/layout_right.hpp" +#include "../__p0009_bits/mdspan.hpp" +#include +#include +#include +#include + +namespace MDSPAN_IMPL_STANDARD_NAMESPACE { +namespace MDSPAN_IMPL_PROPOSED_NAMESPACE { +namespace detail { + +template +constexpr void apply_fun_over_extents(const Extents &ext, F &fun, + ArrayType &indices, + std::index_sequence<>) { + std::apply(fun, indices); +} + +template +constexpr void apply_fun_over_extents(const Extents &ext, F &fun, + ArrayType &indices, + std::index_sequence) { + using index_type = typename Extents::index_type; + for (index_type i = 0; i < ext.extent(R); ++i) { + indices[R] = i; + apply_fun_over_extents(ext, fun, indices, std::index_sequence{}); + } +} + +template struct make_reverse_index_sequence_impl; + +template +struct make_reverse_index_sequence_impl> { + using type = std::index_sequence<(N - 1 - Indices)...>; +}; + +template +using make_reverse_index_sequence = typename make_reverse_index_sequence_impl< + N, std::make_index_sequence>::type; + +template +struct mdspan_copy_impl { + using extents_type = typename DstMDSpanType::extents_type; + + static constexpr void copy_over_extents(const extents_type &ext, + const SrcMDSpanType &src, + const DstMDSpanType &dst) { + // Generic copy algorithm; this assumes a roughly layout-right traversal + // but this may not be cache efficient if we can't determine anything about + // the layout memory ordering + constexpr auto rank = extents_type::rank(); + auto indices = std::array{}; + apply_fun_over_extents( + ext, [&src, &dst](auto... idxs) { dst(idxs...) = src(idxs...); }, + indices, make_reverse_index_sequence{}); + } +}; + +template +struct mdspan_copy_impl< + mdspan>, + mdspan>, + void> { + using extents_type = DstExtents; + using src_mdspan_type = mdspan>; + using dst_mdspan_type = mdspan>; + + static constexpr void copy_over_extents(const extents_type &ext, + const src_mdspan_type &src, + const dst_mdspan_type &dst) { + std::memcpy(dst.data_handle(), src.data_handle(), dst.mapping().required_span_size() * sizeof(ElementType)); + } +}; + +template +struct mdspan_copy_impl< + mdspan>, + mdspan>, + void> { + using extents_type = DstExtents; + using src_mdspan_type = mdspan>; + using dst_mdspan_type = mdspan>; + + static constexpr void copy_over_extents(const extents_type &ext, + const src_mdspan_type &src, + const dst_mdspan_type &dst) { + std::memcpy(dst.data_handle(), src.data_handle(), dst.mapping().required_span_size() * sizeof(ElementType)); + } +}; +} // namespace detail + +template +void copy( + mdspan src, + mdspan + dst) { + using src_type = + mdspan; + using dst_type = + mdspan; + detail::mdspan_copy_impl::copy_over_extents(src.extents(), + src, dst); +} +} // namespace MDSPAN_IMPL_PROPOSED_NAMESPACE +} // namespace MDSPAN_IMPL_STANDARD_NAMESPACE diff --git a/include/mdspan/mdspan.hpp b/include/mdspan/mdspan.hpp index ac72a1a4..8ab38e16 100644 --- a/include/mdspan/mdspan.hpp +++ b/include/mdspan/mdspan.hpp @@ -37,6 +37,7 @@ #if MDSPAN_HAS_CXX_17 #include "../experimental/__p2642_bits/layout_padded.hpp" #include "../experimental/__p2630_bits/submdspan.hpp" +#include "../experimental/p3242_bits/copy.hpp" #endif #endif // MDSPAN_HPP_ diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index f8420b42..ec1a331a 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -62,6 +62,7 @@ mdspan_add_test(test_submdspan) mdspan_add_test(test_submdspan_static_slice) mdspan_add_test(test_layout_padded_left) mdspan_add_test(test_layout_padded_right) +mdspan_add_test(test_mdspan_copy_and_fill) endif() # both of those don't work yet since its using vector if(NOT MDSPAN_ENABLE_CUDA AND NOT MDSPAN_ENABLE_HIP) diff --git a/tests/test_mdspan_copy_and_fill.cpp b/tests/test_mdspan_copy_and_fill.cpp new file mode 100644 index 00000000..6899c770 --- /dev/null +++ b/tests/test_mdspan_copy_and_fill.cpp @@ -0,0 +1,65 @@ +//@HEADER +// ************************************************************************ +// +// Kokkos v. 4.0 +// Copyright (2022) National Technology & Engineering +// Solutions of Sandia, LLC (NTESS). +// +// Under the terms of Contract DE-NA0003525 with NTESS, +// the U.S. Government retains certain rights in this software. +// +// Part of Kokkos, under the Apache License v2.0 with LLVM Exceptions. +// See https://kokkos.org/LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//@HEADER + +#include +#include + +#include + +template +void test_mdspan_copy_impl(const SrcExtents &src_exts, + const DstExtents &dst_exts) { + Kokkos::Experimental::mdarray src1{src_exts}; + Kokkos::Experimental::mdarray dst1{dst_exts}; + auto &src1c = src1.container(); + for (size_t i = 0; i < src1c.size(); ++i) + src1c[i] = static_cast(i * i); + + ASSERT_NE(dst1.container(), src1.container()); + Kokkos::Experimental::copy(src1.to_mdspan(), dst1.to_mdspan()); + ASSERT_EQ(dst1.container(), src1.container()); +} + +TEST(TestMdspanCopyAndFill, test_mdspan_copy) { + test_mdspan_copy_impl( + Kokkos::extents{}, Kokkos::extents{}); + test_mdspan_copy_impl( + Kokkos::extents{}, Kokkos::extents{}); + test_mdspan_copy_impl( + Kokkos::extents{}, Kokkos::extents{}); + + test_mdspan_copy_impl( + Kokkos::dextents{5, 3}, Kokkos::extents{}); + test_mdspan_copy_impl( + Kokkos::dextents{5, 3}, Kokkos::extents{}); + test_mdspan_copy_impl( + Kokkos::dextents{5, 3}, Kokkos::extents{}); + + test_mdspan_copy_impl( + Kokkos::extents{}, Kokkos::dextents{5, 3}); + test_mdspan_copy_impl( + Kokkos::extents{}, Kokkos::dextents{5, 3}); + test_mdspan_copy_impl( + Kokkos::extents{}, Kokkos::dextents{5, 3}); + + test_mdspan_copy_impl( + Kokkos::dextents{5, 3}, Kokkos::dextents{5, 3}); + test_mdspan_copy_impl( + Kokkos::dextents{5, 3}, Kokkos::dextents{5, 3}); + test_mdspan_copy_impl( + Kokkos::dextents{5, 3}, Kokkos::dextents{5, 3}); +} From 53aed2ecf3f508f970e7afa2c59a47eb3e030a18 Mon Sep 17 00:00:00 2001 From: Nicolas Morales Date: Mon, 15 Apr 2024 19:29:20 -0700 Subject: [PATCH 2/2] explicitly construct dst extents type --- include/experimental/p3242_bits/copy.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/experimental/p3242_bits/copy.hpp b/include/experimental/p3242_bits/copy.hpp index cd027f72..5f7a184f 100644 --- a/include/experimental/p3242_bits/copy.hpp +++ b/include/experimental/p3242_bits/copy.hpp @@ -124,7 +124,7 @@ void copy( mdspan; using dst_type = mdspan; - detail::mdspan_copy_impl::copy_over_extents(src.extents(), + detail::mdspan_copy_impl::copy_over_extents(DstExtents{src.extents()}, src, dst); } } // namespace MDSPAN_IMPL_PROPOSED_NAMESPACE