相关疑难解决方法(0)

对于浮点数和双精度,快速乘法/除2(C/C++)

在我正在编写的软件中,我正在进行数百万乘法或除以2(或2的幂)的值.我真的希望这些值int能够访问bitshift运算符

int a = 1;
int b = a<<24
Run Code Online (Sandbox Code Playgroud)

但是,我不能,而且我必须坚持双打.

我的问题是:由于存在双精度(符号,指数,尾数)的标准表示,是否有一种方法可以与指数一起使用以2的幂来获得快速乘法/除法

我甚至可以假设位数将被修复(该软件将在总是具有64位长的双倍的机器上工作)

PS:是的,该算法主要只执行这些操作.这是瓶颈(它已经是多线程的).

编辑:或者我完全错了,聪明的编译器已经为我优化了一些东西?


临时结果(用Qt测量时间,矫枉过正,但我​​不在乎):

#include <QtCore/QCoreApplication>
#include <QtCore/QElapsedTimer>
#include <QtCore/QDebug>

#include <iostream>
#include <math.h>

using namespace std;

int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);

while(true)
{
    QElapsedTimer timer;
    timer.start();

    int n=100000000;
    volatile double d=12.4;
    volatile double D;
    for(unsigned int i=0; i<n; ++i)
    {
        //D = d*32;      // 200 ms
        //D = d*(1<<5);  // 200 ms
        D = ldexp (d,5); // 6000 ms
    } …
Run Code Online (Sandbox Code Playgroud)

c c++ optimization multiplication division

25
推荐指数
4
解决办法
2万
查看次数

为什么 GCC 和 Clang 不使用指数的浮点到整数 PADDD 来优化乘以 2^n 的乘法,即使使用 -ffast-math 也是如此?

考虑到这个功能,

float mulHalf(float x) {
    return x * 0.5f;
}
Run Code Online (Sandbox Code Playgroud)

以下函数与正常输入/输出产生相同的结果。

float mulHalf_opt(float x) {
    __m128i e = _mm_set1_epi32(-1 << 23);
    __asm__ ("paddd\t%0, %1" : "+x"(x) : "xm"(e));
    return x;
}
Run Code Online (Sandbox Code Playgroud)

这是带有 的汇编输出-O3 -ffast-math

mulHalf:
        mulss   xmm0, DWORD PTR .LC0[rip]
        ret

mulHalf_opt:
        paddd   xmm0, XMMWORD PTR .LC1[rip]
        ret
Run Code Online (Sandbox Code Playgroud)

-ffast-math启用-ffinite-math-only“假设参数和结果不是 NaN 或 +-Infs” [1]

因此,如果在 的容差下生成更快的代码,则的编译输出可能会更好地与onmulHalf一起使用。paddd-ffast-math-ffast-math

我从Intel Intrinsics Guide中获得了下表。

(MULSS)
Architecture    Latency Throughput (CPI)
Skylake         4       0.5 …
Run Code Online (Sandbox Code Playgroud)

c floating-point x86 assembly compiler-optimization

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

编译器是否允许优化浮点常数乘法

可疑的代码如下:

float32_t f = someValueFromSomewhere;
f = f * 4;
Run Code Online (Sandbox Code Playgroud)

编译器会优化这个吗?根据C-Standard(如果我理解正确的话),必须将第二个操作数提升为float32_t; 因此,乘法必须使用FPU(或fp仿真)完成.

从理论上讲,只需添加一个立即(可能是溢出检查),就可以在普通硬件寄存器中完成操作.编译器是否允许进行此优化?是否有编译器可以这样做?如果是这样,他们也会认出这个表达

f = f * 4.0f;
Run Code Online (Sandbox Code Playgroud)

这是避免静态代码检查器有关隐式转换的警告所必需的吗?

一些补充:我知道从标准的角度来看两条线都是等价的.但显然编译器可以区分它们.所以问题是在哪个时候允许优化器第一次看到代码(或更好的内部表示).

c floating-point compiler-optimization

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