有一个一般性的问题moving data between SSE and AVX512 registers。与那个问题相反,现在的问题不是关于汇编指令,而是关于C内部函数。
将两个xmm寄存器插入到一个ymm中有一个内在的方法:__m256_mm256_set_m128(__m128hi,__m128lo),其对应于vinsertf128 instruction,但不存在类似的内在将两个ymm寄存器插入到一个zmm寄存器中,例如假定的__m512_mm512_set_m256(__m256 hi,__m256 lo)。使用汇编指令,当我设置ymm寄存器时(即通过VinsertF128),该操作还明确地清除相应ZMM寄存器的高256位,vinsertf32x8指令的所有intrinsic在输入端已经需要一个512位zmm寄存器,而_mm256_set_m128只返回一个256位ymm寄存器。
从一个zmm寄存器中提取四个xmm寄存器的C内部函数是什么?我不能用定义的寄存器编写汇编函数,我需要将指令与任何可用的寄存器内联。
2条答案
按热度按时间35g0bw711#
提取,使用
要进行汇编,要么遍历内存(例如,存储到一个4
__m128
的数组中,然后从中加载),要么使用一系列插入指令。请注意,插入是跨通道操作,因此非常慢。遍历内存可能会更快,您应该测量它。kse8i1jr2#
我们可以使用下面的intrinsic进行强制转换,它们不产生任何指令:
不同类型有类似的intrinsic:
此外,如果我们需要在相同大小的各种类型之间进行转换,我们可以使用以下类型转换intrinsic:
所有造型说明均在www.example.com上列出https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#ig_expand=6371&cats=Cast
因此,将四个xmm寄存器组合成一个zmm寄存器的代码如下:
它被转换为两个vinsertf 128指令和一个vinsertf 32 x8指令。
因此,一旦我们使用了强制转换intrinsic,这就太容易了。分割的代码是类似的,使用上面提到的强制转换。然而,为了提取最低位,你可能只是从一个更宽的类型转换到一个更窄的类型,并丢失数据。
以下是使用__m128i和__m512i数据类型从一个zmm寄存器中提取四个xmm寄存器的示例:m512_split_m128x4,它转换为3个汇编指令,并直接从输入zmm寄存器产生所有结果,而没有任何中间指令,这些指令会创建依赖链,如Peter Cordes在评论中所建议的:
下面是一个更复杂的例子,使用中间m256_split_m128x2函数;但是,它会创建一个依赖关系链: