12

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

4

2 回答 2

14

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 整数和 shuffle 指令之间的任何转换都没有额外的延迟。并且 SSE FP 和 shuffle 指令之间的任何转换都没有额外的延迟。(虽然我没有测试每条指令)。例如,您可以pshufb在两个 FP 指令之间插入这样的“明显整数”指令,而无需额外延迟。shufpd在整数代码中间插入也不会产生额外的延迟。

由于vextracti128vextractf128由 shuffle 单元执行,因此它们也具有这种“无延迟”属性。

这对于优化混合 int+FP 代码可能很有用。如果您需要将 FP 数据重新解释为整数并同时对寄存器进行 shuffle,只需确保所有 FP 指令都位于 shuffle 之前,并且所有整数指令都在 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

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

    vpxor ymm7, ymm7, ymm7
_benchloop:
    vpaddd ymm0, ymm0, ymm7
    jmp _benchloop

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

    vpxor ymm7, ymm7, ymm7
_benchloop:
    vpand ymm6, ymm7, ymm7
    vpaddd ymm0, ymm0, ymm6
    jmp _benchloop

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

于 2014-09-06T18:15:15.700 回答
3

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

于 2013-09-25T06:09:46.757 回答