相关疑难解决方法(0)

为什么GCC不优化a*a*a*a*a*a到(a*a*a)*(a*a*a)?

我正在对科学应用进行一些数值优化.我注意到的一件事是GCC会pow(a,2)通过编译来优化调用a*a,但调用pow(a,6)没有优化,实际上会调用库函数pow,这会大大降低性能.(相比之下,英特尔C++编译器,可执行文件icc,将消除库调用pow(a,6).)

我很好奇的是,当我更换pow(a,6)a*a*a*a*a*a使用GCC 4.5.1和选项" -O3 -lm -funroll-loops -msse4",它采用5分mulsd的说明:

movapd  %xmm14, %xmm13
mulsd   %xmm14, %xmm13
mulsd   %xmm14, %xmm13
mulsd   %xmm14, %xmm13
mulsd   %xmm14, %xmm13
mulsd   %xmm14, %xmm13
Run Code Online (Sandbox Code Playgroud)

如果我写(a*a*a)*(a*a*a),它会产生

movapd  %xmm14, %xmm13
mulsd   %xmm14, %xmm13
mulsd   %xmm14, %xmm13
mulsd   %xmm13, %xmm13
Run Code Online (Sandbox Code Playgroud)

这将乘法指令的数量减少到3. icc具有类似的行为.

为什么编译器不能识别这种优化技巧?

floating-point assembly gcc compiler-optimization fast-math

2083
推荐指数
12
解决办法
20万
查看次数

在C++中实现长方程时,如何通过高级方法提高性能

我正在开发一些工程模拟.这包括实现一些长方程,例如这个方程,以计算橡胶类材料中的应力:

