Skip to content

Commit ed3ee59

Browse files
change leaves computations
1 parent 6b50680 commit ed3ee59

File tree

5 files changed

+106
-75
lines changed

5 files changed

+106
-75
lines changed

include/htool/basic_types/tree.hpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,15 @@ void preorder_tree_traversal(NodeType &node, PreOrderFunction preorder_visitor)
7979
}
8080
}
8181

82+
template <typename NodeType, typename PostOrderFunction>
83+
void postorder_tree_traversal(NodeType &node, PostOrderFunction postorder_visitor) {
84+
const auto &children = node.get_children();
85+
for (auto &child : children) {
86+
postorder_tree_traversal(*child, postorder_visitor);
87+
}
88+
postorder_visitor(node);
89+
}
90+
8291
} // namespace htool
8392

8493
#endif

include/htool/hmatrix/hmatrix.hpp

Lines changed: 62 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -43,45 +43,12 @@ class HMatrix : public TreeNode<HMatrix<CoefficientPrecision, CoordinatePrecisio
4343
std::unique_ptr<Matrix<CoefficientPrecision>> m_dense_data{nullptr};
4444
std::unique_ptr<LowRankMatrix<CoefficientPrecision, CoordinatePrecision>> m_low_rank_data{nullptr};
4545

46-
// Cached leaves
47-
mutable std::vector<const HMatrix *> m_leaves{};
48-
mutable std::vector<const HMatrix *> m_leaves_for_symmetry{};
49-
mutable char m_symmetry_type_for_leaves{'N'};
50-
mutable char m_UPLO_for_leaves{'N'};
46+
//
47+
char m_symmetry_type_for_leaves{'N'};
48+
char m_UPLO_for_leaves{'N'};
5149

5250
StorageType m_storage_type{StorageType::Hierarchical};
5351

