相关疑难解决方法(0)

如果没有Skylake上的VZEROUPPER,为什么这个SSE代码会慢6倍?

我一直试图找出应用程序中的性能问题,并最终将其缩小到一个非常奇怪的问题.如果VZEROUPPER指令被注释掉,则下面的代码在Skylake CPU(i5-6500)上运行速度慢6倍.我测试了Sandy Bridge和Ivy Bridge CPU,两种版本都以相同的速度运行,有或没有VZEROUPPER.

现在我VZEROUPPER对这个代码有了一个相当好的想法,而且我认为当没有VEX编码指令并且没有调用可能包含它们的任何函数时,它对这个代码根本不重要.事实上它不支持其他支持AVX的CPU似乎支持这一点.英特尔®64和IA-32架构优化参考手册中的表11-2也是如此

那么发生了什么?

我留下的唯一理论是,CPU中存在一个错误,它错误地触发了"保存AVX寄存器的上半部分"程序,而不应该这样做.或者其他一些同样奇怪的东西.

这是main.cpp:

#include <immintrin.h>

int slow_function( double i_a, double i_b, double i_c );

int main()
{
    /* DAZ and FTZ, does not change anything here. */
    _mm_setcsr( _mm_getcsr() | 0x8040 );

    /* This instruction fixes performance. */
    __asm__ __volatile__ ( "vzeroupper" : : : );

    int r = 0;
    for( unsigned j = 0; j < 100000000; ++j )
    {
        r |= slow_function( 
                0.84445079384884236262,
                -6.1000481519580951328, …
Run Code Online (Sandbox Code Playgroud)

performance x86 sse intel avx

32
推荐指数
2
解决办法
4072
查看次数

不同的mmx,sse和avx版本是互补的还是互补的?

我想我应该熟悉x86 SIMD扩展.但在我开始之前,我遇到了麻烦.我无法找到关于哪些仍然相关的良好概述.

几十年来,x86架构积累了大量的数学/多媒体扩展:

  • MMX
  • 支持3DNow!
  • SSE
  • SSE2
  • SSE3
  • SSSE3
  • SSE4
  • AVX
  • AVX2
  • AVX512
  • 我忘记了什么吗?

较新的超集是旧的超集,反之亦然?或者它们是互补的吗?

有些人已被弃用吗?哪些仍然相关?我听说过"遗留SSE".

有些是互斥的吗?即他们共享相同的硬件部分?

我应该一起使用哪个来最大化现代Intel/AMD CPU的硬件利用率?为了争论,让我们假设我可以找到适当的指令用途...如果没有别的话,用CPU加热我的房子.

x86 sse avx mmx

20
推荐指数
2
解决办法
4838
查看次数

SIMD指令降低CPU频率

我读了这篇文章。它谈到了为什么AVX-512指令:

英特尔最新的处理器具有高级指令(AVX-512),这可能会导致内核或其他CPU的运行速度变慢,这是因为它们使用了多少电量。

我认为在Agner的博客上也提到了类似的内容(但我找不到确切的帖子)。

我想知道Skylake支持的其他哪些指令会产生类似的效果,即它们会降低功耗以在以后最大化吞吐量吗?所有前缀v指令(如vmovapdvmulpdvaddpdvsubpdvfmadd213pd)?

我正在尝试编译说明列表,以避免在为Xeon Skylake编译C ++应用程序时避免。

optimization x86 intel compiler-optimization avx512

12
推荐指数
2
解决办法
564
查看次数

混合EVEX和VEX编码方案的代价是什么?

这是一个已知的问题是混合VEX编码的指令和非VEX指令有一个点球和程序员必须意识到这一点.

有一些像这样的问题和答案.解决方案取决于您编程的方式(通常您应该zeroupper在转换后使用.但我的问题是关于EVEX编码的方案.只要没有内在函数,例如_mm512_zeroupper()使用VEX编码和EVEX-时似乎没有惩罚但是,EVEX是4字节,VEX是3字节,矢量长度分别是512位和256位.

因为AVX-512不可用(至少对我而言).我想问一下,当我们想要混合它们时,有什么需要注意的.

x86 assembly simd avx512

8
推荐指数
1
解决办法
667
查看次数

Skylake是否需要vzeroupper来使turbo时钟恢复到仅读取ZMM寄存器并写入ak掩码的512位指令后恢复?

编写ZMM寄存器可以使Skylake-X(或类似的)CPU无限期地处于最大涡流降低的状态。(SIMD指令可降低CPU频率动态确定恶意AVX-512指令在何处执行)推测Ice Lake是类似的。

解决方法:zmm16..31不是问题,据@ BeeOnRope的意见,我在报?是有用的,如果你的程序+库不包含SSE指令使用VZEROUPPER 所以这strlen的可以只使用vpxord xmm16,xmm16,xmm16vpcmpeqb,与zmm16)

如果您有硬件,如何进行测试:

@BeeOnRope发布测试代码在RWT线:更换vbroadcastsd zmm15, [zero_dp]vpcmpeqb k0, zmm0, [rdi]为“弄脏”指令,看看是否能运行后循环慢或快。


我假设执行任何512位uop都会暂时触发减少的turbo(同时关闭向量ALU uops的端口1,而512位uop实际上在后端),但问题是:CPU能否在其上恢复如果您vzeroupper仅在读取 ZMM寄存器后就从未使用过,您是否拥有?

(和/或以后的SSE或AVX指令是否会有过渡惩罚或错误的依赖关系?)

具体来说,这样的strlen使用insns vzeroupper在返回之前是否需要a ? (实际上,在任何实际的CPU上,和/或Intel记录的有关面向未来的最佳实践。)假定以后的指令可能包括非VEX SSE和/或VEX编码的AVX1 / 2,而不仅仅是GP整数,以防万一。这与使turbo减少的上256脏情况有关。

; check 64 bytes for zero, strlen building block.
    vpxor     xmm0,xmm0,xmm0    ; zmm0 = 0 using AVX1 implicit zero-extension
    vpcmpeqb  k0, zmm0, [rdi]   ; 512-bit load + ALU, not micro-fused
    ;kortestq k0,k0 / …
Run Code Online (Sandbox Code Playgroud)

x86 assembly intel micro-optimization avx512

5
推荐指数
1
解决办法
109
查看次数

避免AVX-SSE(VEX)过渡处罚

我们的64位应用程序有很多代码(特别是在标准库中),它们在SSE模式下使用xmm0-xmm7寄存器.

我想使用ymm寄存器实现快速内存复制.我无法修改使用xmm寄存器添加VEX前缀的所有代码,我也认为这是不实际的,因为它会增加代码的大小,因为需要CPU解码更大的指令会使它运行得更慢.

我只是想使用两个ymm寄存器(可能是zmm - 支持zmm的经济型处理器可以在今年推出)用于快速内存复制.

问题是:如何使用ymm寄存器但避免过渡处罚?

当我使用ymm8-ymm15寄存器(不是ymm0-ymm7)时会发生惩罚吗?SSE最初有8个128位寄存器(xmm0-xmm7),但在64位模式下,(xmm8-xmm15)也可用于非VEX前缀指令.但是,我已经审查了我们的64位应用程序,它只使用xmm0-xmm7,因为它也有一个32位版本,几乎相同的代码.仅当CPU尝试使用之前使用过的xmm寄存器为ymm并且具有高128位非零值时才会发生惩罚吗?将快速内存复制后使用的ymm寄存器归零是不是更好?例如,我曾使用ymm寄存器复制32个字节的内存 - 将它归零的最快方法是什么?"vpxor ymm15,ymm15,ymm15"足够快吗?(AFAIK,vpxor可以在3个ALU执行端口中的任何一个上执行,p0/p1/p5,而vxorpd只能在p5上执行).是不是将它归零的时间超过使用它来复制32字节内存的收益?

x86 assembly sse avx micro-optimization

4
推荐指数
4
解决办法
908
查看次数

首次使用 AVX 256 位向量会减慢 128 位向量和 AVX 标量运算

最初,我试图重现 Agner Fog 的微架构指南部分“YMM 和 ZMM 向量指令的预热期”中描述的效果,其中写道:

\n
\n

处理器在不使用时关闭向量执行单元的上部部分,以节省电力。在大约 56,000 个时钟周期或 14 \xce\xbcs 的初始预热期间,具有 256 位向量的指令的吞吐量大约比正常情况慢 4.5 倍。

\n
\n

我得到了减速,尽管看起来更接近 2 倍而不是 4.5 倍。但我发现在我的 CPU(Intel i7-9750H Coffee Lake)上,速度下降不仅影响 256 位操作,还影响 128 位向量操作和标量浮点操作(甚至 N 个 GPR-仅限 XMM 触摸指令之后的指令)。

\n

基准程序代码:

\n
# Compile and run:\n# clang++ ymm-throttle.S && ./a.out\n\n.intel_syntax noprefix\n\n.data\nL_F0:\n  .asciz "ref cycles = %u\\n"\n\n.p2align 5\nL_C0:\n  .long 1\n  .long 2\n  .long 3\n  .long 4\n  .long 1\n  .long 2\n  .long 3\n  .long 4\n\n.text\n\n.set initial_scalar_warmup, 5*1000*1000\n.set iteration_count, 30*1000\n.set wait_count, 50*1000\n\n.global _main\n_main:\n …
Run Code Online (Sandbox Code Playgroud)

assembly sse x86-64 simd avx

4
推荐指数
1
解决办法
897
查看次数

是否可以将 ymm16 - ymm31 用于 AVX2 vpcmpeq{size} 指令?

我想知道是否可以按照以下方式做一些事情:

vpcmpeqb %ymm16, %ymm17, %ymm16
Run Code Online (Sandbox Code Playgroud)

尝试使用 gcc 进行编译,我得到:

Assembler messages: Error: unsupported instruction `vpcmpeqb'
Run Code Online (Sandbox Code Playgroud)

AFAICT 这是不可能的felixcloutier说唯一的 EVEX 前缀指令cmpeq有一个掩码目的地,但可能我遗漏了一些东西,或者直接用字节编码来做到这一点。

谢谢!

assembly x86-64 avx avx2 avx512

4
推荐指数
1
解决办法
118
查看次数

AVX2编译的程序是否仍然可以使用支持AVX-512的32个寄存器?

假设以AVX2为目标的编译和C++内在函数,如果我每个体体计算使用17个寄存器编写一个nbody算法,那么第17个寄存器可以间接(寄存器重命名硬件)或直接(visual studio编译器,gcc编译器)映射到AVX上-512注册以减少内存依赖关闭?例如,skylake架构有1或2个AVX-512 fma单元.这个数字是否也改变了总寄存器?(具体来说,至强银4114 cpu)

如果这样可行,它是如何工作的?当所有指令都是AVX2或更低时,第一个硬件线程使用每个ZMM向量的前半部分和第二个硬件线程使用每个ZMM向量的后半部分?


编辑:如果在目标机器上进行在线编译会怎样(例如,使用OpenCL)?司机可以为我注册使用吗?

x86 cpu-architecture cpu-registers compiler-optimization avx512

3
推荐指数
2
解决办法
1012
查看次数

通过 avx 指令向量化间接访问

我最近被介绍了向量指令(理论上)并且对如何使用它们来加速我的应用程序感到兴奋。

我想改进的一个方面是一个非常热的循环:

__declspec(noinline) void pleaseVectorize(int* arr, int* someGlobalArray, int* output)
{
    for (int i = 0; i < 16; ++i)
    {
        auto someIndex = arr[i];
        output[i] = someGlobalArray[someIndex];
    }

    for (int i = 0; i < 16; ++i)
    {
         if (output[i] == 1)
         {
             return i;
         }
    }

    return -1;
}
Run Code Online (Sandbox Code Playgroud)

但是,当然,所有 3 个主要编译器(msvc、gcc、clang)都拒绝对此进行矢量化。我可以理解为什么,但我想得到确认。

如果我必须手动矢量化它,它将是:

(1) VectorLoad "arr", 这带来了 16 个 4 字节整数,让我们说到 zmm0

(2) 16个内存从zmm0[0..3]指向的地址加载到zmm1[0..3],从zmm0[4..7]指向的地址加载到zmm1[4..7]所以等等

(3)比较zmm0和zmm1

(4) 向量 popcnt 到输出中找出最高有效位并基本上除以 8 得到匹配的索引

首先,向量指令可以做这些事情吗?就像他们可以执行这种“收集”操作,即从指向 zmm0 的地址加载?

以下是 clang 生成的内容:

0000000000400530 …
Run Code Online (Sandbox Code Playgroud)

c++ simd vectorization compiler-optimization avx512

3
推荐指数
1
解决办法
697
查看次数

使用 GCC 为 Linux 设备驱动程序编译 Intel AVX 内在函数

我在 corei7 上的 ubuntu 上运行 gcc 版本 4.8.2。

从谷歌搜索中找到了有关 AVX 内在函数的信息,但我不确定这组内在函数是否可以用于 Linux 设备驱动程序并对其进行编译。

如果可以,这里的任何人都可以告诉我什么是 makefile 的正确设置以及在 c 源中包含哪些头文件以使用 gcc 编译这个 avx?

谢谢。

gcc intel linux-device-driver linux-kernel avx

2
推荐指数
2
解决办法
1055
查看次数

我需要在 2021 年使用 _mm256_zeroupper 吗?

摘自Agner Fog 的“用 C++ 优化软件”

在某些 Intel 处理器上混合使用和不使用 AVX 支持编译的代码时会出现问题。由于 YMM 寄存器状态的变化,从 AVX 代码到非 AVX 代码会导致性能下降。在从 AVX 代码到非 AVX 代码的任何转换之前,应该通过调用内部函数 _mm256_zeroupper() 来避免这种惩罚。在以下情况下,这可能是必要的:

• 如果程序的一部分是使用 AVX 支持编译的,而程序的另一部分是在没有 AVX 支持的情况下编译的,则在离开 AVX 部分之前调用 _mm256_zeroupper()。

• 如果使用 CPU 调度在使用和不使用 AVX 的多个版本中编译函数,则在离开 AVX 部分之前调用 _mm256_zeroupper()。

• 如果一段使用AVX 支持编译的代码调用了编译器自带的库以外的库中的函数,而该库没有AVX 支持,则在调用库函数之前先调用_mm256_zeroupper()。

我想知道什么是英特尔处理器。具体来说,是否有过去五年制造的处理器。这样我就知道修复丢失的_mm256_zeroupper()电话是否为时已晚。

c++ sse simd intrinsics avx

2
推荐指数
1
解决办法
137
查看次数