Project
Loading...
Searching...
No Matches
bench_ransHistogram.cxx
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
17
18#include <vector>
19#include <cstring>
20#include <random>
21#include <algorithm>
22#ifdef RANS_PARALLEL_STL
23#include <execution>
24#endif
25#include <iterator>
26
27#include <benchmark/benchmark.h>
28
29#include "rANS/factory.h"
32
33#ifdef ENABLE_VTUNE_PROFILER
34#include <ittnotify.h>
35#endif
36
37#include "helpers.h"
38
39using namespace o2::rans;
40
41inline constexpr size_t MessageSize = 1ull << 22;
42
43template <typename source_T>
45{
46 public:
48
49 const auto& get(size_t messageSize)
50 {
51 if (mSourceMessage.empty()) {
52 LOG(info) << "generating Binomial distribution";
53
54 std::mt19937 mt(0); // same seed we want always the same distrubution of random numbers;
55 const size_t draws = std::min(1ul << 27, static_cast<size_t>(std::numeric_limits<source_T>::max()));
56 const double probability = 0.5;
57 std::binomial_distribution<source_T> dist(draws, probability);
58 const size_t sourceSize = messageSize / sizeof(source_T) + 1;
59 mSourceMessage.resize(sourceSize);
60#ifdef RANS_PARALLEL_STL
61 std::generate(std::execution::par_unseq, mSourceMessage.begin(), mSourceMessage.end(), [&dist, &mt]() { return dist(mt); });
62#else
63 std::generate(mSourceMessage.begin(), mSourceMessage.end(), [&dist, &mt]() { return dist(mt); });
64#endif // RANS_PARALLEL_STL
65 }
66
67 return mSourceMessage;
68 };
69
70 private:
71 std::vector<source_T> mSourceMessage{};
72};
73
75
76template <typename source_T>
78{
79 public:
81
82 const auto& get(size_t messageSize)
83 {
84 if (mSourceMessage.empty()) {
85 LOG(info) << "generating Uniform distribution";
86
87 std::mt19937 mt(0); // same seed we want always the same distrubution of random numbers;
88 const size_t min = 0;
89 const double max = std::min(1ul << 27, static_cast<size_t>(std::numeric_limits<source_T>::max()));
90 std::uniform_int_distribution<source_T> dist(min, max);
91 const size_t sourceSize = messageSize / sizeof(source_T) + 1;
92 mSourceMessage.resize(sourceSize);
93#ifdef RANS_PARALLEL_STL
94 std::generate(std::execution::par_unseq, mSourceMessage.begin(), mSourceMessage.end(), [&dist, &mt]() { return dist(mt); });
95#else
96 std::generate(mSourceMessage.begin(), mSourceMessage.end(), [&dist, &mt]() { return dist(mt); });
97#endif
98 }
99 return mSourceMessage;
100 };
101
102 private:
103 std::vector<source_T> mSourceMessage{};
104};
105
107
108template <class... Args>
109void ransMakeHistogramBenchmark(benchmark::State& st, Args&&... args)
110{
111
112 auto args_tuple = std::make_tuple(std::move(args)...);
113
114 const auto& inputData = std::get<0>(args_tuple).get(MessageSize);
115
116 using histogram_type = std::remove_cv_t<std::remove_reference_t<decltype(std::get<1>(args_tuple))>>;
117 using input_data_type = std::remove_cv_t<std::remove_reference_t<decltype(inputData)>>;
118 using source_type = typename input_data_type::value_type;
119
120 const auto histogram = makeDenseHistogram::fromSamples(gsl::span<const source_type>(inputData));
121 Metrics<source_type> metrics{histogram};
122
123#ifdef ENABLE_VTUNE_PROFILER
124 __itt_resume();
125#endif
126 for (auto _ : st) {
127 histogram_type hist{};
128 // hist.addSamples(gsl::span<const source_type>(inputData));
129 hist.addSamples(inputData.begin(), inputData.end());
130 benchmark::DoNotOptimize(hist);
131 }
132#ifdef ENABLE_VTUNE_PROFILER
133 __itt_pause();
134#endif
135
136 bool isSame = true;
137 histogram_type hist{};
138 hist.addSamples(gsl::span<const source_type>(inputData));
139
140 for (std::ptrdiff_t symbol = histogram.getOffset(); symbol != histogram.getOffset() + static_cast<std::ptrdiff_t>(histogram.size()); ++symbol) {
141 if (histogram[symbol] > 0) {
142 LOG_IF(info, histogram[symbol] != hist[symbol]) << fmt::format("[{}]: {} != {}", symbol, hist[symbol], histogram[symbol]);
143 isSame = isSame && (histogram[symbol] == hist[symbol]);
144 }
145 }
146
147 if (!(isSame)) {
148 st.SkipWithError("Missmatch between encoded and decoded Message");
149 }
150
151 const auto& datasetProperties = metrics.getDatasetProperties();
152 st.SetItemsProcessed(static_cast<int64_t>(inputData.size()) * static_cast<int64_t>(st.iterations()));
153 st.SetBytesProcessed(static_cast<int64_t>(inputData.size()) * sizeof(source_type) * static_cast<int64_t>(st.iterations()));
154 st.counters["AlphabetRangeBits"] = datasetProperties.alphabetRangeBits;
155 st.counters["nUsedAlphabetSymbols"] = datasetProperties.nUsedAlphabetSymbols;
156 st.counters["HistogramSize"] = hist.size() * sizeof(source_type);
157 st.counters["Entropy"] = datasetProperties.entropy;
158 st.counters["SourceSize"] = inputData.size() * sizeof(source_type);
159 st.counters["LowerBound"] = inputData.size() * (static_cast<double>(st.counters["Entropy"]) / 8);
160};
161
162template <class... Args>
163void ransAccessHistogramBenchmark(benchmark::State& st, Args&&... args)
164{
165
166 auto args_tuple = std::make_tuple(std::move(args)...);
167 const auto& inputData = std::get<0>(args_tuple).get(MessageSize);
168
169 using histogram_type = std::remove_cv_t<std::remove_reference_t<decltype(std::get<1>(args_tuple))>>;
170 using input_data_type = std::remove_cv_t<std::remove_reference_t<decltype(inputData)>>;
171 using source_type = typename input_data_type::value_type;
172
173 const auto histogram = makeDenseHistogram::fromSamples(gsl::span<const source_type>(inputData));
174 Metrics<source_type> metrics{histogram};
175
176 histogram_type hist{};
177 hist.addSamples(gsl::span<const source_type>(inputData));
178
179#ifdef ENABLE_VTUNE_PROFILER
180 __itt_resume();
181#endif
182 for (auto _ : st) {
183 for (auto& symbol : inputData) {
184 const uint32_t t = hist[symbol];
185 benchmark::DoNotOptimize(t);
186 }
187 }
188#ifdef ENABLE_VTUNE_PROFILER
189 __itt_pause();
190#endif
191
192 bool isSame = true;
193 for (std::ptrdiff_t symbol = histogram.getOffset(); symbol != histogram.getOffset() + static_cast<std::ptrdiff_t>(histogram.size()); ++symbol) {
194 if (histogram[symbol] > 0) {
195 LOG_IF(info, histogram[symbol] != hist[symbol]) << fmt::format("[{}]: {} != {}", symbol, hist[symbol], histogram[symbol]);
196 isSame = isSame && (histogram[symbol] == hist[symbol]);
197 }
198 }
199
200 if (!(isSame)) {
201 st.SkipWithError("Missmatch between encoded and decoded Message");
202 }
203
204 const auto& datasetProperties = metrics.getDatasetProperties();
205 st.SetItemsProcessed(static_cast<int64_t>(inputData.size()) * static_cast<int64_t>(st.iterations()));
206 st.SetBytesProcessed(static_cast<int64_t>(inputData.size()) * sizeof(source_type) * static_cast<int64_t>(st.iterations()));
207 st.counters["AlphabetRangeBits"] = datasetProperties.alphabetRangeBits;
208 st.counters["nUsedAlphabetSymbols"] = datasetProperties.nUsedAlphabetSymbols;
209 st.counters["HistogramSize"] = hist.size() * sizeof(source_type);
210 st.counters["Entropy"] = datasetProperties.entropy;
211 st.counters["SourceSize"] = inputData.size() * sizeof(source_type);
212 st.counters["LowerBound"] = inputData.size() * (static_cast<double>(st.counters["Entropy"]) / 8);
213};
214
215BENCHMARK_CAPTURE(ransMakeHistogramBenchmark, makeHistogram_Vector_binomial_32, std::reference_wrapper(sourceMessageBinomial32), DenseHistogram<uint32_t>{});
216BENCHMARK_CAPTURE(ransMakeHistogramBenchmark, makeHistogram_Vector_uniform_32, std::reference_wrapper(sourceMessageUniform32), DenseHistogram<uint32_t>{});
217
218BENCHMARK_CAPTURE(ransMakeHistogramBenchmark, makeHistogram_SparseVector_binomial_32, std::reference_wrapper(sourceMessageBinomial32), AdaptiveHistogram<uint32_t>{});
219BENCHMARK_CAPTURE(ransMakeHistogramBenchmark, makeHistogram_SparseVector_uniform_32, std::reference_wrapper(sourceMessageUniform32), AdaptiveHistogram<uint32_t>{});
220
221BENCHMARK_CAPTURE(ransAccessHistogramBenchmark, accessHistogram_Vector_binomial_32, std::reference_wrapper(sourceMessageBinomial32), DenseHistogram<uint32_t>{});
222BENCHMARK_CAPTURE(ransAccessHistogramBenchmark, accessHistogram_Vector_uniform_32, std::reference_wrapper(sourceMessageUniform32), DenseHistogram<uint32_t>{});
223
224BENCHMARK_CAPTURE(ransAccessHistogramBenchmark, accessHistogram_SparseVector_binomial_32, std::reference_wrapper(sourceMessageBinomial32), AdaptiveHistogram<uint32_t>{});
225BENCHMARK_CAPTURE(ransAccessHistogramBenchmark, accessHistogram_SparseVector_uniform_32, std::reference_wrapper(sourceMessageUniform32), AdaptiveHistogram<uint32_t>{});
226
Histogram for source symbols used to estimate symbol probabilities for entropy coding.
std::vector< o2::mid::ColumnData > inputData
benchmark::State & st
constexpr size_t MessageSize
void ransMakeHistogramBenchmark(benchmark::State &st, Args &&... args)
void ransAccessHistogramBenchmark(benchmark::State &st, Args &&... args)
BENCHMARK_CAPTURE(ransMakeHistogramBenchmark, makeHistogram_Vector_binomial_32, std::reference_wrapper(sourceMessageBinomial32), DenseHistogram< uint32_t >{})
BENCHMARK_MAIN()
SourceMessageProxyBinomial< uint32_t > sourceMessageBinomial32
SourceMessageProxyUniform< uint32_t > sourceMessageUniform32
uint32_t source_type
SourceMessageProxyBinomial()=default
const auto & get(size_t messageSize)
SourceMessageProxyUniform()=default
const auto & get(size_t messageSize)
preprocessor defines to enable features based on CPU architecture
static factory classes for building histograms, encoders and decoders.
GLsizei GLenum const void GLuint GLsizei GLfloat * metrics
Definition glcorearb.h:5500
common functionality for rANS benchmarks.
static decltype(auto) fromSamples(source_IT begin, source_IT end, typename std::iterator_traits< source_IT >::value_type min, typename std::iterator_traits< source_IT >::value_type max)
Definition factory.h:144
constexpr size_t min
constexpr size_t max
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"