标签: compiler-optimization

C/C++编译器如何工作?

经过十多年的C/C++编码,我注意到了以下模式 - 非常优秀的程序员倾向于详细了解编译器的内部结构.

我是一个相当优秀的程序员,我有一个特殊的编译器"迷信"集合,所以我想重新启动我的知识并从基础开始.

有人可以推荐在线资源或喜欢的书籍链接吗?我对C/C++编译,优化,GCC和LLVM特别感兴趣.

c c++ compiler-construction compiler-optimization

33
推荐指数
4
解决办法
2万
查看次数

为什么不总是使用编译器优化?

我前面问过的一个问题是未定义的行为,因此编译器优化实际上导致程序中断.

但是如果代码中没有未定义的行为,那么有没有理由不使用编译器优化?我理解有时候,出于调试目的,可能不需要优化代码(如果我错了请纠正我).除此之外,在生产代码上,为什么不总是使用编译器优化?

另外,是否有理由使用,-O而不是-O2-O3

compiler-construction compiler-optimization

33
推荐指数
3
解决办法
9929
查看次数

我应该使用const作为局部变量来进行更好的代码优化吗?

我经常使用const未修改的局部变量,如下所示:

const float height = person.getHeight();
Run Code Online (Sandbox Code Playgroud)

我认为它可以使编译后的代码更快,允许编译器进行更多优化.或者我错了,编译器可以自己弄清楚局部变量永远不会被修改?

c++ optimization performance const compiler-optimization

33
推荐指数
2
解决办法
9822
查看次数

GCC:两个相似循环之间的矢量化差异

在编译时gcc -O3,为什么以下循环没有矢量化(自动):

#define SIZE (65536)

int a[SIZE], b[SIZE], c[SIZE];

int foo () {
  int i, j;

  for (i=0; i<SIZE; i++){
    for (j=i; j<SIZE; j++) {
      a[i] = b[i] > c[j] ? b[i] : c[j];
    }
  }
  return a[0];
}
Run Code Online (Sandbox Code Playgroud)

什么时候呢?

#define SIZE (65536)

int a[SIZE], b[SIZE], c[SIZE];

int foov () {
  int i, j;

  for (i=0; i<SIZE; i++){
    for (j=i; j<SIZE; j++) {
      a[i] += b[i] > c[j] ? b[i] : c[j];
    }
  }
  return a[0];
}
Run Code Online (Sandbox Code Playgroud)

唯一的区别在于内部循环中的表达式的结果是 …

c gcc loops vectorization compiler-optimization

33
推荐指数
1
解决办法
2816
查看次数

调整std :: vector <std :: unique_ptr <T >>的大小

一般概念似乎与正确使用的拥有原始指针相比没有时间开销,只要std::unique_ptr足够的优化.

但是std::unique_ptr,特别是在复合数据结构中使用std::vector<std::unique_ptr<T>>呢?例如,调整矢量的基础数据的大小,这可能发生在push_back.各地要隔离性能,我环路pop_back,shrink_to_fit,emplace_back:

#include <chrono>
#include <vector>
#include <memory>
#include <iostream>

constexpr size_t size = 1000000;
constexpr size_t repeat = 1000;
using my_clock = std::chrono::high_resolution_clock;

