跳至主要內容
  • Hostloc 空間訪問刷分
  • 售賣場
  • 廣告位
  • 賣站?

4563博客

全新的繁體中文 WordPress 網站
  • 首頁
  • 请教一个 C++问题,为什么加了 inline 反而效率降低了
未分類
29 12 月 2020

请教一个 C++问题,为什么加了 inline 反而效率降低了

请教一个 C++问题,为什么加了 inline 反而效率降低了

資深大佬 : zvl0reqglvd 6

老哥们,请教一下下面的程序是因为什么原因造成的?

#include <iostream> #include <chrono> using namespace std;  class Runtime{ private:     std::chrono::high_resolution_clock::time_point _start, _end; public:     Runtime(){  start();     }          void start(){  _start = std::chrono::high_resolution_clock::now();     }     void end() {  _end = std::chrono::high_resolution_clock::now();     }     long long spend() {  return std::chrono::duration_cast<std::chrono::nanoseconds>(_end - _start).count();     }     void printTime() {  end();  std::cout << "time = "     << spend()/1000000 << "/ms = "//毫秒     << spend()/1000 << "/us = "//微秒     << spend() << "/ns" << std::endl;//纳秒     } };  const int N = 1e5; int x[N]; int y[N]; int z[N];  //inline int calc(int a, int b) {     return a + b; }  int main(){     Runtime r;     for (int i=0; i<N; ++i) {  for (int j=0; j<N; ++j) {      for (int k=0; k<N; ++k)   z[i] = calc(y[j], x[k]);         //z[i] = y[j] + x[k];  }     }     r.printTime(); } 

加了 inline 比不加慢一倍,不是说 inline 会减少函数压栈出栈的时间开销,相当于直接在调用点插入代码嘛,但是,实际上开销比不加 inline 慢一倍,不加 inline 的开销和下面注释的那句的开销差不多。感觉很奇怪,难道是编译器自动添加了 inline ?

请问是什么原因造成的啊?

大佬有話說 (17)

  • 資深大佬 : BrettD

    看一下生成的汇编代码是啥

  • 資深大佬 : Huelse

    据我所知,一些编译器是会在编译 release 或者有其他编译选项的时候会自动给`return a+b`这种自动加 inline

  • 資深大佬 : crclz

    1. 看看汇编,用 vscode 比较一下(右键)
    2. 开-O1 或者-O2,再测一下速度,并且再比较一下汇编代码

  • 資深大佬 : YouLMAO

    for (int i=0; i<N; ++i) {
    z[i] = y[N] + x[N];
    }

    这就是 gcc 优化的结果

  • 資深大佬 : GeruzoniAnsasu

    首先开不开优化影响很大,如果被 inline 的代码本身 side effect 比较多,未优化情况下可能会额外多做很多事情,比如频繁读写变量的内存,本来这都是完全不需要的

    另外现在 x64 的 fastcall abi,函数调用已经没有访问内存出入栈的开销了,都可以用寄存器解决,所以 inline 省略掉了函数出入栈这个观念也已经是过时甚至错误的了

    再然后,众所周知 c++编译器行为学都只能马后炮,自己看一眼编译出来的汇编就都明白了

  • 主 資深大佬 : zvl0reqglvd

    要的,谢谢老哥们,鞠躬!!

  • 資深大佬 : lifanxi

    看看汇编找原因。

    具体是什么环境出现了你说描述的现象?我在 gcc 8.3 上重现不出来你说的现象。

  • 資深大佬 : nightwitch

    inline 这个关键词建议直接忘记它有内联建议这个功能,因为现在编译器基本上无视 inline 的这个语义。
    如果你真的确定要内联一个函数,MSVC 要用__forceinline , gcc 要用__attribute__((always_inline))。

    inline 这个关键词现在的主要作用是允许一个符号在不同的编译单元有重复的定义,这样允许你在头文件里写出函数实现和 inline variable.

  • 資深大佬 : mxalbert1996

    不知道你这个是不是这种情况,不过 inline 可能会造成更多 cache miss 从而影响性能。
    https://en.wikipedia.org/wiki/Inline_expansion
    Inlining also imposes a cost on performance, due to the code expansion (due to duplication) hurting instruction cache performance.[6] This is most significant if, prior to expansion, the working set of the program (or a hot section of code) fit in one level of the memory hierarchy (e.g., L1 cache), but after expansion it no longer fits, resulting in frequent cache misses at that level. Due to the significant difference in performance at different levels of the hierarchy, this hurts performance considerably.

  • 資深大佬 : msg7086

    gcc 带上优化编译出来是这样的。

    main:
         vpbroadcastd    ymm1, DWORD PTR x[rip+399996]
         mov    eax, OFFSET FLAT:z
         mov    ecx, OFFSET FLAT:y+400000
    .L3:
         mov    edx, OFFSET FLAT:y
    .L2:
         vpbroadcastd    ymm0, DWORD PTR [rdx]
         add    rdx, 4
         cmp    rcx, rdx
         jne    .L2
         vpaddd   ymm0, ymm1, ymm0
         add    rax, 32
         vmovdqa YMMWORD PTR [rax-32], ymm0
         cmp    rax, OFFSET FLAT:z+400000
         jne    .L3
         xor    eax, eax
         vzeroupper
         ret
    z:
        .zero   400000
    y:
        .zero   400000
    x:
        .zero   400000

    打开 AVX2 以后会直接执行 VPADDD,不仅不会调用 calc,甚至不会调用普通的寄存器加法。

  • 資深大佬 : codehz

    (inline 有你认为的效果要么是编译器版本太旧,要么就是你用了 always_inline 等私有扩展。。。
    按现行 c++标准,inline 关键字不再作为内联使用了)
    至于你这里的问题,你可能没开优化测试的吧

  • 資深大佬 : 786375312123

    看看你的 vs 优化开没开

  • 資深大佬 : no1xsyzy

    @mxalbert1996 按主代码,没有反复写 calc(),发生内联相比不发生内联,也不过是把唯一一处 calc(a, b) 替换为 a+b,并且还去掉了 calc 本身的定义,可以说指令的内存占用反而是减少的。

  • 資深大佬 : codyfeng

    这类问题应该把编译器版本、参数都贴出来

  • 資深大佬 : mxT52CRuqR6o5

    https://godbolt.org/
    不开编译优化我这边看这个在线的编译器结果
    gcc 是完全一样,clang 是编译出来的顺序不一样,都没有 inline
    想要弄清区别肯定是要看汇编的,不知道你用的什么编译器开的什么编译选项

  • 主 資深大佬 : zvl0reqglvd

    @mxT52CRuqR6o5 老哥你好,我用的是 gcc9.2,然后运行的是 g++ -g test.cpp -o test -lm -Wall -std=c++17 -O2 && test.exe ,开了优化的。

  • 資深大佬 : Gwkang

    频繁调用的函数,不内联可以提高 CPU 缓存命中率,你内联之后就没有了函数调用栈,所以慢

文章導覽

上一篇文章
下一篇文章

AD

其他操作

  • 登入
  • 訂閱網站內容的資訊提供
  • 訂閱留言的資訊提供
  • WordPress.org 台灣繁體中文

51la

4563博客

全新的繁體中文 WordPress 網站
返回頂端
本站採用 WordPress 建置 | 佈景主題採用 GretaThemes 所設計的 Memory
4563博客
  • Hostloc 空間訪問刷分
  • 售賣場
  • 廣告位
  • 賣站?
在這裡新增小工具