C++ SIMD与压缩和标量双精度的区别
在实施SIMD支持时,我正在阅读英特尔的intrinsics指南。我有一些困惑,我的问题如下C++ SIMD与压缩和标量双精度的区别,c++,x86,sse,simd,intrinsics,C++,X86,Sse,Simd,Intrinsics,在实施SIMD支持时,我正在阅读英特尔的intrinsics指南。我有一些困惑,我的问题如下 \uuuum128\umm\ucmpeq\ups(\uuuum128 a,\uuuum128 b)文档中说它用于比较压缩单精度浮点。“打包”是什么意思?在使用浮点值之前,是否需要对其进行打包 对于双精度,有一些内部函数,如\u mm\u cmpeq\u sd,这意味着比较“较低”的双精度浮点元素。上下双精度元件是什么意思?我能用它们来比较C++的代码双元素吗?或者我需要在比较它们之前以某种方式处理它们吗
\uuuum128\umm\ucmpeq\ups(\uuuum128 a,\uuuum128 b)
文档中说它用于比较压缩单精度浮点。“打包”是什么意思?在使用浮点值之前,是否需要对其进行打包\u mm\u cmpeq\u sd
,这意味着比较“较低”的双精度浮点元素。上下双精度元件是什么意思?我能用它们来比较C++的代码<代码>双<代码>元素吗?或者我需要在比较它们之前以某种方式处理它们吗在SSE中,128位寄存器可以表示为4个32位元素或2个64位元素 SSE定义了两种类型的操作;标量和压缩。标量运算只对最低有效数据元素(位0~31或0~63)进行运算,压缩运算并行计算所有元素 设计用于使用双精度(64位)浮点元素,并且只比较两个操作数(标量)中的最低有效数据元素(前64位) 设计用于处理双精度(64位)浮点元素,但会并行比较两组64位(压缩) 设计用于处理单精度(32位)浮点元素,并且只比较两个操作数(标量)中的最低有效数据元素(前32位) 设计用于单精度(32位)浮点元素,并将对每组32位进行并行比较(压缩) 如果您使用的是32位浮点,则可以将浮点打包为四个字节,以利用128位空间。这样,
\u mm\u cmpeq\u ps
将能够并行进行4次比较
如果您使用的是64位double,您可以将double成对打包以利用128位空间。这样,\u-mm\u-cmpeq\u-pd
就可以并行进行两次比较
如果一次只进行一次比较,可以使用\u mm\u cmpeq\u sd
比较两个64位双精度或\u mm\u cmpeq\u ss
比较两个32位浮点值
请注意,\u-mm\u-cmpeq\u-sd
和\u-mm\u-cmpeq\u-pd
是SSE2,而\u-mm\u-cmpeq\u-ss
和\u-mm\u-cmpeq\u-ps是SSE。在这种情况下,“压缩”意味着“将若干相同类型的数据放在一块中”-“压缩单精度浮点”意味着存储为128位值的4*32位浮点数
您需要使用各种pack*
指令将每个值“打包”到寄存器中,或者将数据“打包”到内存中,例如,4个浮点值的(倍数)数组[适当对齐]
标量表示寄存器低位n
位中的“一个值”(例如double
将是128位SSE寄存器的低位64位) 除了“\u mm\u cmpeq\u sd
只比较最低有效数据元素(前32位)”之外,这个答案基本上是可以的\u-mm\u-cmpeq\u-sd
设计用于double
s(因此命令名中的字母d
),因此需要更正:“\u-mm\u-cmpeq\u-sd
将只比较最低有效数据元素(前64位)”。下一段也是类似的误解(一个128位长的寄存器只能容纳2个double,函数名应该以字母“d”结尾)。@zkoza是的,double和float操作之间有混淆,谢谢你指出。我在上一次编辑中修复了它,并添加了所有四个标量/压缩和单/双操作以避免任何混淆。如果您在XMM REG中有多个标量浮点数要洗牌到一个寄存器中,那么您实际上需要使用洗牌unpcklps
pack
指令,如packssdw
是缩小整数运算范围的指令。(因此,用零解包是pack(加宽整数元素)的逆运算,这可能是这种奇怪命名约定的根源。请记住,英特尔的整数SIMD(MMX)存在于fpps
SSE1和pd
SSE2之前。)