AVX/SSE 在现代 x86_64 CPU 上求幂需要多少个时钟周期?

How many clock cycles does cost AVX/SSE exponentiation on modern x86_64 CPU?

在现代 x86_64 CPU 上 AVX/SSE 求幂需要多少个时钟周期?

我即将:pow(x, y) = exp(y*log(x))

exp()log() AVX x86_64 指令都需要特定的已知循环次数吗?

或者说循环次数会随着指数级数的不同而变化,有没有最大的循环次数可以取幂?

x86 SIMD 指令集(即不是 x87),至少到 AVX2,不包括 SIMD explogpow,但 pow(x,0.5) 这是平方根。

然而,有一些 SIMD 数学库是根据具有这些功能(以及其他功能)的 SIMD 指令构建的。英特尔的 SVML 包括:

__m256 _mm256_exp_ps(__m256)
__m256 _mm256_log_ps(__m256)
__m256 _mm256_pow_ps(__m256, __m256)

英特尔虚伪地称其为内在函数,而实际上它们是通过多条指令运行的。 SVML 是闭源且昂贵的。但是,通过在安装英特尔 OpenCL 运行时后搜索 svml,我在 OpenCL 目录中找到了一些 svml 文件,因此我认为您可以通过英特尔的 OpenCL 运行时间接获取 SVML。

AMD 还提供了一个名为LibM 的SIMD 数学库,它是闭源但免费的,它也有自己的SIMD 数学函数:

__m128 amd_vrs4_expf(__m128)
__m128 amd_vrs4_logf(__m128)
__m128 amd_vrs4_powf(__m128, __m128)

Agner Fog 的 Vector Class Library 提供了 SVML 和 LibM 的接口。请参阅文件 vectormath_lib.h。从这里您可以找出来自 SVML 和 LibM 的相应功能。

Agner 还为这些功能提供了他自己的代码,他声称这些代码可以与专有的 Intel 和 AMD 版本竞争。对于 Agner 的函数版本,请查看 vectormath_exp.h,例如查看 exp_flog_fpow_template_f,然后查看生成的程序集。

您可以使用 SVML、LibM 和 Agner 自己的函数对 explog 函数进行计时。但是,您应该知道 SVML 和 LibM 在其他硬件上运行不佳。例如,AMD 针对 Intel 没有的 FMA4 进行了优化(但 Intel 最初计划拥有 FMA4,然后在 AMD 已经计划 FMA4 后突然更改为 FMA3)。 Intel appears to do something ummm...well I suggest you read about it.

因此,如果您分别在 AMD 或 Intel 处理器上计时 SVML 或 LibM,您可能会得到非常不同的性能结果 (unless you manage to replace Intel's CPU dispatch function)。与 GPU 不同,x86 指令集是公开可用的,因此您可以构建自己的 explog 函数,而这正是 Agner 所做的。


更新

Glibc 2.22(应该很快就会出来)有一个矢量数学库叫做 libmvec。显然它从 -O1 以及 -ffast-math-fopenmp 开始启用。我不确定为什么 fast-math 和 OpenMP 是必需的(特别是在下面的示例中,因为关联数学不是必需的)但是最终在 GNU C 标准库中有一个 SIMD 数学库真是太好了。

//gcc ./cos.c -O1 -fopenmp -ffast-math -lm -mavx2 
#include <math.h>

int N = 3200;
double b[3200];
double a[3200];

int main (void)
{
  int i;

  #pragma omp simd
  for (i = 0; i < N; i += 1)
  {
    b[i] = cos (a[i]);
  }

  return (0);
}