• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

c++ - 更新 glibc 后 std::tan() 非常慢

[复制链接]
菜鸟教程小白 发表于 2022-8-2 17:48:34 | 显示全部楼层 |阅读模式 打印 上一主题 下一主题

我有一个调用大量触发函数的 C++ 程序。它已经运行了一年多。我最近安装了 gcc-4.8,同时更新了 glibc。这导致我的程序慢了近 x1000 倍。 Using gdb我发现速度变慢的原因是对 std::tan() 的调用。当参数是 pi 或 pi/2 时,函数需要很长时间才能返回。

这是一个 MWE,如果在没有优化的情况下编译,它会重现问题(实际程序在使用和不使用 -O2 标志时都有相同的问题)。

#include <cmath>

int main() {
    double pi = 3.141592653589793;
    double approxPi = 3.14159;
    double ret = 0.;

    for(int i = 0; i < 100000; ++i) ret = std::tan(pi); //Very slow
    for(int i = 0; i < 100000; ++i) ret = std::tan(approxPi); //Not slow
}

这是来自 gdb 的示例回溯(在使用 Ctrl+c 随机中断程序后获得)。从调用 tan 开始,回溯在 MWE 和我的真实程序中是相同的。
#0  0x00007ffff7b1d048 in __mul (p=32, z=0x7fffffffc740, y=0x7fffffffcb30, x=0x7fffffffc890) at ../sysdeps/ieee754/dbl-64/mpa.c:458
#1  __mul (x=0x7fffffffc890, y=0x7fffffffcb30, z=0x7fffffffc740, p=32) at ../sysdeps/ieee754/dbl-64/mpa.c:443
#2  0x00007ffff7b1e348 in cc32 (p=32, y=0x7fffffffc4a0, x=0x7fffffffbf60) at ../sysdeps/ieee754/dbl-64/sincos32.c:111
#3  __c32 (x=<optimized out>, y=0x7fffffffcf50, z=0x7fffffffd0a0, p=32) at ../sysdeps/ieee754/dbl-64/sincos32.c:128
#4  0x00007ffff7b1e170 in __mptan (x=<optimized out>, mpy=0x7fffffffd690, p=32) at ../sysdeps/ieee754/dbl-64/mptan.c:57
#5  0x00007ffff7b45b46 in tanMp (x=<optimized out>) at ../sysdeps/ieee754/dbl-64/s_tan.c:503
#6  __tan_avx (x=<optimized out>) at ../sysdeps/ieee754/dbl-64/s_tan.c:488
#7  0x00000000004005b8 in main ()

