Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 当使用g++;5.3.1使用g+编译的相同程序+;4.8.4,同一命令_C++_Performance_Ubuntu_Gcc5 - Fatal编程技术网

C++ 当使用g++;5.3.1使用g+编译的相同程序+;4.8.4,同一命令

C++ 当使用g++;5.3.1使用g+编译的相同程序+;4.8.4,同一命令,c++,performance,ubuntu,gcc5,C++,Performance,Ubuntu,Gcc5,最近,我开始在g++5.3.1中使用Ubuntu 16.04,并检查我的程序运行速度是否慢了3倍。 在此之前,我使用过Ubuntu 14.04、g++4.8.4。 我使用相同的命令构建它:CFLAGS=-std=c++11-Wall-O3 我的程序包含循环,充满了数学调用(sin、cos、exp)。 你可以找到它 我曾尝试使用不同的优化标志(O0、O1、O2、O3、Ofast)进行编译,但在所有情况下,问题都会重现(Ofast两种变体的运行速度更快,但第一种运行速度仍然慢3倍) 在我的程序中,我

最近,我开始在g++5.3.1中使用Ubuntu 16.04,并检查我的程序运行速度是否慢了3倍。 在此之前,我使用过Ubuntu 14.04、g++4.8.4。 我使用相同的命令构建它:
CFLAGS=-std=c++11-Wall-O3

我的程序包含循环,充满了数学调用(sin、cos、exp)。 你可以找到它

我曾尝试使用不同的优化标志(O0、O1、O2、O3、Ofast)进行编译,但在所有情况下,问题都会重现(Ofast两种变体的运行速度更快,但第一种运行速度仍然慢3倍)

在我的程序中,我使用了
libtinyxml-dev
libgslcblas
。但它们在这两种情况下都有相同的版本,并且在性能方面(根据代码和callgrind评测)在程序中没有任何重要作用

我已经进行了分析,但它没有告诉我为什么会发生这种情况。 . 我只注意到现在程序使用的是
libm-2.23
,而Ubuntu 14.04使用的是
libm-2.19

我的处理器是i7-5820,哈斯韦尔

我不知道为什么它会变慢。你有什么想法吗

请注意,您可以找到最耗时的功能:

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;
            }
        }
    }
}
}
使用其他优化标志不会更改比率


我怎样才能理解是谁,gcc还是libc,减慢了程序的速度?

要获得真正准确的答案,您可能需要一名libm维护人员来查看您的问题。不过,这是我的初稿,如果我找到其他东西,我会把它添加到这个答案中

首先,看看GCC生成的asm,介于和之间。只有4个区别:

  • 在开始时,对于相同的寄存器,
    xorpd
    被转换为
    pxor
  • a
    px或xmm1,xmm1
    在从int转换为double之前添加(
    cvtsi2sd
  • 在转换之前移动了
    movsd
  • 添加(
    addsd
    )在比较(
    ucomisd
    )之前移动
所有这些可能都不足以降低性能。拥有一个优秀的分析器(比如英特尔)可能会更具说服力,但我无法使用

现在,对sin有一个依赖关系,让我们看看发生了什么变化。问题是首先要确定你使用的是什么平台。。。glibc的
sysdeps
中有17个不同的子文件夹(其中定义了sin),因此我选择了
x86_64
一个

首先,处理器功能的处理方式发生了变化,例如,2.19中用于检查FMA/AVX的glibc/sysdeps/x86_64/fpu/multiarch/s_sin.c,但在2.23中是在外部完成的。可能存在未正确报告功能的错误,导致未使用FMA或AVX。然而,我认为这个假设不太可信

其次,在
../x86_64/fpu/s_sinf.s
中,唯一的修改(版权更新除外)更改堆栈偏移量,将其对齐到16字节;同上。我不确定这是否会带来巨大的变化

然而,2.23为数学函数的矢量化版本添加了很多源代码,有些使用AVX512,您的处理器可能不支持AVX512,因为它确实是新的。也许libm会尝试使用这样的扩展,但既然您没有这些扩展,那个么可以使用通用版本吗

编辑:我尝试用GCC4.8.5编译它,但为了它,我需要重新编译glibc-2.19。目前我无法链接,因为:

/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/libm.a(s_sin.o): in function « __cos »:
(.text+0x3542): undefined reference to « _dl_x86_cpu_features »
/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/libm.a(s_sin.o): in function « __sin »:
(.text+0x3572): undefined reference to « _dl_x86_cpu_features »

我将尝试解决这个问题,但事先请注意,这个符号很可能负责根据处理器选择正确的优化版本,这可能是性能影响的一部分。

这是glibc中的一个bug,影响2.23版(在Ubuntu 16.04中使用)和2.24的早期版本(例如,Fedora和Debian已经包括不再受影响的修补版本,Ubuntu 16.10和17.04还没有)

增长放缓源于SSE到AVX寄存器的过渡惩罚。请参见此处的glibc错误报告:

Oleg Strikov在他的Ubuntu bug报告中写了一个相当广泛的分析:


没有补丁,有各种可能的解决方法:您可以静态编译问题(即添加
-static
),也可以通过在程序执行期间设置环境变量
LD\u BIND\u NOW
来禁用延迟绑定。同样,上面的错误报告中有更多详细信息。

我怀疑这是libm本身(它实现了那些数学函数——是的,它们不是内联的)你看了生成的程序集输出了吗?另外,你确定这个函数没有错误,即没有未定义的行为吗?你有数组或类似数组的类型(比如
F
,如果你问我的话,这是个坏名字),您正在使用未检查的索引访问它们,以查看它们是否在边界内。如果程序集输出相同或大致相等,请检查函数本身,因为UB可能会做奇怪的事情。@orbitcowboy,不,我还没有查看asm列表。源代码列表和主要计算。我发现了两个内存泄漏,但它不会影响程序的性能。事实上,我错过了两次删除。之后我有。这与问题无关!
g++ -std=c++11 -O3 main.cpp -o sum
/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/libm.a(s_sin.o): in function « __cos »:
(.text+0x3542): undefined reference to « _dl_x86_cpu_features »
/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/libm.a(s_sin.o): in function « __sin »:
(.text+0x3572): undefined reference to « _dl_x86_cpu_features »