相关疑难解决方法(0)

零防止除法:检查除数的表达式不会导致零与检查除数不为零?

由于减法中的浮点误差,在以下情况下是否可以除零?

float x, y, z;
...
if (y != 1.0)
    z = x / (y - 1.0);
Run Code Online (Sandbox Code Playgroud)

换句话说,以下是否更安全?

float divisor = y - 1.0;
if (divisor != 0.0)
    z = x / divisor;
Run Code Online (Sandbox Code Playgroud)

c++ floating-point floating-accuracy divide-by-zero floating-point-precision

7
推荐指数
2
解决办法
3262
查看次数

双和ffast数学的自动矢量化

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

double gcc g++ vectorization fast-math

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

std :: pow对于不同的指数,行为非常不同

我目前正在尝试优化一些占用50%时间的代码std::pow().我知道指数将始终是一个正整数,并且基数将始终是区间(0,1)中的双精度.为了好玩,我写了一个函数:

inline double int_pow(double base, int exponent)
{
    double out = 1.0;
    for(int i = 0; i < exponent; i++)
    {
        out *= base;
    }

    return out;
}
Run Code Online (Sandbox Code Playgroud)

我正在编译:

> g++ fast-pow.cpp -O3 --std=c++11
Run Code Online (Sandbox Code Playgroud)

我在(0,1)之间产生了1亿个双打,并比较了(1) std::pow(2)int_pow上面我自制函数的时间和(3)直接乘法.这是我的计时例程的草图(这是一个非常快速的组合测试):

