ARM ASIMD & SVE 向量数学库接口
学校的 A64FX 机器上最近装了 ARM 官方的编译器和加速库套件,我摸了一下。令我无语的是 ARM 的手册里并没有说如何为向量数据类型使用数学函数,只是说他们的编译器可以做自动向量化。我找了一下,反而是从华为鲲鹏的网站上找到了他们的数学库函数说明(顺带吐槽一点华为的数学库也叫 SVML,和英特尔的 Short Vector Math Library 一样),其中列出的接口和此前 GCC 在 x86 平台上的 libmvec 接口命名方式相同。我又查了一下 ARM 加速库里的 libamath 的符号表,果然在里面找到了对应的 SVE 版本接口。下面是我试验过的 ASIMD & SVE 向量数学库接口列表。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | // =============== ASIMD =============== // float32x4_t _ZGVnN4v_logf(float32x4_t a); float64x2_t _ZGVnN2v_log (float64x2_t a); // Kunpeng KML_SVML does not provide vectorized log2() float32x4_t _ZGVnN4v_log2f(float32x4_t a); float64x2_t _ZGVnN2v_log2 (float64x2_t a); float32x4_t _ZGVnN4v_log10f(float32x4_t a); float64x2_t _ZGVnN2v_log10 (float64x2_t a); float32x4_t _ZGVnN4v_expf(float32x4_t a); float64x2_t _ZGVnN2v_exp (float64x2_t a); float32x4_t _ZGVnN4v_exp2f(float32x4_t a); float64x2_t _ZGVnN2v_exp2 (float64x2_t a); // Kunpeng KML_SVML does not provide vectorized exp10() float32x4_t _ZGVnN4v_exp10f(float32x4_t a); float64x2_t _ZGVnN2v_exp10 (float64x2_t a); float32x4_t _ZGVnN4v_powf(float32x4_t a, float32x4_t b); float64x2_t _ZGVnN2v_pow (float64x2_t a, float64x2_t b); float32x4_t _ZGVnN4v_sinf(float32x4_t a); float64x2_t _ZGVnN2v_sin (float64x2_t a); float32x4_t _ZGVnN4v_cosf(float32x4_t a); float64x2_t _ZGVnN2v_cos (float64x2_t a); // =============== SVE (no mask vector) =============== // svfloat32_t _ZGVsNxv_logf(svfloat32_t a); svfloat64_t _ZGVsNxv_log (svfloat64_t a); svfloat32_t _ZGVsNxv_log2f(svfloat32_t a); svfloat64_t _ZGVsNxv_log2 (svfloat64_t a); svfloat32_t _ZGVsNxv_log10f(svfloat32_t a); svfloat64_t _ZGVsNxv_log10 (svfloat64_t a); svfloat32_t _ZGVsNxv_expf(svfloat32_t a); svfloat64_t _ZGVsNxv_exp (svfloat64_t a); svfloat32_t _ZGVsNxv_exp2f(svfloat32_t a); svfloat64_t _ZGVsNxv_exp2 (svfloat64_t a); svfloat32_t _ZGVsNxv_exp10f(svfloat32_t a); svfloat64_t _ZGVsNxv_exp10 (svfloat64_t a); svfloat32_t _ZGVsNxv_powf(svfloat32_t a, svfloat32_t b); svfloat64_t _ZGVsNxv_pow (svfloat64_t a, svfloat64_t b); svfloat32_t _ZGVsNxv_sinf(svfloat32_t a); svfloat64_t _ZGVsNxv_sin (svfloat64_t a); svfloat32_t _ZGVsNxv_cosf(svfloat32_t a); svfloat64_t _ZGVsNxv_cos (svfloat64_t a); // =============== SVE (with mask vector) =============== // svfloat32_t _ZGVsMxv_logf(svbool_t pg, svfloat32_t a); svfloat64_t _ZGVsMxv_log (svbool_t pg, svfloat64_t a); svfloat32_t _ZGVsMxv_log2f(svbool_t pg, svfloat32_t a); svfloat64_t _ZGVsMxv_log2 (svbool_t pg, svfloat64_t a); svfloat32_t _ZGVsMxv_log10f(svbool_t pg, svfloat32_t a); svfloat64_t _ZGVsMxv_log10 (svbool_t pg, svfloat64_t a); svfloat32_t _ZGVsMxv_expf(svbool_t pg, svfloat32_t a); svfloat64_t _ZGVsMxv_exp (svbool_t pg, svfloat64_t a); svfloat32_t _ZGVsMxv_exp2f(svbool_t pg, svfloat32_t a); svfloat64_t _ZGVsMxv_exp2 (svbool_t pg, svfloat64_t a); svfloat32_t _ZGVsMxv_exp10f(svbool_t pg, svfloat32_t a); svfloat64_t _ZGVsMxv_exp10 (svbool_t pg, svfloat64_t a); svfloat32_t _ZGVsMxv_powf(svbool_t pg, svfloat32_t a, svfloat32_t b); svfloat64_t _ZGVsMxv_pow (svbool_t pg, svfloat64_t a, svfloat64_t b); svfloat32_t _ZGVsMxv_sinf(svbool_t pg, svfloat32_t a); svfloat64_t _ZGVsMxv_sin (svbool_t pg, svfloat64_t a); svfloat32_t _ZGVsMxv_cosf(svbool_t pg, svfloat32_t a); svfloat64_t _ZGVsMxv_cos (svbool_t pg, svfloat64_t a); |
还有一些数学函数也有对应的向量化版本,如 tan
, atan
, sinh
, cosh
, tanh
, erf
, 等等,此处未列出。在 A64FX 上,ARM 官方编译器在链接时使用 -armpl
会自动链接对应的 libamath.so,用 GCC 10.2.0 以上版本链接则需要指定 ARM Performance Libraries 的路径并手动指定链接某个 libamath_xxx.so
. 在 ARM21 的相对路径 arm-allinea/21.1/arm-linux-compiler-21.1_Generic-AArch64_RHEL-8_aarch64-linux/lib
下,有若干个 libamath_xxx.so
,xxx 包括 tsv110
, thunderx2t99
, neoverse-n1
, aarch64
, aarch64-sve
, a64fx
.
最后还是要点名批评一下 ARM,是谁给你的自信现在还要对自己基于 LLVM 的编译器和基于其他开源库的加速库收费?在自家平台上功能比你多性能比你强的英特尔 oneAPI 套装现在都已经可以随意免费下载了。