函数指针比内联函数运行得更快.为什么?

Has*_*dev 5 c++ performance function-pointers inline-functions

我在计算机上运行了我的基准测试(英特尔i3-3220 @ 3.3GHz,Fedora 18),并得到了非常意外的结果.函数指针实际上比内联函数快一点.

码:

#include <iostream>
#include <chrono>
inline short toBigEndian(short i)
{
    return (i<<8)|(i>>8);
}
short (*toBigEndianPtr)(short i)=toBigEndian;
int main()
{  
    std::chrono::duration<double> t;
    int total=0;
    for(int i=0;i<10000000;i++)
    {
        auto begin=std::chrono::high_resolution_clock::now();
        short a=toBigEndian((short)i);//toBigEndianPtr((short)i);
        total+=a;
        auto end=std::chrono::high_resolution_clock::now();
        t+=std::chrono::duration_cast<std::chrono::duration<double>>(end-begin);
    }
    std::cout<<t.count()<<", "<<total<<std::endl;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

用.编译

g++ test.cpp -std=c++0x -O0
Run Code Online (Sandbox Code Playgroud)

'toBigEndian'循环总是在0.26-0.27秒左右完成,而'toBigEndianPtr'则需要0.21-0.22秒.

更奇怪的是,当我删除'total'时,函数指针在0.35-0.37秒处变慢,而内联函数在约0.27-0.28秒.

我的问题是:

当'total'存在时,为什么函数指针比内联函数更快?

Arn*_*rtz 7

简短回答:事实并非如此.

  • 你用-O0编译,没有优化(很多).如果没有优化,你就不会说"快"了,因为未经优化的代码没有那么快.
  • 你拿地址toBigEndian,这会阻止内联.inline无论如何,关键字是编译器的提示,它可能会或可能不会跟随.你尽力遵循这个提示.

所以,为了给你的测量任何意义,

  • 优化您的代码
  • 使用两个函数,做同样的事情,一个内联,另一个采取内容


Has*_*dev 2

哦,糟糕(我需要审查这里的脏话吗?),我发现了。这在某种程度上与循环内的时间有关。当我将其移到外面时,如下所示,

#include <iostream>
#include <chrono>
inline short toBigEndian(short i)
{
    return (i<<8)|(i>>8);
}

short (*toBigEndianPtr)(short i)=toBigEndian;
int main()
{  
    int total=0;
    auto begin=std::chrono::high_resolution_clock::now();
    for(int i=0;i<100000000;i++)
    {
        short a=toBigEndianPtr((short)i);
        total+=a;
    }
    auto end=std::chrono::high_resolution_clock::now();
    std::cout<<std::chrono::duration_cast<std::chrono::duration<double>>(end-begin).count()<<", "<<total<<std::endl;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

结果正如其应有的那样。内联 0.08 秒,指针 0.20 秒。抱歉打扰你们了。