小编Gid*_*eon的帖子

从64位unsigned int初始化__m128类型

_mm_set_epi64和类似*_epi64指令似乎使用并依赖__m64类型.我想初始化一个类型的变量__m128,使其高64位为0,并将其低64位设置为x,其中x是类型uint64_t(或类似的无符号64位类型).这样做的"正确"方法是什么?

优选地,这应该以与编译器无关的方式完成.

c++ sse intrinsics

9
推荐指数
2
解决办法
4619
查看次数

为什么不直接访问__m128i字段?

在MSDN上阅读这篇文章,它说

您不应直接访问__m128i字段.但是,您可以在调试器中看到这些类型.__m128i类型的变量映射到XMM [0-7]寄存器.

但是,它没有解释原因.为什么?例如,以下是"坏":

void func(unsigned short x, unsigned short y)
{
    __m128i a;
    a.m128i_i64[0] = x;

    __m128i b;
    b.m128i_i64[0] = y;

    // Now do something with a and b ...
}
Run Code Online (Sandbox Code Playgroud)

如果使用某种load功能,而不是像上面的例子那样进行分配?

c++ sse intrinsics

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

我可以使用AVX2分散指令来加速某些负载吗?

我已经介绍了一个AVX2重型功能,瓶颈看起来如下:

std::uint64_t data[8];

// Some computation that fills data

std::uint64_t X[4] = { data[7], data[5], data[3], data[1] };
__m256i vec = _mm256_loadu_si256(reinterpret_cast<__m256i*>(X));

// Compute more with vec
// Later on use data[6], data[4], data[2], and data[0] in a similar fashion
Run Code Online (Sandbox Code Playgroud)

实际上,阵列也适当地对齐(因此load代替loadu).但问题是,AVX(2)有更快的方法吗?具体来说,我正在查看收集说明.我可以用它们来初始化vecdata?或者其他一些指令值得一试?

c++ avx2

4
推荐指数
1
解决办法
658
查看次数

为什么即使是16字节对齐的地址也会导致_mm_load_si128导致访问冲突?

以下编译在MSVC上没有警告.

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

int main() 
{
    __declspec(align(16)) int x = 42;
    std::cout << &x << "\n";  // Print out the address that holds x

    __m128i v = _mm_load_si128((__m128i const*)(x));
}
Run Code Online (Sandbox Code Playgroud)

本质上,代码对齐一个32位整数,并尝试将其加载到__m128i类型中.在需要输入地址为16字节对齐.在不需要它,但都可以导致运行时,上面的代码发出访问冲突.为什么,我该如何解决?_mm_load_si128 _mm_loadu_si128

c++ sse intrinsics

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

为什么_mm_set_epi16有时比_mm_load_si128快?

我知道最好避免_mm_set_epi*,而是依赖_mm_load_si128(_mm_loadu_si128如果数据没有对齐,甚至会有很小的性能损失).但是,这对性能的影响似乎与我不一致.以下是一个很好的例子.

考虑使用SSE内在函数的以下两个函数:

static uint32_t clmul_load(uint16_t x, uint16_t y)
{
    const __m128i c = _mm_clmulepi64_si128(
      _mm_load_si128((__m128i const*)(&x)),
      _mm_load_si128((__m128i const*)(&y)), 0);

    return _mm_extract_epi32(c, 0);
}

static uint32_t clmul_set(uint16_t x, uint16_t y)
{
    const __m128i c = _mm_clmulepi64_si128(
      _mm_set_epi16(0, 0, 0, 0, 0, 0, 0, x),
      _mm_set_epi16(0, 0, 0, 0, 0, 0, 0, y), 0);

    return _mm_extract_epi32(c, 0);
}
Run Code Online (Sandbox Code Playgroud)

以下功能对两者的性能进行了基准测试:

template <typename F>
void benchmark(int t, F f)
{
    std::mt19937 rng(static_cast<unsigned int>(std::time(0)));
    std::uniform_int_distribution<uint32_t> uint_dist10(
      0, std::numeric_limits<uint32_t>::max());

    std::vector<uint32_t> …
Run Code Online (Sandbox Code Playgroud)

c++ sse intrinsics

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

Bron-Kerbosch算法的迭代版本?

所述布隆-Kerbosch算法是用于列出的图表的所有极大派系的方法。我最近只是为了好玩而成功地实现了该算法。缺点是该算法是递归的,因此只能在很小的图上运行,直到堆栈溢出为止。

应该有可能使算法纯粹是迭代的。考虑一下Wikipedia上的基本版本(无限制)。该算法的迭代版本在伪代码中的外观如何?某处有描述吗?

我在想象一个堆栈数据结构来模拟递归。我还应该有一个循环,在其中测试P和X的空度,但是我没有看到完整的答案。

algorithm pseudocode graph-algorithm

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

如果设置了最低位,则有条件地不进行分支

我有三个32位无符号整数,说a,bc.如果最低位b为1,我想异或ca,并将结果保存到c.我们可以通过以下方式执行此操作:

#include <cassert>

int main()
{
  // Some values for a and c
  unsigned a = 16;
  unsigned c = 25;

  unsigned b = 5; // 101_2

  if(b & 1)
  {
    c ^= a;
  }

  assert(c == 9);
}
Run Code Online (Sandbox Code Playgroud)

我可以在没有分支的情况下有条件地执行此操作,即没有if语句吗?

c c++ bit-manipulation

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