Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

initial work on mdspan copy impl #325

Draft
wants to merge 2 commits into
base: stable
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
131 changes: 131 additions & 0 deletions include/experimental/p3242_bits/copy.hpp
Original file line number Diff line number Diff line change
@@ -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 <array>
#include <cstring>
#include <functional>
#include <utility>

namespace MDSPAN_IMPL_STANDARD_NAMESPACE {
namespace MDSPAN_IMPL_PROPOSED_NAMESPACE {
namespace detail {

template <class Extents, class F, class ArrayType>
constexpr void apply_fun_over_extents(const Extents &ext, F &fun,
ArrayType &indices,
std::index_sequence<>) {
std::apply(fun, indices);
}

template <class Extents, class F, class ArrayType, size_t R, size_t... Ranks>
constexpr void apply_fun_over_extents(const Extents &ext, F &fun,
ArrayType &indices,
std::index_sequence<R, Ranks...>) {
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<Ranks...>{});
}
}

template <size_t N, class Indices> struct make_reverse_index_sequence_impl;

template <size_t N, size_t... Indices>
struct make_reverse_index_sequence_impl<N, std::index_sequence<Indices...>> {
using type = std::index_sequence<(N - 1 - Indices)...>;
};

template <size_t N>
using make_reverse_index_sequence = typename make_reverse_index_sequence_impl<
N, std::make_index_sequence<N>>::type;

template <class SrcMDSpanType, class DstMDSpanType, typename Enabled = void>
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<typename extents_type::index_type, rank>{};
apply_fun_over_extents(
ext, [&src, &dst](auto... idxs) { dst(idxs...) = src(idxs...); },
indices, make_reverse_index_sequence<rank>{});
}
};

template <class ElementType, class SrcExtents, class DstExtents>
struct mdspan_copy_impl<
mdspan<ElementType, SrcExtents, layout_left, default_accessor<ElementType>>,
mdspan<ElementType, DstExtents, layout_left, default_accessor<ElementType>>,
void> {
using extents_type = DstExtents;
using src_mdspan_type = mdspan<ElementType, SrcExtents, layout_left,
default_accessor<ElementType>>;
using dst_mdspan_type = mdspan<ElementType, DstExtents, layout_left,
default_accessor<ElementType>>;

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 <class ElementType, class SrcExtents, class DstExtents>
struct mdspan_copy_impl<
mdspan<ElementType, SrcExtents, layout_right, default_accessor<ElementType>>,
mdspan<ElementType, DstExtents, layout_right, default_accessor<ElementType>>,
void> {
using extents_type = DstExtents;
using src_mdspan_type = mdspan<ElementType, SrcExtents, layout_left,
default_accessor<ElementType>>;
using dst_mdspan_type = mdspan<ElementType, DstExtents, layout_left,
default_accessor<ElementType>>;

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 <class SrcElementType, class SrcExtents, class SrcLayoutPolicy,
class SrcAccessorPolicy, class DstElementType, class DstExtents,
class DstLayoutPolicy, class DstAccessorPolicy>
void copy(
mdspan<SrcElementType, SrcExtents, SrcLayoutPolicy, SrcAccessorPolicy> src,
mdspan<DstElementType, DstExtents, DstLayoutPolicy, DstAccessorPolicy>
dst) {
using src_type =
mdspan<SrcElementType, SrcExtents, SrcLayoutPolicy, SrcAccessorPolicy>;
using dst_type =
mdspan<DstElementType, DstExtents, DstLayoutPolicy, DstAccessorPolicy>;
detail::mdspan_copy_impl<src_type, dst_type>::copy_over_extents(DstExtents{src.extents()},
src, dst);
}
} // namespace MDSPAN_IMPL_PROPOSED_NAMESPACE
} // namespace MDSPAN_IMPL_STANDARD_NAMESPACE
1 change: 1 addition & 0 deletions include/mdspan/mdspan.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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_
1 change: 1 addition & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
65 changes: 65 additions & 0 deletions tests/test_mdspan_copy_and_fill.cpp
Original file line number Diff line number Diff line change
@@ -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 <mdspan/mdarray.hpp>
#include <mdspan/mdspan.hpp>

#include <gtest/gtest.h>

template <class T, class SrcLayout, class DstLayout, class SrcExtents,
class DstExtents>
void test_mdspan_copy_impl(const SrcExtents &src_exts,
const DstExtents &dst_exts) {
Kokkos::Experimental::mdarray<T, SrcExtents, SrcLayout> src1{src_exts};
Kokkos::Experimental::mdarray<T, DstExtents, DstLayout> dst1{dst_exts};
auto &src1c = src1.container();
for (size_t i = 0; i < src1c.size(); ++i)
src1c[i] = static_cast<T>(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<int, Kokkos::layout_left, Kokkos::layout_left>(
Kokkos::extents<size_t, 5, 3>{}, Kokkos::extents<size_t, 5, 3>{});
test_mdspan_copy_impl<double, Kokkos::layout_left, Kokkos::layout_left>(
Kokkos::extents<size_t, 5, 3>{}, Kokkos::extents<size_t, 5, 3>{});
test_mdspan_copy_impl<float, Kokkos::layout_left, Kokkos::layout_left>(
Kokkos::extents<size_t, 5, 3>{}, Kokkos::extents<size_t, 5, 3>{});

test_mdspan_copy_impl<int, Kokkos::layout_left, Kokkos::layout_left>(
Kokkos::dextents<size_t, 2>{5, 3}, Kokkos::extents<size_t, 5, 3>{});
test_mdspan_copy_impl<double, Kokkos::layout_left, Kokkos::layout_left>(
Kokkos::dextents<size_t, 2>{5, 3}, Kokkos::extents<size_t, 5, 3>{});
test_mdspan_copy_impl<float, Kokkos::layout_left, Kokkos::layout_left>(
Kokkos::dextents<size_t, 2>{5, 3}, Kokkos::extents<size_t, 5, 3>{});

test_mdspan_copy_impl<int, Kokkos::layout_left, Kokkos::layout_left>(
Kokkos::extents<size_t, 5, 3>{}, Kokkos::dextents<size_t, 2>{5, 3});
test_mdspan_copy_impl<double, Kokkos::layout_left, Kokkos::layout_left>(
Kokkos::extents<size_t, 5, 3>{}, Kokkos::dextents<size_t, 2>{5, 3});
test_mdspan_copy_impl<float, Kokkos::layout_left, Kokkos::layout_left>(
Kokkos::extents<size_t, 5, 3>{}, Kokkos::dextents<size_t, 2>{5, 3});

test_mdspan_copy_impl<int, Kokkos::layout_left, Kokkos::layout_left>(
Kokkos::dextents<size_t, 2>{5, 3}, Kokkos::dextents<size_t, 2>{5, 3});
test_mdspan_copy_impl<double, Kokkos::layout_left, Kokkos::layout_left>(
Kokkos::dextents<size_t, 2>{5, 3}, Kokkos::dextents<size_t, 2>{5, 3});
test_mdspan_copy_impl<float, Kokkos::layout_left, Kokkos::layout_left>(
Kokkos::dextents<size_t, 2>{5, 3}, Kokkos::dextents<size_t, 2>{5, 3});
}
Loading