[BUG] Benchmark registration order affects reported outcomes
メンテナーはふだん 1 日以内に返信
まだ誰も着手していません。
評価
- 難易度
- 4/5
- 見積もり時間
- 3〜5日
- 初心者へのやさしさ
- 48/100
- issue の種類
- バグ
- 明瞭さ
- おおむね明確
- 活発さ
- 静か
- 技術スタック
- cpp
- 領域
- performance
調査の方向性
Windows 11 と MSVC 17.14.15 上で、提供された BM_DoWork と BM_DoWork1 の登録シーケンスを再現し、その後、登録順序を変更した場合の結果を比較します。まず、BENCHMARK と KeepRunningBatch 周辺のベンチマーク登録および実行パスを追跡します。順序によって大きな系統的変化が生じなくなるか、または制限事項が明確に文書化されれば完了です。
索引モデルが issue の本文から書いたものです。
説明
Describe the bug
Hello,
I have the following bechmark:
#include <benchmark/benchmark.h>
#include <gtest/gtest.h>
/**
* defines / pre-allocates a std::vector<std::wstring> examples (within g_dataset)
*/
#include "Helpers.h"
#include <chrono>
#include <cstdint>
#include <ranges>
#include <vector>
#include <execution>
#include <codecvt>
std::string DoWork(const std::wstring& input)
{
std::string result(input.size(), '\0');
std::transform(std::execution::par_unseq, std::begin(input), std::end(input), std::begin(result),
[](wchar_t inChar) { return (char)(inChar & 0x0ff); });
return result;
}
std::wstring DoWork1(const std::string& input)
{
std::wstring result(input.size(), L'\0');
std::transform(std::execution::par_unseq, std::begin(input), std::end(input), std::begin(result),
[](wchar_t inChar) { return (wchar_t)(inChar & 0x0ff); });
return result;
}
template <typename InStringT,
typename Fn,
typename OutStringT = std::invoke_result_t<Fn,InStringT>>
void RunOnExamples(const std::vector<InStringT>& examples, Fn&& fn,
std::vector<OutStringT>& results)
{
for (size_t iterations = 0; iterations < examples.size(); iterations++) {
results[iterations] = fn(examples[iterations]);
}
}
static void BM_DoWork(benchmark::State& state)
{
state.PauseTiming();
auto expectedResults = std::vector<std::string>(g_dataset.examples.size());
state.ResumeTiming();
while (state.KeepRunningBatch(g_dataset.examples.size())) {
RunOnExamples(g_dataset.examples, DoWork, expectedResults);
}
state.SetItemsProcessed(state.iterations() * g_dataset.examples.size());
}
static void BM_DoWork1(benchmark::State& state)
{
state.PauseTiming();
auto expectedResults = std::vector<std::wstring>(g_dataset.examples.size());
std::vector<std::string> examples(g_dataset.examples.size());
static std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> myconv;
for (size_t i = 0; i < g_dataset.examples.size(); i++) {
examples[i] = myconv.to_bytes(g_dataset.examples[i]);
}
state.ResumeTiming();
while (state.KeepRunningBatch(g_dataset.examples.size())) {
RunOnExamples(examples, DoWork1, expectedResults);
}
state.SetItemsProcessed(state.iterations() * g_dataset.examples.size());
}
#pragma endregion
#pragma region Run benchmarks
BENCHMARK(BM_DoWork);
BENCHMARK(BM_DoWork);
BENCHMARK(BM_DoWork);
BENCHMARK(BM_DoWork1);
BENCHMARK(BM_DoWork1);
BENCHMARK(BM_DoWork1);
#pragma endregion
The output looks like this - the items_per_second decreases in rather big jumps:
Run on (20 X 2918 MHz CPU s)
CPU Caches:
L1 Data 48 KiB (x10)
L1 Instruction 32 KiB (x10)
L2 Unified 1280 KiB (x10)
L3 Unified 24576 KiB (x1)
------------------------------------------------------------------------------
Benchmark Time CPU Iterations UserCounters...
------------------------------------------------------------------------------
BM_DoWork 86347685 ns 6438 ns 1000000 items_per_second=155.34G/s
BM_DoWork 86352813 ns 10688 ns 1000000 items_per_second=93.5673G/s
BM_DoWork 86358084 ns 15141 ns 1000000 items_per_second=66.0475G/s
BM_DoWork1 86363182 ns 19484 ns 1000000 items_per_second=51.3232G/s
BM_DoWork1 86369707 ns 25062 ns 1000000 items_per_second=39.9002G/s
BM_DoWork1 86378334 ns 32438 ns 1000000 items_per_second=30.8285G/s
If I reorder the benchmarks, the same pattern is observed.
There has been a similar question on StackOverlow a couple of years ago, but it remained unanswered.
System
Which OS, compiler, and compiler version are you using:
- OS: Microsoft Windows 11
- Compiler and version: MSVC 17.14.15
Expected behavior
Registering benchmarks in different order shouldn't affect the measured performance - a deviation of "a couple" percent is expected, but nothing like the steady decreasing in huge jumps.
- 主要言語
- C++
- スター
- 10.5k
- フォーク
- 1.8k
- 平均マージ
- 2日 2時間
- マージ済み PR(30日)
- 30
環境構築
- Dockerfile・Docker Compose ファイルなし
- プルリクエストのテンプレートなし
- コントリビューションガイドを読む
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
google/benchmark のほかの issue
-
[BUG] Confusing title in docs/platform_specific_build_instructions.md対応中かも @skryabae が 29 日前に担当しました。 オープン
難易度 1/5 1時間未満 初心者へのやさしさ 88/100
メンテナーはふだん 1 日以内に返信
-
[BUG] Memory manager counts allocations not part of benchmark再び着手できるかも このイシューのプルリクエストはマージされずにクローズされました。 オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 68/100
google/benchmark#2149 · コメント 5 件 ·
メンテナーはふだん 1 日以内に返信
-
Three small hardening notes from a security review: CSV formula-prefix neutralization, full C0 escaping in the JSON reporter, and type diagnostics in gbench/compare.py対応中かも @Aryan9891 が 7 日前に担当しました。 オープン
難易度 4/5 3〜5日 初心者へのやさしさ 64/100
google/benchmark#2299 · コメント 3 件 ·
メンテナーはふだん 1 日以内に返信
-
[FR] Add native Zig bindings via top-level `bindings/zig`再び着手できるかも このイシューのプルリクエストはマージされずにクローズされました。 オープン
難易度 5/5 1週間以上 初心者へのやさしさ 42/100
google/benchmark#2266 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
難易度 5/5 1週間以上 初心者へのやさしさ 20/100
google/benchmark#2195 · コメント 3 件 ·
メンテナーはふだん 1 日以内に返信
google/benchmark の issue をすべて見る
似ている issue
-
難易度 2/5 1〜3時間 初心者へのやさしさ 66/100
xiaoyifang/goldendict-ng#3148 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 76/100
メンテナーはふだん 4 日以内に返信
-
documentation
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
-
[Bug]: Launching Space Calibrator causes Bluetooth mouse lag due to a 100% duty-cycle BLE scan対応中かも @Yuuki204 が今日担当しました。 オープンbug
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
-
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
メンテナーはふだん 2 日以内に返信