【发布时间】:2019-08-08 00:52:55
【问题描述】:
我正在尝试编写 SIMD 汇编指令来反转长度在 16 到 32 字节之间的字符串。下面反转一个正好 32 字节长的字符串,但不处理任何更短的字符串。是否有一种 AVX/SSE 方法可以以更简洁的方式更好地做到这一点?我实际上需要 xmm 或 ymm 的 bswap。
Rdx 指向内存中的某个位置,其中包含我想要反转的空终止字符串。反转后,我想用相同地址的反转版本覆盖字符串。
movdqu xmm0, [rdx]
pshufd xmm0,xmm0, 0x1B
pshuflw xmm0,xmm0, 0xB1
pshufhw xmm0, xmm0, 0xB1
movdqa xmm1,xmm0
psrlw xmm1, 8
psllw xmm0, 8
por xmm0,xmm1
movdqu xmm2, [rdx +0x10]
pshufd xmm2,xmm2, 0x1b
pshuflw xmm2,xmm2, 0xB1
pshufhw xmm2, xmm2, 0xB1
movdqa xmm3,xmm2
psrlw xmm3, 8
psllw xmm2, 8
por xmm2,xmm3
movdqu [rdx], xmm2
movdqu [rdx+0x10], xmm0
【问题讨论】:
-
为
pshufb加载一个控制向量以通过一次随机播放来反转整个向量。您在 Intel 上只能获得 1 次随机播放/时钟吞吐量,但vpshufb ymm仍然是单个 uop。所以加载 32 个字节,用vpshufb对 128 位通道进行字节反转,然后用vextracti128分别存储两半。 (或者做窄负载和宽存储。) -
我之前尝试过,但没有成功。有没有比 x86 手册更好的文档可以指点我?我发现的一切都是 C++ 固有的做法,手册本身并不是最清楚的。我对使用这个扩展很陌生。
-
另外,我非常感谢您的回复。
-
您可以编写内在函数并查看编译器输出。或者Intel的x86手册很清楚(felixcloutier.com/x86/pshufb)。不幸的是,这些天来,AVX512 版本的所有内容都有些臃肿,因此请考虑查看 vol.2 的较旧 PDF。不过,Agner Fog 的优化组装指南很不错:agner.org/optimize
-
谢谢你。我非常感谢您提供的信息。