From 742ed967415992a7c0de1ad632dade5a25916da8 Mon Sep 17 00:00:00 2001 From: mari2895 Date: Tue, 23 Jan 2024 18:39:14 -0500 Subject: [PATCH 1/9] tensor indices added to sparse pack --- src/interface/sparse_pack.hpp | 25 +++++++++++++ tst/unit/test_sparse_pack.cpp | 70 +++++++++++++++++++++++++++++++++-- 2 files changed, 92 insertions(+), 3 deletions(-) diff --git a/src/interface/sparse_pack.hpp b/src/interface/sparse_pack.hpp index d1befba64b93..f4bc6b333abf 100644 --- a/src/interface/sparse_pack.hpp +++ b/src/interface/sparse_pack.hpp @@ -90,6 +90,7 @@ KOKKOS_INLINE_FUNCTION PackIdx operator+(T offset, PackIdx idx) { // device namespace variable_names { // Struct that all variable_name types should inherit from +constexpr int ANYDIM = -1234; template struct base_t { KOKKOS_INLINE_FUNCTION @@ -98,6 +99,17 @@ struct base_t { KOKKOS_INLINE_FUNCTION explicit base_t(int idx1) : idx(idx1) {} + template ::value)> + /* + for 2D:, (M, N), + idx(m, n) = N*m + n + for 3D: (L, M, N) + idx(l, m, n) = (M*l + m)*N + n + = l*M*N + m*N + n + */ + KOKKOS_INLINE_FUNCTION explicit base_t(Args... args) + : idx(GetIndex_(std::forward(args)...)) {} + virtual ~base_t() = default; // All of these are just static methods so that there is no @@ -114,6 +126,19 @@ struct base_t { static int size() { return multiply::value; } const int idx; + + private: + template ::value)> + KOKKOS_INLINE_FUNCTION static auto GetIndex_(int first, TailArgs... rest) { + if constexpr (sizeof...(Tail) == 0) + return first; + else if constexpr (sizeof...(TailArgs) == 0) + return first; + else + return (multiply::value * first + + GetIndex_(std::forward(rest)...)); + } }; // An example variable name type that selects all variables available diff --git a/tst/unit/test_sparse_pack.cpp b/tst/unit/test_sparse_pack.cpp index 83ed9b0244f4..6f25ed1d8256 100644 --- a/tst/unit/test_sparse_pack.cpp +++ b/tst/unit/test_sparse_pack.cpp @@ -77,13 +77,76 @@ struct v5 : public parthenon::variable_names::base_t { static std::string name() { return "v5"; } }; +struct v7 : public parthenon::variable_names::base_t { + template + KOKKOS_INLINE_FUNCTION v7(Ts &&...args) + : parthenon::variable_names::base_t(std::forward(args)...) {} + static std::string name() { return "v7"; } +}; + } // namespace TEST_CASE("Test behavior of sparse packs", "[SparsePack]") { + constexpr int N = 6; + constexpr int NDIM = 3; + constexpr int NBLOCKS = 9; + + GIVEN("A tensor variable on a mesh") { + const std::vector tensor_shape{N, N, N, 3, 3}; + Metadata m_tensor({Metadata::Independent}, tensor_shape); + auto pkg = std::make_shared("Test package"); + pkg->AddField(m_tensor); + BlockList_t block_list = MakeBlockList(pkg, NBLOCKS, N, NDIM); + + MeshData mesh_data("base"); + mesh_data.Set(block_list, nullptr); + + WHEN("We initialize the independent variables by hand and deallocate one") { + auto ib = block_list[0]->cellbounds.GetBoundsI(IndexDomain::entire); + auto jb = block_list[0]->cellbounds.GetBoundsJ(IndexDomain::entire); + auto kb = block_list[0]->cellbounds.GetBoundsK(IndexDomain::entire); + for (int b = 0; b < NBLOCKS; ++b) { + auto &pmb = block_list[b]; + auto &pmbd = pmb->meshblock_data.Get(); + auto var = pmbd->Get("v7"); + auto var5 = var.data.Get<5>(); + int slower_rank = var5.GetDim(5); + int faster_rank = var5.GetDim(4); + par_for( + loop_pattern_mdrange_tag, "initializev7", DevExecSpace(), kb.s, kb.e, jb.s, + jb.e, ib.s, ib.e, KOKKOS_LAMBDA(int k, int j, int i) { + for (int l = 0; l < slower_rank; ++l) { + for (int m = 0; m < faster_rank; ++m) { + Real n = m + 1e1 * l; + var5(l, m, k, j, i) = n; + } + } + }); + } + THEN("A sparse pack can correctly index into tensor types") { + auto desc = parthenon::MakePackDescriptor(pkg.get()); + auto sparse_pack = desc.GetPack(&mesh_data); + int nwrong = 0; + par_reduce( + loop_pattern_mdrange_tag, "check vector", DevExecSpace(), 0, + sparse_pack.GetNBlocks() - 1, kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, + KOKKOS_LAMBDA(int b, int k, int j, int i, int <ot) { + for (int l = 0; l < 3; ++l) { + for (int m = 0; m < 3; ++m) { + Real n = m + 1e1 * l; + if (sparse_pack(b, v7(l, m), k, j, i) != n) { + ltot += 1; + } + } + } + }, + nwrong); + REQUIRE(nwrong == 0); + } + } + } + GIVEN("A set of meshblocks and meshblock and mesh data") { - constexpr int N = 6; - constexpr int NDIM = 3; - constexpr int NBLOCKS = 9; const std::vector scalar_shape{N, N, N}; const std::vector vector_shape{N, N, N, 3}; @@ -122,6 +185,7 @@ TEST_CASE("Test behavior of sparse packs", "[SparsePack]") { }); } } + // Deallocate a variable on an arbitrary block block_list[2]->DeallocateSparse("v3"); From f31af2de73181bc9c7cdcb0345e5e2d019aaea2b Mon Sep 17 00:00:00 2001 From: mari2895 Date: Tue, 23 Jan 2024 18:45:28 -0500 Subject: [PATCH 2/9] changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index cdfa0c44eb38..7ddc8d4271c0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## Current develop ### Added (new features/APIs/variables/...) +- [[PR 998]](https://github.com/parthenon-hpc-lab/parthenon/pull/998) tensor indices added to sparse pack - [[PR 969]](https://github.com/parthenon-hpc-lab/parthenon/pull/969) New macro-based auto-naming of profiling regions and kernels - [[PR 981]](https://github.com/parthenon-hpc-lab/parthenon/pull/981) Add IndexSplit - [[PR 983]](https://github.com/parthenon-hpc-lab/parthenon/pull/983) Add Contains to SparsePack From 277df3c3461045c144430640a701f834ba5299d7 Mon Sep 17 00:00:00 2001 From: mari2895 Date: Tue, 23 Jan 2024 18:47:17 -0500 Subject: [PATCH 3/9] updated copyright --- src/interface/sparse_pack.hpp | 2 +- tst/unit/test_sparse_pack.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/interface/sparse_pack.hpp b/src/interface/sparse_pack.hpp index f4bc6b333abf..b25ea584ccb4 100644 --- a/src/interface/sparse_pack.hpp +++ b/src/interface/sparse_pack.hpp @@ -1,5 +1,5 @@ //======================================================================================== -// (C) (or copyright) 2020-2023. Triad National Security, LLC. All rights reserved. +// (C) (or copyright) 2020-2024. Triad National Security, LLC. All rights reserved. // // This program was produced under U.S. Government contract 89233218CNA000001 for Los // Alamos National Laboratory (LANL), which is operated by Triad National Security, LLC diff --git a/tst/unit/test_sparse_pack.cpp b/tst/unit/test_sparse_pack.cpp index 6f25ed1d8256..7dec128ccb76 100644 --- a/tst/unit/test_sparse_pack.cpp +++ b/tst/unit/test_sparse_pack.cpp @@ -1,5 +1,5 @@ //======================================================================================== -// (C) (or copyright) 2020-2023. Triad National Security, LLC. All rights reserved. +// (C) (or copyright) 2020-2024. Triad National Security, LLC. All rights reserved. // // This program was produced under U.S. Government contract 89233218CNA000001 for Los // Alamos National Laboratory (LANL), which is operated by Triad National Security, LLC From faf912ae17aa0043f2018e86ffe33a8af293451c Mon Sep 17 00:00:00 2001 From: Mariam Gogilashvili <83436586+mari2895@users.noreply.github.com> Date: Tue, 23 Jan 2024 19:21:00 -0700 Subject: [PATCH 4/9] Update src/interface/sparse_pack.hpp Co-authored-by: Luke Roberts --- src/interface/sparse_pack.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/interface/sparse_pack.hpp b/src/interface/sparse_pack.hpp index b25ea584ccb4..492a4a870363 100644 --- a/src/interface/sparse_pack.hpp +++ b/src/interface/sparse_pack.hpp @@ -99,7 +99,7 @@ struct base_t { KOKKOS_INLINE_FUNCTION explicit base_t(int idx1) : idx(idx1) {} - template ::value)> + template ::value), REQUIRES(sizeof...(Args) == sizeof...(NCOMP)> /* for 2D:, (M, N), idx(m, n) = N*m + n From 0ba0d6b03668f49b9da8b09fff43b8281b759468 Mon Sep 17 00:00:00 2001 From: mari2895 Date: Thu, 25 Jan 2024 17:40:21 -0500 Subject: [PATCH 5/9] takes into account Luke's suggestions --- src/interface/sparse_pack.hpp | 32 +++++++++++++++++++------------- tst/unit/test_sparse_pack.cpp | 10 ++++++---- 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/src/interface/sparse_pack.hpp b/src/interface/sparse_pack.hpp index b25ea584ccb4..971824d15f76 100644 --- a/src/interface/sparse_pack.hpp +++ b/src/interface/sparse_pack.hpp @@ -99,7 +99,6 @@ struct base_t { KOKKOS_INLINE_FUNCTION explicit base_t(int idx1) : idx(idx1) {} - template ::value)> /* for 2D:, (M, N), idx(m, n) = N*m + n @@ -107,9 +106,11 @@ struct base_t { idx(l, m, n) = (M*l + m)*N + n = l*M*N + m*N + n */ - KOKKOS_INLINE_FUNCTION explicit base_t(Args... args) - : idx(GetIndex_(std::forward(args)...)) {} + template ::value), + REQUIRES(sizeof...(Args) == sizeof...(NCOMP))> + KOKKOS_INLINE_FUNCTION explicit base_t(Args... args) + : idx(GetIndex_(std::forward(args)...)) {} virtual ~base_t() = default; // All of these are just static methods so that there is no @@ -118,6 +119,11 @@ struct base_t { PARTHENON_FAIL("Need to implement your own name method."); return "error"; } + template + static constexpr auto GetDim() { + return std::get(std::make_tuple(NCOMP...)); + } + static std::vector GetShape() { return std::vector{NCOMP...}; } KOKKOS_INLINE_FUNCTION static bool regex() { return REGEX; } KOKKOS_INLINE_FUNCTION @@ -128,16 +134,16 @@ struct base_t { const int idx; private: - template ::value)> - KOKKOS_INLINE_FUNCTION static auto GetIndex_(int first, TailArgs... rest) { - if constexpr (sizeof...(Tail) == 0) - return first; - else if constexpr (sizeof...(TailArgs) == 0) - return first; - else - return (multiply::value * first + - GetIndex_(std::forward(rest)...)); + template + KOKKOS_INLINE_FUNCTION static auto GetIndex_(Args... args) { + int idx = 0; + ( + [&] { + idx *= NCOMP; + idx += args; + }(), + ...); + return idx; } }; diff --git a/tst/unit/test_sparse_pack.cpp b/tst/unit/test_sparse_pack.cpp index 7dec128ccb76..192f4473e660 100644 --- a/tst/unit/test_sparse_pack.cpp +++ b/tst/unit/test_sparse_pack.cpp @@ -77,10 +77,11 @@ struct v5 : public parthenon::variable_names::base_t { static std::string name() { return "v5"; } }; -struct v7 : public parthenon::variable_names::base_t { +using parthenon::variable_names::ANYDIM; +struct v7 : public parthenon::variable_names::base_t { template KOKKOS_INLINE_FUNCTION v7(Ts &&...args) - : parthenon::variable_names::base_t(std::forward(args)...) {} + : parthenon::variable_names::base_t(std::forward(args)...) {} static std::string name() { return "v7"; } }; @@ -131,8 +132,9 @@ TEST_CASE("Test behavior of sparse packs", "[SparsePack]") { loop_pattern_mdrange_tag, "check vector", DevExecSpace(), 0, sparse_pack.GetNBlocks() - 1, kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, KOKKOS_LAMBDA(int b, int k, int j, int i, int <ot) { - for (int l = 0; l < 3; ++l) { - for (int m = 0; m < 3; ++m) { + // 0-th is ANYDIM, 1st is 3. + for (int l = 0; l < v7::GetDim<1>(); ++l) { + for (int m = 0; m < v7::GetDim<1>(); ++m) { Real n = m + 1e1 * l; if (sparse_pack(b, v7(l, m), k, j, i) != n) { ltot += 1; From 5f388d8de1f6a9ea5c6dbfc07fe8b71a9aff3c83 Mon Sep 17 00:00:00 2001 From: mari2895 Date: Mon, 29 Jan 2024 18:02:56 -0500 Subject: [PATCH 6/9] takes into account latest suggestion --- src/interface/sparse_pack.hpp | 13 ++++++++++--- tst/unit/test_sparse_pack.cpp | 4 ++-- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/interface/sparse_pack.hpp b/src/interface/sparse_pack.hpp index 07c23d10c45f..d7e8e31ade1a 100644 --- a/src/interface/sparse_pack.hpp +++ b/src/interface/sparse_pack.hpp @@ -90,7 +90,7 @@ KOKKOS_INLINE_FUNCTION PackIdx operator+(T offset, PackIdx idx) { // device namespace variable_names { // Struct that all variable_name types should inherit from -constexpr int ANYDIM = -1234; +constexpr int ANYDIM = -1234; // ANYDIM must be a slowest-moving index template struct base_t { KOKKOS_INLINE_FUNCTION @@ -109,8 +109,11 @@ struct base_t { template ::value), REQUIRES(sizeof...(Args) == sizeof...(NCOMP))> KOKKOS_INLINE_FUNCTION explicit base_t(Args... args) - : idx(GetIndex_(std::forward(args)...)) {} - + : idx(GetIndex_(std::forward(args)...)) { + static_assert(CheckArgs_(NCOMP...), + "All dimensions must be strictly positive, " + "except the first (slowest), which may be ANYDIM."); + } virtual ~base_t() = default; // All of these are just static methods so that there is no @@ -134,6 +137,10 @@ struct base_t { const int idx; private: + template ::value)> + static constexpr bool CheckArgs_(int head, Tail... tail) { + return (... && (tail > 0)); + } template KOKKOS_INLINE_FUNCTION static auto GetIndex_(Args... args) { int idx = 0; diff --git a/tst/unit/test_sparse_pack.cpp b/tst/unit/test_sparse_pack.cpp index 192f4473e660..cda8edb1cb51 100644 --- a/tst/unit/test_sparse_pack.cpp +++ b/tst/unit/test_sparse_pack.cpp @@ -133,8 +133,8 @@ TEST_CASE("Test behavior of sparse packs", "[SparsePack]") { sparse_pack.GetNBlocks() - 1, kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, KOKKOS_LAMBDA(int b, int k, int j, int i, int <ot) { // 0-th is ANYDIM, 1st is 3. - for (int l = 0; l < v7::GetDim<1>(); ++l) { - for (int m = 0; m < v7::GetDim<1>(); ++m) { + for (int l = 0; l < tensor_shape[4]; ++l) { + for (int m = 0; m < tensor_shape[3]; ++m) { Real n = m + 1e1 * l; if (sparse_pack(b, v7(l, m), k, j, i) != n) { ltot += 1; From 195db4d40f2dadd8750500f3804526c9ec08b878 Mon Sep 17 00:00:00 2001 From: mari2895 Date: Mon, 29 Jan 2024 23:12:59 -0500 Subject: [PATCH 7/9] typo in indices --- tst/unit/test_sparse_pack.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tst/unit/test_sparse_pack.cpp b/tst/unit/test_sparse_pack.cpp index cda8edb1cb51..4efea18a5054 100644 --- a/tst/unit/test_sparse_pack.cpp +++ b/tst/unit/test_sparse_pack.cpp @@ -128,13 +128,15 @@ TEST_CASE("Test behavior of sparse packs", "[SparsePack]") { auto desc = parthenon::MakePackDescriptor(pkg.get()); auto sparse_pack = desc.GetPack(&mesh_data); int nwrong = 0; + int nl = tensor_shape[4]; + int nm = tensor_shape[3]; par_reduce( loop_pattern_mdrange_tag, "check vector", DevExecSpace(), 0, sparse_pack.GetNBlocks() - 1, kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, KOKKOS_LAMBDA(int b, int k, int j, int i, int <ot) { // 0-th is ANYDIM, 1st is 3. - for (int l = 0; l < tensor_shape[4]; ++l) { - for (int m = 0; m < tensor_shape[3]; ++m) { + for (int l = 0; l < nl; ++l) { + for (int m = 0; m < nm; ++m) { Real n = m + 1e1 * l; if (sparse_pack(b, v7(l, m), k, j, i) != n) { ltot += 1; From bed63ee8d61f0462353e24bfe5f194c44e2436a9 Mon Sep 17 00:00:00 2001 From: mari2895 Date: Thu, 1 Feb 2024 14:43:58 -0500 Subject: [PATCH 8/9] inverse ordering of indices in GetDim --- src/interface/sparse_pack.hpp | 2 +- tst/unit/test_sparse_pack.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/interface/sparse_pack.hpp b/src/interface/sparse_pack.hpp index d7e8e31ade1a..9753c401561b 100644 --- a/src/interface/sparse_pack.hpp +++ b/src/interface/sparse_pack.hpp @@ -124,7 +124,7 @@ struct base_t { } template static constexpr auto GetDim() { - return std::get(std::make_tuple(NCOMP...)); + return std::get(std::make_tuple(NCOMP...)); } static std::vector GetShape() { return std::vector{NCOMP...}; } KOKKOS_INLINE_FUNCTION diff --git a/tst/unit/test_sparse_pack.cpp b/tst/unit/test_sparse_pack.cpp index 4efea18a5054..61ea5224afdb 100644 --- a/tst/unit/test_sparse_pack.cpp +++ b/tst/unit/test_sparse_pack.cpp @@ -111,8 +111,8 @@ TEST_CASE("Test behavior of sparse packs", "[SparsePack]") { auto &pmbd = pmb->meshblock_data.Get(); auto var = pmbd->Get("v7"); auto var5 = var.data.Get<5>(); - int slower_rank = var5.GetDim(5); - int faster_rank = var5.GetDim(4); + int slower_rank = var5.GetDim(0); + int faster_rank = var5.GetDim(1); par_for( loop_pattern_mdrange_tag, "initializev7", DevExecSpace(), kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, KOKKOS_LAMBDA(int k, int j, int i) { From 634eb043dffc082cde2b89b438e68195ec65505b Mon Sep 17 00:00:00 2001 From: mari2895 Date: Thu, 1 Feb 2024 18:20:02 -0500 Subject: [PATCH 9/9] reversing changes in test_sparse_pack --- tst/unit/test_sparse_pack.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tst/unit/test_sparse_pack.cpp b/tst/unit/test_sparse_pack.cpp index 61ea5224afdb..4efea18a5054 100644 --- a/tst/unit/test_sparse_pack.cpp +++ b/tst/unit/test_sparse_pack.cpp @@ -111,8 +111,8 @@ TEST_CASE("Test behavior of sparse packs", "[SparsePack]") { auto &pmbd = pmb->meshblock_data.Get(); auto var = pmbd->Get("v7"); auto var5 = var.data.Get<5>(); - int slower_rank = var5.GetDim(0); - int faster_rank = var5.GetDim(1); + int slower_rank = var5.GetDim(5); + int faster_rank = var5.GetDim(4); par_for( loop_pattern_mdrange_tag, "initializev7", DevExecSpace(), kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, KOKKOS_LAMBDA(int k, int j, int i) {