C++ SIMD与压缩和标量双精度的区别

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++的代码双元素吗?或者我需要在比较它们之前以某种方式处理它们吗

在实施SIMD支持时,我正在阅读英特尔的intrinsics指南。我有一些困惑,我的问题如下

  • \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)存在于fp
    ps
    SSE1和
    pd
    SSE2之前。)