标签: sse

现代编译器如何使用mmx/3dnow/sse指令?

我一直在阅读x86指令集扩展,它们在某些特定情况下似乎很有用(例如SSE3中的HADDPD - (Horizo​​ntal-Add-Packed-Double)).这些需要一个特定的寄存器布局,需要有意设置,或者从它之前的一系列指令中进行.像gcc这样的通用编译器多长时间实际使用这些指令(或其子集),还是主要用于手工编码的汇编程序?编译器如何检测使用SIMD指令的适当位置?

compiler-construction x86 assembly gcc sse

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

不同的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
查看次数

长整数例程可以从SSE中受益吗?

我还在研究C++中任意长整数的例程.到目前为止,我已经为64位Intel CPU实现了加/减和乘法.

一切正常,但我想知道我是否可以通过使用SSE来加快速度.我浏览了SSE文档和处理器指令列表,但我找不到任何我认为可以使用的内容,原因如下:

  • SSE有一些整数指令,但大多数指令处理浮点.看起来它不是设计用于整数(例如,是否有较小的整数比较?)

  • SSE的想法是SIMD(相同的指令,多个数据),因此它提供了2或4个独立操作的指令.另一方面,我希望有一个像128位整数加(128位输入和输出)的东西.这似乎不存在.(但是?在AVX2中可能?)

  • 整数加法和减法既不处理输入也不处理输出.因此,手动操作非常麻烦(因而也很慢).

我的问题是:我的评估是正确的还是有什么我忽略的?长整数例程可以从SSE中受益吗?特别是,它们可以帮助我编写更快的添加,子或mul例程吗?

performance integer sse bignum arbitrary-precision

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

SSE(SIMD):通过标量乘以向量

我在程序中执行的常见操作是通过标量缩放矢量(V*s,例如[1,2,3,4]*2 == [2,4,6,8]).是否有SSE(或AVX)指令执行此操作,除了首先在向量中的每个位置加载标量(例如_mm_set_ps(2,2,2,2))然后乘以?

这就是我现在所做的:

__m128 _scalar = _mm_set_ps(s,s,s,s);
__m128 _result = _mm_mul_ps(_vector, _scalar);
Run Code Online (Sandbox Code Playgroud)

我正在寻找像......

__m128 _result = _mm_scale_ps(_vector, s);
Run Code Online (Sandbox Code Playgroud)

c x86 sse simd

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

SSE2整数溢出检查

当使用SSE2指令,如PADDD(即_mm_add_epi32内在),有没有办法来检查任何操作是否溢出?

我想也许MXCSR控制寄存器上的标志可能在溢出后设置,但我没有看到这种情况发生.例如,_mm_getcsr()在以下两种情况下打印相同的值(8064):

#include <iostream>
#include <emmintrin.h>

using namespace std;

void main()
{
    __m128i a = _mm_set_epi32(1, 0, 0, 0);
    __m128i b = _mm_add_epi32(a, a);
    cout << "MXCSR:  " << _mm_getcsr() << endl;
    cout << "Result: " << b.m128i_i32[3] << endl;

    __m128i c = _mm_set_epi32((1<<31)-1, 3, 2, 1);
    __m128i d = _mm_add_epi32(c, c);
    cout << "MXCSR:  " << _mm_getcsr() << endl;
    cout << "Result: " << d.m128i_i32[3] << endl;
}
Run Code Online (Sandbox Code Playgroud)

有没有其他方法来检查SSE2的溢出?

c++ x86 sse simd sse2

19
推荐指数
3
解决办法
3252
查看次数

位向量和浮点向量的快点产品

我试图在i7上以最有效的方式计算浮点数和位向量之间的点积.实际上,我在128或256维向量上进行此操作,但为了说明,让我编写64维代码来说明问题:

// a has 64 elements. b is a bitvector of 64 dimensions.
float dot(float *restrict a, uint64_t b) {
    float sum = 0;
    for(int i=0; b && i<64; i++, b>>=1) {
        if (b & 1) sum += a[i];
    }
    return sum;
}
Run Code Online (Sandbox Code Playgroud)

当然,这是有效的,但问题是,这是整个程序的时间要点(占用50分钟运行的95%CPU时间)所以我迫切需要让它更快.

