我正在将一个包含x86_64内在函数的小型C例程移植到ARM64平台。我找不到_mm_dp_pd的等效ARM64内在函数。
我确实可以使用手臂霓虹灯内部函数。
我不确定如何用等效的ARM64替换x86_64内在函数。
任何帮助将不胜感激。
#ifdef ARM64
float32x4_t a, b;
#else
__m128d a, b;
#endif
#ifdef ARM64
????
#else
res = _mm_dp_pd(a, b, mask);
#endif
答案 0 :(得分:0)
dppd
的速度并不比垂直乘/洗/加的速度快,并且实际上在Intel CPU(https://agner.org/optimize/)上解码为3 oups可能做到了这一点(也许还有一些额外的好处)为面具)。
例如在Skylake上,它的延迟为9c,p01(FMA单元所在的位置)的延迟为2uop,p5(shuffle单元所在的位置)的延迟为1uop。
在Ryzen之前的AMD上它甚至更慢(例如Steamroller上为7微秒),但是Ryzen将其解码为3微秒。 (dpps
仍然很慢,以防万一,您实际上想要四个32位float
元素(float32x4_t
)而不是两个64位double
元素({{1 }})。
无论如何,假设您希望将点积结果广播到__m128d
向量的两个元素上,请进行垂直乘法,然后交换一个向量并进行垂直加法。
将其移植到ARM应该很容易
double
或者,如果您只关心低元素,则可以使用更简单的随机播放,例如__m128d prods = _mm_mul_pd(a,b);
__m128d swap = _mm_shuffle_pd(prods,prods, 0b01);
__m128d dot = _mm_add_pd(prods, swap);
(Fastest way to do horizontal float vector sum on x86)。
如果您需要将上位元素清零,例如movhlps
,那么可能需要在AArch64上附加一条指令。
顺便说一句,顺便说一句,如果您要执行大量DPPD,则可能需要考虑将数据布局更改为数组结构,因此可以并行执行两个点积而无需进行任何改组, mul和FMA。请参阅https://deplinenoise.wordpress.com/2015/03/06/slides-simd-at-insomniac-games-gdc-2015/,以获得有关将数据布局/整个方法设计为SIMD友好的良好解释
但是内循环之外的水平东西并不总是坏的。