| 94 | } |
| 95 | |
| 96 | auto main(int argc, char** argv) -> int |
| 97 | { |
| 98 | if (argc < 5) |
| 99 | { |
| 100 | std::cerr << "Usage: example.benchmark.fibonacci cutoff n nruns {tbb|static}" << std::endl; |
| 101 | return -1; |
| 102 | } |
| 103 | |
| 104 | // skip 'warmup' iterations for performance measurements |
| 105 | static constexpr size_t warmup = 1; |
| 106 | |
| 107 | long cutoff = std::strtol(argv[1], nullptr, 10); |
| 108 | long n = std::strtol(argv[2], nullptr, 10); |
| 109 | std::size_t nruns = std::strtoul(argv[3], nullptr, 10); |
| 110 | |
| 111 | if (nruns <= warmup) |
| 112 | { |
| 113 | std::cerr << "nruns should be >= " << warmup << std::endl; |
| 114 | return -1; |
| 115 | } |
| 116 | |
| 117 | std::variant<exec::tbb::tbb_thread_pool, exec::static_thread_pool> pool; |
| 118 | |
| 119 | if (argv[4] == std::string_view("tbb")) |
| 120 | { |
| 121 | pool.emplace<exec::tbb::tbb_thread_pool>(static_cast<int>(std::thread::hardware_concurrency())); |
| 122 | } |
| 123 | else |
| 124 | { |
| 125 | pool.emplace<exec::static_thread_pool>(std::thread::hardware_concurrency(), |
| 126 | exec::bwos_params{}, |
| 127 | exec::get_numa_policy()); |
| 128 | } |
| 129 | |
| 130 | std::vector<unsigned long> times; |
| 131 | long result; |
| 132 | for (unsigned long i = 0; i < nruns; ++i) |
| 133 | { |
| 134 | auto snd = std::visit([&](auto&& pool) |
| 135 | { return fib_sender(fib_s{cutoff, n, pool.get_scheduler()}); }, |
| 136 | pool); |
| 137 | |
| 138 | auto time = measure<std::chrono::milliseconds>( |
| 139 | [&] { std::tie(result) = stdexec::sync_wait(std::move(snd)).value(); }); |
| 140 | times.push_back(static_cast<unsigned int>(time)); |
| 141 | } |
| 142 | |
| 143 | std::cout << "Avg time: " |
| 144 | << (std::accumulate(times.begin() + warmup, times.end(), 0u) / (times.size() - warmup)) |
| 145 | << "ms. Result: " << result << std::endl; |
| 146 | } |
nothing calls this directly
no test coverage detected