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 指令都需要特定的已知循环次数吗?
- exp():
_mm256_exp_ps()
- 日志():
_mm256_log_ps()
或者说循环次数会随着指数级数的不同而变化,有没有最大的循环次数可以取幂?
x86 SIMD 指令集(即不是 x87),至少到 AVX2,不包括 SIMD exp
、log
或 pow
,但 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_f
、log_f
和 pow_template_f
,然后查看生成的程序集。
您可以使用 SVML、LibM 和 Agner 自己的函数对 exp
和 log
函数进行计时。但是,您应该知道 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 指令集是公开可用的,因此您可以构建自己的 exp
和 log
函数,而这正是 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);
}
在现代 x86_64 CPU 上 AVX/SSE 求幂需要多少个时钟周期?
我即将:pow(x, y) = exp(y*log(x))
即exp()
和 log()
AVX x86_64 指令都需要特定的已知循环次数吗?
- exp():
_mm256_exp_ps()
- 日志():
_mm256_log_ps()
或者说循环次数会随着指数级数的不同而变化,有没有最大的循环次数可以取幂?
x86 SIMD 指令集(即不是 x87),至少到 AVX2,不包括 SIMD exp
、log
或 pow
,但 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_f
、log_f
和 pow_template_f
,然后查看生成的程序集。
您可以使用 SVML、LibM 和 Agner 自己的函数对 exp
和 log
函数进行计时。但是,您应该知道 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 指令集是公开可用的,因此您可以构建自己的 exp
和 log
函数,而这正是 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);
}