相关疑难解决方法(0)

浮点除法与浮点乘法

通过编码是否有任何(非微优化)性能增益

float f1 = 200f / 2
Run Code Online (Sandbox Code Playgroud)

在比较中

float f2 = 200f * 0.5
Run Code Online (Sandbox Code Playgroud)

几年前我的一位教授告诉我,浮点除法比浮点乘法慢,但没有详细说明原因.

这句话适用于现代PC架构吗?

UPDATE1

关于评论,请同时考虑这个案例:

float f1;
float f2 = 2
float f3 = 3;
for( i =0 ; i < 1e8; i++)
{
  f1 = (i * f2 + i / f3) * 0.5; //or divide by 2.0f, respectively
}
Run Code Online (Sandbox Code Playgroud)

更新2 从评论中引用:

[我想]知道什么是算法/架构要求导致>除法在硬件上比复制要复杂得多

c++ floating-point micro-optimization

67
推荐指数
5
解决办法
5万
查看次数

什么是IACA以及如何使用它?

我发现了这个有趣且功能强大的工具IACA(英特尔架构代码分析器),但我无法理解它.我能用它做什么,它的局限性是什么?我该怎么做:

  • 用它来分析C或C++中的代码?
  • 用它来分析x86汇编程序中的代码?

c c++ performance assembly iaca

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

如何在编译时检测SSE/SSE2/AVX/AVX2/AVX-512/AVX-128-FMA/KCVI的可用性?

我正在尝试优化一些矩阵计算,我想知道是否有可能在编译时检测SSE/SSE2/AVX/AVX2/AVX-512/AVX-128-FMA/KCVI [1]是否由编译器?理想情况下,对于GCC和Clang,但我只能管理其中一个.

我不确定它是否可能,也许我将使用自己的宏,但我更愿意检测它并要求用户选择它.


[1] "KCVI"代表骑士角矢量指令优化.像FFTW这样的库检测/利用这些较新的指令优化.

gcc sse clang avx avx512

51
推荐指数
1
解决办法
3万
查看次数

快速计算:可以提高准确性而不会损失太多性能?

我正在尝试快速的Exp(x)函数,这个函数之前在这个回答中描述了一个提高C#计算速度的SO问题:

public static double Exp(double x)
{
  var tmp = (long)(1512775 * x + 1072632447);
  return BitConverter.Int64BitsToDouble(tmp << 32);
}
Run Code Online (Sandbox Code Playgroud)

表达式使用一些IEEE浮点"技巧",主要用于神经集.该功能比常规Math.Exp(x)功能快约5倍.

不幸的是,相对于常规Math.Exp(x)函数,数值精度仅为-4% - + 2%,理想情况下,我希望精度至少在亚百分比范围内.

我已经绘制了近似和常规Exp函数之间的商,并且从图中可以看出,相对差异似乎以几乎恒定的频率重复.

快速和常规exp函数之间的商数

是否有可能利用这种规律性来进一步提高"快速exp"功能的准确性而不会显着降低计算速度,或者精度提高的计算开销是否会超过原始表达式的计算增益?

