From 64800aa2dcdaf8684dbb23cdaddf09b6f1e0b5bd Mon Sep 17 00:00:00 2001 From: Tobias Ribizel Date: Fri, 10 Jan 2025 16:39:28 +0100 Subject: [PATCH] add reference euler path computation kernel --- .../elimination_forest_kernels.cpp | 31 +++++++++---- .../test/factorization/cholesky_kernels.cpp | 43 +++++++++++++++---- 2 files changed, 57 insertions(+), 17 deletions(-) diff --git a/reference/factorization/elimination_forest_kernels.cpp b/reference/factorization/elimination_forest_kernels.cpp index faf7649bcea..dd4b78f7bc1 100644 --- a/reference/factorization/elimination_forest_kernels.cpp +++ b/reference/factorization/elimination_forest_kernels.cpp @@ -244,7 +244,7 @@ void compute_postorder( GKO_INSTANTIATE_FOR_EACH_INDEX_TYPE( GKO_DECLARE_ELIMINATION_FOREST_COMPUTE_POSTORDER); -/* + template IndexType traverse_euler_path(const IndexType* child_ptrs, const IndexType* children, IndexType node, @@ -254,14 +254,26 @@ IndexType traverse_euler_path(const IndexType* child_ptrs, { const auto child_begin = child_ptrs[node]; const auto child_end = child_ptrs[node + 1]; + if (child_begin == child_end) { + euler_path[index] = node; + euler_first[node] = index; + euler_level[index] = level; + return index + 1; + } + euler_path[index] = node; + euler_first[node] = index; + euler_level[index] = level; + index++; for (const auto child_idx : irange{child_begin, child_end}) { const auto child = children[child_idx]; - index = traverse_postorder(child_ptrs, children, child, index, - postorder, inv_postorder); + index = + traverse_euler_path(child_ptrs, children, child, index, level + 1, + euler_path, euler_first, euler_level); + euler_path[index] = node; + euler_level[index] = level; + index++; } - postorder[index] = node; - inv_postorder[node] = index; - return index + 1; + return index; } @@ -280,13 +292,14 @@ void compute_euler_path( IndexType index{}; for (const auto root_idx : irange{root_begin, root_end}) { const auto root = children[root_idx]; - index = traverse_euler_path(child_ptrs, children, root, index, - postorder, inv_postorder); + index = + traverse_euler_path(child_ptrs, children, root, index, IndexType{0}, + euler_path, first_visit, euler_levels); } } GKO_INSTANTIATE_FOR_EACH_INDEX_TYPE( - GKO_DECLARE_ELIMINATION_FOREST_COMPUTE_EULER_PATH);*/ + GKO_DECLARE_ELIMINATION_FOREST_COMPUTE_EULER_PATH); } // namespace elimination_forest diff --git a/reference/test/factorization/cholesky_kernels.cpp b/reference/test/factorization/cholesky_kernels.cpp index 35f127f5a3e..c30e37cb857 100644 --- a/reference/test/factorization/cholesky_kernels.cpp +++ b/reference/test/factorization/cholesky_kernels.cpp @@ -24,6 +24,7 @@ #include "core/matrix/csr_lookup.hpp" #include "core/test/utils.hpp" #include "core/test/utils/assertions.hpp" +#include "ginkgo/core/base/types.hpp" #include "matrices/config.hpp" @@ -434,16 +435,19 @@ TYPED_TEST(Cholesky, KernelComputeLevels) template void reference_euler_path(const IndexType* child_ptrs, const IndexType* children, IndexType node, - IndexType level, - std::vector>& path) + IndexType level, std::vector& path, + std::vector& levels) { - path.emplace_back(node, level); + path.emplace_back(node); + levels.emplace_back(level); const auto child_begin = child_ptrs[node]; const auto child_end = child_ptrs[node + 1]; for (const auto child_idx : gko::irange{child_begin, child_end}) { const auto child = children[child_idx]; - reference_euler_path(child_ptrs, children, child, level + 1, path); - path.emplace_back(node, level); + reference_euler_path(child_ptrs, children, child, level + 1, path, + levels); + path.emplace_back(node); + levels.emplace_back(level); } } @@ -460,20 +464,43 @@ TYPED_TEST(Cholesky, KernelComputeEulerPath) gko::factorization::compute_elimination_forest(this->mtx.get(), forest); gko::array levels{this->ref, size}; - gko::array euler_path{this->ref, size}; - gko::array euler_first{this->ref, size}; - gko::array euler_levels{this->ref, size}; + gko::array euler_path{this->ref, 2 * size}; + gko::array euler_first{this->ref, 2 * size}; + gko::array euler_levels{this->ref, 2 * size}; gko::array subtree_sizes{this->ref, size}; + euler_path.fill(gko::invalid_index()); + euler_levels.fill(gko::invalid_index()); gko::kernels::reference::elimination_forest:: compute_subtree_euler_path_sizes(this->ref, *forest, subtree_sizes.get_data()); gko::kernels::reference::elimination_forest::compute_levels( this->ref, *forest, levels.get_data()); + std::vector ref_path; + std::vector ref_levels; + const auto child_ptrs = forest->child_ptrs.get_const_data(); + const auto children = forest->children.get_const_data(); + for (auto root_idx : + gko::irange{child_ptrs[size], child_ptrs[size + 1]}) { + const auto root = forest->children.get_const_data()[root_idx]; + reference_euler_path(child_ptrs, children, root, index_type{}, + ref_path, ref_levels); + } + ASSERT_LT(ref_path.size(), 2 * size); + ASSERT_LT(ref_levels.size(), 2 * size); + ref_path.resize(2 * size, gko::invalid_index()); + ref_levels.resize(2 * size, gko::invalid_index()); + const gko::array ref_path_array{ + this->ref, ref_path.begin(), ref_path.end()}; + const gko::array ref_levels_array{ + this->ref, ref_levels.begin(), ref_levels.end()}; gko::kernels::reference::elimination_forest::compute_euler_path( this->ref, *forest, subtree_sizes.get_const_data(), levels.get_const_data(), euler_path.get_data(), euler_first.get_data(), euler_levels.get_data()); + + GKO_ASSERT_ARRAY_EQ(ref_path_array, euler_path); + GKO_ASSERT_ARRAY_EQ(ref_levels_array, euler_levels); }, true); }