Skip to content

Commit 7149a55

Browse files
committed
Update
1 parent 028c254 commit 7149a55

File tree

4 files changed

+57
-69
lines changed

4 files changed

+57
-69
lines changed

CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ endmacro()
3131
# the final executable name
3232
set(EXE_NAME babelstream)
3333

34-
# for chrono, some basic CXX features, and generic lambdas; models can overwrite this if required
35-
set(CMAKE_CXX_STANDARD 14)
34+
# for chrono and some basic CXX features, models can overwrite this if required
35+
set(CMAKE_CXX_STANDARD 11)
3636

3737
if (NOT CMAKE_BUILD_TYPE)
3838
message("No CMAKE_BUILD_TYPE specified, defaulting to 'Release'")

src/StreamModels.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
#endif
3737

3838
template <typename T>
39-
std::unique_ptr<Stream<T>> construct_stream(int ARRAY_SIZE, unsigned int deviceIndex) {
39+
std::unique_ptr<Stream<T>> make_stream(int ARRAY_SIZE, unsigned int deviceIndex) {
4040
#if defined(CUDA)
4141
// Use the CUDA implementation
4242
return std::make_unique<CUDAStream<T>>(ARRAY_SIZE, deviceIndex);

src/Unit.h

Lines changed: 19 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,31 @@
11
#pragma once
22
#include <iostream>
33

4-
enum { MegaByte, GigaByte, MibiByte, GibiByte };
5-
64
// Units for output:
75
struct Unit {
8-
int value;
9-
Unit(int v) : value(v) {}
10-
double fmt(double bytes) {
11-
switch(value) {
12-
case MibiByte: return pow(2.0, -20.0) * bytes;
13-
case MegaByte: return 1.0E-6 * bytes;
14-
case GibiByte: return pow(2.0, -30.0) * bytes;
15-
case GigaByte: return 1.0E-9 * bytes;
16-
default: std::cerr << "Unimplemented!" << std::endl; abort();
17-
}
18-
}
19-
char const* str() {
20-
switch(value) {
21-
case MibiByte: return "MiB";
22-
case MegaByte: return "MB";
23-
case GibiByte: return "GiB";
24-
case GigaByte: return "GB";
25-
default: std::cerr << "Unimplemented!" << std::endl; abort();
26-
}
27-
}
28-
Unit kibi() {
29-
switch(value) {
30-
case MegaByte: return Unit(MibiByte);
31-
case GigaByte: return Unit(GibiByte);
32-
default: return *this;
33-
}
34-
}
35-
Unit byte() {
6+
enum class Kind { MegaByte, GigaByte, TeraByte, MibiByte, GibiByte, TebiByte };
7+
Kind value;
8+
explicit Unit(Kind v) : value(v) {}
9+
double fmt(double bytes) const {
3610
switch(value) {
37-
case MibiByte: return Unit(MegaByte);
38-
case GibiByte: return Unit(GigaByte);
39-
default: return *this;
11+
case Kind::MibiByte: return std::pow(2.0, -20.0) * bytes;
12+
case Kind::MegaByte: return 1.0E-6 * bytes;
13+
case Kind::GibiByte: return std::pow(2.0, -30.0) * bytes;
14+
case Kind::GigaByte: return 1.0E-9 * bytes;
15+
case Kind::TebiByte: return std::pow(2.0, -40.0) * bytes;
16+
case Kind::TeraByte: return 1.0E-12 * bytes;
17+
default: std::cerr << "Unimplemented!" << std::endl; std::abort();
4018
}
4119
}
42-
char const* lower() {
20+
char const* str() const {
4321
switch(value) {
44-
case MibiByte: return "mibytes";
45-
case MegaByte: return "mbytes";
46-
case GibiByte: return "gibytes";
47-
case GigaByte: return "gbytes";
48-
default: std::cerr << "Unimplemented!" << std::endl; abort();
22+
case Kind::MibiByte: return "MiB";
23+
case Kind::MegaByte: return "MB";
24+
case Kind::GibiByte: return "GiB";
25+
case Kind::GigaByte: return "GB";
26+
case Kind::TebiByte: return "TiB";
27+
case Kind::TeraByte: return "TB";
28+
default: std::cerr << "Unimplemented!" << std::endl; std::abort();
4929
}
5030
}
5131
};

src/main.cpp

Lines changed: 35 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -27,16 +27,16 @@ unsigned int num_times = 100;
2727
unsigned int deviceIndex = 0;
2828
bool use_float = false;
2929
bool output_as_csv = false;
30-
Unit unit = MegaByte;
30+
Unit unit{Unit::Kind::MegaByte};
3131
bool silence_errors = false;
3232
std::string csv_separator = ",";
3333

3434
// Benchmarks:
3535
constexpr size_t num_benchmarks = 6;
36-
array<char const*, num_benchmarks> labels = {"Copy", "Add", "Mul", "Triad", "Dot", "Nstream"};
36+
std::array<char const*, num_benchmarks> labels = {"Copy", "Add", "Mul", "Triad", "Dot", "Nstream"};
3737
// Weights data moved by benchmark & therefore achieved BW:
3838
// bytes = weight * sizeof(T) * ARRAY_SIZE -> bw = bytes / dur
39-
array<size_t, num_benchmarks> weight = {/*Copy:*/ 2, /*Add:*/ 2, /*Mul:*/ 3, /*Triad:*/ 3, /*Dot:*/ 2, /*Nstream:*/ 4};
39+
std::array<size_t, num_benchmarks> weight = {/*Copy:*/ 2, /*Add:*/ 2, /*Mul:*/ 3, /*Triad:*/ 3, /*Dot:*/ 2, /*Nstream:*/ 4};
4040

4141
// Options for running the benchmark:
4242
// - Classic 5 kernels (Copy, Add, Mul, Triad, Dot).
@@ -63,19 +63,17 @@ bool run_benchmark(int id) {
6363
// Prints all available benchmark labels:
6464
template <typename OStream>
6565
void print_labels(OStream& os) {
66-
for (int i = 0; i < num_benchmarks; ++i) {
66+
for (size_t i = 0; i < num_benchmarks; ++i) {
6767
os << labels[i];
6868
if (i != (num_benchmarks - 1)) os << ",";
6969
}
7070
}
7171

72-
// Clock and duration types:
73-
using clk_t = chrono::high_resolution_clock;
74-
using dur_t = chrono::duration<double>;
75-
7672
// Returns duration of executing function f:
7773
template <typename F>
7874
double time(F&& f) {
75+
using clk_t = std::chrono::high_resolution_clock;
76+
using dur_t = std::chrono::duration<double>;
7977
auto start = clk_t::now();
8078
f();
8179
return dur_t(clk_t::now() - start).count();
@@ -107,7 +105,7 @@ int main(int argc, char *argv[])
107105
else
108106
run<double>();
109107

110-
return 0;
108+
return EXIT_SUCCESS;
111109
}
112110

113111
// Run specified kernels
@@ -163,7 +161,7 @@ void run()
163161
<< "num_times" << csv_separator
164162
<< "n_elements" << csv_separator
165163
<< "sizeof" << csv_separator
166-
<< "max_" << unit.lower() << "_per_sec" << csv_separator
164+
<< "max_" << unit.str() << "_per_sec" << csv_separator
167165
<< "min_runtime" << csv_separator
168166
<< "max_runtime" << csv_separator
169167
<< "avg_runtime" << std::endl;
@@ -182,10 +180,10 @@ void run()
182180
auto fmt_cli = [](char const* function, double bandwidth, double dt_min, double dt_max, double dt_avg) {
183181
std::cout
184182
<< std::left << std::setw(12) << function
185-
<< std::left << std::setw(12) << setprecision(3) << bandwidth
186-
<< std::left << std::setw(12) << setprecision(5) << dt_min
187-
<< std::left << std::setw(12) << setprecision(5) << dt_max
188-
<< std::left << std::setw(12) << setprecision(5) << dt_avg
183+
<< std::left << std::setw(12) << std::setprecision(3) << bandwidth
184+
<< std::left << std::setw(12) << std::setprecision(5) << dt_min
185+
<< std::left << std::setw(12) << std::setprecision(5) << dt_max
186+
<< std::left << std::setw(12) << std::setprecision(5) << dt_avg
189187
<< std::endl;
190188
};
191189
auto fmt_result = [&](char const* function, size_t num_times, size_t num_elements,
@@ -213,15 +211,15 @@ void run()
213211
std::cout.precision(ss);
214212
}
215213

216-
auto stream = construct_stream<T>(ARRAY_SIZE, deviceIndex);
214+
auto stream = make_stream<T>(ARRAY_SIZE, deviceIndex);
217215
auto initElapsedS = time([&] { stream->init_arrays(startA, startB, startC); });
218216

219217
// Result of the Dot kernel, if used.
220218
T sum{};
221-
vector<vector<double>> timings = run_all<T>(stream, sum);
219+
std::vector<std::vector<double>> timings = run_all<T>(stream, sum);
222220

223221
// Create & read host vectors:
224-
vector<T> a(ARRAY_SIZE), b(ARRAY_SIZE), c(ARRAY_SIZE);
222+
std::vector<T> a(ARRAY_SIZE), b(ARRAY_SIZE), c(ARRAY_SIZE);
225223
auto readElapsedS = time([&] { stream->read_arrays(a, b, c); });
226224

227225
check_solution<T>(num_times, a, b, c, sum);
@@ -250,7 +248,7 @@ void run()
250248
<< std::left << std::setw(12) << "Max"
251249
<< std::left << std::setw(12) << "Average"
252250
<< std::endl
253-
<< fixed;
251+
<< std::fixed;
254252
}
255253

256254
for (int i = 0; i < num_benchmarks; ++i)
@@ -280,13 +278,13 @@ void check_solution(const unsigned int ntimes, std::vector<T>& a, std::vector<T>
280278

281279
const T scalar = startScalar;
282280

283-
for (int b = 0; b < num_benchmarks; ++b)
281+
for (size_t b = 0; b < num_benchmarks; ++b)
284282
{
285283
if (!run_benchmark(b)) continue;
286284

287285
for (unsigned int i = 0; i < ntimes; i++)
288286
{
289-
switch((Benchmark)b) {
287+
switch(static_cast<Benchmark>(b)) {
290288
case Benchmark::Copy: goldC = goldA; break;
291289
case Benchmark::Mul: goldB = scalar * goldC; break;
292290
case Benchmark::Add: goldC = goldA + goldB; break;
@@ -307,7 +305,7 @@ void check_solution(const unsigned int ntimes, std::vector<T>& a, std::vector<T>
307305
errC /= c.size();
308306
long double errSum = std::fabs((sum - goldSum)/goldSum);
309307

310-
long double epsi = std::numeric_limits<T>::epsilon() * 100.0;
308+
long double epsi = std::numeric_limits<T>::epsilon() * 1000.0;
311309

312310
bool failed = false;
313311
if (errA > epsi) {
@@ -425,7 +423,7 @@ void parseArguments(int argc, char *argv[])
425423
}
426424
else
427425
{
428-
auto p = find_if(labels.begin(), labels.end(), [&](char const* label) {
426+
auto p = std::find_if(labels.begin(), labels.end(), [&](char const* label) {
429427
return std::string(label) == key;
430428
});
431429
if (p == labels.end()) {
@@ -435,7 +433,7 @@ void parseArguments(int argc, char *argv[])
435433
std::cerr << std::endl;
436434
std::exit(EXIT_FAILURE);
437435
}
438-
selection = (Benchmark)(distance(labels.begin(), p));
436+
selection = (Benchmark)(std::distance(labels.begin(), p));
439437
}
440438
}
441439
else if (!std::string("--csv").compare(argv[i]))
@@ -444,19 +442,27 @@ void parseArguments(int argc, char *argv[])
444442
}
445443
else if (!std::string("--mibibytes").compare(argv[i]))
446444
{
447-
unit = Unit(MibiByte);
445+
unit = Unit(Unit::Kind::MibiByte);
448446
}
449447
else if (!std::string("--megabytes").compare(argv[i]))
450448
{
451-
unit = Unit(MegaByte);
449+
unit = Unit(Unit::Kind::MegaByte);
452450
}
453451
else if (!std::string("--gibibytes").compare(argv[i]))
454452
{
455-
unit = Unit(GibiByte);
453+
unit = Unit(Unit::Kind::GibiByte);
456454
}
457455
else if (!std::string("--gigabytes").compare(argv[i]))
458456
{
459-
unit = Unit(GigaByte);
457+
unit = Unit(Unit::Kind::GigaByte);
458+
}
459+
else if (!std::string("--tebibytes").compare(argv[i]))
460+
{
461+
unit = Unit(Unit::Kind::TebiByte);
462+
}
463+
else if (!std::string("--terabytes").compare(argv[i]))
464+
{
465+
unit = Unit(Unit::Kind::TeraByte);
460466
}
461467
else if (!std::string("--silence-errors").compare(argv[i]))
462468
{
@@ -481,6 +487,8 @@ void parseArguments(int argc, char *argv[])
481487
std::cout << " --mibibytes Use MiB=2^20 for bandwidth calculation (default MB=10^6)" << std::endl;
482488
std::cout << " --gigibytes Use GiB=2^30 for bandwidth calculation (default MB=10^6)" << std::endl;
483489
std::cout << " --gigabytes Use GB=10^9 for bandwidth calculation (default MB=10^6)" << std::endl;
490+
std::cout << " --tebibytes Use TiB=2^40 for bandwidth calculation (default MB=10^6)" << std::endl;
491+
std::cout << " --terabytes Use TB=10^12 for bandwidth calculation (default MB=10^6)" << std::endl;
484492
std::cout << " --silence-errors Ignores validation errors." << std::endl;
485493
std::cout << std::endl;
486494
std::exit(EXIT_SUCCESS);

0 commit comments

Comments
 (0)