template<class T>
auto test(std::vector<T>& v) {
    v.reserve(size);
    for (size_t i = 0; i < size; i++) {
        v.emplace_back(new int());
    }
    auto t0 = my_clock::now();
    for (int i = 0; i < repeat; i++) {
        auto back = std::move(v.back()); …
Run Code Online (Sandbox Code Playgroud)

c++ vector compiler-optimization unique-ptr c++11

33
推荐指数
2
解决办法
2290
查看次数

在Unix上启用优化时,strcpy()/ strncpy()在结构成员上崩溃并有额外的空间?

在编写项目时,我遇到了一个奇怪的问题.

这是我设法编写的用于重新创建问题的最小代码.我故意将一个实际的字符串存储在其他地方,并分配了足够的空间.

// #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stddef.h> // For offsetof()

typedef struct _pack{
    // The type of `c` doesn't matter as long as it's inside of a struct.
    int64_t c;
} pack;

int main(){
    pack *p;
    char str[9] = "aaaaaaaa"; // Input
    size_t len = offsetof(pack, c) + (strlen(str) + 1);
    p = malloc(len);
    // Version 1: crash
        strcpy((char*)&(p->c), str);
    // Version 2: crash
        strncpy((char*)&(p->c), str, strlen(str)+1);
    // Version 3: works!
        memcpy((char*)&(p->c), str, strlen(str)+1); …
Run Code Online (Sandbox Code Playgroud)

c struct segmentation-fault compiler-optimization strcpy

32
推荐指数
3
解决办法
2195
查看次数

GCC 删除了 &amp;&amp; 右操作数中的边界检查,但没有删除左操作数中的边界检查,为什么?

我有以下 C/C++ 代码片段:

#define ARRAY_LENGTH 666

int g_sum = 0;
extern int *g_ptrArray[ ARRAY_LENGTH ];

void test()
{
    unsigned int idx = 0;

    // either enable or disable the check "idx < ARRAY_LENGTH" in the while loop
    while( g_ptrArray[ idx ] != nullptr /* && idx < ARRAY_LENGTH */ )
    {
        g_sum += *g_ptrArray[ idx ];
        ++idx;
    }

    return;
}
Run Code Online (Sandbox Code Playgroud)

当我使用版本 12.2.0 中的 GCC 编译器编译上述代码时,并选择-Os两种情况:

  1. while 循环条件是g_ptrArray[ idx ] != nullptr
  2. while 循环条件是g_ptrArray[ idx ] != …

c c++ arrays gcc compiler-optimization

32
推荐指数
3
解决办法
4196
查看次数

为什么编译器内联产生比手动内联更慢的代码?

背景

以C++编写的一个数值软件的以下关键循环基本上将两个对象的成员比较:

for(int j=n;--j>0;)
    asd[j%16]=a.e<b.e;
Run Code Online (Sandbox Code Playgroud)

ab是类ASD:

struct ASD  {
    float e;
    ...
};
Run Code Online (Sandbox Code Playgroud)

我正在调查将此比较放在轻量级成员函数中的效果:

bool test(const ASD& y)const {
    return e<y.e;
}
Run Code Online (Sandbox Code Playgroud)

并像这样使用它:

for(int j=n;--j>0;)
    asd[j%16]=a.test(b);
Run Code Online (Sandbox Code Playgroud)

编译器正在内联这个函数,但问题是,汇编代码会有所不同,导致运行时开销超过10%.我要问:

问题

  1. 为什么编译器会推出不同的汇编代码?

  2. 为什么生产的组件更慢?

编辑: 第二个问题已通过实施@ KamyarSouri的建议(j%16)得到了回答.汇编代码现在看起来几乎相同(请参阅http://pastebin.com/diff.php?i=yqXedtPm).唯一的区别是第18,33,48行:

000646F9  movzx       edx,dl 
Run Code Online (Sandbox Code Playgroud)

材料

此图表显示了我的代码的50个测试的FLOP/s(最多为缩放因子).

在此输入图像描述

用于生成绘图的gnuplot脚本:http://pastebin.com/8amNqya7

编译器选项:

/ Zi/W3/WX-/MP/Ox/Ob2/Oi/Ot/Oy/GL/D"WIN32"/ D"NDEBUG"/ D"_CONSOLE"/ D"_UNICODE"/ D"UNICODE"/ Gm-/EHsc/MT/GS-/Gy/arch:SSE2/fp:exact/Zc:wchar_t/Zc:forScope/Gd/analyze-

链接器选项:/ INCREMENTAL:NO"kernel32.lib""user32.lib""gdi32.lib""winspool.lib""comdlg32.lib""advapi32.lib""shell32.lib""ole32.lib""oleaut32. lib""uuid.lib""odbc32.lib""odbccp32.lib"/ ALLOWISOLATION/MANIFESTUAC:"level ='asInvoker'uiAccess ='false'"/ SUBSYSTEM:CONSOLE/OPT:REF/OPT:ICF/LTCG/TLBID …

c++ performance assembly inlining compiler-optimization

31
推荐指数
1
解决办法
1091
查看次数

为什么gcc不能虚拟化这个函数调用?

#include <cstdio>
#include <cstdlib>
struct Interface {
    virtual void f() = 0;
};

struct Impl1: Interface {
    void f() override {
        std::puts("foo");
    }
};

// or __attribute__ ((visibility ("hidden")))/anonymous namespace
static Interface* const ptr = new Impl1 ;

int main() {
    ptr->f();
}
Run Code Online (Sandbox Code Playgroud)

使用g ++ - 7编译时-O3 -flto -fdevirtualize-at-ltrans -fipa-pta -fuse-linker-plugin,上述ptr->f()调用不能被虚拟化.

似乎没有外部库可以修改ptr.这是GCC优化器的缺陷,还是因为其他一些来源使得虚拟化在这种情况下不可用?

Godbolt链接

更新:似乎clang-7 with -flto -O3 -fwhole-program-vtables -fvisibility=hidden是唯一可以虚拟化此程序的编译器+标志(如2018/03).

c++ gcc compiler-optimization

30
推荐指数
2
解决办法
1664
查看次数

为什么 gcc 在条件乘法的 std::vector&lt;float&gt; 向量化方面比 clang 差得多?

考虑使用以下 float 循环,使用 -O3 -mavx2 -mfma 编译

for (auto i = 0; i < a.size(); ++i) {
    a[i] = (b[i] > c[i]) ? (b[i] * c[i]) : 0;
}
Run Code Online (Sandbox Code Playgroud)

Clang 在矢量化方面做得非常出色。它使用 256 位 ymm 寄存器,并了解 vblendps/vandps 之间的差异,以获得尽可能最佳的性能。

.LBB0_7:
        vcmpltps        ymm2, ymm1, ymm0
        vmulps  ymm0, ymm0, ymm1
        vandps  ymm0, ymm2, ymm0
Run Code Online (Sandbox Code Playgroud)

然而,海湾合作委员会的情况要糟糕得多。由于某种原因,它并没有比 SSE 128 位向量更好(-mprefer-vector-width=256 不会改变任何东西)。

.L6:
        vcomiss xmm0, xmm1
        vmulss  xmm0, xmm0, xmm1
        vmovss  DWORD PTR [rcx+rax*4], xmm0
Run Code Online (Sandbox Code Playgroud)

如果将其替换为普通数组(如指南中所示),gcc 会将其矢量化为 AVX ymm。

int a[256], b[256], c[256];
auto foo …
Run Code Online (Sandbox Code Playgroud)

c++ gcc vectorization avx compiler-optimization

30
推荐指数
2
解决办法
3498
查看次数