标签: sse2

如何优化循环?

我有以下瓶颈功能.

typedef unsigned char byte;
void CompareArrays(const byte * p1Start, const byte * p1End, const byte * p2, byte * p3)
{
     const byte b1 = 128-30;
     const byte b2 = 128+30;
     for (const byte * p1 = p1Start; p1 != p1End; ++p1, ++p2, ++p3) {
        *p3 = (*p1 < *p2 ) ? b1 : b2;
    }
}
Run Code Online (Sandbox Code Playgroud)

我想C++用SSE2内部函数替换代码.我试过_mm_cmpgt_epi8但它使用了签名比较.我需要无符号比较.

是否有任何技巧(SSE,SSE2,SSSE3)来解决我的问题?

注意: 在这种情况下,我不想使用多线程.

c++ optimization assembly intrinsics sse2

6
推荐指数
1
解决办法
1278
查看次数

SIMD:为什么SSE RGB到YUV颜色转换的速度与c ++实现速度相同?

我刚刚尝试优化RGB到YUV420转换器.使用查找表产生了速度增加,使用定点算法也是如此.但是我期待使用SSE指令获得真正的收益.我的第一次尝试导致代码变慢,并且在链接所有操作之后,它与原始代码的速度大致相同.我的实施中是否有问题,或者SSE指令是否不适合手头的任务?

原始代码的一部分如下:

#define RRGB24YUVCI2_00   0.299
#define RRGB24YUVCI2_01   0.587
#define RRGB24YUVCI2_02   0.114
#define RRGB24YUVCI2_10  -0.147
#define RRGB24YUVCI2_11  -0.289
#define RRGB24YUVCI2_12   0.436
#define RRGB24YUVCI2_20   0.615
#define RRGB24YUVCI2_21  -0.515
#define RRGB24YUVCI2_22  -0.100

