ARM64 固有的 x86_64 点向量积
Posted
技术标签:
【中文标题】ARM64 固有的 x86_64 点向量积【英文标题】:x86_64 Dot Vector Product Intrinsic to ARM64 【发布时间】:2018-08-02 14:30:05 【问题描述】:我正在将一个包含 x86_64 内部函数的小型 C 例程移植到 ARM64 平台。我找不到 _mm_dp_pd 的等效 ARM64 内在函数。
我确实可以访问 arm neon 内在函数。
我不确定如何将 x86_64 内部函数替换为 ARM64 等效项。
任何帮助将不胜感激。
#ifdef ARM64
float32x4_t a, b;
#else
__m128d a, b;
#endif
#ifdef ARM64
????
#else
res = _mm_dp_pd(a, b, mask);
#endif
【问题讨论】:
正确格式化您的代码 "我假设 float32x4_t a; 可以替换 __m128d a;"糟糕的开始。 【参考方案1】:dppd
并不比垂直乘法/随机播放/加法快,实际上在英特尔 CPU (https://agner.org/optimize/) 上解码为 3 微指令,这可能正是这样做的(可能还有一些额外的掩码奖励) .
例如在 Skylake 上,延迟为 9c,p01(FMA 单元所在的位置)为 2 uop,p5(随机播放单元所在的位置)为 1 uop。
在 Ryzen 之前的 AMD 上它甚至更慢(例如 Steamroller 上的 7 微指令),但 Ryzen 将其解码为 3 微指令。 (不过,dpps
仍然很慢,如果您实际上想要四个 32 位 float
元素 (float32x4_t
) 而不是两个 64 位 double
元素 (__m128d
))。
无论如何,假设您希望将点积结果广播到 double
向量的两个元素,请进行垂直乘法,然后交换一个向量并进行垂直加法。
将其移植到 ARM 应该很容易
__m128d prods = _mm_mul_pd(a,b);
__m128d swap = _mm_shuffle_pd(prods,prods, 0b01);
__m128d dot = _mm_add_pd(prods, swap);
或者,如果您只关心低元素,那么您可以使用更简单的 shuffle,例如 movhlps
(Fastest way to do horizontal float vector sum on x86)。
如果您需要将上面的元素归零,就像 dppd
可以做的那样,那么它可能需要在 AArch64 上执行额外的指令。
顺便说一句,如果您正在执行大量 DPPD,您可能希望将数据布局更改为数组结构,这样您就可以并行执行两个点积而无需任何改组,使用mul 和一个 FMA。请参阅https://deplinenoise.wordpress.com/2015/03/06/slides-simd-at-insomniac-games-gdc-2015/,了解有关设计数据布局/整体方法以实现 SIMD 友好的良好说明
但内部循环之外的横向内容并不总是坏事。
【讨论】:
以上是关于ARM64 固有的 x86_64 点向量积的主要内容,如果未能解决你的问题,请参考以下文章
文件是为 arm64 构建的,它不是被链接的架构 (x86_64)
反应原生模块中的“arm64-v8a”、“x86_64”上的应用程序崩溃
目标 'arm64-apple-ios' 在 iOS 'Heimdall' 中出现错误;找到:x86_64“