我的猜测是上面的分支是游戏杀手(防止无序执行,导致坏分支预测).我不确定矢量指令是否可以在这里使用和帮助.使用gcc 4.8和-std = c99 -march = native -mtune = native -Ofast -funroll-loops,我现在得到这个输出

    movl    $4660, %edx
    movl    $5, %ecx
    xorps   %xmm0, %xmm0
    .p2align 4,,10
    .p2align 3
.L4:
    testb   $1, %cl
    je  .L2
    addss   (%rdx), %xmm0
.L2:
    leaq …
Run Code Online (Sandbox Code Playgroud)

c optimization assembly sse x86-64

19
推荐指数
3
解决办法
2841
查看次数

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/AVX高效执行double/int64转换?

SSE2具有在单精度浮点数和32位整数之间转换向量的指令.

  • _mm_cvtps_epi32()
  • _mm_cvtepi32_ps()

但是没有双精度和64位整数的等价物.换句话说,他们失踪了:

  • _mm_cvtpd_epi64()
  • _mm_cvtepi64_pd()

似乎AVX也没有它们.

模拟这些内在函数的最有效方法是什么?

c++ floating-point sse simd avx

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

自动向量化:说服编译器不需要别名检查

我正在做一些图像处理,我从矢量化中受益.我有一个矢量化ok的函数,但是我无法说服编译器输入和输出缓冲区没有重叠,因此不需要进行别名检查.我应该可以使用__restrict__,但如果缓冲区没有定义为__restrict__作为函数参数到达时,没有办法说服编译器我绝对确定2个缓冲区永远不会重叠.

这是功能:

__attribute__((optimize("tree-vectorize","tree-vectorizer-verbose=6")))
void threshold(const cv::Mat& inputRoi, cv::Mat& outputRoi, const unsigned char th) {

    const int height = inputRoi.rows;
    const int width = inputRoi.cols;

    for (int j = 0; j < height; j++) {
        const uint8_t* __restrict in = (const uint8_t* __restrict) inputRoi.ptr(j);
        uint8_t* __restrict out = (uint8_t* __restrict) outputRoi.ptr(j);
        for (int i = 0; i < width; i++) {
           out[i] = (in[i] < valueTh) ? 255 : 0;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我可以说服编译器不执行别名检查的唯一方法是将内部循环放在一个单独的函数中,其中指针被定义为__restrict__参数.如果我将此内部函数声明为内联,则再次激活别名检查.

您可以通过此示例查看效果,我认为这是一致的: …

c++ gcc opencv sse vectorization

18
推荐指数
1
解决办法
2142
查看次数

AVX 256位代码的性能略差于同等的128位SSSE3代码

我正在尝试编写非常有效的汉明距离代码.受WojciechMuła非常聪明的SSE3 popcount 实现的启发,我编写了一个AVX2等效解决方案,这次使用256位寄存器. 基于所涉及的操作的双倍并行性,我预计至少会有30%-40%的改进,但令我惊讶的是,AVX2代码稍慢(约2%)!

有人可以告诉我可能的原因,为什么我没有获得预期的性能提升?

展开,两个64字节块的SSE3汉明距离:

INT32 SSE_PopCount(const UINT32* __restrict pA, const UINT32* __restrict pB) {

   __m128i paccum  = _mm_setzero_si128();

   __m128i a       = _mm_loadu_si128 (reinterpret_cast<const __m128i*>(pA));
   __m128i b       = _mm_loadu_si128 (reinterpret_cast<const __m128i*>(pB));
   __m128i err     = _mm_xor_si128   (a, b);
   __m128i lo      = _mm_and_si128   (err, low_mask);
   __m128i hi      = _mm_srli_epi16  (err, 4);
           hi      = _mm_and_si128   (hi, low_mask);
   __m128i popcnt1 = _mm_shuffle_epi8(lookup, lo);
   __m128i popcnt2 = _mm_shuffle_epi8(lookup, hi);
           paccum  = _mm_add_epi8(paccum, popcnt1);
           paccum  = _mm_add_epi8(paccum, popcnt2);

           a       = _mm_loadu_si128 (reinterpret_cast<const …
Run Code Online (Sandbox Code Playgroud)

c++ performance sse avx2

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