SimiLie
Loading...
Searching...
No Matches
csr.hpp
1// SPDX-FileCopyrightText: 2024 Baptiste Legouix
2// SPDX-License-Identifier: MIT
3
4#pragma once
5
6#include <fstream>
7
8#include <ddc/ddc.hpp>
9
10#include <similie/tensor/tensor_impl.hpp>
11
12#include "csr_dynamic.hpp"
13
14namespace sil {
15
16namespace csr {
17
18namespace detail {
19
20template <class Ids>
21struct ArrayOfVectorsToArrayOfArrays;
22
23template <std::size_t... I>
24struct ArrayOfVectorsToArrayOfArrays<std::index_sequence<I...>>
25{
26 template <std::size_t N>
27 static void run(
28 std::array<std::array<std::size_t, N>, sizeof...(I)>& arr,
29 std::array<std::vector<std::size_t>, sizeof...(I)> const& vec)
30 {
31 (std::copy_n(vec[I].begin(), N, arr[I].begin()), ...);
32 }
33};
34
35} // namespace detail
36
37// Only natural indexing supported
38template <
39 std::size_t N,
40 tensor::TensorIndex HeadTensorIndex,
41 tensor::TensorNatIndex... TailTensorIndex>
42class Csr
43{
44private:
45 ddc::DiscreteDomain<HeadTensorIndex, TailTensorIndex...> m_domain;
46 std::array<std::size_t, HeadTensorIndex::mem_size() + 1> m_coalesc_idx;
47 std::array<std::array<std::size_t, N>, sizeof...(TailTensorIndex)> m_idx;
48 std::array<double, N> m_values;
49
50public:
51 constexpr Csr(
52 ddc::DiscreteDomain<HeadTensorIndex, TailTensorIndex...> domain,
53 std::array<std::size_t, HeadTensorIndex::mem_size() + 1> coalesc_idx,
54 std::array<std::array<std::size_t, N>, sizeof...(TailTensorIndex)> idx,
55 std::array<double, N> values)
56 : m_domain(domain)
57 , m_coalesc_idx(coalesc_idx)
58 , m_idx(idx)
59 , m_values(values)
60 {
61 }
62
64 {
65 std::
66 copy_n(csr_dyn.coalesc_idx().begin(),
67 HeadTensorIndex::mem_size() + 1,
68 m_coalesc_idx.begin());
69 detail::ArrayOfVectorsToArrayOfArrays<
70 std::make_index_sequence<sizeof...(TailTensorIndex)>>::run(m_idx, csr_dyn.idx());
71 std::copy_n(csr_dyn.values().begin(), N, m_values.begin());
72 }
73
74 ddc::DiscreteDomain<HeadTensorIndex, TailTensorIndex...> domain()
75 {
76 return m_domain;
77 }
78
79 constexpr std::array<std::size_t, HeadTensorIndex::mem_size() + 1> coalesc_idx() const
80 {
81 return m_coalesc_idx;
82 }
83
84 constexpr std::array<std::array<std::size_t, N>, sizeof...(TailTensorIndex)> idx() const
85 {
86 return m_idx;
87 }
88
89 constexpr std::array<double, N> values() const
90 {
91 return m_values;
92 }
93};
94
95/*
96 Vector-Csr multiplication
97 */
98template <
99 std::size_t N,
100 tensor::TensorIndex HeadTensorIndex,
101 tensor::TensorNatIndex... TailTensorIndex>
103 double,
104 ddc::DiscreteDomain<TailTensorIndex...>,
105 Kokkos::layout_right,
106 Kokkos::DefaultHostExecutionSpace::memory_space>
109 double,
110 ddc::DiscreteDomain<TailTensorIndex...>,
111 Kokkos::layout_right,
112 Kokkos::DefaultHostExecutionSpace::memory_space> prod,
114 double,
115 ddc::DiscreteDomain<HeadTensorIndex>,
116 Kokkos::layout_right,
117 Kokkos::DefaultHostExecutionSpace::memory_space> dense,
119{
120 ddc::parallel_fill(prod, 0.);
121 for (std::size_t i = 0; i < csr.coalesc_idx().size() - 1;
122 ++i) { // TODO base on iterator ? Kokkosify ?
123 double const dense_value = dense.mem(ddc::DiscreteElement<HeadTensorIndex>(i));
124 std::size_t const j_begin = csr.coalesc_idx()[i];
125 std::size_t const j_end = csr.coalesc_idx()[i + 1];
126 Kokkos::parallel_for(
127 "vector_dense_multiplication",
128 Kokkos::RangePolicy<Kokkos::DefaultHostExecutionSpace>(j_begin, j_end),
129 [&](const int j) {
130 prod(ddc::DiscreteElement<TailTensorIndex...>(csr.idx()[ddc::type_seq_rank_v<
131 TailTensorIndex,
132 ddc::detail::TypeSeq<TailTensorIndex...>>][j]...))
133 += dense_value * csr.values()[j];
134 });
135 }
136 return prod;
137}
138
139/*
140 Csr-dense multiplication
141 */
142template <
143 std::size_t N,
144 tensor::TensorIndex HeadTensorIndex,
145 tensor::TensorNatIndex... TailTensorIndex>
147 double,
148 ddc::DiscreteDomain<HeadTensorIndex>,
149 Kokkos::layout_right,
150 Kokkos::DefaultHostExecutionSpace::memory_space>
153 double,
154 ddc::DiscreteDomain<HeadTensorIndex>,
155 Kokkos::layout_right,
156 Kokkos::DefaultHostExecutionSpace::memory_space> prod,
159 double,
160 ddc::DiscreteDomain<TailTensorIndex...>,
161 Kokkos::layout_right,
162 Kokkos::DefaultHostExecutionSpace::memory_space> dense)
163{
164 ddc::parallel_fill(prod, 0.);
165 for (std::size_t i = 0; i < csr.coalesc_idx().size() - 1;
166 ++i) { // TODO base on iterator ? Kokkosify ?
167 std::size_t const j_begin = csr.coalesc_idx()[i];
168 std::size_t const j_end = csr.coalesc_idx()[i + 1];
169 Kokkos::parallel_reduce(
170 "csr_dense_multiplication",
171 Kokkos::RangePolicy<Kokkos::DefaultHostExecutionSpace>(j_begin, j_end),
172 [&](const int j, double& lsum) {
173 double const dense_value = dense(
174 ddc::DiscreteElement<TailTensorIndex...>(csr.idx()[ddc::type_seq_rank_v<
175 TailTensorIndex,
176 ddc::detail::TypeSeq<TailTensorIndex...>>][j]...));
177 lsum += dense_value * csr.values()[j];
178 },
179 prod.mem(ddc::DiscreteElement<HeadTensorIndex>(i)));
180 }
181 return prod;
182}
183
184template <std::size_t N, class... TensorIndex>
185std::ostream& operator<<(std::ostream& os, Csr<N, TensorIndex...> const& csr)
186{
187 os << "----------\n";
188 for (std::size_t i = 0; i < csr.coalesc_idx().size(); ++i) {
189 os << csr.coalesc_idx()[i] << " ";
190 }
191 os << "\n";
192 for (std::size_t i = 0; i < N; ++i) {
193 for (std::size_t j = 0; j < sizeof...(TensorIndex) - 1; ++j) {
194 os << csr.idx()[j][i] << " ";
195 }
196 os << csr.values()[i];
197 os << "\n";
198 }
199 return os;
200}
201
202} // namespace csr
203
204} // namespace sil
std::array< std::vector< std::size_t >, sizeof...(TailTensorIndex)> idx() const
std::vector< double > values() const
std::vector< std::size_t > coalesc_idx() const
constexpr std::array< std::array< std::size_t, N >, sizeof...(TailTensorIndex)> idx() const
Definition csr.hpp:84
constexpr std::array< double, N > values() const
Definition csr.hpp:89
constexpr std::array< std::size_t, HeadTensorIndex::mem_size()+1 > coalesc_idx() const
Definition csr.hpp:79
Csr(CsrDynamic< HeadTensorIndex, TailTensorIndex... > csr_dyn)
Definition csr.hpp:63
ddc::DiscreteDomain< HeadTensorIndex, TailTensorIndex... > domain()
Definition csr.hpp:74
constexpr Csr(ddc::DiscreteDomain< HeadTensorIndex, TailTensorIndex... > domain, std::array< std::size_t, HeadTensorIndex::mem_size()+1 > coalesc_idx, std::array< std::array< std::size_t, N >, sizeof...(TailTensorIndex)> idx, std::array< double, N > values)
Definition csr.hpp:51
sil::tensor::Tensor< double, ddc::DiscreteDomain< TailTensorIndex... >, Kokkos::layout_right, Kokkos::DefaultHostExecutionSpace::memory_space > tensor_prod(sil::tensor::Tensor< double, ddc::DiscreteDomain< TailTensorIndex... >, Kokkos::layout_right, Kokkos::DefaultHostExecutionSpace::memory_space > prod, sil::tensor::Tensor< double, ddc::DiscreteDomain< HeadTensorIndex >, Kokkos::layout_right, Kokkos::DefaultHostExecutionSpace::memory_space > dense, Csr< N, HeadTensorIndex, TailTensorIndex... > csr)
Definition csr.hpp:107
std::ostream & operator<<(std::ostream &os, Csr< N, TensorIndex... > const &csr)
Definition csr.hpp:185
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:14