Project
Loading...
Searching...
No Matches
Encoder.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_ENCODER_H_
17#define RANS_INTERNAL_ENCODE_ENCODER_H_
18
19#include <algorithm>
20#include <iomanip>
21#include <memory>
22
23#include <fairlogger/Logger.h>
24#include <stdexcept>
25
26#include <gsl/span>
27
30
31namespace o2::rans
32{
33
34namespace encoderImpl
35{
36
37template <typename stream_IT, typename literals_IT = std::nullptr_t>
38[[nodiscard]] inline constexpr decltype(auto) makeReturn(stream_IT streamEnd, literals_IT literalsEnd = nullptr) noexcept
39{
40 if constexpr (std::is_null_pointer_v<literals_IT>) {
41 return streamEnd;
42 } else {
43 return std::make_pair(streamEnd, literalsEnd);
44 }
45};
46
47} // namespace encoderImpl
48
49template <class encoder_T, class symbolTable_T, std::size_t nStreams_V>
51{
52 public:
53 using symbolTable_type = symbolTable_T;
54 using symbol_type = typename symbolTable_T::value_type;
55 using coder_type = encoder_T;
56 using source_type = typename symbolTable_type::source_type;
57 using stream_type = typename coder_type::stream_type;
58 using size_type = std::size_t;
59 using difference_type = std::ptrdiff_t;
60
61 static constexpr size_type NStreams = nStreams_V;
62
63 Encoder() = default;
64
65 template <typename renormedSymbolTable_T>
66 Encoder(const renormedSymbolTable_T& renormedFrequencyTable) : mSymbolTable{renormedFrequencyTable}
67 {
68 const size_t symbolTablePrecission = mSymbolTable.getPrecision();
69 const size_t encoderLowerBound = coder_type::getStreamingLowerBound();
70 if (symbolTablePrecission > encoderLowerBound) {
71 throw EncodingError(fmt::format(
72 "Renorming precision of symbol table ({} Bits) exceeds renorming lower bound of encoder ({} Bits).\
73 This can cause overflows during encoding.",
74 symbolTablePrecission, encoderLowerBound));
75 }
76 };
77
78 [[nodiscard]] inline const symbolTable_type& getSymbolTable() const noexcept { return mSymbolTable; };
79
80 [[nodiscard]] inline static constexpr size_type getNStreams() noexcept { return NStreams; };
81
82 template <typename stream_IT, typename source_IT, typename literals_IT = std::nullptr_t, std::enable_if_t<utils::isCompatibleIter_v<typename symbolTable_T::source_type, source_IT>, bool> = true>
83 decltype(auto) process(source_IT inputBegin, source_IT inputEnd, stream_IT outputBegin, literals_IT literalsBegin = nullptr) const;
84
85 template <typename literals_IT = std::nullptr_t>
86 inline decltype(auto) process(gsl::span<const source_type> inputStream, gsl::span<stream_type> outputStream, literals_IT literalsBegin = nullptr) const
87 {
88 return process(inputStream.data(), inputStream.data() + inputStream.size(), outputStream.data(), literalsBegin);
89 };
90
91 protected:
93
94 static constexpr size_type NCoderStreams = coder_type::getNstreams();
96
97 // compile time preconditions:
98 static_assert(internal::isPow2(nStreams_V), "the number of streams must be a power of 2");
99 static_assert(coder_type::getNstreams() <= Encoder::getNStreams(), "The specified coder type has more streams than your encoder");
100 static_assert(NCoders % 2 == 0, "At least 2 encoders must run in parallel");
101};
102
103template <class encoder_T, class symbolTable_T, std::size_t nStreams_V>
104template <typename stream_IT, typename source_IT, typename literals_IT, std::enable_if_t<utils::isCompatibleIter_v<typename symbolTable_T::source_type, source_IT>, bool>>
105decltype(auto) Encoder<encoder_T, symbolTable_T, nStreams_V>::process(source_IT inputBegin, source_IT inputEnd, stream_IT outputBegin, literals_IT literalsBegin) const
106{
107
108 using namespace internal;
109 using namespace utils;
110 using namespace encoderImpl;
111
112 if (inputBegin == inputEnd) {
113 LOG(warning) << "passed empty message to encoder, skip encoding";
114 return makeReturn(outputBegin, literalsBegin);
115 }
116
117 if (std::is_null_pointer_v<literals_IT> && mSymbolTable.hasEscapeSymbol()) {
118 throw HistogramError("The Symbol table used requires you to pass a literals iterator");
119 }
120
121 std::array<coder_type, NCoders> coders;
122
123 for (auto& coder : coders) {
124 coder = coder_type{mSymbolTable.getPrecision()};
125 }
126
127 // calculate sizes and numbers of iterations:
128 const auto inputBufferSize = std::distance(inputBegin, inputEnd); // size of the input buffer
129 const size_t nRemainderSymbols = inputBufferSize % NStreams;
130 const size_t nPartialCoderIterations = nRemainderSymbols / NCoderStreams;
131 const size_t nFractionalEncodes = nRemainderSymbols % NCoderStreams;
132
133 // from here on, everything runs backwards!
134 // We are encoding symbols from the end of the message to the beginning of the message.
135 // Since rANS works like a stack, this allows the decoder to work in forward direction.
136 // To guarante consistency betweenn different coder implementations, all interleaved
137 // streams have to run backwards as well, i.e. stream m of coder n+1 runs before stream p of coder n.
138
139 stream_IT outputIter = outputBegin;
140 source_IT inputIter = advanceIter(inputEnd, -1);
141 source_IT inputREnd = advanceIter(inputBegin, -1);
142
143 EncoderSymbolMapper<symbolTable_type, coder_type, literals_IT> symbolMapper{this->mSymbolTable, literalsBegin};
144 typename coder_type::symbol_type encoderSymbols[2]{};
145
146 // one past the end. Will not be dereferenced, thus safe.
147#pragma GCC diagnostic push
148#pragma GCC diagnostic ignored "-Warray-bounds"
149 coder_type* codersREnd = advanceIter(coders.data(), -1);
150#pragma GCC diagnostic pop
151 coder_type* activeCoder = codersREnd + nPartialCoderIterations;
152
153 // we are encoding backwards!
154 if (nFractionalEncodes) {
155 // one more encoding step than nPartialCoderIterations for masked encoding
156 // will not cause out of range for coders
157 ++activeCoder;
158 inputIter = symbolMapper.unpackSymbols(inputIter, encoderSymbols[0], nFractionalEncodes);
159 outputIter = activeCoder->putSymbols(outputIter, encoderSymbols[0], nFractionalEncodes);
160 --activeCoder;
161 }
162
163 // align encoders
164 while (activeCoder != codersREnd) {
165 if (inputIter != inputREnd) {
166 inputIter = symbolMapper.unpackSymbols(inputIter, encoderSymbols[0]);
167 outputIter = (activeCoder--)->putSymbols(outputIter, encoderSymbols[0]);
168 }
169 }
170
171 constexpr size_t lastCoderIdx = NCoders - 1;
172 while (inputIter != inputREnd) {
173 // iterate over coders
174 for (size_t i = 0; i < coders.size(); i += 2) {
175 inputIter = symbolMapper.unpackSymbols(inputIter, encoderSymbols[0]);
176 outputIter = coders[lastCoderIdx - i].putSymbols(outputIter, encoderSymbols[0]);
177 inputIter = symbolMapper.unpackSymbols(inputIter, encoderSymbols[1]);
178 outputIter = coders[lastCoderIdx - (i + 1)].putSymbols(outputIter, encoderSymbols[1]);
179 }
180 }
181
182 for (size_t i = coders.size(); i-- > 0;) {
183 outputIter = coders[i].flush(outputIter);
184 }
185
186 return makeReturn(outputIter, symbolMapper.getIncompressibleIterator());
187}
188
189}; // namespace o2::rans
190
191#endif /* RANS_INTERNAL_ENCODE_ENCODER_H_ */
Looks up statistical properties in symbol table for each source symbol. Specialed for each coder type...
int32_t i
configStandalone Light OpenGL display display_light Apply smoothing to points Enable Z buffer Highlight links Highlight seeds Highlight sector tracks Highlight final tracks Show individual Show related Highlight grid Show only individual collision Color clusters belonging to track objects Set line Enable drawing TPC data Enable drawing TOF data Enable drawing magnetic field Set field line step count Invert colors configStandalone Heavy OpenGL display display_heavy Show tracks with ITS contribution Show tracks with TOF contribution Enable propagation of loopers Show clusters at nominal x of pad row for early transformed data Split CE tracks when they cross the central Mark clusters Mark adjacent clusters Hide rejected tracks Apply filter on tracks to be displayed Separate increase X h configStandalone Camera window renderer OpenGL display display_camera Orient the camera such that the y axis is always upwards Full Screen MultiSample Anti Downsampling Anti Enable Vertical Sync Target frame or if the backend cannot limit to the refresh Use OpenGL indirect draws to reduce number of draw calls Display h configStandalone Vulkan display display_vulkan Have uniform buffers in host accessible device memory h internal
Timeframe settings Average distance in cm of events merged into Randomize distance around average distance of merged events Simulate correct bunch interactions instead of placing only the average number of events A value[n] sets TFlen for[n] collisions in Number of bunches per trainsort Number of bunch trains Instantaneous interaction rate Do not simulate border Total number of collisions to be placed in the interior of all time Do not select random but walk over array of events in stride steps h Event generator settings h configStandalone Use CPU for GPU Force usage of the specified GPU device no CPU fallback Continue processing after an error First event to process
common helper classes and functions
typename coder_type::stream_type stream_type
Definition Encoder.h:57
Encoder(const renormedSymbolTable_T &renormedFrequencyTable)
Definition Encoder.h:66
typename symbolTable_T::value_type symbol_type
Definition Encoder.h:54
const symbolTable_type & getSymbolTable() const noexcept
Definition Encoder.h:78
std::ptrdiff_t difference_type
Definition Encoder.h:59
static constexpr size_type NCoders
Definition Encoder.h:95
decltype(auto) process(gsl::span< const source_type > inputStream, gsl::span< stream_type > outputStream, literals_IT literalsBegin=nullptr) const
Definition Encoder.h:86
static constexpr size_type NStreams
Definition Encoder.h:61
symbolTable_type mSymbolTable
Definition Encoder.h:92
std::size_t size_type
Definition Encoder.h:58
static constexpr size_type getNStreams() noexcept
Definition Encoder.h:80
typename symbolTable_type::source_type source_type
Definition Encoder.h:56
static constexpr size_type NCoderStreams
Definition Encoder.h:94
encoder_T coder_type
Definition Encoder.h:55
symbolTable_T symbolTable_type
Definition Encoder.h:53
constexpr decltype(auto) makeReturn(stream_IT streamEnd, literals_IT literalsEnd=nullptr) noexcept
Definition Encoder.h:38
constexpr bool isPow2(T x) noexcept
Definition utils.h:104
Common utility functions.
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"