SimiLie
Loading...
Searching...
No Matches
csr_dynamic.hpp
1// SPDX-FileCopyrightText: 2024 Baptiste Legouix
2// SPDX-License-Identifier: MIT
3
4#pragma once
5
6#include <fstream>
7#include <type_traits>
8
9#include <ddc/ddc.hpp>
10
11#include <similie/misc/macros.hpp>
12#include <similie/tensor/tensor_impl.hpp>
13
14namespace sil {
15
16namespace csr {
17
18// Only natural indexing supported
19template <tensor::TensorIndex HeadTensorIndex, tensor::TensorNatIndex... TailTensorIndex>
21{
22private:
23 ddc::DiscreteDomain<HeadTensorIndex, TailTensorIndex...> m_domain;
24 std::vector<std::size_t> m_coalesc_idx;
25 std::array<std::vector<std::size_t>, sizeof...(TailTensorIndex)> m_idx;
26 std::vector<double> m_values;
27
28public:
29 CsrDynamic(ddc::DiscreteDomain<HeadTensorIndex, TailTensorIndex...> domain)
30 : m_domain(domain)
31 , m_coalesc_idx({0})
32 , m_idx()
33 , m_values()
34 {
35 }
36
38 ddc::DiscreteDomain<HeadTensorIndex, TailTensorIndex...> domain,
39 std::vector<std::size_t> coalesc_idx,
40 std::array<std::vector<std::size_t>, sizeof...(TailTensorIndex)> idx,
41 std::vector<double> values)
42 : m_domain(domain)
43 , m_coalesc_idx(coalesc_idx)
44 , m_idx(idx)
45 , m_values(values)
46 {
47 }
48
49 ddc::DiscreteDomain<HeadTensorIndex, TailTensorIndex...> domain()
50 {
51 return m_domain;
52 }
53
54 std::vector<std::size_t> coalesc_idx() const // Can be constexpr with C++23
55 {
56 return m_coalesc_idx;
57 }
58
59 std::array<std::vector<std::size_t>, sizeof...(TailTensorIndex)> idx()
60 const // Can be constexpr with C++23
61 {
62 return m_idx;
63 }
64
65 std::vector<double> values() const // Can be constexpr with C++23
66 {
67 return m_values;
68 }
69
72 double,
73 ddc::DiscreteDomain<TailTensorIndex...>,
74 Kokkos::layout_right,
75 Kokkos::DefaultHostExecutionSpace::memory_space> dense)
76 {
77 m_coalesc_idx.push_back(m_coalesc_idx.back());
78 ddc::host_for_each(dense.domain(), [&](ddc::DiscreteElement<TailTensorIndex...> elem) {
79 if (dense(elem) != 0) {
80 m_coalesc_idx.back() += 1;
81 (m_idx[ddc::type_seq_rank_v<
82 TailTensorIndex,
83 ddc::detail::TypeSeq<TailTensorIndex...>>]
84 .push_back(elem.template uid<TailTensorIndex>()),
85 ...);
86 m_values.push_back(dense(elem));
87 }
88 });
89 }
90
91 // Returns a slice orthogonal to first index
92 CsrDynamic<HeadTensorIndex, TailTensorIndex...> get(
93 ddc::DiscreteElement<HeadTensorIndex> id) const
94 {
95 const std::size_t id_begin = m_coalesc_idx[id.uid()];
96 const std::size_t id_end = m_coalesc_idx[id.uid() + 1];
97 std::vector<std::size_t> new_coalesc_idx {0, id_end - id_begin};
98 std::array<std::vector<std::size_t>, sizeof...(TailTensorIndex)> new_idx;
99 ((new_idx[ddc::type_seq_rank_v<TailTensorIndex, ddc::detail::TypeSeq<TailTensorIndex...>>]
100 = std::vector<std::size_t>(
101 m_idx[ddc::type_seq_rank_v<
102 TailTensorIndex,
103 ddc::detail::TypeSeq<TailTensorIndex...>>]
104 .begin()
105 + id_begin,
106 m_idx[ddc::type_seq_rank_v<
107 TailTensorIndex,
108 ddc::detail::TypeSeq<TailTensorIndex...>>]
109 .begin()
110 + id_begin + id_end)),
111 ...);
112 std::vector<double>
113 new_values(m_values.begin() + id_begin, m_values.begin() + id_begin + id_end);
114
115 return CsrDynamic<HeadTensorIndex, TailTensorIndex...>(
116 ddc::DiscreteDomain<HeadTensorIndex, TailTensorIndex...>(m_domain),
117 new_coalesc_idx,
118 new_idx,
119 new_values);
120 }
121
122 void write(std::ofstream& file)
123 {
124 auto const write_block = [&file](auto const& values) {
125 std::size_t const byte_size
126 = values.size() * sizeof(typename std::decay_t<decltype(values)>::value_type);
127 file.write(reinterpret_cast<const char*>(&byte_size), sizeof(byte_size));
128 file.write(reinterpret_cast<const char*>(values.data()), byte_size);
129 };
130
131 write_block(coalesc_idx());
132 for (std::size_t i = 0; i < sizeof...(TailTensorIndex); ++i) {
133 write_block(idx()[i]);
134 }
135 write_block(values());
136 }
137};
138
139// Convert Csr to dense tensor
140template <tensor::TensorIndex HeadId, tensor::TensorNatIndex... TailId>
142 double,
143 ddc::DiscreteDomain<HeadId, TailId...>,
144 Kokkos::layout_right,
145 Kokkos::DefaultHostExecutionSpace::memory_space>
148 double,
149 ddc::DiscreteDomain<HeadId, TailId...>,
150 Kokkos::layout_right,
151 Kokkos::DefaultHostExecutionSpace::memory_space> dense,
153{
154 SIMILIE_DEBUG_LOG("similie_perform_csr2dense");
155 ddc::parallel_fill(dense, 0.);
156 for (std::size_t i = 0; i < csr.coalesc_idx().size() - 1; ++i) {
157 std::size_t const j_begin = csr.coalesc_idx()[i];
158 std::size_t const j_end = csr.coalesc_idx()[i + 1];
159 Kokkos::parallel_for(
160 "similie_perform_csr2dense",
161 Kokkos::RangePolicy<Kokkos::DefaultHostExecutionSpace>(j_begin, j_end),
162 [&](const int j) {
163 dense(ddc::DiscreteElement<HeadId>(i),
164 ddc::DiscreteElement<TailId...>(csr.idx()[ddc::type_seq_rank_v<
165 TailId,
166 ddc::detail::TypeSeq<TailId...>>][j]...))
167 = csr.values()[j];
168 });
169 }
170 return dense;
171}
172
173template <class... TensorIndex>
174std::ostream& operator<<(std::ostream& os, CsrDynamic<TensorIndex...> const& csr)
175{
176 os << "----------\n";
177 for (std::size_t i = 0; i < csr.coalesc_idx().size(); ++i) {
178 os << csr.coalesc_idx()[i] << " ";
179 }
180 os << "\n";
181 for (std::size_t i = 0; i < csr.idx()[0].size(); ++i) {
182 for (std::size_t j = 0; j < sizeof...(TensorIndex) - 1; ++j) {
183 os << csr.idx()[j][i] << " ";
184 }
185 os << csr.values()[i];
186 os << "\n";
187 }
188 return os;
189}
190
191} // namespace csr
192
193} // namespace sil
CsrDynamic(ddc::DiscreteDomain< HeadTensorIndex, TailTensorIndex... > domain)
CsrDynamic(ddc::DiscreteDomain< HeadTensorIndex, TailTensorIndex... > domain, std::vector< std::size_t > coalesc_idx, std::array< std::vector< std::size_t >, sizeof...(TailTensorIndex)> idx, std::vector< double > values)
std::array< std::vector< std::size_t >, sizeof...(TailTensorIndex)> idx() const
void write(std::ofstream &file)
std::vector< double > values() const
CsrDynamic< HeadTensorIndex, TailTensorIndex... > get(ddc::DiscreteElement< HeadTensorIndex > id) const
ddc::DiscreteDomain< HeadTensorIndex, TailTensorIndex... > domain()
void push_back(sil::tensor::Tensor< double, ddc::DiscreteDomain< TailTensorIndex... >, Kokkos::layout_right, Kokkos::DefaultHostExecutionSpace::memory_space > dense)
std::vector< std::size_t > coalesc_idx() const
sil::tensor::Tensor< double, ddc::DiscreteDomain< HeadId, TailId... >, Kokkos::layout_right, Kokkos::DefaultHostExecutionSpace::memory_space > csr2dense(sil::tensor::Tensor< double, ddc::DiscreteDomain< HeadId, TailId... >, Kokkos::layout_right, Kokkos::DefaultHostExecutionSpace::memory_space > dense, CsrDynamic< HeadId, TailId... > csr)
std::ostream & operator<<(std::ostream &os, Csr< N, TensorIndex... > const &csr)
Definition csr.hpp:191
Tensor(ddc::Chunk< ElementType, SupportType, Allocator >) -> Tensor< ElementType, SupportType, Kokkos::layout_right, typename Allocator::memory_space >
The top-level namespace of SimiLie.
Definition csr.hpp:15