我正在尝试学习gcc自动矢量化模块.从这里阅读文档后.
这是我尝试过的(debian jessie amd64):
$ cat ex1.c
int a[256], b[256], c[256];
foo () {
int i;
for (i=0; i<256; i++){
a[i] = b[i] + c[i];
}
}
Run Code Online (Sandbox Code Playgroud)
然后,我只是运行:
$ gcc -x c -Ofast -msse2 -c -ftree-vectorize -fopt-info-vec-missed ex1.c
ex1.c:5:3: note: misalign = 0 bytes of ref b[i_11]
ex1.c:5:3: note: misalign = 0 bytes of ref c[i_11]
ex1.c:5:3: note: misalign = 0 bytes of ref a[i_11]
ex1.c:5:3: note: virtual phi. skip.
ex1.c:5:3: note: num. args = 4 (not unary/binary/ternary …Run Code Online (Sandbox Code Playgroud) 我试着理解SSE指令的矢量化是如何工作的.
这里是一个实现矢量化的代码片段:
#include <stdlib.h>
#include <stdio.h>
#define SIZE 10000
void test1(double * restrict a, double * restrict b)
{
int i;
double *x = __builtin_assume_aligned(a, 16);
double *y = __builtin_assume_aligned(b, 16);
for (i = 0; i < SIZE; i++)
{
x[i] += y[i];
}
}
Run Code Online (Sandbox Code Playgroud)
和我的编译命令:
gcc -std=c99 -c example1.c -O3 -S -o example1.s
Run Code Online (Sandbox Code Playgroud)
这里是汇编程序代码的输出:
.file "example1.c"
.text
.p2align 4,,15
.globl test1
.type test1, @function
test1:
.LFB7:
.cfi_startproc
xorl %eax, %eax
.p2align 4,,10
.p2align 3
.L3:
movapd (%rdi,%rax), %xmm0
addpd …Run Code Online (Sandbox Code Playgroud) 我正在探索如何基于函数签名在C99中简单循环的不同实现自动矢量化。
这是我的代码:
/* #define PRAGMA_SIMD _Pragma("simd") */
#define PRAGMA_SIMD
#ifdef __INTEL_COMPILER
#define ASSUME_ALIGNED(a) __assume_aligned(a,64)
#else
#define ASSUME_ALIGNED(a)
#endif
#ifndef ARRAY_RESTRICT
#define ARRAY_RESTRICT
#endif
void foo1(double * restrict a, const double * restrict b, const double * restrict c)
{
ASSUME_ALIGNED(a);
ASSUME_ALIGNED(b);
ASSUME_ALIGNED(c);
PRAGMA_SIMD
for (int i = 0; i < 2048; ++i) {
if (c[i] > 0) {
a[i] = b[i];
} else {
a[i] = 0.0;
}
}
}
void foo2(double * restrict a, const double * restrict b, …Run Code Online (Sandbox Code Playgroud) simd c99 variable-length-array restrict-qualifier auto-vectorization
在这里和互联网上,我可以找到很多关于现代编译器在许多实际情况下击败SSE的帖子,我刚刚在一些代码中遇到过我在2006年为基于整数的图像处理编写的一些SSE代码并将代码强制降低标准C分支,运行速度更快.
在具有多核和高级流水线等的现代处理器上,较旧的SSE代码是否表现不佳gcc -O2?
请考虑执行相同计算的以下三个功能:
#include <x86intrin.h>
void testfunc_loop(double a, double b, double* dst)
{
double f[] = {a,b,-a,-b};
for(int n = 0; n < 4; ++n)
{
dst[n] = 0.1 + f[n]*(1.0 + 0.5*f[n]);
}
}
void testfunc_flat(double a, double b, double* dst)
{
dst[0] = 0.1 + ( a)*(1.0 + 0.5*( a));
dst[1] = 0.1 + ( b)*(1.0 + 0.5*( b));
dst[2] = 0.1 + (-a)*(1.0 + 0.5*(-a));
dst[3] = 0.1 + (-b)*(1.0 + 0.5*(-b));
}
void testfunc_avx(double a, double b, double* …Run Code Online (Sandbox Code Playgroud) 我试图将一些简单的计算向量化,以加快SIMD架构的速度.但是,我还想将它们作为内联函数,因为函数调用和非向量化代码也需要计算时间.但是,我不能总是同时实现它们.实际上,我的大多数内联函数都无法自动向量化.这是一个简单的测试代码:
inline void add1(double *v, int Length) {
for(int i=0; i < Length; i++) v[i] += 1;
}
void call_add1(double v[], int L) {
add1(v, L);
}
int main(){return 0;}
Run Code Online (Sandbox Code Playgroud)
在Mac OS X 10.12.3上,编译它:
clang++ -O3 -Rpass=loop-vectorize -Rpass-analysis=loop-vectorize -std=c++11 -ffast-math test.cpp
test.cpp:2:5: remark: vectorized loop (vectorization width: 2, interleaved count: 2) [-Rpass=loop-vectorize]
for(int i=0; i < Length; i++) v[i] += 1;
^
Run Code Online (Sandbox Code Playgroud)
但是,非常相似的东西(只在call_add1中移动参数)不起作用:
inline void add1(double *v, int Length) {
for(int i=0; i < Length; i++) v[i] += 1;
} …Run Code Online (Sandbox Code Playgroud) 我是 rust/SIMD 新手,我有以下代码片段作为我的程序的瓶颈,我想知道我是否可以利用它的自动向量化功能
fn is_subset(a: Vec<i64>, b: Vec<i64>) -> bool {
for i in 0..a.len() {
if (a[i] & !b[i]) != 0 {
return false;
}
}
true
}
Run Code Online (Sandbox Code Playgroud)
我还有另一种编写方法(使用迭代器,因此可以预先知道行程计数),这会创建自动向量化吗?
fn is_subset(a: Vec<i64>, b: Vec<i64>) -> bool {
return a.iter().zip(b.iter()).all(|(x, y)| x & y == *x)
}
Run Code Online (Sandbox Code Playgroud) 为什么 clang 17.0.1 不会矢量化以下函数中的循环:
void adapt(std::span<const F, N + 1> signal)
{
F true_val = signal.back();
F y = dot_prod<F, N>(&signal[0], w.begin());
F e = true_val - y;
F dot = dot_prod<F, N>(&signal[0], &signal[0]);
F nu = mu / (eps + dot);
for (size_t i = 0; i < N; i++)
{
w[i] += nu * e * signal[i];
}
}
Run Code Online (Sandbox Code Playgroud)
不存在浮点关联性的附带依赖性或问题,并且 GCC 13.2 对其进行矢量化没有任何问题。
其背景是我正在尝试优化我的代码以使用矢量化点积。std::inner_product由于浮点关联性问题,通常会发出标量实现,除非您使用-ffast-math. 但是,我只想-ffast-math应用于单个函数,并且我一直在寻找一种可移植的方法来为 clang 和 GCC 执行此操作。在查看输出时,我注意到 clang 不会矢量化另一个循环。 …
我正在使用 Qt5 编写一个程序,我需要分配一个QVector <float>使其data()指针 32 字节对齐的指针。
无论如何,我可以在不修改 Qt 库本身的情况下做到这一点吗?
我的代码看起来像这样:
QVector <float> vec;
vec.resize(n);
float *wricker_ptr = wricker.data(); // this should be 32-byte aligned
for (int i=0; i<n; i++)
{
wricker_ptr[i] = /* some computed value */;
}
Run Code Online (Sandbox Code Playgroud)
我正在使用英特尔的 C++ 编译器。
我想探索 gcc (10.3) 的自动矢量化。我有以下简短的程序(请参阅https://godbolt.org/z/5v9a53aj6),它计算向量所有元素的总和:
#include <stdio.h>
#define LEN 1024
// -ffast-math -march=tigerlake -O3 -fno-unroll-loops
int
main()
{
float v[LEN] __attribute__ ((aligned(64)));
float s = 0;
for (unsigned int i = 0; i < LEN; i++) s += v[i];
printf("%g\n", s);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我用选项编译-ffast-math -march=tigerlake -O3 -fno-unroll-loops。由于 Tigerlake 处理器具有 avx512,我希望 gcc 自动向量化使用 zmm 寄存器,但它实际上在最内层循环中使用 ymm 寄存器(avx/avx2):
vaddps ymm0, ymm0, YMMWORD PTR [rax]
Run Code Online (Sandbox Code Playgroud)
如果我替换-march=tigerlake为-mavx512f,则使用 zmm 寄存器:
vaddps zmm0, zmm0, ZMMWORD PTR [rax]
Run Code Online (Sandbox Code Playgroud)
如果我只是指定,为什么不使用 …