RawSpeed
fast raw decoding library
Loading...
Searching...
No Matches
main.cpp
Go to the documentation of this file.
1/*
2 RawSpeed - RAW file decoder.
3
4 Copyright (C) 2017 Roman Lebedev
5
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) any later version.
10
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public
17 License along with this library; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19*/
20
21#include "RawSpeed-API.h"
23#include "adt/Array1DRef.h"
24#include "adt/Casts.h"
26#include "common/ChecksumFile.h"
27#include <chrono>
28#include <cstdint>
29#include <ctime>
30#include <memory>
31#include <ratio>
32#include <string>
33#include <string_view>
34#include <tuple>
35#include <type_traits>
36#include <utility>
37#include <vector>
38#include <benchmark/benchmark.h>
39
40#ifdef HAVE_OPENMP
41#include <omp.h>
42#endif
43
44#define HAVE_STEADY_CLOCK
45
50
51namespace {
52
54
55} // namespace
56
57extern "C" int RAWSPEED_READONLY rawspeed_get_number_of_processor_cores() {
58 return currThreadCount;
59}
60
61namespace {
62
63struct CPUClock final {
64 using rep = std::clock_t;
65 using period = std::ratio<1, CLOCKS_PER_SEC>;
66 using duration = std::chrono::duration<rep, period>;
67 using time_point = std::chrono::time_point<CPUClock, duration>;
68
69 // static constexpr bool is_steady = false;
70
71 static time_point now() noexcept {
72 return time_point{duration{std::clock()}};
73 }
74};
75
76#if defined(HAVE_STEADY_CLOCK)
77template <bool HighResIsSteady = std::chrono::high_resolution_clock::is_steady>
78struct ChooseSteadyClock final {
79 using type = std::chrono::high_resolution_clock;
80};
81
82template <> struct ChooseSteadyClock<false> {
83 using type = std::chrono::steady_clock;
84};
85#endif
86
87struct ChooseClockType final {
88#if defined(HAVE_STEADY_CLOCK)
90#else
91 using type = std::chrono::high_resolution_clock;
92#endif
93};
94
95template <typename Clock, typename period = std::ratio<1, 1>>
96struct Timer final {
97 using rep = double;
98 using duration = std::chrono::duration<rep, period>;
99
100 mutable typename Clock::time_point start = Clock::now();
101
103 duration elapsed = Clock::now() - start;
104 start = Clock::now();
105 return elapsed;
106 }
107};
108
109// Lazy cache for the referenced file's content - not actually read until
110// requested the first time.
111struct Entry final {
113 std::unique_ptr<std::vector<
118
120 if (Storage)
121 return Content;
122
123 std::tie(Storage, Content) =
124 FileReader(Name.FullFileName.c_str()).readFile();
125 return Content;
126 }
127};
128
129inline void BM_RawSpeed(benchmark::State& state, Entry* entry, int threads) {
130 currThreadCount = threads;
131
132#ifdef HAVE_PUGIXML
133 static const CameraMetaData metadata(RAWSPEED_SOURCE_DIR "/data/cameras.xml");
134#else
135 static const CameraMetaData metadata{};
136#endif
137
140
141 unsigned pixels = 0;
142 for (auto _ : state) {
143 RawParser parser(entry->getFileContents());
144 auto decoder(parser.getDecoder(&metadata));
145
146 decoder->failOnUnknown = false;
147 decoder->checkSupport(&metadata);
148
149 decoder->decodeRaw();
150 decoder->decodeMetaData(&metadata);
151 RawImage raw = decoder->mRaw;
152
153 benchmark::DoNotOptimize(raw);
154
156 }
157
158 // These are total over all the `state.iterations()` iterations.
159 const double CPUTime = TT().count();
160 const double WallTime = WT().count();
161
162 // For each iteration:
163 state.counters.insert({
164 {"CPUTime,s",
165 benchmark::Counter(CPUTime, benchmark::Counter::Flags::kAvgIterations)},
166 {"WallTime,s",
167 benchmark::Counter(WallTime, benchmark::Counter::Flags::kAvgIterations)},
168 {"CPUTime/WallTime", CPUTime / WallTime}, // 'Threading factor'
169 {"Pixels", pixels},
170 {"Pixels/CPUTime",
171 benchmark::Counter(pixels / CPUTime,
172 benchmark::Counter::Flags::kIsIterationInvariant)},
173 {"Pixels/WallTime",
174 benchmark::Counter(pixels / WallTime,
175 benchmark::Counter::Flags::kIsIterationInvariant)},
176 /* {"Raws", 1}, */
177 {"Raws/CPUTime",
178 benchmark::Counter(1.0 / CPUTime,
179 benchmark::Counter::Flags::kIsIterationInvariant)},
180 {"Raws/WallTime",
181 benchmark::Counter(1.0 / WallTime,
182 benchmark::Counter::Flags::kIsIterationInvariant)},
183 });
184 // Could also have counters wrt. the filesize,
185 // but i'm not sure they are interesting.
186}
187
188void addBench(Entry* entry, std::string tName, int threads) {
189 tName += std::to_string(threads);
190
191 auto* b = benchmark::RegisterBenchmark(tName, &BM_RawSpeed, entry, threads);
192 b->Unit(benchmark::kMillisecond);
193 b->UseRealTime();
194 b->MeasureProcessCPUTime();
195}
196
197} // namespace
198
199int main(int argc_, char** argv_) {
200 benchmark::MaybeReenterWithoutASLR(argc_, argv_);
201 benchmark::Initialize(&argc_, argv_);
202
203 auto argv = rawspeed::Array1DRef(argv_, argc_);
204
205 auto hasFlag = [argv](std::string_view flag) {
206 int found = 0;
207 for (int i = 1; i < argv.size(); ++i) {
208 if (!argv(i) || argv(i) != flag)
209 continue;
210 found = i;
211 argv(i) = nullptr;
212 }
213 return found;
214 };
215
216 bool threading = hasFlag("-t");
217
218#ifdef HAVE_OPENMP
219 const auto threadsMax = omp_get_max_threads();
220#else
221 const auto threadsMax = 1;
222#endif
223
224 const auto threadsMin = threading ? 1 : threadsMax;
225
226 // Were we told to use the repo (i.e. filelist.sha256 in that directory)?
227 int useChecksumFile = hasFlag("-r");
228 std::vector<Entry> Worklist;
229 if (useChecksumFile && useChecksumFile + 1 < argv.size()) {
230 char*& checksumFileRepo = argv(useChecksumFile + 1);
231 if (checksumFileRepo) {
232 const auto readEntries = rawspeed::ReadChecksumFile(checksumFileRepo);
233 Worklist.reserve(readEntries.size());
234 for (const rawspeed::ChecksumFileEntry& entryName : readEntries) {
235 Entry Entry;
236 Entry.Name = entryName;
237 Worklist.emplace_back(std::move(Entry));
238 }
239 }
240 checksumFileRepo = nullptr;
241 }
242
243 // If there are normal filenames, append them.
244 for (int i = 1; i < argv.size(); i++) {
245 if (!argv(i))
246 continue;
247
248 Entry Entry;
249 const char* fName = argv(i);
250 // These are supposed to be either absolute paths, or relative the run dir.
251 // We don't do any beautification.
252 Entry.Name.FullFileName = fName;
253 Entry.Name.RelFileName = fName;
254 Worklist.emplace_back(std::move(Entry));
255 }
256
257 // And finally, actually add the raws to be benchmarked.
258 for (Entry& entry : Worklist) {
259 std::string tName(entry.Name.RelFileName);
260 tName += "/threads:";
261
262 for (auto threads = threadsMin; threads <= threadsMax; threads++)
263 addBench(&entry, tName, threads);
264 }
265
266 benchmark::RunSpecifiedBenchmarks();
267}
std::pair< std::unique_ptr< std::vector< uint8_t, DefaultInitAllocatorAdaptor< uint8_t, AlignedAllocator< uint8_t, 16 > > > >, Buffer > readFile() const
iPoint2D RAWSPEED_READONLY getUncroppedDim() const
Definition RawImage.cpp:167
virtual std::unique_ptr< RawDecoder > getDecoder(const CameraMetaData *meta=nullptr)
Definition RawParser.cpp:42
area_type RAWSPEED_READONLY area() const
Definition Point.h:81
int main()
static const rawspeed::CameraMetaData metadata
Definition main.cpp:54
void addBench(Entry *entry, std::string tName, int threads)
Definition main.cpp:188
void BM_RawSpeed(benchmark::State &state, Entry *entry, int threads)
Definition main.cpp:129
constexpr RAWSPEED_READNONE Ttgt implicit_cast(Tsrc value)
Definition Casts.h:32
std::vector< ChecksumFileEntry > ReadChecksumFile(const std::string &RootDir, const std::string &ChecksumFileBasename)
Array1DRef(T *data_, int numElts_) -> Array1DRef< T >
int RAWSPEED_READONLY rawspeed_get_number_of_processor_cores()
Definition main.cpp:57
std::chrono::duration< rep, period > duration
Definition main.cpp:66
static time_point now() noexcept
Definition main.cpp:71
std::chrono::time_point< CPUClock, duration > time_point
Definition main.cpp:67
std::ratio< 1, CLOCKS_PER_SEC > period
Definition main.cpp:65
std::chrono::high_resolution_clock type
Definition main.cpp:79
Definition main.cpp:111
rawspeed::ChecksumFileEntry Name
Definition main.cpp:112
std::unique_ptr< std::vector< uint8_t, rawspeed::DefaultInitAllocatorAdaptor< uint8_t, rawspeed::AlignedAllocator< uint8_t, 16 > > > > Storage
Definition main.cpp:116
rawspeed::Buffer Content
Definition main.cpp:117
const rawspeed::Buffer & getFileContents()
Definition main.cpp:119
std::chrono::duration< rep, period > duration
Definition main.cpp:98