Project
Loading...
Searching...
No Matches
EncoderSymbolMapper.h
Go to the documentation of this file.
1// Copyright 2019-2023 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
15
16#ifndef RANS_INTERNAL_ENCODE_ENCODERSYMBOLMAPPER_H_
17#define RANS_INTERNAL_ENCODE_ENCODERSYMBOLMAPPER_H_
18
19#include <array>
20
21#include <fairlogger/Logger.h>
22
24
26
27#ifdef RANS_SIMD
30#endif /* RANS_SIMD */
33
34namespace o2::rans::internal
35{
36
37template <typename symbolTable_T, typename coder_T, typename incompressible_IT, typename derived_T>
39{
40 public:
41 using symbolTable_type = symbolTable_T;
42 using coder_type = coder_T;
43 using size_type = std::size_t;
44 using difference_type = std::ptrdiff_t;
45 using source_type = typename symbolTable_type::source_type;
46 using symbol_type = typename symbolTable_type::symbol_type;
47 using coderSymbol_type = typename coder_type::symbol_type;
49
50 template <typename source_IT>
51 [[nodiscard]] source_IT unpackSymbols(source_IT sourceIter, coderSymbol_type& symbol, size_type nStreams)
52 {
53 return static_cast<derived_T*>(this)->unpackSymbols(sourceIter, symbol, nStreams);
54 };
55
56 template <typename source_IT>
57 [[nodiscard]] source_IT unpackSymbols(source_IT sourceIter, coderSymbol_type& symbol)
58 {
59 return static_cast<derived_T*>(this)->unpackSymbols(sourceIter, symbol);
60 };
61
63
64 protected:
65 template <typename source_IT>
66 [[nodiscard]] inline const symbol_type& lookupSymbol(source_IT sourceIter)
67 {
68 // LOGP(info, "unpacking {}", fmt::ptr(sourceIter));
69 if constexpr (!std::is_null_pointer_v<incompressible_iterator>) {
70 const symbol_type& symbol = (*mSymbolTable)[*sourceIter];
71 if (mSymbolTable->isEscapeSymbol(symbol)) {
72 *mIncompressibleIter++ = *sourceIter;
73 }
74 return symbol;
75 } else {
76 return *mSymbolTable->lookupUnsafe(*sourceIter);
77 }
78 };
79
82 incompressible_IT incompressibleIter = nullptr) : mSymbolTable{&symbolTable},
83 mIncompressibleIter{incompressibleIter} {};
84
87};
88
89template <typename symbolTable_T, typename coder_T, typename incompressible_IT = std::nullptr_t>
91 coder_T,
92 incompressible_IT,
93 EncoderSymbolMapper<symbolTable_T, coder_T, incompressible_IT>>
94{
96
97 public:
106
107 static_assert(coder_type::getNstreams() == 1);
108
110
111 EncoderSymbolMapper(const symbolTable_type& symbolTable, incompressible_IT incompressibleIter = nullptr) : base_type{symbolTable, incompressibleIter} {};
112
113 template <typename source_IT>
114 [[nodiscard]] inline source_IT unpackSymbols(source_IT sourceIter, coderSymbol_type& unpacked)
115 {
116 unpacked = this->lookupSymbol(sourceIter);
117 return --sourceIter;
118 };
119
120 template <typename source_IT>
121 [[nodiscard]] inline source_IT unpackSymbols(source_IT sourceIter, coderSymbol_type& unpacked, size_type nStreams)
122 {
123 return this->unpackSymbols(sourceIter, unpacked);
124 };
125};
126
127template <size_t streamingLowerBound_V, typename symbolTable_T, typename incompressible_IT>
128class EncoderSymbolMapper<symbolTable_T,
129 CompatEncoderImpl<streamingLowerBound_V>,
130 incompressible_IT> : public EncoderSymbolMapperInterface<symbolTable_T,
131 CompatEncoderImpl<streamingLowerBound_V>,
132 incompressible_IT,
133 EncoderSymbolMapper<symbolTable_T, incompressible_IT>>
134{
136
137 public:
146
147 static_assert(coder_type::getNstreams() == 1);
148
150
151 EncoderSymbolMapper(const symbolTable_type& symbolTable, incompressible_IT incompressibleIter = nullptr) : base_type{symbolTable, incompressibleIter} {};
152
153 template <typename source_IT>
154 [[nodiscard]] inline source_IT unpackSymbols(source_IT sourceIter, coderSymbol_type& unpacked)
155 {
156 unpacked = &this->lookupSymbol(sourceIter);
157 return --sourceIter;
158 };
159
160 template <typename source_IT>
161 [[nodiscard]] inline source_IT unpackSymbols(source_IT sourceIter, coderSymbol_type& unpacked, size_type nStreams)
162 {
163 return this->unpackSymbols(sourceIter, unpacked);
164 };
165};
166
167#ifdef RANS_SINGLE_STREAM
168template <size_t streamingLowerBound_V, typename symbolTable_T, typename incompressible_IT>
169class EncoderSymbolMapper<symbolTable_T,
170 SingleStreamEncoderImpl<streamingLowerBound_V>,
171 incompressible_IT> : public EncoderSymbolMapperInterface<symbolTable_T,
172 SingleStreamEncoderImpl<streamingLowerBound_V>,
173 incompressible_IT,
174 EncoderSymbolMapper<symbolTable_T, incompressible_IT>>
175{
176 using base_type = EncoderSymbolMapperInterface<symbolTable_T, SingleStreamEncoderImpl<streamingLowerBound_V>, incompressible_IT, EncoderSymbolMapper<symbolTable_T, incompressible_IT>>;
177
178 public:
180 using coder_type = typename base_type::coder_type;
181 using size_type = typename base_type::size_type;
183 using source_type = typename base_type::source_type;
184 using symbol_type = typename base_type::symbol_type;
187
188 static_assert(coder_type::getNstreams() == 1);
189
190 EncoderSymbolMapper() = default;
191
192 EncoderSymbolMapper(const symbolTable_type& symbolTable, incompressible_IT incompressibleIter = nullptr) : base_type{symbolTable, incompressibleIter} {};
193
194 template <typename source_IT>
195 [[nodiscard]] inline source_IT unpackSymbols(source_IT sourceIter, coderSymbol_type& unpacked)
196 {
197 unpacked = &this->lookupSymbol(sourceIter);
198 return --sourceIter;
199 };
200
201 template <typename source_IT>
202 [[nodiscard]] inline source_IT unpackSymbols(source_IT sourceIter, coderSymbol_type& unpacked, size_type nStreams)
203 {
204 return this->unpackSymbols(sourceIter, unpacked);
205 };
206};
207#endif /* RANS_SINGLE_STREAM */
208
209#ifdef RANS_SSE
210template <size_t streamingLowerBound_V, typename symbolTable_T, typename incompressible_IT>
211class EncoderSymbolMapper<symbolTable_T,
212 SSEEncoderImpl<streamingLowerBound_V>,
213 incompressible_IT> : public EncoderSymbolMapperInterface<symbolTable_T,
214 SSEEncoderImpl<streamingLowerBound_V>,
215 incompressible_IT,
216 EncoderSymbolMapper<symbolTable_T, incompressible_IT>>
217{
218 using base_type = EncoderSymbolMapperInterface<symbolTable_T, SSEEncoderImpl<streamingLowerBound_V>, incompressible_IT, EncoderSymbolMapper<symbolTable_T, incompressible_IT>>;
219
220 public:
222 using coder_type = typename base_type::coder_type;
223 using size_type = typename base_type::size_type;
225 using source_type = typename base_type::source_type;
226 using symbol_type = typename base_type::symbol_type;
229
230 static_assert(coder_type::getNstreams() == 4);
231
232 EncoderSymbolMapper() = default;
233
234 EncoderSymbolMapper(const symbolTable_type& symbolTable, incompressible_IT incompressibleIter = nullptr) : base_type{symbolTable, incompressibleIter} {};
235
236 template <typename source_IT>
237 [[nodiscard]] inline source_IT unpackSymbols(source_IT sourceIter, coderSymbol_type& unpacked)
238 {
239 using namespace simd;
240 std::array<const symbol_type*, 4> ret;
241 ret[3] = &this->lookupSymbol(sourceIter - 0);
242 ret[2] = &this->lookupSymbol(sourceIter - 1);
243 ret[1] = &this->lookupSymbol(sourceIter - 2);
244 ret[0] = &this->lookupSymbol(sourceIter - 3);
245
246 aosToSoa(gsl::make_span(ret).template subspan<0, 2>(), &unpacked.frequencies[0], &unpacked.cumulativeFrequencies[0]);
247 aosToSoa(gsl::make_span(ret).template subspan<2, 2>(), &unpacked.frequencies[1], &unpacked.cumulativeFrequencies[1]);
248
249 return utils::advanceIter(sourceIter, -coder_type::getNstreams());
250 };
251
252 template <typename source_IT>
253 [[nodiscard]] inline source_IT unpackSymbols(source_IT sourceIter, coderSymbol_type& unpacked, size_type nActiveStreams)
254 {
255 using namespace internal::simd;
256
257 difference_type currentStream = nActiveStreams;
258
259 epi32_t<SIMDWidth::SSE, 2> frequencies;
260 epi32_t<SIMDWidth::SSE, 2> cumulativeFrequencies;
261
262 while (currentStream-- > 0) {
263 const auto& symbol = this->lookupSymbol(sourceIter--);
264 frequencies(currentStream) = symbol.getFrequency();
265 cumulativeFrequencies(currentStream) = symbol.getCumulative();
266 }
267
268 unpacked.frequencies[0] = load(frequencies[0]);
269 unpacked.frequencies[1] = load(frequencies[1]);
270
271 unpacked.cumulativeFrequencies[0] = load(cumulativeFrequencies[0]);
272 unpacked.cumulativeFrequencies[1] = load(cumulativeFrequencies[1]);
273
274 return sourceIter;
275 };
276};
277#endif /* RANS_SSE */
278
279#ifdef RANS_AVX2
280template <size_t streamingLowerBound_V, typename symbolTable_T, typename incompressible_IT>
281class EncoderSymbolMapper<symbolTable_T,
282 AVXEncoderImpl<streamingLowerBound_V>,
283 incompressible_IT> : public EncoderSymbolMapperInterface<symbolTable_T,
284 AVXEncoderImpl<streamingLowerBound_V>,
285 incompressible_IT,
286 EncoderSymbolMapper<symbolTable_T, incompressible_IT>>
287{
288 using base_type = EncoderSymbolMapperInterface<symbolTable_T, AVXEncoderImpl<streamingLowerBound_V>, incompressible_IT, EncoderSymbolMapper<symbolTable_T, incompressible_IT>>;
289
290 public:
292 using coder_type = typename base_type::coder_type;
293 using size_type = typename base_type::size_type;
295 using source_type = typename base_type::source_type;
296 using symbol_type = typename base_type::symbol_type;
299
300 static_assert(coder_type::getNstreams() == 8);
301
302 EncoderSymbolMapper() = default;
303
304 EncoderSymbolMapper(const symbolTable_type& symbolTable, incompressible_IT incompressibleIter = nullptr) : base_type{symbolTable, incompressibleIter} {};
305
306 template <typename source_IT>
307 [[nodiscard]] inline source_IT unpackSymbols(source_IT sourceIter, coderSymbol_type& unpacked)
308 {
309 using namespace simd;
310 std::array<const Symbol*, 8> ret;
311 ret[7] = &this->lookupSymbol(sourceIter - 0);
312 ret[6] = &this->lookupSymbol(sourceIter - 1);
313 ret[5] = &this->lookupSymbol(sourceIter - 2);
314 ret[4] = &this->lookupSymbol(sourceIter - 3);
315 ret[3] = &this->lookupSymbol(sourceIter - 4);
316 ret[2] = &this->lookupSymbol(sourceIter - 5);
317 ret[1] = &this->lookupSymbol(sourceIter - 6);
318 ret[0] = &this->lookupSymbol(sourceIter - 7);
319
320 aosToSoa(gsl::make_span(ret).template subspan<0, 4>(), &unpacked.frequencies[0], &unpacked.cumulativeFrequencies[0]);
321 aosToSoa(gsl::make_span(ret).template subspan<4, 4>(), &unpacked.frequencies[1], &unpacked.cumulativeFrequencies[1]);
322
323 return utils::advanceIter(sourceIter, -coder_type::getNstreams());
324 };
325
326 template <typename source_IT>
327 [[nodiscard]] inline source_IT unpackSymbols(source_IT sourceIter, coderSymbol_type& unpacked, size_type nActiveStreams)
328 {
329 using namespace internal::simd;
330
331 difference_type currentStream = nActiveStreams;
332
333 epi32_t<SIMDWidth::SSE, 2> frequencies;
334 epi32_t<SIMDWidth::SSE, 2> cumulativeFrequencies;
335
336 while (currentStream-- > 0) {
337 const auto& symbol = this->lookupSymbol(sourceIter--);
338 frequencies(currentStream) = symbol.getFrequency();
339 cumulativeFrequencies(currentStream) = symbol.getCumulative();
340 }
341
342 unpacked.frequencies[0] = load(frequencies[0]);
343 unpacked.frequencies[1] = load(frequencies[1]);
344
345 unpacked.cumulativeFrequencies[0] = load(cumulativeFrequencies[0]);
346 unpacked.cumulativeFrequencies[1] = load(cumulativeFrequencies[1]);
347
348 return sourceIter;
349 };
350};
351#endif /* RANS_AVX2 */
352
353} // namespace o2::rans::internal
354
355#endif /* RANS_INTERNAL_ENCODE_ENCODERSYMBOLMAPPER_H_ */
Lookup table containing statistical information for each symbol in the alphabet required for encoding...
rANS encoding operations that encode multiple symbols simultaniously using SIMD. Unified implementati...
rANS encoding operations based on ryg's fast algorithm and a naive rANS implementation for all 64Bit ...
common helper classes and functions
uint32_t source_type
const symbol_type & lookupSymbol(source_IT sourceIter)
EncoderSymbolMapperInterface(const symbolTable_type &symbolTable, incompressible_IT incompressibleIter=nullptr)
typename symbolTable_type::source_type source_type
source_IT unpackSymbols(source_IT sourceIter, coderSymbol_type &symbol)
incompressible_iterator getIncompressibleIterator() const
typename coder_type::symbol_type coderSymbol_type
source_IT unpackSymbols(source_IT sourceIter, coderSymbol_type &symbol, size_type nStreams)
typename symbolTable_type::symbol_type symbol_type
EncoderSymbolMapper(const symbolTable_type &symbolTable, incompressible_IT incompressibleIter=nullptr)
source_IT unpackSymbols(source_IT sourceIter, coderSymbol_type &unpacked)
typename base_type::coderSymbol_type coderSymbol_type
typename base_type::coder_type coder_type
EncoderSymbolMapper(const symbolTable_type &symbolTable, incompressible_IT incompressibleIter=nullptr)
typename base_type::source_type source_type
typename base_type::symbolTable_type symbolTable_type
typename base_type::incompressible_iterator incompressible_iterator
source_IT unpackSymbols(source_IT sourceIter, coderSymbol_type &unpacked, size_type nStreams)
typename base_type::size_type size_type
typename base_type::symbol_type symbol_type
typename base_type::difference_type difference_type
preprocessor defines to enable features based on CPU architecture
auto make_span(const o2::rans::internal::simd::AlignedArray< T, width_V, size_V > &array)
Freq_IT advanceIter(Freq_IT iter, std::ptrdiff_t distance)
Definition utils.h:191