如何解决使用 [[unlikely/likely]] 属性时,MSVC C++ 编译器在相同代码的不同版本上提供不一致的性能
我只是在尝试使用 [[unlikely/likely]]
编译时可用的 /std:c++latest
分支提示。
为此,我使用了 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0479r0.html 在底部 Appendix A
#include <array>
#include <cstdint>
#include <random>
#include <chrono>
std::uint16_t clamp(int i) {
if (i < 0) [[unlikely]] {
return 0;
}
else if (i > 0xFFFF) {
return 0xFFFFu;
}
return i;
}
int main() {
std::mt19937 gen(42);
std::bernoulli_distribution d(.001),up_down(.5);
std::vector<int> data;
for (std::size_t i = 0; i != 1000000; ++i) {
if (d(gen)) {
data.push_back(up_down(gen) ? -1 : 0xFFFFF);
}
else {
data.push_back(1);
}
}
auto Prev = std::chrono::high_resolution_clock::Now();
std::uint32_t result = 0;
for (int i = 0; i != 10000; ++i) {
for (auto val : data) {
result += clamp(val);
}
}
auto After = std::chrono::high_resolution_clock::Now();
std::chrono::duration<double> Elapsed = After - Prev;
std::chrono::milliseconds Time = std::chrono::duration_cast<std::chrono::milliseconds>(Elapsed);
std::cout << (Time.count()) << '\n';
return result > 5 ? 1 : 2;
}
请注意,所有编译都是在 x64 发布模式下使用 /O2
在最新版本的 Visual Studio 2019 (16.10.3) 和 Intel(R) Core(TM) i7-7700HQ 2.8Ghz cpu 上完成的。
然后我测试了如何使用 [[unlikely]]
、[[likely]]
并且没有属性会影响所用的时间。
首先测试 [[unlikely]]]
我发现在我的系统上运行大约需要 6750 毫秒。然后我测试了 [[likely]]
,它也需要大约 6750 毫秒才能运行。起初我认为这可能只是因为属性是提示,因此编译器可以忽略它们。然后我测试了 no attribute
(只是不使用 [[unlikely/likely]]
)并且代码在大约 9000 毫秒内运行。如果编译器之前忽略了这些属性,那么它应该给出 6750 毫秒的相同时间,对吗?
然后我回去测试 [[likely]]
,发现它现在运行了大约 9000 毫秒???在这一点上,我真的很困惑,所以回去检查 [[unlikely]]
并发现它在 ~6750 毫秒内运行。再次检查 [[likely]]
它现在运行在 ~6750 毫秒。
这太奇怪了,在对生成的程序集进行一些挖掘之后,我发现有时生成的程序集会超过 6000 行,有时会在 2000 行以下加上后续编译???对于相同代码的后续编译也是如此。在谷歌搜索之后,我发现了一条奇怪的评论:
Why godbolt generate different asm output than my actual asm code in Visual Studio?
回到我的实验,我根据编译顺序发现了这些结果:
-
No attribute
=>[[unlikely]]
=>[[likely]]
~9000ms => ~6750ms => ~6750ms 并继续 ~6750ms 进行后续
[[likely]]
编译并切换回[[unlikely]]
获得相同结果,而切换回No attribute
获得 ~9000ms . -
No attribute
=>[[likely]]
=>[[unlikely]]
~9000ms => ~9000ms => ~9000ms 和后续的
[[unlikely]]
编译得到相同的 ~9000ms 结果,这在切换到[[likely]]
时是一样的,并且只表现出第一个序列中显示的行为编译No attribute
后编译时。
为了确保这不是一些随机的怪癖,我在每一步都没有编译的情况下多次运行这些测试(只需运行从文件资源管理器生成的 .exe 文件)并获得一致的结果。我什至从每个不同的编译序列中保存了每个不同的 .exe 文件,然后再次运行它们,得到了同样奇怪的结果。
我还没有比较 .exe 字节,但我想避免这样做,因为我不是很精通那个领域"^-^
我是否遗漏了什么,这是一个错误吗?一切都如此不一致,这似乎很奇怪。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。