vextracti128和vextractf128有什么区别?

use*_*757 9 x86 simd avx avx2

vextracti128vextractf128具有相同的功能,参数和返回值.另外一个是AVX指令集,而另一个是AVX2.有什么不同?

Evg*_*uev 11

vextracti128并且vextractf128不仅具有相同的功能,参数和返回值.它们具有相同的指令长度.并且它们具有相同的吞吐量(根据Agner Fog的优化手册).

不完全清楚的是它们的延迟值(具有依赖链的紧密循环中的性能).指令本身的延迟是3个周期.但在阅读英特尔优化手册的第2.1.3节("执行引擎")之后,我们可能会怀疑vextracti128在处理浮点数据时vextractf128应该获得额外的1个时钟延迟,并且在处理整数数据时应该获得额外的1个时钟延迟.测量表明这不是真的,延迟总是保持3个周期(至少对于Haswell处理器而言).据我所知,优化手册中的任何地方都没有记录.

静止指令集只是处理器的接口.Haswell是此接口的唯一实现,包含这两个指令(暂时).我们可以忽略这些指令的实现(很可能)相同的事实.并按预期使用这些指令 - vextracti128用于整数数据和vextractf128FP数据.(如果我们只需要在不执行任何int/FP操作的情况下重新排序数据,那么显而易见的选择是vextractf128由几个较旧的处理器支持).同样经验表明,英特尔有时会降低下一代CPU中某些指令的性能,因此明智的做法是遵守这些指令的亲和性,以避免将来出现任何可能的速度降级.

由于英特尔优化手册不是非常详细地描述了用于SIMD指令的int/FP域之间的关系,我已经做了一些测量(在Haswell上)并获得了一些有趣的结果:


随机指示

SSE整数和随机指令之间的任何转换都没有额外的延迟.并且SSE FP和shuffle指令之间的任何转换都没有额外的延迟.(虽然我没有测试每条指令).例如,您可以pshufb在两个FP指令之间插入这样的"明显整数"指令而不会有额外的延迟.shufpd在整数代码的中间插入也不会产生额外的延迟.

由于vextracti128vextractf128由shuffle单位执行,他们也有这种"无延迟"属性.

这可能对优化混合int + FP代码很有用.如果您需要将FP数据重新解释为整数并同时对寄存器进行随机播放,只需确保所有FP指令都在shuffle之前,并且所有整数指令都在它之后.


FP逻辑指令

andps 和其他FP逻辑指令也具有忽略FP/int域的属性.

如果pand在FP代码中添加整数逻辑指令(如),则会产生额外的2个周期延迟(一个到达int域,另一个到达FP).所以SIMD FP代码的明显选择是andps.同样andps可以在整数代码的中间使用而没有任何延迟.更好的是在int和FP指令之间使用这样的指令.有趣的是,FP逻辑指令使用与所有shuffle指令相同的端口号5.


注册访问

英特尔优化手册描述了生产者和消费者微操作之间的旁路延迟.但它并没有说明微操作如何与寄存器相互作用.

这段代码每次迭代只需要3个时钟(正如所要求的那样vaddps):

    vxorps ymm7, ymm7, ymm7
_benchloop:
    vaddps ymm0, ymm0, ymm7
    jmp _benchloop
Run Code Online (Sandbox Code Playgroud)

但是这个每次迭代需要2个时钟(比需要多1个vpaddd):

    vpxor ymm7, ymm7, ymm7
_benchloop:
    vpaddd ymm0, ymm0, ymm7
    jmp _benchloop
Run Code Online (Sandbox Code Playgroud)

这里唯一的区别是整数域而不是FP域的计算.要获得1个时钟/迭代,我们需要添加一条指令:

    vpxor ymm7, ymm7, ymm7
_benchloop:
    vpand ymm6, ymm7, ymm7
    vpaddd ymm0, ymm0, ymm6
    jmp _benchloop
Run Code Online (Sandbox Code Playgroud)

其中暗示:(1)存储在SIMD寄存器中的所有值都属于FP域,(2)从SIMD寄存器读取会使整数运算的延迟增加1.(这里{ymm0,ymm6}和ymm7之间的区别在于ymm7存储在一些临时存储器中并且作为真正的"寄存器"工作,而ymm0和ymm6是临时的并且由内部CPU的互连状态而不是某些永久存储器表示,所以ymm0和ymm6不是"读"但只是在微操作之间传递.


Pau*_*l R 3

好问题 - 看起来 AVX 指令vextractf128适用于任何向量类型(int、float、double),而 AVX2 指令vextracti128仅适用于 int 向量。我建议当你有 AVX2 和整数向量时使用后者,以防它在某些情况下提供更好的性能,否则使用前者。