(作为旁注,我也尝试过在同一个SO问题中提出的替代方法之一,但这种方法在C#中似乎没有计算效率,至少在一般情况下并非如此.)

5月14日更新

根据@Adriano的要求,我现在已经执行了一个非常简单的基准测试.我已经使用每个替代exp函数对[-100,100]范围内的浮点值执行了1000万次计算.由于我感兴趣的值范围从-20到0,我还明确列出了x = -5处的函数值.结果如下:

      Math.Exp: 62.525 ms, exp(-5) = 0.00673794699908547
Empty function: 13.769 ms
     ExpNeural: 14.867 ms, exp(-5) = 0.00675211846828461
    ExpSeries8: 15.121 ms, exp(-5) = 0.00641270968867667
   ExpSeries16: 32.046 ms, exp(-5) = 0.00673666189488182
          exp1: 15.062 ms, exp(-5) = -12.3333325982094
          exp2: 15.090 …
Run Code Online (Sandbox Code Playgroud)

c# performance floating-accuracy exp

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

用 10 条或更少的指令实现 tanh(x) 的最佳非三角浮点近似

描述

\n

对于没有内置浮点三角学的机器,我需要一个相当准确的快速双曲正切,因此例如通常的tanh(x) = (exp(2x) - 1) / (exp(2x) + 1)公式将需要近似值exp(2x)
\n所有其他指令,如加法、减法、乘法、除法,甚至 FMA(= 1 次操作中的 MUL+ADD)都存在。

\n

现在我有几个近似值,但没有一个在准确性方面令人满意。

\n

[评论更新:]

\n
    \n
  • trunc()/的说明floor()可用
  • \n
  • 有一种方法可以透明地将浮点数重新解释为整数并执行各种位操作
  • \n
  • 有一系列称为 SEL.xx(.GT、.LE 等)的指令,它们比较 2 个值并选择要写入目标的内容
  • \n
  • DIV 慢两倍,所以没有什么异常,DIV 可以使用
  • \n
\n

方法一

\n

\n

精度:\xc2\xb11.2% 绝对误差,请参见此处

\n

伪代码(A = 累加器寄存器,T = 临时寄存器):

\n
[1] FMA T, 36.f / 73.f, A, A   // T := 36/73 + X^2\n[2] MUL A, A, T                // A := X(36/73 …
Run Code Online (Sandbox Code Playgroud)

algorithm math floating-point ieee-754 approximation

16
推荐指数
2
解决办法
786
查看次数

使用SSE对数,还是切换到FPU?

我正在做一些统计计算.我需要它们快速,所以我重写了大部分内容以使用SSE.我对它很陌生,所以我想知道这里的正确方法是什么:

据我所知,SSE中没有log2或ln功能,至少不能达到4.1,这是我使用的硬件支持的最新版本.

是否更好:

  1. 提取4个浮点数,并对它们进行FPU计算以确定它是否具有熵 - 我不需要将任何这些值加载回SSE寄存器,只需将它们加到另一个浮点数中
  2. 找到执行log2的SSE函数

sse logarithm simd natural-logarithm

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

如何在x64代码中获取exp()函数的内在函数?

我有以下代码,并期望使用函数的内在版本exp().不幸的是,它不是在x64版本中,使其比类似的Win32(即32位版本)慢:

#include "stdafx.h"
#include <cmath>
#include <intrin.h>
#include <iostream>

int main()
{
  const int NUM_ITERATIONS=10000000;
  double expNum=0.00001;
  double result=0.0;

  for (double i=0;i<NUM_ITERATIONS;++i)
  {
    result+=exp(expNum); // <-- The code of interest is here
    expNum+=0.00001;
  }

  // To prevent the above from getting optimized out...
  std::cout << result << '\n';
}
Run Code Online (Sandbox Code Playgroud)

我正在使用以下开关进行构建:

/Zi /nologo /W3 /WX-
/Ox /Ob2 /Oi /Ot /Oy /GL /D "WIN32" /D "NDEBUG" 
/D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /Gm- 
/EHsc /GS /Gy /arch:SSE2 /fp:fast /Zc:wchar_t /Zc:forScope …
Run Code Online (Sandbox Code Playgroud)

c++ visual-studio-2010 intrinsics visual-c++ visual-c++-2010

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

使用AVX最快的指数函数实现

我正在寻找在AVX元件(单精度浮点)上运行的指数函数的有效(快速)近似.即 - __m256 _mm256_exp_ps( __m256 x )没有SVML.

相对精度应该类似于~1e-6,或~20个尾数位(1 ^ 2 ^ 20).

如果用英特尔内在函数用C风格编写,我会很高兴.
代码应该是可移植的(Windows,macOS,Linux,MSVC,ICC,GCC等).


这类似于使用SSE的指数函数的最快实现,但是这个问题寻求非常快速且精度低(当前的答案提供了大约1e-3的精度).

此外,这个问题是寻找AVX/AVX2(和FMA).但请注意,这两个问题的答案很容易在SSE4 __m128或AVX2 之间移植__m256,因此未来读者应根据所需的精度/性能权衡进行选择.

x86 simd avx exponential avx2

7
推荐指数
3
解决办法
1944
查看次数

使用双精度运算的快速SSE低精度指数

我正在寻找快速SSE低精度(~1e-3)指数函数.

我遇到了这个很好的答案:

/* max. rel. error = 3.55959567e-2 on [-87.33654, 88.72283] */
__m128 FastExpSse (__m128 x)
{
    __m128 a = _mm_set1_ps (12102203.0f); /* (1 << 23) / log(2) */
    __m128i b = _mm_set1_epi32 (127 * (1 << 23) - 298765);
    __m128i t = _mm_add_epi32 (_mm_cvtps_epi32 (_mm_mul_ps (a, x)), b);
    return _mm_castsi128_ps (t);
}
Run Code Online (Sandbox Code Playgroud)

根据Nicol N. Schraudolph的工作:NN Schraudolph."指数函数的快速,紧凑近似." Neural Computation,11(4),1999年5月,pp.853-862.

现在我需要一个"双精度"版本:__m128d FastExpSSE (__m128d x).这是因为我不控制输入和输出精度,这恰好是双精度,并且两次转换double - > float,then float - > double占用了50%的CPU资源.

需要做哪些改变?

我天真地试过这个:

__m128i double_to_uint64(__m128d x) { …
Run Code Online (Sandbox Code Playgroud)

c++ precision sse simd exponential

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

如何将VDT的双重版本的Pade Exp fast_ex()的标量代码转换成SSE2?

下面是我想要转换的代码:该double版本的VDT的帕德精通fast_ex()约(这里的老回购资源):

inline double fast_exp(double initial_x){
    double x = initial_x;
    double px=details::fpfloor(details::LOG2E * x +0.5);

    const int32_t n = int32_t(px);

    x -= px * 6.93145751953125E-1;
    x -= px * 1.42860682030941723212E-6;

    const double xx = x * x;

    // px = x * P(x**2).
    px = details::PX1exp;
    px *= xx;
    px += details::PX2exp;
    px *= xx;
    px += details::PX3exp;
    px *= x;

    // Evaluate Q(x**2).
    double qx = details::QX1exp;
    qx *= xx;
    qx += details::QX2exp;
    qx …
Run Code Online (Sandbox Code Playgroud)

c++ intrinsics sse2 exp

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

How does numpy compute an exponential?

After reading this question, I'm wondering what happens under the hood when np.exp is called: what is the mathematical/numerical routine used to derive the values in the returned array? For example, I think that to compute np.sqrt(x), a solution in y to y ** 2 - x = 0 is found using Newton's method.

(np.exp 的文档字符串没有说​​明这是如何完成的)

python math numpy

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

如何使用SSE2处理exp()?

我正在制作一个基本上利用SSE2优化此代码的代码:

double *pA = a;
double *pB = b[voiceIndex];
double *pC = c[voiceIndex];

for (int sampleIndex = 0; sampleIndex < blockSize; sampleIndex++) {
    pC[sampleIndex] = exp((mMin + std::clamp(pA[sampleIndex] + pB[sampleIndex], 0.0, 1.0) * mRange) * ln2per12);
}
Run Code Online (Sandbox Code Playgroud)

在这:

double *pA = a;
double *pB = b[voiceIndex];
double *pC = c[voiceIndex];

// SSE2
__m128d bound_lower = _mm_set1_pd(0.0);
__m128d bound_upper = _mm_set1_pd(1.0);
__m128d rangeLn2per12 = _mm_set1_pd(mRange * ln2per12);
__m128d minLn2per12 = _mm_set1_pd(mMin * ln2per12);

__m128d loaded_a = _mm_load_pd(pA);
__m128d loaded_b = _mm_load_pd(pB); …
Run Code Online (Sandbox Code Playgroud)

c++ simd intrinsics sse2 exp

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