- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
在 this文章中,描述了一种在 gcc 中移动错误代码的技术,以帮助尽可能地优化热路径的大小。这方面的一个例子是:
#define unlikely(x) __builtin_expect (!!(x), 0)
bool testForTerriblyUnlikelyEdgeCase() {
//test for error condition here
}
void example() {
if (unlikely(testForTerriblyUnlikelyEdgeCase())) {
[&]() __attribute__((noinline,cold)) {
//error handling code here
}();
}
}
这是一项很棒的技术,但需要大量的样板文件。包装它以尽可能减少样板的最佳方法是什么?理想情况下 C++14 兼容允许特定于 gcc 的功能。
最佳答案
想到了两种方法:
__attribute__
语法):
template <typename Fn>
[[gnu::cold]] [[gnu::noinline]]
void cold_path(Fn&& fn)
{
std::forward<Fn>(fn)();
}
您还可以扩展此解决方案以利用要测试的条件,例如:
template <typename Expr, typename Fn>
void cold_path_if(Expr&& expr, Fn&& fn)
{
if (unlikely(std::forward<Expr>(expr))) {
cold_path(std::forward<Fn>(fn));
}
}
把它们放在一起,你有:
void example() {
cold_path_if(testForTerriblyUnlikelyEdgeCase(), [&]{
std::cerr << "Oh no, something went wrong" << std::endl;
std::abort();
});
}
这是它在
Compiler Explorer 上的样子.
// A type implicitly convertible to any function type, used to make the
// macro below not require '()' to invoke the lambda
namespace detail {
class invoker
{
public:
template <typename Fn>
/* IMPLICIT */ invoker(Fn&& fn){ fn(); }
};
}
这是作为一个可从函数隐式转换的类完成的,因此您可以编写类似
detail::invoker foo = []{ ... }
的代码。 .然后我们想把定义的第一部分带到捕获,并将它包装成一个宏。
__COUNTER__
名称的宏;但这是非标准的:
#define COLD_HANDLER ::detail::invoker some_unique_name ## __COUNTER__ = [&]() __attribute__((noinline,cold))
这只是将自动调用程序的创建包装起来,直到定义 lambda 为止,因此您需要做的就是编写
COLD_HANDLER { ... }
使用现在看起来像:
void example() {
if (unlikely(testForTerriblyUnlikelyEdgeCase())) {
COLD_HANDLER {
//error handling code here
};
}
}
这是
compiler explorer 上的示例
std::fprintf
而不是
stds::cerr
,因此组件更小且更易于比较)
Bonus Question: Is the unlikely(...) in the if statement redundant since the lambda is explicitly marked cold?
__attribute__((cold))
似乎表明所有导致冷函数的分支都被标记为
unlikely
,这应该使用
unlikely
宏是多余的和不必要的——尽管拥有它应该不会有什么坏处。
The cold attribute is used to inform the compiler that a function is unlikely executed. The function is optimized for size rather than speed and on many targets it is placed into special subsection of the text section so all cold functions appears close together improving code locality of non-cold parts of program. The paths leading to call of cold functions within code are marked as unlikely by the branch prediction mechanism. It is thus useful to mark functions used to handle unlikely conditions, such as perror, as cold to improve optimization of hot functions that do call marked functions in rare occasions.
关于c++ - 在 C++ 中样板化 "cold/never_inline"错误处理技术的最佳方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62761997/
在 this文章中,描述了一种在 gcc 中移动错误代码的技术,以帮助尽可能地优化热路径的大小。这方面的一个例子是: #define unlikely(x) __builtin_expect (!!
我是一名优秀的程序员,十分优秀!