Merge pull request #433 from fastfloat/benchmark-rounds-to-nearest

Benchmark fast_float with and without FASTFLOAT_ROUNDS_TO_NEAREST
This commit is contained in:
Daniel Lemire 2026-11-09 12:35:25 -05:00 committed by GitHub
commit 8ec59686a1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 68 additions and 1 deletions

View File

@ -681,6 +681,10 @@ cmake --build build
Importantly, by default, the benchmark is built in Release mode.
The lines marked `assume nearest` time the same code compiled with
`FASTFLOAT_ROUNDS_TO_NEAREST` (see [Assuming the default rounding
mode](#assuming-the-default-rounding-mode)).
The instructions are similar under Windows.
Under Linux and macOS, it is recommended to run the benchmarks in a privileged manner to get access

View File

@ -8,7 +8,7 @@ FetchContent_Declare(
FetchContent_MakeAvailable(counters)
add_executable(realbenchmark benchmark.cpp)
add_executable(realbenchmark benchmark.cpp benchmark_rtn.cpp)
target_link_libraries(realbenchmark PRIVATE counters::counters)
add_executable(bench_ip bench_ip.cpp)
add_executable(bench_uint16 bench_uint16.cpp)

View File

@ -50,6 +50,12 @@ double findmax_fastfloat32(std::vector<std::basic_string<CharT>> &s) {
return answer;
}
// Defined in benchmark_rtn.cpp, with FASTFLOAT_ROUNDS_TO_NEAREST.
template <typename CharT>
double findmax_fastfloat64_rtn(std::vector<std::basic_string<CharT>> &s);
template <typename CharT>
double findmax_fastfloat32_rtn(std::vector<std::basic_string<CharT>> &s);
counters::event_collector collector{};
#ifdef USING_COUNTERS
@ -193,8 +199,12 @@ void process(std::vector<std::string> &lines, size_t volume) {
std::cout << "ASCII volume = " << volumeMB << " MB " << std::endl;
pretty_print(volume, lines.size(), "fastfloat (64)",
time_it_ns(lines, findmax_fastfloat64<char>, repeat));
pretty_print(volume, lines.size(), "fastfloat (64, assume nearest)",
time_it_ns(lines, findmax_fastfloat64_rtn<char>, repeat));
pretty_print(volume, lines.size(), "fastfloat (32)",
time_it_ns(lines, findmax_fastfloat32<char>, repeat));
pretty_print(volume, lines.size(), "fastfloat (32, assume nearest)",
time_it_ns(lines, findmax_fastfloat32_rtn<char>, repeat));
std::vector<std::u16string> lines16 = widen(lines);
volume = 2 * volume;
@ -202,8 +212,12 @@ void process(std::vector<std::string> &lines, size_t volume) {
std::cout << "UTF-16 volume = " << volumeMB << " MB " << std::endl;
pretty_print(volume, lines.size(), "fastfloat (64)",
time_it_ns(lines16, findmax_fastfloat64<char16_t>, repeat));
pretty_print(volume, lines.size(), "fastfloat (64, assume nearest)",
time_it_ns(lines16, findmax_fastfloat64_rtn<char16_t>, repeat));
pretty_print(volume, lines.size(), "fastfloat (32)",
time_it_ns(lines16, findmax_fastfloat32<char16_t>, repeat));
pretty_print(volume, lines.size(), "fastfloat (32, assume nearest)",
time_it_ns(lines16, findmax_fastfloat32_rtn<char16_t>, repeat));
}
void fileload(std::string filename) {

View File

@ -0,0 +1,49 @@
// The same parsing loops as findmax_fastfloat64 and findmax_fastfloat32 in
// benchmark.cpp, but compiled with FASTFLOAT_ROUNDS_TO_NEAREST: fast_float
// assumes the default rounding mode and skips its check before the fast path.
//
// We rename the fast_float namespace in this file. Otherwise, the two
// configurations would define the same inline functions differently, and the
// linker could keep either one (an ODR violation).
#include <stdexcept>
#include <string>
#include <vector>
#define FASTFLOAT_ROUNDS_TO_NEAREST
#define fast_float fast_float_rtn
#include "fast_float/fast_float.h"
template <typename CharT>
double findmax_fastfloat64_rtn(std::vector<std::basic_string<CharT>> &s) {
double answer = 0;
double x = 0;
for (auto &st : s) {
auto [p, ec] = fast_float::from_chars(st.data(), st.data() + st.size(), x);
if (p == st.data()) {
throw std::runtime_error("bug in findmax_fastfloat_rtn");
}
answer = answer > x ? answer : x;
}
return answer;
}
template <typename CharT>
double findmax_fastfloat32_rtn(std::vector<std::basic_string<CharT>> &s) {
float answer = 0;
float x = 0;
for (auto &st : s) {
auto [p, ec] = fast_float::from_chars(st.data(), st.data() + st.size(), x);
if (p == st.data()) {
throw std::runtime_error("bug in findmax_fastfloat_rtn");
}
answer = answer > x ? answer : x;
}
return answer;
}
template double findmax_fastfloat64_rtn<char>(std::vector<std::string> &);
template double findmax_fastfloat32_rtn<char>(std::vector<std::string> &);
template double
findmax_fastfloat64_rtn<char16_t>(std::vector<std::u16string> &);
template double
findmax_fastfloat32_rtn<char16_t>(std::vector<std::u16string> &);