tests/scripts/test_cpu_kernel_bench.py:42 asserts
self.assertGreater(got["timing"]["calls_per_sample"], 1)
and that is not a property of the code under test. It is a property of how fast the machine is.
The mechanism
examples/cpu_kernel_bench/main.cpp:663-670 calibrates by doubling:
size_t calls_per_sample = 1;
for (;;) {
const auto begin = Clock::now();
for (size_t i = 0; i < result.calls_per_sample; ++i) fixture.Run();
const auto end = Clock::now();
const double ns = ...;
if (ns >= std::max(2.0e6, 1000.0 * overhead) || result.calls_per_sample >= (1U << 20)) break;
result.calls_per_sample *= 2;
}
It starts at 1 and doubles until ONE SAMPLE takes at least 2 ms. So calls_per_sample == 1 is the correct output whenever a single call already fills the 2 ms budget. Under ThreadSanitizer instrumentation the kernel runs several times slower, one call clears 2 ms on the first iteration, the loop breaks immediately, and the assertion fails on the calibrator working exactly as designed.
Observed
sanitize-cpu (thread) on PR #1856, job 97470564992:
596/606 Test #596: test_cpu_kernel_bench_cli ...***Failed 0.17 sec
FAIL: test_json_schema_and_deterministic_checksum
File "tests/scripts/test_cpu_kernel_bench.py", line 42
self.assertGreater(got["timing"]["calls_per_sample"], 1)
AssertionError: 1 not greater than 1
Zero WARNING: ThreadSanitizer lines in the whole job — no race was detected. The sanitizer lane failed on a timing assertion, not on a finding.
Not attributable to the pull request that surfaced it
PR #1856 changes zero files matching kernel_bench, and zero C++ files at all — its diff is .agents/, two scripts/ltx25-* files and one tests/scripts/ suite. The assertion is byte-identical on main. Two of the last three completed main runs had no failing jobs, so the lane is normally green; this is latent and fires when the runner is slow enough, which under tsan is most of the time it is unlucky.
What the assertion should be
Do not weaken it to >= 1, which asserts nothing — the field is initialised to 1. Assert the PROPERTY the calibrator guarantees instead:
calls_per_sample is a power of two (it only ever doubles), and
- the reported sample duration met the floor:
median_ns >= max(2.0e6, 1000 * overhead) or calls_per_sample == 1 << 20 (the cap).
That holds on a fast machine and a slow one, and it still reds a calibrator that stopped early, which is what the current line is presumably reaching for.
Owner
Not owned by an active row. Filed from #1743 / PR #1856 work, where it appeared as an unexplained sanitize-cpu (thread) red on a change containing no C++. Whoever owns examples/cpu_kernel_bench should take it; it needs no GPU and no lease.
tests/scripts/test_cpu_kernel_bench.py:42assertsand that is not a property of the code under test. It is a property of how fast the machine is.
The mechanism
examples/cpu_kernel_bench/main.cpp:663-670calibrates by doubling:It starts at 1 and doubles until ONE SAMPLE takes at least 2 ms. So
calls_per_sample == 1is the correct output whenever a single call already fills the 2 ms budget. Under ThreadSanitizer instrumentation the kernel runs several times slower, one call clears 2 ms on the first iteration, the loop breaks immediately, and the assertion fails on the calibrator working exactly as designed.Observed
sanitize-cpu (thread)on PR #1856, job 97470564992:Zero
WARNING: ThreadSanitizerlines in the whole job — no race was detected. The sanitizer lane failed on a timing assertion, not on a finding.Not attributable to the pull request that surfaced it
PR #1856 changes zero files matching
kernel_bench, and zero C++ files at all — its diff is.agents/, twoscripts/ltx25-*files and onetests/scripts/suite. The assertion is byte-identical onmain. Two of the last three completedmainruns had no failing jobs, so the lane is normally green; this is latent and fires when the runner is slow enough, which under tsan is most of the time it is unlucky.What the assertion should be
Do not weaken it to
>= 1, which asserts nothing — the field is initialised to 1. Assert the PROPERTY the calibrator guarantees instead:calls_per_sampleis a power of two (it only ever doubles), andmedian_ns >= max(2.0e6, 1000 * overhead)orcalls_per_sample == 1 << 20(the cap).That holds on a fast machine and a slow one, and it still reds a calibrator that stopped early, which is what the current line is presumably reaching for.
Owner
Not owned by an active row. Filed from #1743 / PR #1856 work, where it appeared as an unexplained
sanitize-cpu (thread)red on a change containing no C++. Whoever ownsexamples/cpu_kernel_benchshould take it; it needs no GPU and no lease.