在_mm_set_epi64和类似*_epi64指令似乎使用并依赖__m64类型.我想初始化一个类型的变量__m128,使其高64位为0,并将其低64位设置为x,其中x是类型uint64_t(或类似的无符号64位类型).这样做的"正确"方法是什么?
优选地,这应该以与编译器无关的方式完成.
您不应直接访问__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功能,而不是像上面的例子那样进行分配?
我已经介绍了一个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)有更快的方法吗?具体来说,我正在查看收集说明.我可以用它们来初始化vec从data?或者其他一些指令值得一试?
以下编译在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
我知道最好避免_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) 所述布隆-Kerbosch算法是用于列出的图表的所有极大派系的方法。我最近只是为了好玩而成功地实现了该算法。缺点是该算法是递归的,因此只能在很小的图上运行,直到堆栈溢出为止。
应该有可能使算法纯粹是迭代的。考虑一下Wikipedia上的基本版本(无限制)。该算法的迭代版本在伪代码中的外观如何?某处有描述吗?
我在想象一个堆栈数据结构来模拟递归。我还应该有一个循环,在其中测试P和X的空度,但是我没有看到完整的答案。
我有三个32位无符号整数,说a,b和c.如果最低位b为1,我想异或c与a,并将结果保存到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语句吗?