我不明白为什么这样的代码没有用gcc 4.4.6进行矢量化
int MyFunc(const float *pfTab, float *pfResult, int iSize, int iIndex)
{
for (int i = 0; i < iSize; i++)
pfResult[i] = pfResult[i] + pfTab[iIndex];
}
note: not vectorized: unhandled data-ref
Run Code Online (Sandbox Code Playgroud)
但是,如果我写下面的代码
int MyFunc(const float *pfTab, float *pfResult, int iSize, int iIndex)
{
float fTab = pfTab[iIndex];
for (int i = 0; i < iSize; i++)
pfResult[i] = pfResult[i] + fTab;
}
Run Code Online (Sandbox Code Playgroud)
gcc成功自动向量化此循环
如果我添加omp指令
int MyFunc(const float *pfTab, float *pfResult, int iSize, int iIndex)
{
float fTab = …Run Code Online (Sandbox Code Playgroud) 检查以下代码:
#include <stdio.h>
#include <omp.h>
#define ARRAY_SIZE (1024)
float A[ARRAY_SIZE];
float B[ARRAY_SIZE];
float C[ARRAY_SIZE];
int main(void)
{
for (int i = 0; i < ARRAY_SIZE; i++)
{
A[i] = i * 2.3;
B[i] = i + 4.6;
}
double start = omp_get_wtime();
for (int loop = 0; loop < 1000000; loop++)
{
#pragma omp simd
for (int i = 0; i < ARRAY_SIZE; i++)
{
C[i] = A[i] * B[i];
}
}
double end = omp_get_wtime();
printf("Work consumed %f seconds\n", …Run Code Online (Sandbox Code Playgroud) 让我们考虑一个简单的简化,例如点积:
pub fn add(a:&[f32], b:&[f32]) -> f32 {
a.iter().zip(b.iter()).fold(0.0, |c,(x,y)| c+x*y))
}
Run Code Online (Sandbox Code Playgroud)
使用 rustc 1.68 与-C opt-level=3 -C target-feature=+avx2,+fma
我得到
.LBB0_5:
vmovss xmm1, dword ptr [rdi + 4*rsi]
vmulss xmm1, xmm1, dword ptr [rdx + 4*rsi]
vmovss xmm2, dword ptr [rdi + 4*rsi + 4]
vaddss xmm0, xmm0, xmm1
vmulss xmm1, xmm2, dword ptr [rdx + 4*rsi + 4]
vaddss xmm0, xmm0, xmm1
vmovss xmm1, dword ptr [rdi + 4*rsi + 8]
vmulss xmm1, xmm1, dword ptr [rdx + …Run Code Online (Sandbox Code Playgroud) 在 gcc 编译器中有没有办法只启用自动矢量化?我确实知道该-ftree-vectorize标志可以启用自动矢量化。但它至少需要-O2优化级别。有没有办法在不使用-O2优化标志的情况下启用自动矢量化?
提前致谢。
这是一个非常简单的阶乘函数。
int factorial(int num) {
if (num == 0)
return 1;
return num*factorial(num-1);
}
Run Code Online (Sandbox Code Playgroud)
GCC在-O2上为此功能进行的组装是合理的。
factorial(int):
mov eax, 1
test edi, edi
je .L1
.L2:
imul eax, edi
sub edi, 1
jne .L2
.L1:
ret
Run Code Online (Sandbox Code Playgroud)
但是,在-O3或-Ofast上,它决定使事情变得更复杂(几乎100行!):
factorial(int):
test edi, edi
je .L28
lea edx, [rdi-1]
mov ecx, edi
cmp edx, 6
jbe .L8
mov DWORD PTR [rsp-12], edi
movd xmm5, DWORD PTR [rsp-12]
mov edx, edi
xor eax, eax
movdqa xmm0, XMMWORD PTR .LC0[rip]
movdqa xmm4, XMMWORD PTR .LC2[rip]
shr …Run Code Online (Sandbox Code Playgroud) 使用intel编译器,如果用户确认没有使用依赖关系,则仍然可以对循环进行矢量化#pragma ivdep.
我在GCC找到了一个#pragma GCC ivdep,但收到如下错误:
warning: ignoring #pragma GCC ivdep [-Wunknown-pragmas]
#pragma GCC ivdep
拿这个代码。
#include <stdlib.h>
int main(int argc , char **argv) {
int *x = malloc(argc*sizeof(int));
for (int i = 0; i < argc; ++i) {
x[i] = argc;
}
int t = 0;
for (int i = 0; i < argc; ++i) {
t += x[i];
}
free(x);
return t;
Run Code Online (Sandbox Code Playgroud)
这个循环
for (int i = 0; i < argc; ++i) {
x[i] = argc;
}
Run Code Online (Sandbox Code Playgroud)
向量化为
movdqu xmmword ptr [rax + 4*rdx], xmm0
movdqu xmmword ptr [rax + 4*rdx + 16], …Run Code Online (Sandbox Code Playgroud) 我有以下Java代码(所有数组在我们调用“arrays”之前都已初始化,并且所有数组的大小均为“arraySize”)
int arraySize = 64;
float[] a;
float[] b;
float[] result;
public void arrays() {
for (int i = 0; i < arraySize; i++) {
result[i] = ((a[i] * b[i] + b[i] - b[i]) / b[i]) +
a[i] + a[i] + a[i] + a[i];
}
}
Run Code Online (Sandbox Code Playgroud)
JIT 的输出是:
# {method} {0x00000001034751a8} 'arrays' '()V' in 'main/ComplexExpression'
# [sp+0x30] (sp of caller)
[Entry Point]
0x000000010c4c55a0: mov 0x8(%rsi),%r10d
0x000000010c4c55a4: movabs $0x800000000,%r11
0x000000010c4c55ae: add %r11,%r10
0x000000010c4c55b1: cmp %r10,%rax
0x000000010c4c55b4: jne 0x000000010c44b780 ; {runtime_call ic_miss_stub} …Run Code Online (Sandbox Code Playgroud) 简单的C代码,只需添加一个双精度。
void test(double *a, double *b, long n) {
for (long j = 0; j < n; j++)
for (long i = 0; i < n; i++) {
b[i] = b[i] + a[j];
}
}
Run Code Online (Sandbox Code Playgroud)
在编译器资源管理器中获取ASM结果:https : //godbolt.org/z/tJ-d39
有一addpd和二addsd。两者都是与双精度有关的。
另一个类似的锈代码,获得了更多的双精度添加工具:https://godbolt.org/z/c49Wuh
pub unsafe fn test(a: &mut [f64], b: &mut [f64], n: usize) {
for j in 0..n {
for i in 0..n {
*b.get_unchecked_mut(i) = *b.get_unchecked_mut(i) + *a.get_unchecked_mut(j);
}
}
}
Run Code Online (Sandbox Code Playgroud)