T = (
    mu * (
            pow(l1 * pow(l1 * l2 * l3, -0.1e1 / 0.3e1), a) * a
            * (
                pow(l1 * l2 * l3, -0.1e1 / 0.3e1)
                - l1 * l2 * l3 * pow(l1 * l2 * l3, -0.4e1 / 0.3e1) / 0.3e1
            ) * pow(l1 * l2 * l3, 0.1e1 / 0.3e1) / l1
            - pow(l2 * pow(l1 * l2 * l3, -0.1e1 / 0.3e1), a) * a / l1 / 0.3e1
            - pow(l3 * …
Run Code Online (Sandbox Code Playgroud)

c++ floating-point optimization performance g++

91
推荐指数
6
解决办法
4436
查看次数

浮点乘法与重复加法

我们N是一个编译时无符号整数.

GCC可以优化

unsigned sum = 0;
for(unsigned i=0; i<N; i++) sum += a; // a is an unsigned integer   
Run Code Online (Sandbox Code Playgroud)

简单地说 a*N.这可以理解,因为模数运算说(a%k + b%k)%k = (a+b)%k.

但GCC不会优化

float sum = 0;
for(unsigned i=0; i<N; i++) sum += a;  // a is a float
Run Code Online (Sandbox Code Playgroud)

a*(float)N.

但是通过使用关联数学,-Ofast我发现GCC可以按顺序减少这一点log2(N).例如,因为N=8它可以在三个添加中进行总和.

sum = a + a
sum = sum + sum // (a + a) + (a + a)
sum = sum + sum …
Run Code Online (Sandbox Code Playgroud)

c floating-point optimization gcc

43
推荐指数
1
解决办法
1636
查看次数

为什么 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
查看次数

为什么编译器会在编译的汇编代码中生成额外的sqrts

我正在尝试使用以下简单的C代码来分析计算sqrt所需的时间,其中readTSC()是一个读取CPU循环计数器的函数.

double sum = 0.0;
int i;
tm = readTSC();
for ( i = 0; i < n; i++ )
   sum += sqrt((double) i);
tm = readTSC() - tm;
printf("%lld clocks in total\n",tm);
printf("%15.6e\n",sum);
Run Code Online (Sandbox Code Playgroud)

但是,当我使用打印出汇编代码时

gcc -S timing.c -o timing.s
Run Code Online (Sandbox Code Playgroud)

在英特尔机器上,结果(如下所示)令人惊讶?

为什么汇编代码中有两个sqrts,一个使用sqrtsd指令而另一个使用函数调用?它是否与循环展开和尝试在一次迭代中执行两个sqrts相关?

以及如何理解这条线

ucomisd %xmm0, %xmm0
Run Code Online (Sandbox Code Playgroud)

为什么它与%xmm0自身相比?

//----------------start of for loop----------------
call    readTSC
movq    %rax, -32(%rbp)
movl    $0, -4(%rbp)
jmp .L4
.L6:
cvtsi2sd    -4(%rbp), %xmm1
// 1. use sqrtsd instruction
sqrtsd  %xmm1, %xmm0
ucomisd %xmm0, …
Run Code Online (Sandbox Code Playgroud)

c assembly gcc x86-64 compiler-optimization

14
推荐指数
1
解决办法
464
查看次数

可以在典型项目中安全使用-ffast-math吗?

在回答我建议的问题时-ffast-math,评论指出这是危险的.

我个人的感觉是,在科学计算之外,没关系.我还认为严肃的财务应用程序使用固定点而不是浮点数.

当然,如果你想在你的项目中使用它,最终的答案是在你的项目上测试它,看看它对它有多大影响.但我认为,尝试并具有此类优化经验的人可以给出一般答案:

可以ffast-math正常项目中安全使用吗?

鉴于IEEE 754浮点具有舍入误差,假设您已经生活在不精确的计算中.


这个答案特别启发了这样一个事实:-ffast-math除了重新排序操作会导致稍微不同的结果(不检查NaN或零,禁用签名零只是为了说明一些),但我没有看到效果是什么其中最终将是一个真实的代码.


我试着想到浮点的典型用法,这就是我提出的:

  • GUI(2D,3D,物理引擎,动画)
  • 自动化(例如汽车电子)
  • 机器人
  • 工业测量(例如电压)

和学校项目,但这些并不重要.

c c++ floating-point optimization ieee-754

13
推荐指数
5
解决办法
1415
查看次数

clang的`-Ofast`选项在实践中有什么作用,尤其是与gcc的差异?

类似于问题gcc的ffast-math实际上做了什么?并且与Clang优化级别的SO问题有关,我想知道在实际条件下优化是做什么clang-Ofast,以及它们是否与gcc完全不同,或者这是否依赖于编译器依赖于硬件.

根据clang优化级别的公认答案,-Ofast增加了-O3优化:-fno-signed-zeros -freciprocal-math -ffp-contract=fast -menable-unsafe-fp-math -menable-no-nans -menable-no-infs.这似乎完全与浮点数学相关.但是这些优化对于像C++这样的事物来说意味着什么呢?像英特尔酷睿i7这样的CPU上的浮点数通用数学函数以及这些差异有多可靠?

例如,实际上:

该代码std::isnan(std::numeric_limits<float>::infinity() * 0)返回真正的我-O3.我相信这是符合IEEE数学标准的结果.

随着-Ofast不过,我得到一个错误的返回值.此外,该操作(std::numeric_limits<float>::infinity() * 0) == 0.0f返回true.

我不知道这是否与gcc中看到的相同.我不清楚结果如何依赖于结构,也不清楚编译器如何依赖它们,也不清楚是否存在任何适用的标准-Ofast.

如果有人可能会产生类似于一组单元测试代码公案来解决这个问题,那可能是理想的.我已经开始做这样的事情,但宁愿不重新发明轮子.

c++ floating-point x86-64 clang compiler-optimization

9
推荐指数
1
解决办法
2830
查看次数

双和ffast数学的自动矢量化

为什么必须使用-ffast-mathg ++来实现使用doubles 的循环向量化?我不喜欢-ffast-math因为我不想失去精确度.

double gcc g++ vectorization fast-math

6
推荐指数
1
解决办法
3359
查看次数

动态 - 数学 - 数学

是否可以在运行时选择性地打开/关闭-ffast-math?例如,使用公共基类Math创建类FastMath和AccurateMath,以便一个人能够在运行时使用这两个实现?将次正常闪烁归零等同样如此.

特别是,我不知道使用-ffast-math进行编译是否会发出一条指令,该指令一旦执行就会影响线程中的所有数值计算(例如,设置一个标志以将subnormals刷新为零).

c optimization performance gcc fast-math

6
推荐指数
2
解决办法
979
查看次数

GCC中不同优化级别的不同输出

我正在重写我上学期为大学开发的光线追踪器,但遇到了以下问题:当我在 Debug 中编译和运行我的代码时,输​​出符合预期

预期结果

但是当我启用更高的优化级别(例如“-O2”)时,结果会完全不同:

实际结果

我不确定为什么会发生这种情况。我追踪到球体相交代码

//#pragma GCC push_options
//#pragma GCC optimize("O0")

Intersection Sphere::intersect(const Ray& ray, const float previous) const
{
    const auto oc = ray.origin - center_;
    const auto lhv = -dot(ray.direction, oc);
    const auto discriminant = lhv * lhv - (oc.lensqr() - radius_ * radius_);

    if (discriminant < 0.0F)
    {
        return Intersection::failure();
    }
    float distance;
    const auto rhv = std::sqrt(discriminant);
    const auto r = std::minmax(lhv + rhv, lhv - rhv);
    if (r.first <= 0.0F)
    {
        if (r.second <= 0.0F) …
Run Code Online (Sandbox Code Playgroud)

gcc g++ sfml c++17

6
推荐指数
1
解决办法
132
查看次数