为何使用 inline 函数并不能达到真正 inline 写代码的性能?

2022-11-26 10:20:53 +08:00
 xwu

使用 inline 关键字定义函数

#include <chrono>
#include <iostream>

using namespace std;
using namespace chrono;

inline int minus_ab(int a, int b) {
    return a - b;
}

inline int add_ab(int a, int b) {
    return a + b;
}

inline int multi_ab(int a, int b) {
    return a * b;
}


int main(int argc, char** argv){
    auto tick = high_resolution_clock::now();
    int x;
    int max_kRound = atoi(argv[1]);
    int a=1, b=2;
    for (int i=0; i<max_kRound*1000; i++) {
        x = add_ab(a, b);
        x = minus_ab(a, b);
        x = multi_ab(a, b);
    }
    auto tock = high_resolution_clock::now();
    auto duration = duration_cast<microseconds>(tock - tick);
    cout << "max round= " << max_kRound << "k" << endl;
    cout << duration.count() / 1000 << " ms" << endl;
}

真正 inline 的写代码

...
    for (int i=0; i<max_kRound*1000; i++) {
        x = a+b;
        x = a-b;
        x = a*b;
    }
... 

上面两个程序我分别设置循环数为 1e9 ,结果第一个程序大概是第二个的三倍时间。我理解的 inline 是在编译阶段把函数中的代码拷贝到函数调用出,所以两个代码应该是等价的,为什么性能上有差别?

另外我还尝试去掉 inline 结果速度比用 inline 还快。是我对 inline 的理解不对吗?

3263 次点击
所在节点    C++
16 条回复
yianing
2022-11-26 10:30:08 +08:00
inline 大多还是用作多次定义用的,但是有 static 一般也不用 inline ,内联这个语意要看编译器,https://en.cppreference.com/w/cpp/language/inline
wudicgi
2022-11-26 11:16:16 +08:00
先看看汇编,是否真的把代码内联进去了。或者是汇编代码有什么其他差异

inline 修饰符本身不是强制的, MSVC 有 __forceinline, gcc 有 __attribute__((always_inline)) 修饰符强制内联
AlohaV2
2022-11-26 11:23:32 +08:00
加-O3 再试试
ivan_wl
2022-11-26 11:26:49 +08:00
你这个代码里对 x 一番操作,最后又没有使用 x ,这个 x 可能会被优化掉的吧
disk
2022-11-26 11:52:01 +08:00
inline 只是建议,你这段代码不好,不开优化不会展开,开了整个循环直接被优化掉
codehz
2022-11-26 11:52:31 +08:00
inline 的语义早就改了,甚至和 inline 这个词本来的意思都不一样了,强制或者建议两个都不是,唯一的用途就是打破 ODR 可以多次定义,正因为如此,inline 也可以被用在变量上了
Opportunity
2022-11-26 11:53:08 +08:00
都是巧合,你这代码开 o2 就把循环体全优化掉了,实际就是给 atoi 计时
agagega
2022-11-26 12:01:15 +08:00
inline 更多的意义已经是改变编译器处理多个同名函数的方式了,具体有没有 inline ,效果变好没有,看汇编吧
xtreme1
2022-11-26 12:19:01 +08:00
当前的主流编译器都会忽略 inline 作为指令(建议)生成内联函数这个原始含义了.
真正的含义楼上都说完了
msg7086
2022-11-26 12:19:14 +08:00
1.你理解的当然不对。
2.纠结优化前的代码性能没有什么意义,谁发布软件会发非优化版的。优化后全变成常数根本测不出性能差距来。

你这些代码就算不会被优化掉,也会被优化成 simd 展开,到最后根本不会去执行加减乘除,都是跑 avx2 指令去了。
minami
2022-11-26 12:21:10 +08:00
inline 现在很大程度上取决于编译器怎么想,想要真正 inline ,还是用宏吧
icyalala
2022-11-26 12:27:45 +08:00
虽然但是。。
像上面说的,开了优化就没区别了。想要了解编译器怎么想的,去看看 https://godbolt.org/z/ee3ahjsx9
但你要想在没有优化时也 inline ,那就加个 __attribute__((always_inline))
Tanix2
2022-11-26 13:40:17 +08:00
第一个 diff 窗口是加 inline 和不加 inline 的汇编对比,第二个对比窗口是加 inline 和删掉函数手动 inline 的对比,优化等级都是-O1 ,main 函数是完全一样的: https://godbolt.org/z/xfxa8x14M
现代的编译器已经足够智能了,inline 的含义也发生了变化,一般的建议是只对可能出现在多个编译单元的函数用 inline ,比如定义在头文件中的函数。
dynos01
2022-11-26 18:40:35 +08:00
https://en.cppreference.com/w/cpp/language/inline

Since this meaning of the keyword inline is non-binding, compilers are free to use inline substitution for any function that's not marked inline, and are free to generate function calls to any function marked inline. Those optimization choices do not change the rules regarding multiple definitions and shared statics listed above.

编译器并不是见到 inline 就一定会内联一个函数。多数情况下,编译器比程序员更了解一个函数适合不适合 inline ,所以就不用操心这个问题了。
Jooooooooo
2022-11-26 21:45:41 +08:00
因为你测性能的代码完全是错的.
dazhangpan
2022-11-27 18:09:34 +08:00
现在还有对底层性能优化感兴趣的人啊 XD

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/898026

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX