标签: intrinsics

SSE2代码优化

我正在使用SSE2内在函数来优化我的应用程序的瓶颈,并提出以下问题:

ddata = _mm_xor_si128(_mm_xor_si128(
    _mm_sll_epi32(xdata, 0x7u), _mm_srl_epi32(tdata, 0x19u)), xdata);
Run Code Online (Sandbox Code Playgroud)

在Microsoft C++编译器上,这将无法编译,因为类型__m128iunsigned int(传递给_mm_sll_epi32指令)不可互换.

为什么会这样,我应该如何传递任意unsigned int_mm_sll_epi32


_m128i 是:

typedef union __declspec(intrin_type) _CRT_ALIGN(16) __m128i {
    __int8              m128i_i8[16];
    __int16             m128i_i16[8];
    __int32             m128i_i32[4];    
    __int64             m128i_i64[2];
    unsigned __int8     m128i_u8[16];
    unsigned __int16    m128i_u16[8];
    unsigned __int32    m128i_u32[4];
    unsigned __int64    m128i_u64[2];
} __m128i;
Run Code Online (Sandbox Code Playgroud)

c++ sse simd intrinsics sse2

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

AVX 256位等效于_mm_load1_ps

使用SSE,您可以将内存中的单个浮点数加载到__m128的所有4个插槽中,并使用内部_mm_load1_ps()

当使用带有AVX的256位宽SIMD时,似乎没有_mm256_load1_ps()将单个浮点数从存储器加载到向量的所有8个插槽中.

为什么会遗漏这个遗漏,最好的方法是什么呢?

或者甚至更好:有没有办法将单个浮点数加载到向量的目标槽0..7?

simd intrinsics avx

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

为什么java内部函数仍然有代码?

Java API中有许多内在函数的方法,但在查看源代码时仍然有与它们相关的代码.

例如,Integer.bitCount()是一个内在函数,但如果打开Integer类文件,则可以看到它的代码.

如果编译器/ jvm不一定使用此代码,那么该代码可以用于什么目的?

java intrinsics

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

最好的方法是洗掉两个__m128i的64位部分

我有两个__m128is,a并且b,我想要洗牌,以便在64位a的低位64位dst和64位的高位b落在64位的高位64位dst.即

dst[ 0:63]  = a[64:127]
dst[64:127] = b[0:63]
Run Code Online (Sandbox Code Playgroud)

相当于:

__m128i dst = _mm_unpacklo_epi64(_mm_srli_si128i(a, 8), b);
Run Code Online (Sandbox Code Playgroud)

要么

__m128i dst = _mm_castpd_si128(mm_shuffle_pd(_mm_castsi128_pd(a),_mm_castsi128_pd(b),1));
Run Code Online (Sandbox Code Playgroud)

有没有比第一种方法更好的方法呢?第二个只是一条指令,但切换到浮点SIMD执行比第一条指令的额外指令更昂贵.

sse intel simd intrinsics

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

如何实现便携式指针比较和交换?

compareAndSwapStackOverflow答案中找到了这段代码:

boolean CompareAndSwapPointer(volatile * void * ptr,
                              void * new_value,
                              void * old_value) {
#if defined(_MSC_VER)
   if (InterlockedCompareExchange(ptr, new_value, old_value) == old_value) return false;
   else return true;
#elif (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) > 40100
   return __sync_bool_compare_and_swap(ptr, old_value, new_value);
#else
#  error No implementation
#endif
}
Run Code Online (Sandbox Code Playgroud)

这是使用便携式快速代码的最合适方式(除了程序集内联).

此外,一个问题是这些特定builtin方法具有不同的参数并从一个编译器返回另一个编译器的值,这可能需要一些额外的更改,如if then else本示例中所示.

另一个问题是这些builtin方法在机器代码级别中的行为,它们的行为是否完全相同?(例如使用相同的装配说明)

注意:另一个问题是,如果有许多支持的平台不仅仅是(WindowsLinux)在这个例子中.代码可能会变得非常大.

c intrinsics

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

使用AVX对64位结构进行排序?

我有一个64位结构,代表几个数据,其中一个是浮点值:

struct MyStruct{
    uint16_t a;
    uint16_t b;
    float f;
}; 
Run Code Online (Sandbox Code Playgroud)

我有四个这样的结构,让我们说一个 std::array<MyStruct, 4>

是否可以使用AVX对浮动成员进行数组排序MyStruct::f

c++ intrinsics avx

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

当它应该向上舍入时,SSE会向下舍入

我正在开发一个应用程序,它将-1.0到1.0范围内的Float样本转换为带符号的16位,以确保优化(SSE)例程的输出是准确的我已编写了一组运行非优化版本的测试SSE版本并比较它们的输出.

