这是一段看似非常特殊的C++代码.出于某种奇怪的原因,奇迹般地对数据进行排序使得代码几乎快了六倍.
#include <algorithm>
#include <ctime>
#include <iostream>
int main()
{
// Generate data
const unsigned arraySize = 32768;
int data[arraySize];
for (unsigned c = 0; c < arraySize; ++c)
data[c] = std::rand() % 256;
// !!! With this, the next loop runs faster.
std::sort(data, data + arraySize);
// Test
clock_t start = clock();
long long sum = 0;
for (unsigned i = 0; i < 100000; ++i)
{
// Primary loop
for (unsigned c = 0; c < arraySize; ++c) …Run Code Online (Sandbox Code Playgroud) 我一直在挖掘Linux内核的某些部分,发现这样的调用:
if (unlikely(fd < 0))
{
/* Do something */
}
Run Code Online (Sandbox Code Playgroud)
要么
if (likely(!err))
{
/* Do something */
}
Run Code Online (Sandbox Code Playgroud)
我找到了它们的定义:
#define likely(x) __builtin_expect((x),1)
#define unlikely(x) __builtin_expect((x),0)
Run Code Online (Sandbox Code Playgroud)
我知道它们是为了优化,但它们是如何工作的?使用它们可以预期性能/尺寸减少多少?至少在瓶颈代码中(当然在用户空间中)是否值得麻烦(并且可能失去可移植性).
我遇到了#define他们使用的一个__builtin_expect.
文件说:
内置功能:
long __builtin_expect (long exp, long c)您可以使用
__builtin_expect为编译器提供分支预测信息.一般来说,你应该更喜欢使用实际的配置文件反馈(-fprofile-arcs),因为程序员在预测程序实际执行情况方面是非常糟糕的.但是,有些应用程序难以收集此数据.返回值是值
exp,它应该是一个整数表达式.内置的语义是预期的exp == c.例如:Run Code Online (Sandbox Code Playgroud)if (__builtin_expect (x, 0)) foo ();表示我们不打算打电话
foo,因为我们预计x会为零.
那么为什么不直接使用:
if (x)
foo ();
Run Code Online (Sandbox Code Playgroud)
而不是复杂的语法__builtin_expect?
我知道内核非常使用likely和unlikely宏.宏的文档位于内置函数:long __builtin_expect(long exp,long c).但他们并没有真正讨论细节.
究竟如何做一个编译器处理likely(x)和__builtin_expect((x),1)?
它是由代码生成器还是优化器处理的?
它取决于优化级别吗?
代码生成的示例是什么?
built-in ×2
c ×2
gcc ×2
linux ×2
optimization ×2
c++ ×1
java ×1
linux-kernel ×1
macros ×1
performance ×1