void time_me(int exp, size_t reps)
{
    volatile double foo = 0.0;
    double base = 0.0;

    size_t i;
    for (i = 0; i < reps; ++i)
    {
        base = ((double) rand() / (RAND_MAX)) + 1;
        foo = pow(base, …
Run Code Online (Sandbox Code Playgroud)

c++ performance numerical-methods

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

C中的整数幂

在C代码中,通常写

a = b*b;
Run Code Online (Sandbox Code Playgroud)

代替

a = pow(b, 2.0);
Run Code Online (Sandbox Code Playgroud)

对于double变量.我知道因为它pow是一个能够处理非整数指数的通用函数,所以应该天真地认为第一个版本更快.我不知道编译器(gcc)是否将调用转换为pow整数指数,以指示乘法作为任何可选优化的一部分.

假设没有进行这种优化,那么手动写出乘法的最大整数指数是b*b* ... *b多少,如?

我知道我可以在给定的机器上进行性能测试,以确定我是否应该关心,但我想更深入地了解什么是"正确的事情".

c optimization gcc gnu compiler-optimization

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

Boost ICL 中函数“contains”的基本用法:区间类型和函数的某些组合是否未实现?

我开始使用 Boost ICL,并偶然发现了非常基本的东西。例如,函数contains应返回 true 或 false,具体取决于给定元素是否在区间内。然而,这适用[right,left]_open_intervals但不适用[open,closed]_inteval(参见下面的示例)。

这似乎太明显了,不可能是一个疏忽。我正在以预期的方式使用图书馆吗?

例如(使用 gcc 4.8 或 clang 3.3 和 Boost 1.54):

#include <boost/concept_check.hpp> //needed to make this MWE work, boost icl should include it internally

#include<boost/icl/right_open_interval.hpp>
#include<boost/icl/closed_interval.hpp>
#include<boost/icl/open_interval.hpp>
int main(){
    boost::icl::right_open_interval<double> roi(6.,7.);
    assert(boost::icl::contains(roi, 6.) == true);  //ok
    assert(boost::icl::contains(roi, 6.) == false); //ok

    boost::icl::closed_interval<double> oi(4.,5.); // or open_interval
    assert(boost::icl::contains( oi, 4.) == false); //error: "candidate template ignored"
    assert(boost::icl::contains( oi, 5.) == false); //error: "candidate template ignored"
}
Run Code Online (Sandbox Code Playgroud)

注意:以上称为“静态”间隔(因为它们的绑定属性是类型的一部分)。动态间隔按预期工作。

c++ boost boost-icl

5
推荐指数
1
解决办法
1679
查看次数

优化一组多项式以获得计算速度

我有一组由计算机代数系统(CAS)产生的多项式表达式.例如,这是该集合的一个元素.

-d*d*L*L*QB*B*L*L*Q + 2*d*F*Ĵ*L*Q + 2*b*表F*H*L*QF*F*Ĵ*Ĵ*QB*b*表Ĵ*∫*q + 2*b*表d*H*Ĵ*QF*F*H*H*QD*d*H*H*q + b*b*∫*∫*○*O-2*b*d*H*Ĵ*○*O + d*d*H*H*○*0-2*b*b*∫*L*N*O + 2*b*表d*H*L*n个*O + 2*b*表F*H*Ĵ*N*0-2*d*F*H*H*N*O + 2*b*表d*∫*L*M*0-2*d*d*H*L*M*0-2*b*表F*Ĵ*∫*M*O + 2*d*F*H*Ĵ*M*O + b*b*L*L*N*N-2*b*表F*H*L*N*N + F*F*H*H*N*N-2*b*表d*L*L*m*n个+ 2*b*表F*Ĵ*L*米*N + 2*d*F*H*L*m*n个-2*F*F*H*Ĵ*m*n个+ d*d*L*L*m*m的-2*d*F*Ĵ*L*M*M + F*F*Ĵ*Ĵ*m*m的

我需要尽快在C程序中执行所有这些操作.如果你仔细研究这些公式中的任何一个,很明显我们可以优化它们的计算速度.例如,在上面粘贴的多项式中,我可以立即看到术语-d*d*l*l*q,2*d*f*j*l*q和-f*f*j*j*q,这样我就可以用-q*square(d*lf*j)替换它们的总和.我相信这里可以做很多这样的事情.我不相信(但也许我错了)任何编译器都能找到这个优化,或者更高级的优化.我试图让maxima(一个CAS)为我做这个,但没有任何结果(因为我是极限初学者,我可能错过了一个神奇的命令).所以,我的第一个问题是:我们可以使用什么工具/算法来优化多项式表达式以获得计算速度?

当优化一组共享大多数变量的多项式表达式时,事情变得更加复杂.实际上,通过表达式优化表达式可能是次优的,因为在优化之前编译器可以识别公共部分,但是如果不作为整体执行则不再存在.所以,我的第二个问题是:我们可以使用哪些工具/算法来优化一组多项式表达式以获得计算速度?

最好的祝福,

PS:这篇文章与" 计算机代数软件以及最小化一组多项式中的操作数量 "有一些相似之处,但是那一点给出的答案指向CAS程序而不是说我们如何使用它们来实现我们的目标.

algorithm optimization performance computer-algebra-systems polynomials

5
推荐指数
1
解决办法
139
查看次数

C/C++编译器是否会对可交换运算符(例如:+,*)重新排序以优化常量

请问以下代码的第2行

int bar;
int foo = bar * 3 * 5;
Run Code Online (Sandbox Code Playgroud)

被优化为

int bar;
int foo = bar * 15;
Run Code Online (Sandbox Code Playgroud)

甚至更多:

int foo = 3 * bar * 5;
Run Code Online (Sandbox Code Playgroud)

可以优化吗?

目的实际上是问我是否可以写

int foo = bar * 3 * 5;
Run Code Online (Sandbox Code Playgroud)

代替

int foo = bar * (3 * 5);
Run Code Online (Sandbox Code Playgroud)

保存括号.(并且减轻了手动操作那些常量排序的需要=>并且在许多情况下,使用相关变量的分组常量更有意义,而不是为了优化而分组常量)

c++ optimization

5
推荐指数
1
解决办法
254
查看次数

矢量化:什么时候值得手动展开循环?

我想大致了解何时可以期望编译器对循环进行矢量化,以及何时值得我展开循环以帮助它决定使用矢量化。

我知道细节非常重要(什么编译器,什么编译选项,什么架构,如何在循环中编写代码等),但我想知道是否有一些针对现代编译器的通用指南。

我将更具体地给出一个简单循环的示例(代码不应该计算任何有用的东西):

    double *A,*B; // two arrays
    int delay = something
    [...]


    double numer = 0, denomB = 0, denomA = 0;
    for (int idxA = 0; idxA < Asize; idxA++)
    {
        int idxB = idxA + (Bsize-Asize)/2 + delay;
        numer  += A[idxA] * B[idxB];
        denomA += A[idxA] * A[idxA];
        denomB += B[idxB] * B[idxB];
    }
Run Code Online (Sandbox Code Playgroud)

我可以期望编译器对循环进行矢量化吗?或者重写如下代码是否有用?

    for ( int idxA = 0; idxA < Asize; idxA+=4 )
    {
        int idxB = idxA + (Bsize-Asize)/2 …
Run Code Online (Sandbox Code Playgroud)

c c++ vectorization loop-unrolling

5
推荐指数
1
解决办法
1072
查看次数

如果没有 -fwrapv,GCC 将不会使用自己的优化技巧

考虑这个 C++ 代码:

#include <cstdint>

// returns a if less than b or if b is INT32_MIN
int32_t special_min(int32_t a, int32_t b)
{
    return a < b || b == INT32_MIN ? a : b;
}
Run Code Online (Sandbox Code Playgroud)

GCC-fwrapv正确地认识到减去 1b可以消除特殊情况,并为 x86-64 生成以下代码

    lea     edx, [rsi-1]
    mov     eax, edi
    cmp     edi, edx
    cmovg   eax, esi
    ret
Run Code Online (Sandbox Code Playgroud)

但如果没有-fwrapv它,会生成更糟糕的代码:

    mov     eax, esi
    cmp     edi, esi
    jl      .L4
    cmp     esi, -2147483648
    je      .L4
    ret
.L4:
    mov     eax, edi …
Run Code Online (Sandbox Code Playgroud)

c++ optimization gcc x86-64 compiler-optimization

5
推荐指数
1
解决办法
205
查看次数

为什么LLVM不通过优化浮点指令?

往上看.我写了示例函数:

source.ll:

define i32 @bleh(i32 %x) {
entry:
  %addtmp = add i32 %x, %x
  %addtmp1 = add i32 %addtmp, %x
  %addtmp2 = add i32 %addtmp1, %x
  %addtmp3 = add i32 %addtmp2, %x
  %addtmp4 = add i32 %addtmp3, 1
  %addtmp5 = add i32 %addtmp4, 2
  %addtmp6 = add i32 %addtmp5, 3
  %multmp = mul i32 %x, 3
  %addtmp7 = add i32 %addtmp6, %multmp
  ret i32 %addtmp7
}
Run Code Online (Sandbox Code Playgroud)

source-fp.ll:

define double @bleh(double %x) {
entry:
  %addtmp = fadd double %x, %x
  %addtmp1 …
Run Code Online (Sandbox Code Playgroud)

floating-point llvm compiler-optimization

4
推荐指数
1
解决办法
1176
查看次数