Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/141.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++ std::fabs()的优化不好?_C++_Bit Manipulation - Fatal编程技术网

C++ std::fabs()的优化不好?

C++ std::fabs()的优化不好?,c++,bit-manipulation,C++,Bit Manipulation,最近,我正在使用一个应用程序,其代码类似于: for (auto x = 0; x < width - 1 - left; ++x) { // store / reset points temp = hPoint = 0; for(int channel = 0; channel < audioData.size(); channel++) { if (peakmode) /* fir rms of window size */

最近,我正在使用一个应用程序,其代码类似于:

for (auto x = 0; x < width - 1 - left; ++x)
{
    // store / reset points
    temp = hPoint = 0;
    for(int channel = 0; channel < audioData.size(); channel++)
    {
        if (peakmode) /* fir rms of window size */
        {
            for (int z = 0; z < sizeFactor; z++)
            {
                temp += audioData[channel][x * sizeFactor + z + offset];
            }
            hPoint += temp / sizeFactor;
        }
        else /* highest sample in window */
        {
            for (int z = 0; z < sizeFactor; z++)
            {
                temp = audioData[channel][x * sizeFactor + z + offset];
                if (std::fabs(temp) > std::fabs(hPoint))
                hPoint = temp;
            }
        }
        .. some other code
    }
    ... some more code
}
这使得渲染时间减少了12倍,同时仍然产生相同的有效输出。请注意,audiodata中的所有内容都事先经过消毒,不包括NAN/infs/非规范化,并且只有[-1,1]的范围

这种优化是否会产生错误的结果?或者,为什么标准库函数没有这样实现?我想这与处理非正常值有关


e:浮点模型的布局符合ieee,并且sizeof(float)==sizeof(int)==4

那么,您可以将浮点模式设置为符合ieee。通常,使用诸如
--fast math
之类的开关,编译器可以忽略诸如NaN、INF和非规范化之类的IEEE角点情况。如果编译器也使用内部函数,它可能会发出相同的代码


顺便说一句,如果您要假设IEEE格式,那么在比较之前不需要将强制转换为浮点。IEEE格式很好:对于所有正有限值,
a标准库函数如何实现它。。。。依赖于实现。因此,您可能会发现标准库的不同实现具有不同的性能

我想在
int
不是32位的平台上可能会出现问题。您最好使用int32\u t(cstdint>)

就我所知,std::abs以前是内联的吗?或者您观察到的优化主要是由于抑制了函数调用

我突然想到,可以将浮点转换为整数,删除符号位,然后仅使用临时变量将其转换回

不,你不能,因为这违反了法律

这种优化是否会产生错误的结果

从技术上讲,此代码导致未定义的行为,因此它总是给出错误的“结果”。不是绝对值的结果总是意外或不正确的,而是如果程序有未定义的行为,您不可能推理程序的行为

或者,为什么标准库函数没有这样实现

您的怀疑是有道理的,处理非规范值和其他异常值是很棘手的,stdlib函数也需要考虑这些,另一个原因仍然是未定义的行为

一个(非)解决方案,如果您关心性能:

您可以使用联合,而不是强制转换和指针<很不幸,它只在C中工作,而不是C++。< /强>不会导致乌布,但它仍然是不可移植的(尽管它可能与大多数IEEE -75的平台,如果不是全部)一起工作。
但是,当然,这可能比调用
fabs()
快,也可能不快。只有一件事是肯定的:它并不总是正确的。

您可能期望
fabs()
在硬件中实现。毕竟在1980年有一个8087指令。你不会打败硬件。

关于重构如何提高性能的一些观察:

  • 如前所述,
    x*sizeFactor+offset
    可以从内部循环中分解出来

  • peakmode
    实际上是一个改变函数行为的开关-生成两个函数,而不是测试开关的中间循环。这有两个好处:

  • 易于维护
  • 更少的局部变量和代码路径会妨碍优化

  • temp
    除以
    sizeFactor
    可以推迟到
    peakmode
    版本中的
    channel
    循环之外

  • abs(hPoint)
    可以在更新
    hPoint
    时预先计算

  • 如果
    audioData
    是一个向量向量,您可以通过在
    channel
    循环体的开头引用
    audioData[channel]
    来获得一些性能优势,从而将
    z
    循环中的数组索引降低到一维

  • 最后,对
    fabs
    的计算应用您认为合适的任何特定优化。你在这里做的任何事情都会影响便携性,所以这是最后的选择


在VS2008中,使用以下方法跟踪
hpoint
hIsNeg
的绝对值以记住它是正的还是负的速度大约是使用
fabs()的两倍:

int-hIsNeg=0;
...
//内循环,更换
//如果(标准:晶圆厂(温度)>标准:晶圆厂(hPoint))
//H点=温度;
如果(温度<0)
{
如果(-temp>hpoint)
{
hpoint=-temp;
hIsNeg=1;
}
}
其他的
{
如果(温度>hpoint)
{
H点=温度;
hIsNeg=0;
}
}
...
//后循环
如果(hIsNeg)
hpoint=-hpoint;

它取决于浮点数表示法。换句话说,这是一个肮脏的把戏。这些把戏正是实现应该为您做的。它们是实现——它们为特定的平台和浮点表示以及所有其他内容而实现。:-“可能”不是软件工程中应该遇到的词。让我们检查一下。如果你想对优化着迷,这里有这样一个问题:我还将发布一个答案,其中包含一些以便携方式优化功能的建议。真是巧合。就在昨天,我在我的盒子上对各种abs实现进行了一些计时:很好,我不知道!我还将在msvc上尝试/fp开关,尽管我很确定我已经将其设置为fp:fastOn msvc您可以在您的函数(即在全局范围内)之前添加一个
#pragma intrinsic(fabs)
。@MSalters不
/Oi
启用所有的intrinsic,这样您就不需要pragmas了?在(gcc explorer)上可以很好地看到符合IEEE标准的东西“IEEE格式很好”-仅使用符号大小整数表示-0.5<-0.125,但
if ((const float &&)(*((int *)&temp) & ~0x80000000) > (const float &&)(*((int *)&hPoint) & ~0x80000000))
    hPoint = temp;
union {
    float f;
    unsigned u;
} pun = { .f = -3.14 };

pun.u &= ~0x80000000;

printf("abs(-pi) = %f\n", pun.f);
int hIsNeg=0 ;
...
//Inside loop, replacing
//    if (std::fabs(temp) > std::fabs(hPoint))
//        hPoint = temp;
if( temp < 0 )
{
    if( -temp > hpoint )
    {
        hpoint = -temp ;
        hIsNeg = 1 ;
    }
}
else
{
    if( temp > hpoint )
    {
        hpoint = temp ;
        hIsNeg = 0 ;
    }
}
...
//After loop
if( hIsNeg )
    hpoint = -hpoint ;