我从各种来源(虽然大多数来自我的同事)中听到过,-O3用g ++ 的优化级别进行编译在某种程度上是"危险的",并且除非被证明是必要的,否则应该避免.
这是真的,如果是的话,为什么?我应该坚持-O2吗?
numpy基于我与优化的 C/C++ 代码的令人震惊的比较,我试图了解怎么能这么快,这仍然远不能重现 numpy 的速度。
考虑以下示例:给定一个带有shape=(N, N)和的二维数组dtype=float32,它表示 N 维的 N 个向量的列表,我正在计算每对向量之间的成对差异。使用numpy广播,这简单地写为:
def pairwise_sub_numpy( X ):
return X - X[:, None, :]
Run Code Online (Sandbox Code Playgroud)
使用timeit我可以测量性能N=512:在我的笔记本电脑上每次通话需要 88 毫秒。
现在,在 C/C++ 中,一个简单的实现写为:
#define X(i, j) _X[(i)*N + (j)]
#define res(i, j, k) _res[((i)*N + (j))*N + (k)]
float* pairwise_sub_naive( const float* _X, int N )
{
float* _res = (float*) aligned_alloc( 32, N*N*N*sizeof(float));
for (int i = 0; i < N; i++) {
for …Run Code Online (Sandbox Code Playgroud) 关于编译器(GCC)所做的优化,标准做法是什么?每个选项(-O,-O1,-O2,-O3,-Os,-s,-fexpensive-optimizations)的作用有何不同,我如何确定最佳选项?
由于学校作业,我必须将C++代码转换为程序集(ARMv8).然后我必须使用GCC的-O0,-O1,-O2,-O3和-Os优化来编译C++代码,记下时间并与汇编代码的执行时间进行比较.因为,我想我知道-O3必须比-O1和-O2快.但是,我得到-O2是最快的,然后是-O1,-O3,-Os,-O0.这是通常的吗?(计算的时间约为30秒).
使用gcc v4.8.1
如果我做:
//func.hpp
#ifndef FUNC_HPP
#define FUNC_HPP
int func(int);
#endif
//func.cpp
#include "func.hpp"
int func(int x){
return 5*x+7;
}
//main.cpp
#include <iostream>
#include "func.hpp"
using std::cout;
using std::endl;
int main(){
cout<<func(5)<<endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
即使是简单的功能func也不会内联.无相结合inline,extern,static,并__attribute__((always_inline))在样机和/或定义改变了这种(这些说明的一些明显的组合,导致它甚至不会编译和/或产生警告,不谈论那些).我正在使用g++ *.cpp -O3 -o run和g++ *.cpp -O3 -S组装输出.当我看到装配输出时,我仍然看到call func.它似乎只有我能够正确内联函数的方法是拥有原型(可能没有必要)和头文件中函数的定义.如果标题只包含在整个程序中的一个文件中(仅main.cpp作为例子包含),它将编译并且函数将被正确内联,甚至不需要inline符.如果要将标头包含在多个文件中,则inline需要使用说明符来解决多个定义错误,这似乎是其唯一目的.该功能当然可以正确内联.
所以我的问题是:我做错了吗?我错过了什么吗?无论发生什么:
"编译器比你聪明.它知道什么时候应该比你更好地内联函数.永远不要使用C数组.总是使用std :: vector!"
- 每个其他StackOverflow用户
真?所以调用func(5)并打印结果比打印32更快?我会盲目地跟着你离开悬崖的边缘所有人都知道并且所有明智的gcc.
为了记录,上面的代码只是一个例子.我正在写一个光线跟踪器,当我将我的数学和其他实用程序类的所有代码移动到它们的头文件并使用说明inline符时,我看到了大量的性能提升.对于某些场景,字面意思快10倍.
c++ ×4
c ×2
g++ ×2
gcc ×2
optimization ×2
arrays ×1
compilation ×1
inline ×1
numpy ×1
performance ×1