是否可以在std :: bitset的基础数据上使用SSE指令?我正在使用的位集大于无符号长整数,因此to_ulong()方法是不够的.例如,我可以使用这样的指令:
__m128i* ptr= (__m128i*)(&my_bitset[0]);
Run Code Online (Sandbox Code Playgroud)
然后按正常情况执行SSE操作?
对于使用带有SSE的std :: bitset的人来说,我试图搜索互联网,但它似乎并不是一个常见的用例.
假设从一个竞争激烈的高速缓存行中需要三段数据,是否有一种方法可以“原子地”加载所有这三件事,从而避免到任何其他内核的多次往返?
实际上,对于所有3个成员的快照,我实际上都不需要原子性的正确性保证,只是在正常情况下,所有3个项目都是在同一时钟周期中读取的。我想避免高速缓存行到达的情况,但是在读取所有3个对象之前会出现无效请求。这将导致第三次访问需要发送另一个请求以共享线路,从而使争用更加严重。
例如,
class alignas(std::hardware_destructive_interference_size) Something {
std::atomic<uint64_t> one;
std::uint64_t two;
std::uint64_t three;
};
void bar(std::uint64_t, std::uint64_t, std::uint64_t);
void f1(Something& something) {
auto one = something.one.load(std::memory_order_relaxed);
auto two = something.two;
if (one == 0) {
bar(one, two, something.three);
} else {
bar(one, two, 0);
}
}
void f2(Something& something) {
while (true) {
baz(something.a.exchange(...));
}
}
Run Code Online (Sandbox Code Playgroud)
我能否以某种方式确保one,two并且three所有组件都可以在没有大量RFO的情况下(f1而f2不是同时运行)一起加载到一起?
用于此问题的目标体系结构/平台是Intel x86 Broadwell,但是如果有某种技术或编译器内在函数可以允许某些可移植的工作尽力而为,那也很好。
我有一段代码在竞争激烈的锁下运行,所以它需要尽可能快。代码非常简单——它是对一堆数据的基本乘加,如下所示:
for( int i = 0; i < size; i++ )
{
c[i] += (double)a[i] * (double)b[i];
}
Run Code Online (Sandbox Code Playgroud)
在启用了 SSE 支持的 -O3 下,代码正在按照我的预期进行矢量化。但是,打开 AVX 代码生成后,我的速度降低了大约 10-15%,而不是加速,我不知道为什么。
这是基准代码:
#include <chrono>
#include <cstdio>
#include <cstdlib>
int main()
{
int size = 1 << 20;
float *a = new float[size];
float *b = new float[size];
double *c = new double[size];
for (int i = 0; i < size; i++)
{
a[i] = rand();
b[i] = rand();
c[i] = rand();
}
for (int j …Run Code Online (Sandbox Code Playgroud) 我在 C/C++ 代码中明确使用了英特尔 SIMD 内在扩展。为了编译代码,我需要在命令行上指定 -mavx、-mavx512 或类似的内容。我对这一切都很满意。
然而,从阅读 gcc 手册页来看,并不清楚这些命令行标志是否也告诉 gcc 编译器尝试使用英特尔 SIMD 指令自动矢量化 C/C++ 代码。有人知道情况是否如此吗?-mavx 标志只是允许您手动将 SIMD 内在函数插入代码中,还是还告诉编译器在编译 C/C++ 代码时使用 SIMD 指令?
uint8_t data[] = "mykeyxyz:1234\nky:123\n...";。我的字符串行有 format key:value,其中每一行都有len(key) <= 16保证。我想加载mykeyxyz到 a 中__m128i,但将较高的位置填为 0。
最简单的方法是使用 255 或 0 掩码的数组,但这需要另一个内存负载。有没有办法更快地做到这一点?
接受的答案使总程序时间加快了约 2%。要进行比较,请进行测试1brc_valid13.cpp(1brc_valid14.cpp使用已接受的答案)。硬件:AMD 2950X、Ubuntu 18.04、g++ 11.4,编译命令:g++ -o main 1brc_final_valid.cpp -O3 -std=c++17 -march=native -m64 -lpthread
编辑:最好没有 AVX512
编辑 2:我需要变量,len以便我可以开始解析值部分。
编辑 3:该函数将在循环中使用(例如解析 100 万行文本)。但strcmp_mask基本上总是在 L1 缓存内
编辑 4:我通过解析 10 亿行(key,value)并处理它们来对函数进行基准测试。您可以下载代码/数据并在我的存储库中复制结果: https: //github.com/lehuyduc/1brc-simd。此外,讨论帖将包含更多信息
编辑 5:我测试maskafterc256发现它导致我的代码慢了 50 倍!如果我替换_mm256_set_epi8为 …
我编写了一些代码,并使用 gcc 和本机架构选项对其进行了编译。
通常,我可以使用此代码并在没有 AVX2(仅 AVX)的旧计算机上运行它,并且它工作正常。然而,编译器似乎实际上正在发出 AVX2 指令(终于!),而不是我需要自己包含 SIMD 内在函数。
我想修改程序,以便支持两种途径(AVX2 和非 AVX2)。换句话说,我想要以下伪代码。
if (AVX2){
callAVX2Version();
}else if (AVX){
callAVXVersion();
}else{
callSSEVersion();
}
void callAVX2Version(){
#pragma gcc -mavx2
}
void callAVXVersion(){
#pragma gcc -mavx
}
Run Code Online (Sandbox Code Playgroud)
我知道如何执行运行时检测部分,我的问题是是否可以执行功能特定的 SIMD 选择部分。
我需要找到比最后一个滚动最大峰值低 X 或更多 % 的值的索引。
峰值是一个数组 ( highs) 中元素的滚动最大值,而值位于另一个数组 ( lows) 中。数组具有相等的长度,并且值保证 <= peaks 数组中的对应项,没有 0、NAN 或无穷大元素。since保证小于till。
迭代实现很简单:
inline
size_t trail_max_intern(double *highs,
double *lows,
double max,
double trail,
size_t since,
size_t till)
{
for (; since < till; ++since) {
if (max < highs[since]) {
max = highs[since];
}
if (lows[since] / max <= trail) {
break;
}
}
return since;
}
size_t trail_max_iter(double *highs, double *lows, double trail, size_t since, size_t till)
{ …Run Code Online (Sandbox Code Playgroud) 英特尔C++编译器和/或GCC是否支持以下内在函数,例如自2012/2013年以来MSVC的内在函数?
int _rdrand16_step(uint16_t*);
int _rdrand32_step(uint32_t*);
int _rdrand64_step(uint64_t*);
int _rdseed16_step(uint16_t*);
int _rdseed32_step(uint32_t*);
int _rdseed64_step(uint64_t*);
Run Code Online (Sandbox Code Playgroud)
如果支持这些内在函数,那么它们支持哪个版本(请使用编译时常量)?
这个问题是在编写一些与计算机图形学相关的代码时发现的,简化版的代码如下所示:
\n#include <bits/stdc++.h>\n\n#define __AVX__ 1\n#define __AVX2__ 1\n#pragma GCC target("avx,avx2,popcnt,tune=native")\n#include <immintrin.h>\n\nnamespace with_avx {\nclass vec {\n public:\n vec(double x = 0, double y = 0, double z = 0, double t = 0) {\n vec_data = _mm256_set_pd(t, z, y, x);\n }\n __m256d vec_data;\n};\n} // namespace with_avx\n\nnamespace without_avx {\nclass vec {\n public:\n vec(double x = 0, double y = 0, double z = 0, double t = 0) {\n vec_data[0] = x, vec_data[1] = y, vec_data[2] = z, vec_data[3] = t;\n }\n …Run Code Online (Sandbox Code Playgroud) 我在 corei7 上的 ubuntu 上运行 gcc 版本 4.8.2。
从谷歌搜索中找到了有关 AVX 内在函数的信息,但我不确定这组内在函数是否可以用于 Linux 设备驱动程序并对其进行编译。
如果可以,这里的任何人都可以告诉我什么是 makefile 的正确设置以及在 c 源中包含哪些头文件以使用 gcc 编译这个 avx?
谢谢。
什么更有效,为什么?
具体地_mm_loadu_si128与_mm_load_si128在C.
(编者注:或者这是标记的程序集,可能它们意味着movdqu与movdqa手写的asm.这是不一样的,特别是没有AVX,因为_mm_load_si128可以编译成ALU指令的内存操作数而根本没有单独movdqa的.)
c++ ×6
avx ×5
simd ×5
gcc ×4
sse ×3
assembly ×2
c ×2
intrinsics ×2
optimization ×2
x86 ×2
avx2 ×1
avx512 ×1
bitset ×1
debugging ×1
g++ ×1
icc ×1
intel ×1
linux-kernel ×1
performance ×1
rdrand ×1