//@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 namespace Test { #ifdef KOKKOS_ENABLE_CXX11_DISPATCH_LAMBDA namespace Impl { template struct TestDeepCopy { using a_base_t = Kokkos::View; using b_base_t = Kokkos::View; using a_char_t = Kokkos::View; using b_char_t = Kokkos::View; using policyA_t = Kokkos::RangePolicy; using policyB_t = Kokkos::RangePolicy; static void reset_a_copy_and_b( Kokkos::View a_char_copy, Kokkos::View b_char) { const int N = b_char.extent_int(0); Kokkos::parallel_for( "TestDeepCopy: FillA_copy", policyA_t(0, N), KOKKOS_LAMBDA(const int& i) { a_char_copy(i) = char(0); }); Kokkos::parallel_for( "TestDeepCopy: FillB", policyB_t(0, N), KOKKOS_LAMBDA(const int& i) { b_char(i) = char(0); }); } static int compare_equal( Kokkos::View a_char_copy, Kokkos::View a_char) { const int N = a_char.extent_int(0); int errors; Kokkos::parallel_reduce( "TestDeepCopy: FillA_copy", policyA_t(0, N), KOKKOS_LAMBDA(const int& i, int& lsum) { if (a_char_copy(i) != a_char(i)) lsum++; }, errors); return errors; } static void run_test(int num_bytes) { a_base_t a_base("test_space_to_space", (num_bytes + 128) / 8); a_base_t a_base_copy("test_space_to_space", (num_bytes + 128) / 8); Kokkos::View b_base( "test_space_to_space", (num_bytes + 128) / 8); Kokkos::View a_char( (char*)a_base.data(), a_base.extent(0) * 8); Kokkos::View a_char_copy( (char*)a_base_copy.data(), a_base.extent(0) * 8); Kokkos::View b_char( (char*)b_base.data(), b_base.extent(0) * 8); Kokkos::parallel_for( "TestDeepCopy: FillA", policyA_t(0, a_char.extent(0)), KOKKOS_LAMBDA(const int& i) { a_char(i) = static_cast(i % 97) + 1; }); reset_a_copy_and_b(a_char_copy, b_char); { size_t check = compare_equal(a_char_copy, a_char); ASSERT_EQ(check, a_char.extent(0)); } // (a.data()%8, (a.data()+a.extent(0))%8, b.data()%8, // (b.data()+b.extent(0))%8 (0,0,0,0) { int a_begin = 0; int a_end = 0; int b_begin = 0; int b_end = 0; auto a = Kokkos::subview( a_char, std::pair(a_begin, a_char.extent_int(0) - a_end)); auto b = Kokkos::subview( b_char, std::pair(b_begin, b_char.extent_int(0) - b_end)); auto a_copy = Kokkos::subview( a_char_copy, std::pair(a_begin, a_char_copy.extent_int(0) - a_end)); Kokkos::deep_copy(b, a); Kokkos::deep_copy(a_copy, b); int check = compare_equal(a_copy, a); ASSERT_EQ(check, 0); } { int a_begin = 0; int a_end = 5; int b_begin = 0; int b_end = 5; auto a = Kokkos::subview( a_char, std::pair(a_begin, a_char.extent_int(0) - a_end)); auto b = Kokkos::subview( b_char, std::pair(b_begin, b_char.extent_int(0) - b_end)); auto a_copy = Kokkos::subview( a_char_copy, std::pair(a_begin, a_char_copy.extent_int(0) - a_end)); Kokkos::deep_copy(b, a); Kokkos::deep_copy(a_copy, b); int check = compare_equal(a_copy, a); ASSERT_EQ(check, 0); } { int a_begin = 3; int a_end = 0; int b_begin = 3; int b_end = 0; auto a = Kokkos::subview( a_char, std::pair(a_begin, a_char.extent_int(0) - a_end)); auto b = Kokkos::subview( b_char, std::pair(b_begin, b_char.extent_int(0) - b_end)); auto a_copy = Kokkos::subview( a_char_copy, std::pair(a_begin, a_char_copy.extent_int(0) - a_end)); Kokkos::deep_copy(b, a); Kokkos::deep_copy(a_copy, b); int check = compare_equal(a_copy, a); ASSERT_EQ(check, 0); } { int a_begin = 3; int a_end = 6; int b_begin = 3; int b_end = 6; auto a = Kokkos::subview( a_char, std::pair(a_begin, a_char.extent_int(0) - a_end)); auto b = Kokkos::subview( b_char, std::pair(b_begin, b_char.extent_int(0) - b_end)); auto a_copy = Kokkos::subview( a_char_copy, std::pair(a_begin, a_char_copy.extent_int(0) - a_end)); Kokkos::deep_copy(b, a); Kokkos::deep_copy(a_copy, b); int check = compare_equal(a_copy, a); ASSERT_EQ(check, 0); } { int a_begin = 5; int a_end = 4; int b_begin = 3; int b_end = 6; auto a = Kokkos::subview( a_char, std::pair(a_begin, a_char.extent_int(0) - a_end)); auto b = Kokkos::subview( b_char, std::pair(b_begin, b_char.extent_int(0) - b_end)); auto a_copy = Kokkos::subview( a_char_copy, std::pair(a_begin, a_char_copy.extent_int(0) - a_end)); Kokkos::deep_copy(b, a); Kokkos::deep_copy(a_copy, b); int check = compare_equal(a_copy, a); ASSERT_EQ(check, 0); } { int a_begin = 0; int a_end = 8; int b_begin = 2; int b_end = 6; auto a = Kokkos::subview( a_char, std::pair(a_begin, a_char.extent_int(0) - a_end)); auto b = Kokkos::subview( b_char, std::pair(b_begin, b_char.extent_int(0) - b_end)); auto a_copy = Kokkos::subview( a_char_copy, std::pair(a_begin, a_char_copy.extent_int(0) - a_end)); Kokkos::deep_copy(b, a); Kokkos::deep_copy(a_copy, b); int check = compare_equal(a_copy, a); ASSERT_EQ(check, 0); } { int a_begin = 2; int a_end = 6; int b_begin = 0; int b_end = 8; auto a = Kokkos::subview( a_char, std::pair(a_begin, a_char.extent_int(0) - a_end)); auto b = Kokkos::subview( b_char, std::pair(b_begin, b_char.extent_int(0) - b_end)); auto a_copy = Kokkos::subview( a_char_copy, std::pair(a_begin, a_char_copy.extent_int(0) - a_end)); Kokkos::deep_copy(b, a); Kokkos::deep_copy(a_copy, b); int check = compare_equal(a_copy, a); ASSERT_EQ(check, 0); } } }; } // namespace Impl TEST(TEST_CATEGORY, deep_copy_alignment) { { Impl::TestDeepCopy::run_test(100000); } { Impl::TestDeepCopy::run_test(100000); } { Impl::TestDeepCopy::run_test(100000); } } #endif namespace Impl { template struct TestDeepCopyScalarConversion { struct TagFill {}; struct TagCompare {}; using view_type_s1_1d = Kokkos::View; using view_type_s2_1d = Kokkos::View; using view_type_s1_2d = Kokkos::View; using view_type_s2_2d = Kokkos::View; using base_layout1 = std::conditional_t::value, Kokkos::LayoutLeft, Layout1>; using base_layout2 = std::conditional_t::value, Kokkos::LayoutLeft, Layout2>; using base_type_s1_1d = Kokkos::View; using base_type_s2_1d = Kokkos::View; using base_type_s1_2d = Kokkos::View; using base_type_s2_2d = Kokkos::View; view_type_s1_1d view_s1_1d; view_type_s2_1d view_s2_1d; view_type_s1_2d view_s1_2d; view_type_s2_2d view_s2_2d; Kokkos::View error_count; void create_views(int64_t N0, int64_t N1) { base_type_s1_1d b_s1_1d("TestDeepCopyConversion::b_s1_1d", N0); base_type_s2_1d b_s2_1d("TestDeepCopyConversion::b_s2_1d", N0); base_type_s1_2d b_s1_2d("TestDeepCopyConversion::b_s1_2d", N0, N1); base_type_s2_2d b_s2_2d("TestDeepCopyConversion::b_s2_2d", N0, N1); view_s1_1d = view_type_s1_1d(b_s1_1d, Kokkos::ALL); view_s2_1d = view_type_s2_1d(b_s2_1d, Kokkos::ALL); view_s1_2d = view_type_s1_2d(b_s1_2d, Kokkos::ALL, Kokkos::ALL); view_s2_2d = view_type_s2_2d(b_s2_2d, Kokkos::ALL, Kokkos::ALL); error_count = Kokkos::View( "TestDeepCopyConversion::error_count"); } KOKKOS_FUNCTION void operator()(TagFill, const int64_t i) const { view_s2_1d(i) = static_cast(i + 1); for (int64_t j = 0; j < static_cast(view_s2_2d.extent(1)); j++) view_s2_2d(i, j) = static_cast((i + 1) * 1000 + j + 1); } KOKKOS_FUNCTION void operator()(TagCompare, const int64_t i) const { int64_t errors = 0; if (view_s1_1d(i) != static_cast(static_cast(i + 1))) errors++; for (int64_t j = 0; j < static_cast(view_s1_2d.extent(1)); j++) { if (view_s1_2d(i, j) != static_cast(static_cast((i + 1) * 1000 + j + 1))) errors++; } if (errors > 0) Kokkos::atomic_add(&error_count(), errors); } void run_tests(int64_t N0, int64_t N1) { create_views(N0, N1); Kokkos::parallel_for("TestDeepCopyConversion::Fill", Kokkos::RangePolicy>(0, N0), *this); Kokkos::deep_copy(view_s1_1d, view_s2_1d); Kokkos::deep_copy(view_s1_2d, view_s2_2d); Kokkos::parallel_for("TestDeepCopyConversion::Compare", Kokkos::RangePolicy>(0, N0), *this); int64_t errors = 0; Kokkos::deep_copy(errors, error_count); ASSERT_EQ(errors, 0); Kokkos::deep_copy(view_s1_1d, static_cast(0)); Kokkos::deep_copy(view_s1_2d, static_cast(0)); Kokkos::parallel_for("TestDeepCopyConversion::Compare", Kokkos::RangePolicy>(0, N0), *this); Kokkos::deep_copy(errors, error_count); ASSERT_GT(errors, 0); Kokkos::deep_copy(error_count, 0); Kokkos::deep_copy(TEST_EXECSPACE(), view_s1_1d, view_s2_1d); Kokkos::deep_copy(TEST_EXECSPACE(), view_s1_2d, view_s2_2d); Kokkos::parallel_for("TestDeepCopyConversion::Compare", Kokkos::RangePolicy>(0, N0), *this); Kokkos::deep_copy(errors, error_count); ASSERT_EQ(errors, 0); } }; } // namespace Impl TEST(TEST_CATEGORY, deep_copy_conversion) { #ifdef KOKKOS_IMPL_32BIT GTEST_SKIP() << "Failing KOKKOS_IMPL_32BIT"; // FIXME_32BIT #endif int64_t N0 = 19381; int64_t N1 = 17; using right = Kokkos::LayoutRight; using left = Kokkos::LayoutLeft; using stride = Kokkos::LayoutStride; Impl::TestDeepCopyScalarConversion().run_tests( N0, N1); Impl::TestDeepCopyScalarConversion().run_tests( N0, N1); Impl::TestDeepCopyScalarConversion().run_tests( N0, N1); Impl::TestDeepCopyScalarConversion().run_tests( N0, N1); Impl::TestDeepCopyScalarConversion().run_tests( N0, N1); Impl::TestDeepCopyScalarConversion().run_tests( N0, N1); Impl::TestDeepCopyScalarConversion().run_tests( N0, N1); Impl::TestDeepCopyScalarConversion().run_tests( N0, N1); Impl::TestDeepCopyScalarConversion().run_tests( N0, N1); Impl::TestDeepCopyScalarConversion().run_tests( N0, N1); } } // namespace Test