54-
void set_leaves_in_cache() const {
55-
if (m_leaves.empty()) {
56-
std::stack<std::pair<const HMatrix<CoefficientPrecision, CoordinatePrecision> *, bool>> hmatrix_stack;
57-
hmatrix_stack.push(std::pair<const HMatrix<CoefficientPrecision, CoordinatePrecision> *, bool>(this, m_symmetry != 'N'));
58-
59-
while (!hmatrix_stack.empty()) {
60-
auto &current_element = hmatrix_stack.top();
61-
hmatrix_stack.pop();
62-
const HMatrix<CoefficientPrecision, CoordinatePrecision> *current_hmatrix = current_element.first;
63-
bool has_symmetric_ancestor = current_element.second;
64-
65-
if (current_hmatrix->is_leaf()) {
66-
m_leaves.push_back(current_hmatrix);
67-
68-
if (has_symmetric_ancestor && current_hmatrix->get_target_cluster().get_offset() != current_hmatrix->get_source_cluster().get_offset()) {
69-
m_leaves_for_symmetry.push_back(current_hmatrix);
70-
}
71-
}
72-
73-
if (m_symmetry_type_for_leaves == 'N' && current_hmatrix->get_symmetry() != 'N') {
74-
m_symmetry_type_for_leaves = current_hmatrix->get_symmetry();
75-
m_UPLO_for_leaves = current_hmatrix->get_UPLO();
76-
}
77-
78-
for (const auto &child : current_hmatrix->get_children()) {
79-
hmatrix_stack.push(std::pair<const HMatrix<CoefficientPrecision, CoordinatePrecision> *, bool>(child.get(), current_hmatrix->get_symmetry() != 'N' || has_symmetric_ancestor));
80-
}
81-
}
82-
}
83-
}
84-
8552
public:
8653
// Root constructor
8754
HMatrix(const Cluster<CoordinatePrecision> &target_cluster, const Cluster<CoordinatePrecision> &source_cluster) : TreeNode<HMatrix, HMatrixTreeData<CoefficientPrecision, CoordinatePrecision>>(), m_target_cluster(&target_cluster), m_source_cluster(&source_cluster) {
@@ -90,7 +57,7 @@ class HMatrix : public TreeNode<HMatrix<CoefficientPrecision, CoordinatePrecisio
9057
// Child constructor
9158
HMatrix(const HMatrix &parent, const Cluster<CoordinatePrecision> *target_cluster, const Cluster<CoordinatePrecision> *source_cluster) : TreeNode<HMatrix, HMatrixTreeData<CoefficientPrecision, CoordinatePrecision>>(parent), m_target_cluster(target_cluster), m_source_cluster(source_cluster) {}
9259

93-
HMatrix(const HMatrix &rhs) : TreeNode<HMatrix<CoefficientPrecision, CoordinatePrecision>, HMatrixTreeData<CoefficientPrecision, CoordinatePrecision>>(rhs), m_target_cluster(rhs.m_target_cluster), m_source_cluster(rhs.m_source_cluster), m_symmetry(rhs.m_symmetry), m_UPLO(rhs.m_UPLO), m_leaves(), m_leaves_for_symmetry(), m_symmetry_type_for_leaves(), m_storage_type(rhs.m_storage_type) {
60+
HMatrix(const HMatrix &rhs) : TreeNode<HMatrix<CoefficientPrecision, CoordinatePrecision>, HMatrixTreeData<CoefficientPrecision, CoordinatePrecision>>(rhs), m_target_cluster(rhs.m_target_cluster), m_source_cluster(rhs.m_source_cluster), m_symmetry(rhs.m_symmetry), m_UPLO(rhs.m_UPLO), m_symmetry_type_for_leaves(), m_storage_type(rhs.m_storage_type) {
9461
if (m_target_cluster->is_root() or is_cluster_on_partition(*m_target_cluster)) {
9562
Logger::get_instance().log(LogLevel::INFO, "Deep copy of HMatrix");
9663
}
@@ -120,20 +87,20 @@ class HMatrix : public TreeNode<HMatrix<CoefficientPrecision, CoordinatePrecisio
12087
for (auto &child : rhs.m_children) {
12188
this->m_children.emplace_back(std::make_unique<HMatrix<CoefficientPrecision, CoordinatePrecision>>(*child));
12289
}
123-
m_target_cluster = rhs.m_target_cluster;
124-
m_source_cluster = rhs.m_source_cluster;
125-
m_symmetry = rhs.m_symmetry;
126-
m_UPLO = rhs.m_UPLO;
127-
m_storage_type = rhs.m_storage_type;
90+
m_target_cluster = rhs.m_target_cluster;
91+
m_source_cluster = rhs.m_source_cluster;
92+
m_symmetry = rhs.m_symmetry;
93+
m_UPLO = rhs.m_UPLO;
94+
m_storage_type = rhs.m_storage_type;
95+
m_symmetry_type_for_leaves = rhs.m_symmetry_type_for_leaves;
96+
m_UPLO_for_leaves = rhs.m_UPLO_for_leaves;
12897

12998
if (rhs.m_dense_data) {
13099
m_dense_data = std::make_unique<Matrix<CoefficientPrecision>>(*rhs.m_dense_data);
131100
}
132101
if (rhs.m_low_rank_data) {
133102
m_low_rank_data = std::make_unique<LowRankMatrix<CoefficientPrecision, CoordinatePrecision>>(*rhs.m_low_rank_data);
134103
}
135-
m_leaves.clear();
136-
m_leaves_for_symmetry.clear();
137104
return *this;
138105
}
139106

@@ -175,14 +142,7 @@ class HMatrix : public TreeNode<HMatrix<CoefficientPrecision, CoordinatePrecisio
175142
int get_rank() const {
176143
return m_storage_type == StorageType::LowRank ? m_low_rank_data->rank_of() : -1;
177144
}
178-
const std::vector<const HMatrix *> &get_leaves() const {
179-
set_leaves_in_cache();
180-
return m_leaves;
181-
}
182-
const std::vector<const HMatrix *> &get_leaves_for_symmetry() const {
183-
set_leaves_in_cache();
184-
return m_leaves_for_symmetry;
185-
}
145+
186146
const Matrix<CoefficientPrecision> *get_dense_data() const { return m_dense_data.get(); }
187147
Matrix<CoefficientPrecision> *get_dense_data() { return m_dense_data.get(); }
188148
const LowRankMatrix<CoefficientPrecision, CoordinatePrecision> *get_low_rank_data() const { return m_low_rank_data.get(); }
@@ -233,6 +193,8 @@ class HMatrix : public TreeNode<HMatrix<CoefficientPrecision, CoordinatePrecisio
233193
// HMatrix node setters
234194
void set_symmetry(char symmetry) { m_symmetry = symmetry; }
235195
void set_UPLO(char UPLO) { m_UPLO = UPLO; }
196+
void set_symmetry_for_leaves(char symmetry) const { m_symmetry_type_for_leaves = symmetry; }
197+
void set_UPLO_for_leaves(char UPLO) const { m_UPLO_for_leaves = UPLO; }
236198
void set_target_cluster(const Cluster<CoordinatePrecision> *new_target_cluster) { m_target_cluster = new_target_cluster; }
237199

238200
// Test properties
@@ -267,23 +229,52 @@ class HMatrix : public TreeNode<HMatrix<CoefficientPrecision, CoordinatePrecisio
267229

268230
void set_dense_data(std::unique_ptr<Matrix<CoefficientPrecision>> dense_matrix_ptr) {
269231
this->delete_children();
270-
m_leaves.clear();
271-
m_leaves_for_symmetry.clear();
272-
m_dense_data = std::move(dense_matrix_ptr);
273-
// m_dense_data = std::make_unique<Matrix<CoefficientPrecision>>();
274-
// m_dense_data->assign(dense_matrix.nb_rows(), dense_matrix.nb_cols(), dense_matrix.release(), true);
232+
m_dense_data = std::move(dense_matrix_ptr);
275233
m_storage_type = StorageType::Dense;
276234
}
277235
};
278236

237+
template <typename CoefficientPrecision, typename CoordinatePrecision = underlying_type<CoefficientPrecision>>
238+
std::pair<std::vector<const HMatrix<CoefficientPrecision, CoordinatePrecision> *>, std::vector<const HMatrix<CoefficientPrecision, CoordinatePrecision> *>> get_leaves_from(const HMatrix<CoefficientPrecision, CoordinatePrecision> &hmatrix) {
239+
std::pair<std::vector<const HMatrix<CoefficientPrecision, CoordinatePrecision> *>, std::vector<const HMatrix<CoefficientPrecision, CoordinatePrecision> *>> result;
240+
auto &leaves = result.first;
241+
auto &leaves_for_symmetry = result.second;
242+
std::stack<std::pair<const HMatrix<CoefficientPrecision, CoordinatePrecision> *, bool>> hmatrix_stack;
243+
hmatrix_stack.push(std::pair<const HMatrix<CoefficientPrecision, CoordinatePrecision> *, bool>(&hmatrix, hmatrix.get_symmetry() != 'N'));
244+
245+
while (!hmatrix_stack.empty()) {
246+
auto &current_element = hmatrix_stack.top();
247+
hmatrix_stack.pop();
248+
const HMatrix<CoefficientPrecision, CoordinatePrecision> *current_hmatrix = current_element.first;
249+
bool has_symmetric_ancestor = current_element.second;
250+
251+
if (current_hmatrix->is_leaf()) {
252+
leaves.push_back(current_hmatrix);
253+
254+
if (has_symmetric_ancestor && current_hmatrix->get_target_cluster().get_offset() != current_hmatrix->get_source_cluster().get_offset()) {
255+
leaves_for_symmetry.push_back(current_hmatrix);
256+
}
257+
}
258+
259+
for (const auto &child : current_hmatrix->get_children()) {
260+
hmatrix_stack.push(std::pair<const HMatrix<CoefficientPrecision, CoordinatePrecision> *, bool>(child.get(), current_hmatrix->get_symmetry() != 'N' || has_symmetric_ancestor));
261+
}
262+
}
263+
return result;
264+
}
265+
279266
template <typename CoefficientPrecision, typename CoordinatePrecision = underlying_type<CoefficientPrecision>>
280267
void copy_to_dense(const HMatrix<CoefficientPrecision, CoordinatePrecision> &hmatrix, CoefficientPrecision *ptr) {
281268

282269
int target_offset = hmatrix.get_target_cluster().get_offset();
283270
int source_offset = hmatrix.get_source_cluster().get_offset();
284271
int target_size = hmatrix.get_target_cluster().get_size();
285272

286-
for (auto leaf : hmatrix.get_leaves()) {
273+
std::vector<const HMatrix<CoefficientPrecision, CoordinatePrecision> *> leaves;
274+
std::vector<const HMatrix<CoefficientPrecision, CoordinatePrecision> *> leaves_for_symmetry;
275+
std::tie(leaves, leaves_for_symmetry) = get_leaves_from(hmatrix); // C++17 structured binding
276+
277+
for (auto leaf : leaves) {
287278
int local_nr = leaf->get_target_cluster().get_size();
288279
int local_nc = leaf->get_source_cluster().get_size();
289280
int row_offset = leaf->get_target_cluster().get_offset() - target_offset;
@@ -332,8 +323,11 @@ void copy_to_dense_in_user_numbering(const HMatrix<CoefficientPrecision, Coordin
332323
int target_size = target_cluster.get_size();
333324
const auto &target_permutation = target_cluster.get_permutation();
334325
const auto &source_permutation = source_cluster.get_permutation();
326+
std::vector<const HMatrix<CoefficientPrecision, CoordinatePrecision> *> leaves;
327+
std::vector<const HMatrix<CoefficientPrecision, CoordinatePrecision> *> leaves_for_symmetry;
328+
std::tie(leaves, leaves_for_symmetry) = get_leaves_from(hmatrix); // C++17 structured binding
335329

336-
for (auto leaf : hmatrix.get_leaves()) {
330+
for (auto leaf : leaves) {
337331
int local_nr = leaf->get_target_cluster().get_size();
338332
int local_nc = leaf->get_source_cluster().get_size();
339333
int row_offset = leaf->get_target_cluster().get_offset();
@@ -357,7 +351,7 @@ void copy_to_dense_in_user_numbering(const HMatrix<CoefficientPrecision, Coordin
357351
}
358352
}
359353
if (hmatrix.get_symmetry_for_leaves() != 'N') {
360-
for (auto leaf : hmatrix.get_leaves_for_symmetry()) {
354+
for (auto leaf : leaves_for_symmetry) {
361355
int local_nr = leaf->get_target_cluster().get_size();
362356
int local_nc = leaf->get_source_cluster().get_size();
363357
int row_offset = leaf->get_target_cluster().get_offset();
@@ -381,8 +375,11 @@ void copy_diagonal(const HMatrix<CoefficientPrecision, CoordinatePrecision> &hma
381375

382376
int target_offset = hmatrix.get_target_cluster().get_offset();
383377
int source_offset = hmatrix.get_source_cluster().get_offset();
378+
std::vector<const HMatrix<CoefficientPrecision, CoordinatePrecision> *> leaves;
379+
std::vector<const HMatrix<CoefficientPrecision, CoordinatePrecision> *> leaves_for_symmetry;
380+
std::tie(leaves, leaves_for_symmetry) = get_leaves_from(hmatrix); // C++17 structured binding
384381

385-
for (auto leaf : hmatrix.get_leaves()) {
382+
for (auto leaf : leaves) {
386383
int local_nr = leaf->get_target_cluster().get_size();
387384
int local_nc = leaf->get_source_cluster().get_size();
388385
int offset_i = leaf->get_target_cluster().get_offset() - target_offset;
@@ -418,8 +415,11 @@ void copy_diagonal_in_user_numbering(const HMatrix<CoefficientPrecision, Coordin
418415
const auto &permutation = hmatrix.get_target_cluster().get_permutation();
419416
int target_offset = hmatrix.get_target_cluster().get_offset();
420417
// int source_offset = hmatrix.get_source_cluster().get_offset();
418+
std::vector<const HMatrix<CoefficientPrecision, CoordinatePrecision> *> leaves;
419+
std::vector<const HMatrix<CoefficientPrecision, CoordinatePrecision> *> leaves_for_symmetry;
420+
std::tie(leaves, leaves_for_symmetry) = get_leaves_from(hmatrix); // C++17 structured binding
421421

422-
for (auto leaf : hmatrix.get_leaves()) {
422+
for (auto leaf : leaves) {
423423
int local_nr = leaf->get_target_cluster().get_size();
424424
int local_nc = leaf->get_source_cluster().get_size();
425425
int offset_i = leaf->get_target_cluster().get_offset();

include/htool/hmatrix/linalg/add_hmatrix_matrix_product_row_major.hpp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,9 @@ void add_hmatrix_matrix_product_row_major(char transa, char transb, std::complex
5656

5757
template <typename CoefficientPrecision, typename CoordinatePrecision = CoefficientPrecision>
5858
void sequential_add_hmatrix_matrix_product_row_major(char transa, char transb, CoefficientPrecision alpha, const HMatrix<CoefficientPrecision, CoordinatePrecision> &A, const CoefficientPrecision *B, CoefficientPrecision beta, CoefficientPrecision *C, int mu) {
59-
auto &leaves = A.get_leaves();
60-
auto &leaves_for_symmetry = A.get_leaves_for_symmetry();
59+
std::vector<const HMatrix<CoefficientPrecision, CoordinatePrecision> *> leaves;
60+
std::vector<const HMatrix<CoefficientPrecision, CoordinatePrecision> *> leaves_for_symmetry;
61+
std::tie(leaves, leaves_for_symmetry) = get_leaves_from(A); // C++17 structured binding
6162

6263
if ((transa == 'T' && A.get_symmetry_for_leaves() == 'H')
6364
|| (transa == 'C' && A.get_symmetry_for_leaves() == 'S')) {
@@ -110,9 +111,9 @@ void sequential_add_hmatrix_matrix_product_row_major(char transa, char transb, C
110111

111112
template <typename CoefficientPrecision, typename CoordinatePrecision = CoefficientPrecision>
112113
void openmp_add_hmatrix_matrix_product_row_major(char transa, char transb, CoefficientPrecision alpha, const HMatrix<CoefficientPrecision, CoordinatePrecision> &A, const CoefficientPrecision *B, CoefficientPrecision beta, CoefficientPrecision *C, int mu) {
113-
// set_leaves_in_cache();
114-
auto &leaves = A.get_leaves();
115-
auto &leaves_for_symmetry = A.get_leaves_for_symmetry();
114+
std::vector<const HMatrix<CoefficientPrecision, CoordinatePrecision> *> leaves;
115+
std::vector<const HMatrix<CoefficientPrecision, CoordinatePrecision> *> leaves_for_symmetry;
116+
std::tie(leaves, leaves_for_symmetry) = get_leaves_from(A); // C++17 structured binding
116117

117118
if ((transa == 'T' && A.get_symmetry_for_leaves() == 'H')
118119
|| (transa == 'C' && A.get_symmetry_for_leaves() == 'S')) {

include/htool/hmatrix/linalg/add_hmatrix_vector_product.hpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@ void sequential_add_hmatrix_vector_product(char trans, CoefficientPrecision alph
6161
int local_input_offset = A.get_source_cluster().get_offset();
6262
int local_output_offset = A.get_target_cluster().get_offset();
6363
char trans_sym = (A.get_symmetry_for_leaves() == 'S') ? 'T' : 'C';
64+
std::vector<const HMatrix<CoefficientPrecision, CoordinatePrecision> *> leaves;
65+
std::vector<const HMatrix<CoefficientPrecision, CoordinatePrecision> *> leaves_for_symmetry;
66+
std::tie(leaves, leaves_for_symmetry) = get_leaves_from(A); // C++17 structured binding
6467

6568
if (trans != 'N') {
6669
out_size = A.get_source_cluster().get_size();
@@ -77,17 +80,15 @@ void sequential_add_hmatrix_vector_product(char trans, CoefficientPrecision alph
7780

7881
// Contribution champ lointain
7982
std::vector<CoefficientPrecision> temp(out_size, 0);
80-
// for (int b = 0; b < A.get_leaves().size(); b++) {
81-
for (auto &leaf : A.get_leaves()) {
83+
for (auto &leaf : leaves) {
8284
int input_offset = (leaf->*get_input_cluster)().get_offset();
8385
int output_offset = (leaf->*get_output_cluster)().get_offset();
8486
add_hmatrix_vector_product(trans, alpha, *leaf, in + input_offset - local_input_offset, CoefficientPrecision(1), out + (output_offset - local_output_offset));
8587
}
8688

8789
// Symmetry part of the diagonal part
8890
if (A.get_symmetry_for_leaves() != 'N') {
89-
// for (int b = 0; b < A.get_leaves_for_symmetry().size(); b++) {
90-
for (auto &leaf_for_symmetry : A.get_leaves_for_symmetry()) {
91+
for (auto &leaf_for_symmetry : leaves_for_symmetry) {
9192
int input_offset = (leaf_for_symmetry->*get_input_cluster)().get_offset();
9293
int output_offset = (leaf_for_symmetry->*get_output_cluster)().get_offset();
9394
add_hmatrix_vector_product(trans_sym, alpha, *leaf_for_symmetry, in + output_offset - local_input_offset, CoefficientPrecision(1), out + (input_offset - local_output_offset));
@@ -97,10 +98,9 @@ void sequential_add_hmatrix_vector_product(char trans, CoefficientPrecision alph
9798

9899
template <typename CoefficientPrecision, typename CoordinatePrecision = CoefficientPrecision>
99100
void openmp_add_hmatrix_vector_product(char trans, CoefficientPrecision alpha, const HMatrix<CoefficientPrecision, CoordinatePrecision> &A, const CoefficientPrecision *in, CoefficientPrecision beta, CoefficientPrecision *out) {
100-
101-
// A.set_leaves_in_cache();
102-
auto &leaves = A.get_leaves();
103-
auto &leaves_for_symmetry = A.get_leaves_for_symmetry();
101+
std::vector<const HMatrix<CoefficientPrecision, CoordinatePrecision> *> leaves;
102+
std::vector<const HMatrix<CoefficientPrecision, CoordinatePrecision> *> leaves_for_symmetry;
103+
std::tie(leaves, leaves_for_symmetry) = get_leaves_from(A); // C++17 structured binding
104104

105105
int out_size(A.get_target_cluster().get_size());
106106
auto get_output_cluster{&HMatrix<CoefficientPrecision, CoordinatePrecision>::get_target_cluster};

0 commit comments

Comments
 (0)