void RealRGB24toYUV420Converter::Convert(void* pRgb, void* pY, void* pU, void* pV)
{
  yuvType* py = (yuvType *)pY;
  yuvType* pu = (yuvType *)pU;
  yuvType* pv = (yuvType *)pV;
  unsigned char* src = (unsigned char *)pRgb;

  /// Y have range 0..255, U & V have range -128..127.
  double u,v;
  double r,g,b;

  /// Step in 2x2 …
Run Code Online (Sandbox Code Playgroud)

c++ optimization rgb yuv sse2

6
推荐指数
1
解决办法
5263
查看次数

Visual Studio可以告诉我SSE2寄存器溢出计数的编译代码吗?

我没有任何真正的编译器知识,我曾经为选定的代码段手工编写SSE2函数.我知道如何阅读生成的机器代码,但很大程度上没有意识到编译器可能实现的疯狂优化.我的所有工作都是使用Visual Studio完成的.

有没有办法让Visual Studio告诉我一个函数的SSE2寄存器溢出计数?原因是我们很快就能够批量生成类似SSE2的代码(模板化),并且我们希望将它们中的每一个编译成适当质量的机器代码.我们可能无法手动检查每一个.我希望得到的是一些保证编译的代码是可接受和简洁的.我不需要最后一点果汁.

或者,是否有一个关键字的作用就像__forceinline迫使编译器不溢出任何SSE2寄存器,如"__forcenospill"?(如果必须发生溢出,编译将失败,因此我会发现问题,并尝试重构我的SSE2代码.)

使用现有的矢量库或阻塞器是不可能的,因为有些计算需要高度注册(在"简单操作"中一步操作6个或更多操作数(注1);中间值提升为16位或者32位运行并转换回来等等)用通用向量库来重新表示它将意味着运行时加倍或三倍(在那里,完成了).

商业工具也没关系,鉴于项目的性质,我当然可以负担得起.

如果没有这样的工具,我将采用剖析.您可以关注这篇文章,让我知道这些事情不存在.

谢谢!

(注1)它是一种自适应阈值算法.

compiler-construction optimization sse2 visual-studio

6
推荐指数
0
解决办法
441
查看次数

SIMD数组添加任意数组长度

我正在学习使用SIMD功能,通过使用矢量内在函数重写我的个人图像处理库.一个基本功能是一个简单的"数组+=",即

void arrayAdd(unsigned char* A, unsigned char* B, size_t n) {
    for(size_t i=0; i < n; i++) { B[i] += A[i] };
}
Run Code Online (Sandbox Code Playgroud)

对于任意数组长度,明显的SIMD代码(假设由16对齐)类似于:

size_t i = 0;
__m128i xmm0, xmm1;
n16 = n - (n % 16);
for (; i < n16; i+=16) {
    xmm0 = _mm_load_si128( (__m128i*) (A + i) );
    xmm1 = _mm_load_si128( (__m128i*) (B + i) );
    xmm1 = _mm_add_epi8( xmm0, xmm1 );
    _mm_store_si128( (__m128i*) (B + i), xmm1 );
}
for (; i …
Run Code Online (Sandbox Code Playgroud)

c arrays sse simd sse2

6
推荐指数
1
解决办法
1624
查看次数

simd矢量访问

我是SIMD编程的新手,我有一些基本的问题,我现在看了几天后似乎无法弄清楚.

我想要优化的代码基本上是一个简单但很大的算术公式,自动分析coude并行计算独立的乘法/加法应该相当简单,但我读到自动向量化仅适用于循环.

我已多次阅读,因为应该不惜一切代价避免通过联合或其他方式访问矢量中的单个元素,而应该替换为_mm_shuffle_pd(我只处理双打)...

我知道这是一个非常基本的问题,但我似乎并不知道如何将__m128d向量的内容存储为双精度而不将其作为联合访问.此外,与标量代码相比,这样的操作能否带来任何性能提升?

union {
  __m128d v;
  double d[2];
} vec;
union {
  __m128d v;
double d[2];
} vec2;

vec.v = index1;
vec2.v = index2;
temp1 = _mm_mul_pd(temp1, _mm_set_pd(bvec[vec.d[1]], bvec[vec2[1]]));
Run Code Online (Sandbox Code Playgroud)

此外,两个工会看起来很丑陋,但在使用时

union dvec {
  __m128d v;
  double d[2];
} vec;
Run Code Online (Sandbox Code Playgroud)

试图将indexX声明为dvec,编译器抱怨dvec未声明

c x86 simd intrinsics sse2

6
推荐指数
1
解决办法
2894
查看次数

使用XMM0寄存器和内存提取(C++代码)的速度是仅使用XMM寄存器的ASM的两倍 - 为什么?

我正在尝试实现一些内联汇编程序(在Visual Studio 2012 C++代码中)以利用SSE.我想添加7个数字1e9次,所以我把它们从RAM放到xmm0到xmm6的CPU寄存器中.当我使用此代码在visual studio 2012中使用内联汇编时:

C++代码:

for(int i=0;i<count;i++)
        resVal+=val1+val2+val3+val4+val5+val6+val7;
Run Code Online (Sandbox Code Playgroud)

我的ASM代码:

int count=1000000000;

    double resVal=0.0;
       //placing values to register
    __asm{  
        movsd xmm0,val1;placing var1 in xmm0 register  
        movsd xmm1,val2  
        movsd xmm2,val3  
        movsd xmm3,val4  
        movsd xmm4,val5  
        movsd xmm5,val6  
        movsd xmm6,val7  
        pxor xmm7,xmm7;//turns xmm7 to zero
         }

    for(int i=0;i<count;i++)
    {
        __asm
        {
            addsd xmm7,xmm0;//+=var1
            addsd xmm7,xmm1;//+=var2
            addsd xmm7,xmm2;
            addsd xmm7,xmm3;
            addsd xmm7,xmm4;
            addsd xmm7,xmm5;
            addsd xmm7,xmm6;//+=var7
        }

    }

    __asm
        {
            movsd resVal,xmm7;//placing xmm7 into resVal
        }
Run Code Online (Sandbox Code Playgroud)

这是来自C++编译器的代码'resVal + = val1 + val2 + …

c++ optimization performance assembly sse2

6
推荐指数
1
解决办法
3105
查看次数

使用SSE2(作为浮点数)缩放字节像素值(y = ax + b)?

我想计算y = ax + b,其中x和y是一个像素值[即,值范围为0~255的字节],a而且b是浮点数

由于我需要对图像中的每个像素应用此公式,此外,a和b对于不同的像素是不同的.在C++中直接计算很慢,所以我很有兴趣知道c ++中的sse2指令.

搜索之后,我发现浮点数与sse2的乘法和加法一样_mm_mul_ps_mm_add_ps.但首先,我需要将字节中的x转换为float(4字节).

问题是,在我从字节数据源(_mm_load_si128)加载数据后,如何将数据从byte转换为float?

c++ x86 simd sse2 visual-studio

6
推荐指数
1
解决办法
958
查看次数

gcc -mno-sse2舍入

我正在做一个我做RGB转换为luma的项目,而且我对-mno-sse2标志有一些舍入问题:

这是测试代码:

#include <stdio.h>
#include <stdint.h>

static double rec709_luma_coeff[3] = {0.2126, 0.7152, 0.0722};

int main()
{
    uint16_t n = 242 * rec709_luma_coeff[0] + 242 * rec709_luma_coeff[1] + 242 * rec709_luma_coeff[2];

    printf("%u\n", n);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

而这就是我得到的:

user@gentoo>gcc -mno-sse2 test.c -o test && ./test
241
user@gentoo> gcc test.c -o test && ./test
242
Run Code Online (Sandbox Code Playgroud)

我想gcc使用sse2优化进行double乘法,但我没有得到的是为什么优化版本是正确的.

另外,您建议我使用什么来获得更一致的结果,ceil()或者floor()

c gcc compilation rounding sse2

6
推荐指数
1
解决办法
276
查看次数

如何将VDT的双重版本的Pade Exp fast_ex()的标量代码转换成SSE2?

下面是我想要转换的代码:该double版本的VDT的帕德精通fast_ex()约(这里的老回购资源):

inline double fast_exp(double initial_x){
    double x = initial_x;
    double px=details::fpfloor(details::LOG2E * x +0.5);

    const int32_t n = int32_t(px);

    x -= px * 6.93145751953125E-1;
    x -= px * 1.42860682030941723212E-6;

    const double xx = x * x;

    // px = x * P(x**2).
    px = details::PX1exp;
    px *= xx;
    px += details::PX2exp;
    px *= xx;
    px += details::PX3exp;
    px *= x;

    // Evaluate Q(x**2).
    double qx = details::QX1exp;
    qx *= xx;
    qx += details::QX2exp;
    qx …
Run Code Online (Sandbox Code Playgroud)

c++ intrinsics sse2 exp

6
推荐指数
1
解决办法
159
查看次数

使用 SSE2 将 unsigned int 钳位为 0x10000

我想仅使用 SSE2指令将 32 位无符号整数钳制为固定值 (0x10000)。

基本上,这个 C 代码: if (c>0x10000) c=0x10000;

下面的代码有效,但我想知道是否可以简化它,考虑到它是一个特定的常量(0xFFFF+0x0001)

movdqa    xmm3, xmm0 <-- xmm0 contains 4 dword unsigned values
movdqa    xmm4, xmm5 <-- xmm5: four dword 0x10000 values
pxor      xmm3, xmm5
pcmpgtd   xmm4, xmm0
psrad     xmm3, 31
pxor      xmm4, xmm3
pand      xmm0, xmm4
pandn     xmm4, xmm5
por       xmm0, xmm4
Run Code Online (Sandbox Code Playgroud)

的值c在 0x00000000-0xFFFFFFFF 范围内,但假设它在 0x00000000-0x00FFFFFF 或 0x00000000-0x00FF0000 范围内的代码可能是可接受的。

x86 assembly simd sse2 clamp

6
推荐指数
3
解决办法
253
查看次数