相关疑难解决方法(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
查看次数

SSE-copy,AVX-copy和std :: copy性能

我试图通过SSE和AVX提高复制操作的性能:

    #include <immintrin.h>

    const int sz = 1024;
    float *mas = (float *)_mm_malloc(sz*sizeof(float), 16);
    float *tar = (float *)_mm_malloc(sz*sizeof(float), 16);
    float a=0;
    std::generate(mas, mas+sz, [&](){return ++a;});

    const int nn = 1000;//Number of iteration in tester loops    
    std::chrono::time_point<std::chrono::system_clock> start1, end1, start2, end2, start3, end3; 

    //std::copy testing
    start1 = std::chrono::system_clock::now();
    for(int i=0; i<nn; ++i)
        std::copy(mas, mas+sz, tar);
    end1 = std::chrono::system_clock::now();
    float elapsed1 = std::chrono::duration_cast<std::chrono::microseconds>(end1-start1).count();

    //SSE-copy testing
    start2 = std::chrono::system_clock::now();
    for(int i=0; i<nn; ++i)
    {
        auto _mas = mas;
        auto _tar = tar; …
Run Code Online (Sandbox Code Playgroud)

c++ performance sse simd avx

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

如果您的程序+库不包含SSE指令,那么使用VZEROUPPER是否有用?

我理解VZEROUPPER在混合SSE和AVX代码时使用很重要,但如果我只使用AVX(和普通的x86-64代码)而不使用任何传统的SSE指令呢?

如果我从不在我的代码中使用单个SSE指令,是否有任何性能原因我需要使用VZEROUPPER

这假设我没有调用任何外部库(可能使用SSE).

performance x86 assembly avx micro-optimization

9
推荐指数
1
解决办法
413
查看次数

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 ×3

performance ×3

x86 ×3

assembly ×2

intel ×2

micro-optimization ×2

sse ×2

avx512 ×1

c++ ×1

simd ×1