最近,我开始使用Ubuntu 16.04和g++ 5.3.1,并发现我的程序运行慢了3倍。之前我使用的是Ubuntu 14.04和g++ 4.8.4。我用相同的命令构建它:
我的程序包含循环,其中填充了数学调用(sin,cos,exp)。你可以在这里找到它。
我尝试使用不同的优化标志(O0、O1、O2、O3、Ofast)进行编译,但在所有情况下都会出现问题(使用Ofast两个变量都运行得更快,但第一个仍然慢了3倍)。
在我的程序中,我使用
我已经进行了性能分析,但它并没有给我任何关于为什么会出现这种情况的想法。Kcachegrind比较(左边更慢)。我只注意到现在程序使用
我的处理器是i7-5820,Haswell。
我不知道为什么它变得更慢了。你有任何想法吗?
附言:下面是最耗时的函数。
我很想知道为什么这个简单的示例程序在g++ 4.8.4 libc-2.19 (libm-2.19)下比在g++ 5.3.1 libc-2.23 (libm-2.23)下快2.5倍。
CFLAGS = -std=c++11 -Wall -O3
。我的程序包含循环,其中填充了数学调用(sin,cos,exp)。你可以在这里找到它。
我尝试使用不同的优化标志(O0、O1、O2、O3、Ofast)进行编译,但在所有情况下都会出现问题(使用Ofast两个变量都运行得更快,但第一个仍然慢了3倍)。
在我的程序中,我使用
libtinyxml-dev
和libgslcblas
。但是它们在两种情况下都有相同的版本,并且在性能方面(根据代码和callgrind分析)对程序没有任何重要影响。我已经进行了性能分析,但它并没有给我任何关于为什么会出现这种情况的想法。Kcachegrind比较(左边更慢)。我只注意到现在程序使用
libm-2.23
,而不是Ubuntu 14.04中的libm-2.19
。我的处理器是i7-5820,Haswell。
我不知道为什么它变得更慢了。你有任何想法吗?
附言:下面是最耗时的函数。
void InclinedSum::prepare3D()
{
double buf1, buf2;
double sum_prev1 = 0.0, sum_prev2 = 0.0;
int break_idx1, break_idx2;
int arr_idx;
for(int seg_idx = 0; seg_idx < props->K; seg_idx++)
{
const Point& r = well->segs[seg_idx].r_bhp;
for(int k = 0; k < props->K; k++)
{
arr_idx = seg_idx * props->K + k;
F[arr_idx] = 0.0;
break_idx2 = 0;
for(int m = 1; m <= props->M; m++)
{
break_idx1 = 0;
for(int l = 1; l <= props->L; l++)
{
buf1 = ((cos(M_PI * (double)(m) * well->segs[k].r1.x / props->sizes.x - M_PI * (double)(l) * well->segs[k].r1.z / props->sizes.z) -
cos(M_PI * (double)(m) * well->segs[k].r2.x / props->sizes.x - M_PI * (double)(l) * well->segs[k].r2.z / props->sizes.z)) /
( M_PI * (double)(m) * tan(props->alpha) / props->sizes.x + M_PI * (double)(l) / props->sizes.z ) +
(cos(M_PI * (double)(m) * well->segs[k].r1.x / props->sizes.x + M_PI * (double)(l) * well->segs[k].r1.z / props->sizes.z) -
cos(M_PI * (double)(m) * well->segs[k].r2.x / props->sizes.x + M_PI * (double)(l) * well->segs[k].r2.z / props->sizes.z)) /
( M_PI * (double)(m) * tan(props->alpha) / props->sizes.x - M_PI * (double)(l) / props->sizes.z )
) / 2.0;
buf2 = sqrt((double)(m) * (double)(m) / props->sizes.x / props->sizes.x + (double)(l) * (double)(l) / props->sizes.z / props->sizes.z);
for(int i = -props->I; i <= props->I; i++)
{
F[arr_idx] += buf1 / well->segs[k].length / buf2 *
( exp(-M_PI * buf2 * fabs(r.y - props->r1.y + 2.0 * (double)(i) * props->sizes.y)) -
exp(-M_PI * buf2 * fabs(r.y + props->r1.y + 2.0 * (double)(i) * props->sizes.y)) ) *
sin(M_PI * (double)(m) * r.x / props->sizes.x) *
cos(M_PI * (double)(l) * r.z / props->sizes.z);
}
if( fabs(F[arr_idx] - sum_prev1) > F[arr_idx] * EQUALITY_TOLERANCE )
{
sum_prev1 = F[arr_idx];
break_idx1 = 0;
} else
break_idx1++;
if(break_idx1 > 1)
{
//std::cout << "l=" << l << std::endl;
break;
}
}
if( fabs(F[arr_idx] - sum_prev2) > F[arr_idx] * EQUALITY_TOLERANCE )
{
sum_prev2 = F[arr_idx];
break_idx2 = 0;
} else
break_idx2++;
if(break_idx2 > 1)
{
std::cout << "m=" << m << std::endl;
break;
}
}
}
}
}
进一步调查。 我编写了以下简单程序:
#include <cmath>
#include <iostream>
#include <chrono>
#define CYCLE_NUM 1E+7
using namespace std;
using namespace std::chrono;
int main()
{
double sum = 0.0;
auto t1 = high_resolution_clock::now();
for(int i = 1; i < CYCLE_NUM; i++)
{
sum += sin((double)(i)) / (double)(i);
}
auto t2 = high_resolution_clock::now();
microseconds::rep t = duration_cast<microseconds>(t2-t1).count();
cout << "sum = " << sum << endl;
cout << "time = " << (double)(t) / 1.E+6 << endl;
return 0;
}
我很想知道为什么这个简单的示例程序在g++ 4.8.4 libc-2.19 (libm-2.19)下比在g++ 5.3.1 libc-2.23 (libm-2.23)下快2.5倍。
编译命令如下:
g++ -std=c++11 -O3 main.cpp -o sum
使用其他优化标志不改变比率。
我如何理解是谁,gcc还是libc,使程序变慢?
F
,如果你问我,这是一个糟糕的名字),并且你正在使用未经检查的索引来访问它们,以查看它们是否在边界内。如果汇编输出相同或大致相等,请检查函数本身,因为未定义的行为可能会产生奇怪的结果。 - PaulMcKenzie