标签: mmx

SSE内在函数中的if/else语句

我正在尝试使用SSE内在函数优化一小段代码(我是关于该主题的完全初学者),但我有点坚持使用条件.

我原来的代码是:

unsigned long c;
unsigned long constant = 0x12345678;
unsigned long table[256];
int n, k;

for( n = 0; n < 256; n++ )
{
  c = n;
  for( k = 0; k < 8; k++ )
    {
      if( c & 1 ) c = constant ^ (c >> 1);
      else c >>= 1;
    }
  table[n] = c;
}
Run Code Online (Sandbox Code Playgroud)

这段代码的目标是计算一个crc表(常量可以是任何多项式,它在这里不起作用),

我想我的优化代码是这样的:

__m128 x;
__m128 y;
__m128 *table;

x = _mm_set_ps(3, 2, 1, 0);
y = _mm_set_ps(3, 2, 1, 0); …
Run Code Online (Sandbox Code Playgroud)

c++ if-statement sse intrinsics mmx

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

MMX 寄存器是否总是存在于现代处理器中?

当我查看最近处理器的图表和概述时 [1],我从未看到提及 MMX 寄存器 MM0 - MM7。但从规格来看,它们似乎仍然存在。可以依赖它们存在于支持 SSE 的所有处理器中吗?除了更旧的 FPU 堆栈之外,它们是否与其他任何东西冲突?它们是否与一般 64 位的物理寄存器相同?

虽然 XMM 和 YMM 对于向量要好得多,但我偶尔想使用 MMX 寄存器来存储值,否则这些值会溢出到堆栈中。Speedwise 这看起来好一点,而且有时我想避免额外的商店和负载。

[1] http://www.realworldtech.com/haswell-cpu/

x86 assembly cpu-registers mmx amd-processor

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

SSE内在函数:将32位浮点数转换为UNSIGNED 8位整数

使用SSE内在函数,我得到了一个四个32位浮点数的向量,它被钳位到0-255范围并四舍五入到最接近的整数.我现在想把这四个写成字节.

有一个内部函数_mm_cvtps_pi8会将32位转换为8位有符号整数,但问题是任何超过127的值都会被钳位到127.我找不到任何会压缩无符号8位值的指令.

我有一种直觉,我可能想要做的是移动指令的一些组合_mm_cvtps_pi16_mm_shuffle_pi8后面的操作,以获得我关心的四个字节到内存中.这是最好的方法吗?我将看看我是否可以弄清楚如何编码shuffle控制掩码.

更新:以下似乎完全符合我的要求.有没有更好的办法?

#include <tmmintrin.h>
#include <stdio.h>

unsigned char out[8];
unsigned char shuf[8] = { 0, 2, 4, 6, 128, 128, 128, 128 };
float ins[4] = {500, 0, 120, 240};