在开始之前,我已经确认SSE舍入模式设置为最接近.

在我的测试用例中,公式为:

ratio = 65536 / 2
output = round(input * ratio)
Run Code Online (Sandbox Code Playgroud)

在大多数情况下,结果是准确的,但在一个特定的输入上,我看到输入失败-0.8499908447265625.

-0.8499908447265625 * (65536 / 2) = -27852.5
Run Code Online (Sandbox Code Playgroud)

正常代码正确地将其舍入为-27853,但SSE代码将此舍入为-27852.

这是使用中的SSE代码:

void Float_S16(const float *in, int16_t *out, const unsigned int samples)
{
  static float ratio = 65536.0f / 2.0f;
  static __m128 mul  = _mm_set_ps1(ratio);

  for(unsigned int i = 0; i < samples; i += 4, in += 4, out += 4)
  {
    __m128  xin;
    __m128i con;

    xin = _mm_load_ps(in);
    xin = _mm_mul_ps(xin, …
Run Code Online (Sandbox Code Playgroud)

c++ x86 sse rounding-error intrinsics

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

是否有针对intel avx2中的movemask指令的反向指令?

movemask指令采用__m256i并返回int32,其中每个位(取决于输入向量元素类型的前4位,8位或所有32位)是相应向量元素的最高有效位.

我想做反过来:取一个32(其中只有4,8或32个最低有效位有意义),并获得__m256i,其中每个int8,int32或int64大小的块的最高有效位设置为原始位.

基本上,我想从压缩的位掩码转到可被其他AVX2指令(例如maskstore,maskload,mask_gather)用作掩码的位掩码.

我无法快速找到这样做的指令,所以我在这里问.如果没有一条具有该功能的指令,您是否可以想到一个聪明的黑客,只需很少的指令即可实现这一点?

我目前的方法是使用256元素查找表.我想在一个没有其他事情发生的循环中使用这个操作来加速它.注意,我对长多指令序列或实现此操作的小循环不太感兴趣.

x86 icc intrinsics avx avx2

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

如何在没有编译器浪费指令归零上层元素的情况下将标量合并到向量中?英特尔内在函数的设计限制?

我没有特定的用例; 我问这是否真的是英特尔内在函数中的设计缺陷/限制,或者我是否只是遗漏了某些内容.

如果你想将标量浮点数与现有向量相结合,那么在没有高元素归零或使用英特尔内在函数将标量广播到向量中的情况下似乎没有办法实现.我没有研究过GNU C本机向量扩展和相关的内置函数.

如果额外的内在优化了,这不会太糟糕,但它不与gcc(5.4或6.2).也没有好的方法可以使用pmovzxinsertps作为负载,因为他们的内在函数只采用向量args的相关原因.(并且gcc不会将标量 - >向量加载到asm指令中.)

__m128 replace_lower_two_elements(__m128 v, float x) {
  __m128 xv = _mm_set_ss(x);        // WANTED: something else for this step, some compilers actually compile this to a separate insn
  return _mm_shuffle_ps(v, xv, 0);  // lower 2 elements are both x, and the garbage is gone
}
Run Code Online (Sandbox Code Playgroud)

gcc 5.3 -march = nehalem -O3输出,启用SSE4.1并调整该Intel CPU :(没有SSE4.1会更糟;多个指令将上层元素归零).

    insertps  xmm1, xmm1, 0xe    # pointless zeroing of upper elements.  shufps only reads the low element of xmm1 …
Run Code Online (Sandbox Code Playgroud)

c x86 gcc sse intrinsics

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

PTEST可用于测试两个寄存器是否为零或其他条件?

除了测试单个寄存器是否为零之外,您还可以使用SSE4.1ptest做什么?

您是否可以使用SF和CF的组合来测试有关两个未知输入寄存器的任何有用信息?

什么是PTEST有益?您认为检查打包比较的结果(如PCMPEQD或CMPPS)会有好处,但至少在Intel CPU上,使用PTEST + JCC比使用PMOVMSK(B)进行比较和分支的成本更高./PS/PD)+宏融合CMP + JCC.

另请参阅检查TWO SSE寄存器是否在不破坏它们的情况下都不为零

x86 assembly sse intrinsics sse4

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

标签 统计

intrinsics ×10

sse ×5

x86 ×4

avx ×3

c++ ×3

simd ×3

c ×2

assembly ×1

avx2 ×1

gcc ×1

icc ×1

intel ×1

java ×1

rounding-error ×1

sse2 ×1

sse4 ×1