C++ 基准C`std::isdigit`
我试图从标题C++ 基准C`std::isdigit`,c++,assembly,compiler-optimization,google-benchmark,C++,Assembly,Compiler Optimization,Google Benchmark,我试图从标题cctype中对函数进行基准测试(为了清楚起见,这是从C继承的函数) 代码片段如下所示: void BM_IsDigit_C(::benchmark::State& state) { const char c = GenerateRandomChar(); for (auto _ : state) { ::benchmark::DoNotOptimize(std::isdigit(static_cast<unsigned char>(c)));
cctype
中对函数进行基准测试(为了清楚起见,这是从C继承的函数)
代码片段如下所示:
void BM_IsDigit_C(::benchmark::State& state) {
const char c = GenerateRandomChar();
for (auto _ : state) {
::benchmark::DoNotOptimize(std::isdigit(static_cast<unsigned char>(c)));
}
}
BENCHMARK(BM_IsDigit_C);
但由于空循环,它被完全忽略:
68:sub$0x1,%rbx您可以,但是现在度量包括了(不公平的,IMO)不是isdigit本身固有的加载和存储。还显示:仔细决定是否要知道延迟或吞吐量(或两者),对于小块代码,它们往往非常不同。@JesperJuhl但显然不是这样,否则调用isdigit
有什么意义?它不会忽略isdigit()
,它只是将它从循环中提升出来,因为您使用DoNotOptimize
的方式。您需要让编译器忘记c
是循环不变量,并在每次迭代中具体化isdigit(c)
结果。这可能需要一个tmp VAR和两个Dono优化,我不确定。正如harold所说,时间安排可能没有您希望的那么有意义,因为您的实际用例将对前端吞吐量或后端延迟敏感,而这与哪一个很重要。(可能不是后端ALU端口压力)此外,如果您在isdigit
上分支,它只是sub
或lea
/macro fusedcmp+jcc
=2个总UOP。如果要进行分支,则无需在寄存器中具体化布尔值。(对于更简单的ASCII版本来说,这种差异更为重要,而不是在更高的代码点也是数字字符的情况下进行表格查找的区域设置感知版本。)
movzbl %r13b,%eax
sub $0x30,%eax
cmp $0x9,%eax
setbe %al
movzbl %al,%eax
68: sub $0x1,%rbx <---|
jne 68 ------|