int main()
{
    __m128 x = _mm_load_ps(ins);    // Load the floats
    __m64 y = _mm_cvtps_pi16(x);    // Convert them to 16-bit ints
    __m64 sh = *(__m64*)shuf;       // Get the shuffle mask into a register
    y = _mm_shuffle_pi8(y, sh);     // Shuffle the …
Run Code Online (Sandbox Code Playgroud)

x86 sse mmx

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

有没有办法使用MMX / SSE减去x86上饱和的压缩无符号双字?

我一直在看MMX / SSE,我想知道。对于无符号字节和字(而非双字),有打包,饱和减法的说明。

有什么方法可以做我想要的,如果没有,为什么没有呢?

x86 assembly sse mmx saturation-arithmetic

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

对于 64 位目标,在 MSVC 2019 中找不到像 _mm_cvtpd_pi32 这样的 MMX 内在函数;与 2013 年相比有何变化?

我目前正在将大型代码库从 VS2013 更新到 VS2019。我遇到的编译器错误之一如下:

内部函数.h(348):错误C3861:“_mm_cvtpd_pi32”:未找到标识符

这个内部函数在 Visual Studio 的“emmintrin.h”中定义。我只在针对 64 位构建时收到此错误。仔细检查会发现,在 2013 年到 2019 年之间,emmintrin.h 的定义从这个改变了:

extern __m64 _mm_cvtpd_pi32(__m128d _A);
extern __m64 _mm_cvttpd_pi32(__m128d _A);
extern __m128d _mm_cvtpi32_pd(__m64 _A);
Run Code Online (Sandbox Code Playgroud)

对此:

#if defined(_M_IX86)
extern __m64 _mm_cvtpd_pi32(__m128d _A);
extern __m64 _mm_cvttpd_pi32(__m128d _A);
extern __m128d _mm_cvtpi32_pd(__m64 _A);
#endif
Run Code Online (Sandbox Code Playgroud)

即:预处理器指令确保函数现在仅可用于 32 位目标。无论目标是什么(64 位或 32 位),产生错误的第 3 方头文件都会使用这些函数。据推测,这里最好的做法是编辑这个头文件,以确保仅对 32 位目标调用此函数。然而,我更好奇的是,为什么从 2013 年到 2019 年发生了变化?我在这里看到了这个函数的描述:

https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtpd_pi32&expand=1705

从一开始它就从未适用于 64 位目标吗?或者它是否已被我需要考虑的 64 位版本替换?

x86-64 intrinsics visual-c++ mmx visual-studio-2019

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

内在向量元素类型(如 epi64x 或 pi32)的名称和含义是什么?

英特尔内在函数的名称中内置了向量的子类型。例如,_mm_set1_ps是 a ps,即packed single-precisionaka。A float。尽管它们中的大多数的含义是明确的,但它们的“全名”packed single-precision从功能描述中并不总是清晰的。我创建了下表。不幸的是,有些条目丢失了。它们有何价值?其他问题见表下方。

缩写 全名 C/++ 等效项
附注 压缩单精度 漂浮
酸碱度 压缩半精度 没有任何**
PD 压缩双精度 双倍的
个人电脑 压缩半精度复数 没有任何**
pi8 ??? int8_t
PI16 ??? int16_t
pi32 ??? int32_t
Epi8 ??? int8_t
表观16 ??? int16_t
表观32 ??? int32_t
表观64 ??? int64_t
外延64x ??? int64_t

附加问题:

  1. 我有错过任何吗?
  2. epiX和 和有什么区别piX
  3. 为什么不pi64存在?
  4. epi64和 和有什么区别epi64x

** 我发现了这个,但似乎没有标准方法来表示 C/++ 中的半精度(复数)值。如果这有任何改变,请纠正我。

sse intel intrinsics sse2 mmx

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

同时使用多个SIMD指令集的好处

我正在编写一个多线程的高度并行应用程序.我已经编写了一个SSE加速线程类.如果我要写一个MMX加速线程类,那么同时运行两个(一个SSE线程和每个核心一个MMX线程)性能会明显提高吗?

我认为这个设置有助于隐藏内存延迟,但我想在开始花时间之前确定它.

c c++ sse simd mmx

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

将 MMX/SSE 指令移植到 AltiVec

我在 ASM 方面的经验极其有限,在 SIMD 方面的经验就更少了。

但碰巧我有以下 MMX/SSE 优化代码,我想将其移植到 AltiVec 指令以在 PPC/Cell 处理器上使用。

这可能是一个很大的问题..尽管只有几行代码,但我在尝试弄清楚这里发生的事情时遇到了无穷无尽的麻烦。

原函数:

static inline int convolve(const short *a, const short *b, int n)
{
    int out = 0;
    union {
        __m64 m64;
        int i32[2];
    } tmp;
    tmp.i32[0] = 0;
    tmp.i32[1] = 0;
    while (n >= 4) {
        tmp.m64 = _mm_add_pi32(tmp.m64,
                               _mm_madd_pi16(*((__m64 *)a),
                                             *((__m64 *)b)));
        a += 4;
        b += 4;
        n -= 4;
    }
    out = tmp.i32[0] + tmp.i32[1];
    _mm_empty();

    while (n --)
        out += (*(a++)) * (*(b++)); …
Run Code Online (Sandbox Code Playgroud)

c simd altivec mmx

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

MMX指令和x87 FPU标记字

section .data
    qVar1: dq 1


section .bss
    var28: resb  28


section .text
    _main:

        ; Use an MMX instruction

            movq mm0, [qVar1] ; Move quadword from r/m64 to mm.

        ; Read Tag Word

            fstenv [var28]
            mov    ax, [var28 + 8] ; move the Tag Word to ax
Run Code Online (Sandbox Code Playgroud)

这一刻ax0101 0101 0101 0110

但是从英特尔手册,第9.5.1MMX指令和x87 FPU标签字,我引用:

在每个MMX指令之后,整个x87 FPU标记字被设置为有效(00B).

那么为什么ax不是全零呢?

x86 assembly fpu x87 mmx

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

为什么xmm逻辑移位不起作用?

我在xmm1寄存器中加载了一些内容,让我们说它可以被视为

xmm1 = | bgra | bgra | bgra | bgra | (each one a dw)
Run Code Online (Sandbox Code Playgroud)

现在,我希望每个双字在逻辑上向右移1个字节,所以它最终会像这样:

xmm1 = | 0bgr | 0bgr | 0bgr | 0bgr | (each one a dw)
Run Code Online (Sandbox Code Playgroud)

我在intel doc上发现我可能正在寻找函数"psrld": 在此输入图像描述

然而,它起初并没有像我预期的那样发挥xmm1作用

xmm1           {v4_float = {0x0, 0x0, 0x0, 0x0}, v2_double = {0x0, 0x0}, v16_int8 = {0x37, 0x51, 0x9e, 0x0, 0x3e, 0x58, 0xa5, 0x0, 0x3e, 0x5a, 0xa7, 0x0, 0x4a, 0x66, 0xb3, 0x0}, v8_int16 = {0x5137, 0x9e, 0x583e, 0xa5, 0x5a3e, 0xa7, 0x664a, 0xb3}, …
Run Code Online (Sandbox Code Playgroud)

assembly intel simd nasm mmx

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