Skip to content

Commit 31e2664

Browse files
committed
add a flag to toggle shortest-length testing
1 parent 2e11ef7 commit 31e2664

File tree

4 files changed

+43
-25
lines changed

4 files changed

+43
-25
lines changed

README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,16 @@ cmake --build build --config Release
9292
./build/benchmarks/thoroughfloat64
9393
```
9494

95+
## Fixed-point evaluation
96+
97+
By default, we compare algorithms that output shortest string representation
98+
which can round-trip to the original floating-point value. We can also compare
99+
algorithms that output fixed-length representation of a given length:
100+
101+
```
102+
./build/benchmarks/benchmark -f data/canada.txt -F [length]
103+
```
104+
95105
## Other existing benchmarks
96106

97107
- [dtoa Benchmark](https://github.com/miloyip/dtoa-benchmark)

benchmarks/algorithms.h

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -314,27 +314,31 @@ int std_to_chars(T d, std::span<char>& buffer) {
314314
}
315315

316316
template <arithmetic_float T>
317-
std::array<BenchArgs<T>, Benchmarks::COUNT> initArgs(bool errol = false) {
318-
std::array<BenchArgs<T>, Benchmarks::COUNT> args;
319-
args[Benchmarks::DRAGON4] = { "dragon4" , Benchmarks::dragon4<T> , true , 10 };
320-
args[Benchmarks::ERROL3] = { "errol3" , Benchmarks::errol3<T> , errol };
321-
args[Benchmarks::TO_STRING] = { "std::to_string" , Benchmarks::to_string<T> , ERROL_SUPPORTED };
322-
args[Benchmarks::FMT_FORMAT] = { "fmt::format" , Benchmarks::fmt_format<T> , true };
323-
args[Benchmarks::NETLIB] = { "netlib" , Benchmarks::netlib<T> , NETLIB_SUPPORTED && std::is_same_v<T, double>, 10 };
324-
args[Benchmarks::SNPRINTF] = { "snprintf" , Benchmarks::snprintf<T> , true };
325-
args[Benchmarks::GRISU2] = { "grisu2" , Benchmarks::grisu2<T> , std::is_same_v<T, double> };
326-
args[Benchmarks::GRISU_EXACT] = { "grisu_exact" , Benchmarks::grisu_exact<T> , true };
327-
args[Benchmarks::SCHUBFACH] = { "schubfach" , Benchmarks::schubfach<T> , true };
328-
args[Benchmarks::DRAGONBOX] = { "dragonbox" , Benchmarks::dragonbox<T> , true };
329-
args[Benchmarks::RYU] = { "ryu" , Benchmarks::ryu<T> , true };
330-
args[Benchmarks::TEJU_JAGUA] = { "teju_jagua" , Benchmarks::teju_jagua<T> , true };
331-
args[Benchmarks::DOUBLE_CONVERSION] = { "double_conversion" , Benchmarks::double_conversion<T> , true };
332-
args[Benchmarks::ABSEIL] = { "abseil" , Benchmarks::abseil<T> , ABSEIL_SUPPORTED };
333-
args[Benchmarks::STD_TO_CHARS] = { "std::to_chars" , Benchmarks::std_to_chars<T> , TO_CHARS_SUPPORTED };
334-
args[Benchmarks::GRISU3] = { "grisu3" , Benchmarks::grisu3<T> , std::is_same_v<T, double> };
335-
args[Benchmarks::SWIFT_DTOA] = { "SwiftDtoa" , Benchmarks::swiftDtoa<T> , SWIFT_LIB_SUPPORTED };
336-
args[Benchmarks::YY_DOUBLE] = { "yy_double" , Benchmarks::yy_double<T> , YY_DOUBLE_SUPPORTED && std::is_same_v<T, double> };
337-
return args;
317+
std::array<BenchArgs<T>, Benchmarks::COUNT> initArgs(size_t fixed_size, bool use_errol = false) {
318+
if (fixed_size == 0) { // shortest length representation
319+
std::array<BenchArgs<T>, Benchmarks::COUNT> args;
320+
args[Benchmarks::DRAGON4] = { "dragon4" , Benchmarks::dragon4<T> , true , 10 };
321+
args[Benchmarks::ERROL3] = { "errol3" , Benchmarks::errol3<T> , ERROL_SUPPORTED && use_errol };
322+
args[Benchmarks::TO_STRING] = { "std::to_string" , Benchmarks::to_string<T> , true };
323+
args[Benchmarks::FMT_FORMAT] = { "fmt::format" , Benchmarks::fmt_format<T> , true };
324+
args[Benchmarks::NETLIB] = { "netlib" , Benchmarks::netlib<T> , NETLIB_SUPPORTED && std::is_same_v<T, double>, 10 };
325+
args[Benchmarks::SNPRINTF] = { "snprintf" , Benchmarks::snprintf<T> , true };
326+
args[Benchmarks::GRISU2] = { "grisu2" , Benchmarks::grisu2<T> , std::is_same_v<T, double> };
327+
args[Benchmarks::GRISU_EXACT] = { "grisu_exact" , Benchmarks::grisu_exact<T> , true };
328+
args[Benchmarks::SCHUBFACH] = { "schubfach" , Benchmarks::schubfach<T> , true };
329+
args[Benchmarks::DRAGONBOX] = { "dragonbox" , Benchmarks::dragonbox<T> , true };
330+
args[Benchmarks::RYU] = { "ryu" , Benchmarks::ryu<T> , true };
331+
args[Benchmarks::TEJU_JAGUA] = { "teju_jagua" , Benchmarks::teju_jagua<T> , true };
332+
args[Benchmarks::DOUBLE_CONVERSION] = { "double_conversion" , Benchmarks::double_conversion<T> , true };
333+
args[Benchmarks::ABSEIL] = { "abseil" , Benchmarks::abseil<T> , ABSEIL_SUPPORTED };
334+
args[Benchmarks::STD_TO_CHARS] = { "std::to_chars" , Benchmarks::std_to_chars<T> , TO_CHARS_SUPPORTED };
335+
args[Benchmarks::GRISU3] = { "grisu3" , Benchmarks::grisu3<T> , std::is_same_v<T, double> };
336+
args[Benchmarks::SWIFT_DTOA] = { "SwiftDtoa" , Benchmarks::swiftDtoa<T> , SWIFT_LIB_SUPPORTED };
337+
args[Benchmarks::YY_DOUBLE] = { "yy_double" , Benchmarks::yy_double<T> , YY_DOUBLE_SUPPORTED && std::is_same_v<T, double> };
338+
return args;
339+
} else { // fixed-length representation
340+
throw std::runtime_error("fixed length representation not yet implemented");
341+
}
338342
};
339343

340344
} // namespace Benchmarks

benchmarks/benchmark.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,8 @@ int main(int argc, char **argv) {
147147
options.add_options()
148148
("f,file", "File name.",
149149
cxxopts::value<std::string>()->default_value(""))
150+
("F,fixed", "Fixed-point representation.",
151+
cxxopts::value<size_t>()->default_value("0"))
150152
("v,volume", "Volume (number of floats generated).",
151153
cxxopts::value<size_t>()->default_value("100000"))
152154
("m,model", "Random Model.",
@@ -198,10 +200,11 @@ int main(int argc, char **argv) {
198200
std::variant<std::array<BenchArgs<float>, Benchmarks::COUNT>,
199201
std::array<BenchArgs<double>, Benchmarks::COUNT>> algorithms;
200202
const bool errol = result["errol"].as<bool>();
203+
const size_t fixed_size = result["fixed"].as<size_t>();
201204
if (single)
202-
algorithms = Benchmarks::initArgs<float>(errol);
205+
algorithms = Benchmarks::initArgs<float>(fixed_size, errol);
203206
else
204-
algorithms = Benchmarks::initArgs<double>(errol);
207+
algorithms = Benchmarks::initArgs<double>(fixed_size, errol);
205208

206209
if(repeat > 0) {
207210
fmt::println("# forcing repeat count to {}", repeat);
@@ -233,6 +236,7 @@ int main(int argc, char **argv) {
233236
fmt::println("\nEXAMPLES:");
234237
fmt::println(" ./benchmark --single # Run benchmark with single precision (float)");
235238
fmt::println(" ./benchmark --file=data/canada.txt # Run benchmark using numbers from a file");
239+
fmt::println(" ./benchmark --fixed=10 # Test fixed-point representation instead of shortest length");
236240
fmt::println(" ./benchmark --test # Test correctness instead of performance");
237241
fmt::println(" ./benchmark --volume=1000 --model=uniform # Generate 1000 uniform random numbers");
238242
fmt::println(" ./benchmark --algo-filter=ryu,grisu # Only test algorithms containing 'ryu' or 'grisu'");

benchmarks/random_generators.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@ template <typename T>
3333
struct integer_uniform_generator : float_number_generator<T> {
3434
std::random_device rd;
3535
std::mt19937_64 gen;
36-
std::uniform_int_distribution<uint64_t> dis;
37-
explicit integer_uniform_generator(uint64_t a = 0, uint64_t b = 1)
36+
std::uniform_int_distribution<long> dis;
37+
explicit integer_uniform_generator(long a = LONG_MIN, long b = LONG_MAX)
3838
: rd(), gen(rd()), dis(a, b) {}
3939
std::string describe() override {
4040
return std::string(

0 commit comments

Comments
 (0)