我正在使用C内部函数处理从SSE到NEON的端口。我有两个由32位字组成的128位块:

[A1  A2  A3  A4] [B1  B2  B3  B4]

我需要把它们分成两部分:
[A1  B1  A2  B2] [A3  B3  A4  B4]

128位块及其相关的步幅给我带来了麻烦。我看过ARM的NEON Part 1: Load and Stores,但我没有看到超过两个16字节块的内容。
如何从两个128位块收集数据?

最佳答案

VZIP.32正是你想要的

from MSB to LSB:
q0: A4 | A3 | A2 | A1
q1: B4 | B3 | B2 | B1

vzip.32 q0, q1

q0: B2 | A2 | B1 | A1
q1: B4 | A4 | B3 | A3

但在aarch64上,情况却大不相同。
from MSB to LSB:
v0: A4 | A3 | A2 | A1
v1: B4 | B3 | B2 | B1

zip2 v2.4s, v0.4s, v1.4s
zip1 v3.4s, v0.4s, v1.4s

v2: B2 | A2 | B1 | A1
v3: B4 | A4 | B3 | A3

你不应该把时间浪费在本质上。
我的汇编版本4x4矩阵乘法(float,complex)的运行速度几乎是Clang编译的“spoon-fed”内部函数版本的三倍。
*GCC(7.1.1)编译的版本比Clang编译的版本稍快,但速度不太快。
下面是以32位整数为例的intrinsics版本。它适用于A-32霓虹灯、Aarch32和Aarch64。
uint32x4_t vecA, vecB;
...

uint32x4x2_t vecR = vzipq_u32(vecA, vecB);
uint32x4_t vecX = vecR.val[0];
uint32x4_t vecY = vecR.val[1];

请注意,vzip2合并第一个(下)半部分,而vzip1合并第二个(上)半部分。可通过uint32x4x2_tval[0]val[1]访问它们。一旦对val[]进行访问,编译器就可以选择zip1zip2指令。

10-08 08:33