我尝试在四个不同的系统上运行代码(MWE 和真实程序)。其中两个在我运行代码的集群中。两台是我的笔记本电脑。 MWE 在其中一个集群和一台笔记本电脑上运行没有问题。我检查了每个系统使用哪个版本的 libm.so.6 以防万一。下面的列表显示了系统描述(取自 cat /etc/*-release),CPU 是 32 位还是 64 位,MWE 是否慢,最后运行 /lib/libc.so.6 的输出和 cat /proc/cpuinfo .
  • SUSE Linux Enterprise Server 11 (x86_64),64 位,使用 libm-2.11.1.so(MWE 很快)

  • GNU C Library stable release version 2.11.1 (20100118), by Roland McGrath et al.
    Copyright (C) 2009 Free Software Foundation, Inc.
    This is free software; see the source for copying conditions.
    There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
    PARTICULAR PURPOSE.
    Configured for x86_64-suse-linux.
    Compiled by GNU CC version 4.3.4 [gcc-4_3-branch revision 152973].
    Compiled on a Linux 2.6.32 system on 2012-04-12.
    Available extensions:
            crypt add-on version 2.1 by Michael Glad and others
            GNU Libidn by Simon Josefsson
            Native POSIX Threads Library by Ulrich Drepper et al
            BIND-8.2.3-T5B
    For bug reporting instructions, please see:
    <http://www.gnu.org/software/libc/bugs.html>.
    
    processor       : 0
    vendor_id       : GenuineIntel
    cpu family      : 6
    model           : 63
    model name      : Intel(R) Xeon(R) CPU E5-2680 v3 @ 2.50GHz
    stepping        : 2
    microcode       : 53
    cpu MHz         : 1200.000
    cache size      : 30720 KB
    physical id     : 0
    siblings        : 24
    core id         : 0
    cpu cores       : 12
    apicid          : 0
    initial apicid  : 0
    fpu             : yes
    fpu_exception   : yes
    cpuid level     : 15
    wp              : yes
    flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good xtopology nonstop_tsc aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 fma cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm ida arat epb xsaveopt pln pts dts tpr_shadow vnmi flexpriority ept vpid fsgsbase bmi1 avx2 smep bmi2 erms invpcid
    bogomips        : 5000.05
    clflush size    : 64
    cache_alignment : 64
    address sizes   : 46 bits physical, 48 bits virtual
    power management:
    
  • CentOS 版本 6.7(最终版),64 位,使用 libm-2.12.so(MWE 很慢)

  • GNU C Library stable release version 2.12, by Roland McGrath et al.
    Copyright (C) 2010 Free Software Foundation, Inc.
    This is free software; see the source for copying conditions.
    There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
    PARTICULAR PURPOSE.
    Compiled by GNU CC version 4.4.7 20120313 (Red Hat 4.4.7-16).
    Compiled on a Linux 2.6.32 system on 2015-09-22.
    Available extensions:
            The C stubs add-on version 2.1.2.
            crypt add-on version 2.1 by Michael Glad and others
            GNU Libidn by Simon Josefsson
            Native POSIX Threads Library by Ulrich Drepper et al
            BIND-8.2.3-T5B
            RT using linux kernel aio
    libc ABIs: UNIQUE IFUNC
    For bug reporting instructions, please see:
    <http://www.gnu.org/software/libc/bugs.html>.
    
    processor       : 0
    vendor_id       : GenuineIntel
    cpu family      : 6
    model           : 26
    model name      : Intel(R) Xeon(R) CPU           E5507  @ 2.27GHz
    stepping        : 5
    cpu MHz         : 1596.000
    cache size      : 4096 KB
    physical id     : 0
    siblings        : 4
    core id         : 0
    cpu cores       : 4
    apicid          : 0
    initial apicid  : 0
    fpu             : yes
    fpu_exception   : yes
    cpuid level     : 11
    wp              : yes
    flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts rep_good xtopology nonstop_tsc aperfmperf pni dtes64 monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr pdcm dca sse4_1 sse4_2 popcnt lahf_lm tpr_shadow vnmi flexpriority ept vpid
    bogomips        : 4533.16
    clflush size    : 64
    cache_alignment : 64
    address sizes   : 40 bits physical, 48 bits virtual
    power management:
    
  • Ubuntu 精确 (12.04.5 LTS),64 位,使用 libm-2.15.so(我的第一台笔记本电脑,MWE 很慢)

  • GNU C Library (Ubuntu EGLIBC 2.15-0ubuntu10.15) stable release version 2.15, by Roland McGrath et al.
    Copyright (C) 2012 Free Software Foundation, Inc.
    This is free software; see the source for copying conditions.
    There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
    PARTICULAR PURPOSE.
    Compiled by GNU CC version 4.6.3.
    Compiled on a Linux 3.2.79 system on 2016-05-26.
    Available extensions:
        crypt add-on version 2.1 by Michael Glad and others
        GNU Libidn by Simon Josefsson
        Native POSIX Threads Library by Ulrich Drepper et al
        BIND-8.2.3-T5B
    libc ABIs: UNIQUE IFUNC
    For bug reporting instructions, please see:
    <http://www.debian.org/Bugs/>.
    
    processor   : 0
    vendor_id   : GenuineIntel
    cpu family  : 6
    model       : 42
    model name  : Intel(R) Core(TM) i7-2620M CPU @ 2.70GHz
    stepping    : 7
    microcode   : 0x1a
    cpu MHz     : 800.000
    cache size  : 4096 KB
    physical id : 0
    siblings    : 4
    core id     : 0
    cpu cores   : 2
    apicid      : 0
    initial apicid  : 0
    fpu     : yes
    fpu_exception   : yes
    cpuid level : 13
    wp      : yes
    flags       : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic popcnt tsc_deadline_timer aes xsave avx lahf_lm ida arat epb xsaveopt pln pts dtherm tpr_shadow vnmi flexpriority ept vpid
    bogomips    : 5387.59
    clflush size    : 64
    cache_alignment : 64
    address sizes   : 36 bits physical, 48 bits virtual
    power management:
    
  • Ubuntu 精确 (12.04.5 LTS),32 位,使用 libm-2.15.so(我的第二台笔记本电脑,MWE 很快)

  • GNU C Library (Ubuntu EGLIBC 2.15-0ubuntu10.12) stable release version 2.15, by Roland McGrath et al.
    Copyright (C) 2012 Free Software Foundation, Inc.
    This is free software; see the source for copying conditions.
    There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
    PARTICULAR PURPOSE.
    Compiled by GNU CC version 4.6.3.
    Compiled on a Linux 3.2.68 system on 2015-03-26.
    Available extensions:
        crypt add-on version 2.1 by Michael Glad and others
        GNU Libidn by Simon Josefsson
        Native POSIX Threads Library by Ulrich Drepper et al
        BIND-8.2.3-T5B
    libc ABIs: UNIQUE IFUNC
    For bug reporting instructions, please see:
    <http://www.debian.org/Bugs/>.
    
    processor    : 0
    vendor_id    : GenuineIntel
    cpu family    : 6
    model        : 15
    model name    : Intel(R) Core(TM)2 Duo CPU     T5800  @ 2.00GHz
    stepping    : 13
    microcode    : 0xa3
    cpu MHz        : 800.000
    cache size    : 2048 KB
    physical id    : 0
    siblings    : 2
    core id        : 0
    cpu cores    : 2
    apicid        : 0
    initial apicid    : 0
    fdiv_bug    : no
    hlt_bug        : no
    f00f_bug    : no
    coma_bug    : no
    fpu        : yes
    fpu_exception    : yes
    cpuid level    : 10
    wp        : yes
    flags        : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe nx lm constant_tsc arch_perfmon pebs bts aperfmperf pni dtes64 monitor ds_cpl est tm2 ssse3 cx16 xtpr pdcm lahf_lm dtherm
    bogomips    : 3989.79
    clflush size    : 64
    cache_alignment    : 64
    address sizes    : 36 bits physical, 48 bits virtual
    power management:
    

    我希望我已经设法提供了足够的背景信息。这些是我的问题。
  • 为什么 std::tan() 变慢?
  • 有没有办法恢复到正常速度?

  • 我非常喜欢不需要安装/替换一堆库的解决方案。这可能适用于我的笔记本电脑,但我对集群节点没有必要的权限。

    更新 #1:
    正如 Sam Varshavchik 所解释的那样,我删除了关于将常量传递给 tan 的观察。我添加了运行 /lib/libc.so.6 的输出到我的系统列表。还增加了第四个系统。至于时间,这里是运行 time ./mwe 的输出与 pi循环( approxPi 注释掉)。
    real    0m11.483s
    user    0m11.465s
    sys 0m0.004s
    

    这是approxPi循环( pi 注释掉)。
    real    0m0.011s
    user    0m0.008s
    sys 0m0.000s
    

    更新 #2:
    对于每个系统,添加CPU是32位还是64位以及cat /proc/cpuinfo的输出对于第一个核心。



    Best Answer-推荐答案


    超越函数(三角函数和指数之类的东西)的精度始终是一个问题 1 .

    为什么某些触发函数调用比其他函数调用慢

    对于三角函数的许多参数,有一个快速近似,可以为大多数参数产生高度准确的结果。然而,对于某些参数,近似值可能是非常错误的。因此,需要采用更精确的方法,但这些方法需要更长的时间(如您所见)。

    为什么新库现在可能会更慢

    长期以来,英特尔对其三角函数浮点版本的准确性做出了误导性声明,称它们比实际准确得多 2 .这么多,那个 glibc 过去只有 sin(double)作为 fsin(float) 的包装器3 .您可能已升级到已纠正此错误的 glibc 版本。我不能代表 AMD 的 libm,但它可能仍然依赖于三角函数浮点版本的准确性的错误声明 4 , 5 .

    该怎么办

    如果您想要速度并且不太在意精度,那么请使用 tan ( ftan ) 的浮点版本。否则,如果您需要准确性,那么您将无法使用较慢的方法。你能做的最好是缓存 tan(pi 的结果) 和 tan(pi/2)并在您认为可能需要它们时使用预先计算的值。

    关于c++ - 更新 glibc 后 std::tan() 非常慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37504423/

    回复

    使用道具 举报

    懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    关注0

    粉丝2

    帖子830918

    发布主题
    阅读排行 更多
    广告位

    扫描微信二维码

    查看手机版网站

    随时了解更新最新资讯

    139-2527-9053

    在线客服(服务时间 9:00~18:00)

    在线QQ客服
    地址:深圳市南山区西丽大学城创智工业园
    电邮:jeky_zhao#qq.com
    移动电话:139-2527-9053

    Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap