Assembly 如何使用SSE/AVX指令有效地将64位整数的2 x 2矩阵相乘?
有没有办法用SSE或AVX将无符号64位整数的2 x 2矩阵相乘Assembly 如何使用SSE/AVX指令有效地将64位整数的2 x 2矩阵相乘?,assembly,x86-64,matrix-multiplication,Assembly,X86 64,Matrix Multiplication,有没有办法用SSE或AVX将无符号64位整数的2 x 2矩阵相乘 这比不使用SSE/AVX指令更有效?如果只需要结果的底部64位,事情就更容易了。假设ymm0包含矩阵A的四个值,ymm1包含矩阵B的四个值,则可以按如下方式计算乘积: vpermq ymm2,ymm0,0x8D vpermq ymm3,ymm1,0x4E vpermq ymm0,ymm0,0xD8 vpclmullqlqdq xmm4,xmm0,xmm1 vpclmulhqlqdq xmm
这比不使用SSE/AVX指令更有效?如果只需要结果的底部64位,事情就更容易了。假设ymm0包含矩阵A的四个值,ymm1包含矩阵B的四个值,则可以按如下方式计算乘积:
vpermq ymm2,ymm0,0x8D
vpermq ymm3,ymm1,0x4E
vpermq ymm0,ymm0,0xD8
vpclmullqlqdq xmm4,xmm0,xmm1
vpclmulhqlqdq xmm5,xmm0,xmm1
vpclmullqhqdq xmm6,xmm0,xmm1
vpclmulhqhqdq xmm7,xmm0,xmm1
vpclmullqlqdq xmm8,xmm2,xmm3
vpclmulhqlqdq xmm9,xmm2,xmm3
vpclmullqhqdq xmm10,xmm2,xmm3
vpclmulhqhqdq xmm11,xmm2,xmm3
vpunpcklqdq xmm0,xmm4,xmm6
vpunpcklqdq xmm1,xmm5,xmm7
vpunpcklqdq xmm2,xmm8,xmm10
vpunpcklqdq xmm3,xmm9,xmm11
vinserti128 ymm0,ymm0,xmm1,1
vinserti128 ymm2,ymm2,xmm3,1
vpaddq ymm0,ymm0,ymm2
因此,ymm0包含矩阵乘积的四个底部64位整数。如果您想要完整的128位结果,事情会稍微复杂一些(同样,输入时ymm0=矩阵a,ymm1=矩阵B):
然后你可以得到四个128位的矩阵乘积系数,用ymm0和ymm1表示。矩阵是如何用RAM表示的?试着用C编写,让C编译器来解决这个问题。它能够为我生成相当好的代码。答案可能取决于您是否考虑64b x 64b->128b,或者您是否只需要结果的底部64位。这可能还取决于您是否可以将多个独立的2x2矩阵乘法流水线化。@fuz GCC在生成64位整数矩阵乘法的SIMD指令之前,似乎至少需要AVX2。使用多个32x32=>64位SIMD
pmuludq
很难击败标量64位。用于SIMD 64位乘法的AVX512DQ使其更加合理。这看起来很酷,但就我所知,这个问题不是关于无卡利乘法的,使用进位跟随,仍然是编码;)vpclmullqdq
是无进位乘法:异或而不是加法。但是结果中混合了vpaddq
和vpxor
。如果使用vpmuludq
执行此操作,则不需要如此多的洗牌,但这不太可能比4xmul
快(在现代Intel中,端口1和端口6各有4个UOP,完全管道化)。如果您想在YMM regs中获得结果,可以存储/重新加载或vmovq
+随机播放。
vpcmpeqq ymm12,ymm12,ymm12
vpermq ymm2,ymm0,0x8D
vpermq ymm3,ymm1,0x4E
vpermq ymm0,ymm0,0xD8
vpsllq ymm12,ymm12,63
vpclmullqlqdq xmm4,xmm0,xmm1
vpclmulhqlqdq xmm5,xmm0,xmm1
vpclmullqhqdq xmm6,xmm0,xmm1
vpclmulhqhqdq xmm7,xmm0,xmm1
vpclmullqlqdq xmm8,xmm2,xmm3
vpclmulhqlqdq xmm9,xmm2,xmm3
vpclmullqhqdq xmm10,xmm2,xmm3
vpclmulhqhqdq xmm11,xmm2,xmm3
vpunpcklqdq xmm0,xmm4,xmm5
vpunpckhqdq xmm1,xmm4,xmm5
vpunpcklqdq xmm2,xmm6,xmm7
vpunpckhqdq xmm3,xmm6,xmm7
vpunpcklqdq xmm4,xmm8,xmm9
vpunpckhqdq xmm5,xmm8,xmm9
vpunpcklqdq xmm6,xmm10,xmm11
vpunpckhqdq xmm7,xmm10,xmm11
vinserti128 ymm0,ymm0,xmm2,1
vinserti128 ymm1,ymm1,xmm3,1
vinserti128 ymm2,ymm4,xmm6,1
vinserti128 ymm3,ymm5,xmm7,1
vpaddq ymm2,ymm2,ymm0
vpaddq ymm3,ymm3,ymm1
vpxor ymm4,ymm12,ymm0
vpxor ymm5,ymm12,ymm2
vpcmpgtq ymm6,ymm4,ymm5
vpsubq ymm3,ymm3,ymm6
vpunpcklqdq ymm0,ymm2,ymm3
vpunpckhqdq ymm1,ymm2,ymm3