标签: auto-vectorization

重叠数组的总和,自动矢量化和限制

Arstechnia最近有一篇文章为什么一些编程语言比其他语言更快.它比较了Fortran和C,并提到了求和数组.在Fortran中,假设数组不重叠,从而允许进一步优化.在C/C++中,指向相同类型的指针可能会重叠,因此通常不能使用此优化.但是,在C/C++中,可以使用restrictor __restrict关键字告诉编译器不要假设指针重叠.所以我开始研究自动矢量化.

以下代码在GCC和MSVC中进行矢量化

void dot_int(int *a, int *b, int *c, int n) {
    for(int i=0; i<n; i++) {
        c[i] = a[i] + b[i];
    }
}
Run Code Online (Sandbox Code Playgroud)

我使用和不使用重叠数组测试了它,它得到了正确的结果.但是,我使用SSE手动向量化循环的方式不能处理重叠数组.

int i=0;    
for(; i<n-3; i+=4) {
    __m128i a4 = _mm_loadu_si128((__m128i*)&a[i]);
    __m128i b4 = _mm_loadu_si128((__m128i*)&b[i]);
    __m128i c4 = _mm_add_epi32(a4,b4);
    _mm_storeu_si128((__m128i*)c, c4);
}
for(; i<n; i++) {
    c[i] = a[i] + b[i];
}
Run Code Online (Sandbox Code Playgroud)

接下来我尝试使用__restrict.我假设由于编译器可以假设数组不重叠,它不会处理重叠数组,但GCC和MSVC仍然可以获得重叠数组的正确结果,即使是__restrict.

void dot_int_restrict(int * __restrict a, int * __restrict b, int * __restrict c, …
Run Code Online (Sandbox Code Playgroud)

c c++ optimization sse auto-vectorization

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

GCC自动矢量化对运行时没有影响,即使被称为"有利可图"

在过去的几天里,我一直在阅读gcc 4.7的自动向量化.我按照我在网上看到的一些例子,设置似乎是正确的.但是当我实际运行代码并在矢量化开启或关闭之间进行比较时,运行时没有明显的差异.

这是我一直在使用的代码:

#include <string.h>
#include <stdlib.h>
#include <emmintrin.h>
#include <stdio.h>
#include <math.h>

int main(int argc, char** argv) {

    long b = strtol(argv[2], NULL, 0); 
    unsigned long long int i;
    unsigned long long int n = (int)pow(2,29);                                                                                                                                                                                            
    float total = 0;

    float *__restrict__ x1; 
    float *__restrict__ y1; 

    posix_memalign((void *)&x1, 16, sizeof(float)*n);
    posix_memalign((void *)&y1, 16, sizeof(float)*n);


    float *__restrict__ x = __builtin_assume_aligned(x1,16);
    float *__restrict__ y = __builtin_assume_aligned(y1,16);

    for (i=0;i<n;i++) {
            x[i] = i;
            y[i] = i;
    }   

    for (i=0; i<n; i++) { …
Run Code Online (Sandbox Code Playgroud)

c gcc auto-vectorization

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

如何帮助gcc矢量化C代码

我有以下C代码.第一部分只是从标准中读入一个复数的矩阵,称为矩阵M.有趣的部分是第二部分.

#include <stdio.h>
#include <complex.h>
#include <stdlib.h>
#include <assert.h>
#include <math.h>

int main() {
    int n, m, c, d;
    float re, im;

    scanf("%d %d", &n, &m);
    assert(n==m);
    complex float M[n][n];

    for(c=0; c<n; c++) {
      for(d=0; d<n; d++) {
    scanf("%f%fi", &re, &im);
    M[c][d] = re + im * I;
      }
    }

    for(c=0; c<n; c++) {
      for(d=0; d<n; d++) {
        printf("%.2f%+.2fi ", creal(M[c][d]), cimag(M[c][d]));
      }
      printf("\n");
    }
/*
Example:input   
2 3
1+2i 2+3i 74-4i
3+4i 4+5i -7-8i
*/
    /* Part …
Run Code Online (Sandbox Code Playgroud)

c gcc auto-vectorization

8
推荐指数
2
解决办法
2899
查看次数

展开循环并使用矢量化进行独立求和

对于以下循环,如果我告诉它使用关联数学,例如,GCC将仅对循环进行矢量化-Ofast.

float sumf(float *x)
{
  x = (float*)__builtin_assume_aligned(x, 64);
  float sum = 0;
  for(int i=0; i<2048; i++) sum += x[i];
  return sum;
}
Run Code Online (Sandbox Code Playgroud)

这是装配 -Ofast -mavx

sumf(float*):
    vxorps  %xmm0, %xmm0, %xmm0
    leaq    8192(%rdi), %rax
.L2:
    vaddps  (%rdi), %ymm0, %ymm0
    addq    $32, %rdi
    cmpq    %rdi, %rax
    jne .L2
    vhaddps %ymm0, %ymm0, %ymm0
    vhaddps %ymm0, %ymm0, %ymm1
    vperm2f128  $1, %ymm1, %ymm1, %ymm0
    vaddps  %ymm1, %ymm0, %ymm0
    vzeroupper
    ret
Run Code Online (Sandbox Code Playgroud)

这清楚地表明循环已被矢量化.

但是这个循环也有一个依赖链.为了克服添加的延迟,我需要在x86_64上展开并执行至少三次部分和(不包括Skylake,需要展开八次并使用需要在Haswell和Broadwell上展开10次的FMA指令进行添加) .据我所知,我可以展开循环-funroll-loops.

这是装配-Ofast -mavx -funroll-loops.

sumf(float*):
    vxorps …
Run Code Online (Sandbox Code Playgroud)

c x86 gcc loop-unrolling auto-vectorization

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

是否有可能使GCC自动矢量化器输出内在函数而不是汇编?

我看到的"问题"只是使用autovectorizer将用户编写的循环代码转换为每次编译的SIMD指令,作为通常优化的一部分,如果你更改编译器,你就不能确定它也会自动矢量化你的代码同样好.

因此,如果您只想要针对单个处理器,我希望编译器为我生成高级C代码,用于特定函数,该函数使用x86内部包装函数,这些函数通用于不同的编译器供应商.

是否有一个Decompiler,或者甚至是GCC的编译器选项给我这个代码?

c x86 gcc intrinsics auto-vectorization

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

如何在 gcc 中为复数启用 SSE3 addsubps 自动向量化?

我有一个简单的循环,取 n 个复数的乘积。当我执行这个循环数百万次时,我希望它尽可能快。我知道可以使用 SSE3 和 gcc 内在函数快速完成此操作_mm_addsub_ps,但我感兴趣的是是否可以让 gcc 自动向量化这样的代码,即复数的乘积:

#include <complex.h>
complex float f(complex float x[], int n ) {
  complex float p = 1.0;
  for (int i = 0; i < n; i++)
    p *= x[i];
  return p;
}
Run Code Online (Sandbox Code Playgroud)

您获得的程序集gcc -S -O3 -ffast-math是:

        .file   "test.c"
        .section        .text.unlikely,"ax",@progbits
.LCOLDB2:
        .text
.LHOTB2:
        .p2align 4,,15
        .globl  f
        .type   f, @function
f:
.LFB0:
        .cfi_startproc
        testl   %esi, %esi
        jle     .L4
        leal    -1(%rsi), %eax
        pxor    %xmm2, %xmm2
        movss   .LC1(%rip), %xmm3
        leaq …
Run Code Online (Sandbox Code Playgroud)

c gcc sse complex-numbers auto-vectorization

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

循环中的gcc自动矢量化控制流程

在下面的代码中,为什么第二个循环能够自动矢量化但第一个不能?如何修改代码以便自动进行矢量化?gcc说:

注意:没有矢量化:控制循环中的流程.

我使用的是gcc 8.2,标志是-O3 -fopt-info-vec-all.我正在编译x86-64 avx2.

#include <stdlib.h>
#include <math.h>

void foo(const float * x, const float * y, const int * v, float * vec, float * novec, size_t size) {
    size_t i;
    float bar;
    for (i=0 ; i<size ; ++i){
        bar = x[i] - y[i];
        novec[i] = v[i] ? bar : NAN;
    }
    for (i=0 ; i<size ; ++i){
        bar = x[i];
        vec[i] = v[i] ? bar : NAN;
    }
}
Run Code Online (Sandbox Code Playgroud)

更新:这会自动执行:

for (i=0 ; i<size ; ++i){ …
Run Code Online (Sandbox Code Playgroud)

c gcc avx2 auto-vectorization

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

生成慢vpermpd指令; 为什么?

我有一个过滤器m_f作用于输入向量v通过

Real d2v = m_f[0]*v[i];
for (size_t j = 1; j < m_f.size(); ++j)
{
   d2v += m_f[j] * (v[i + j] + v[i - j]);
}
Run Code Online (Sandbox Code Playgroud)

perf 告诉我们这个循环在哪里热:

在此输入图像描述

vaddpdvfma231pd意义; 没有它们,我们肯定无法执行此操作.但缓慢vpermpd让我感到困惑.它完成了什么?

c++ assembly signal-processing avx auto-vectorization

6
推荐指数
2
解决办法
119
查看次数

为什么矢量化在这个 for 循环中没有好处?

我正在尝试将此 for 循环向量化。使用 Rpass 标志后,我收到以下评论:

int someOuterVariable = 0;

for (unsigned int i = 7; i != -1; i--)
{
  array[someOuterVariable + i] -= 0.3 * anotherArray[i];
}

Remark:
The cost-model indicates that vectorization is not beneficial
the cost-model indicates that interleaving is not beneficial
Run Code Online (Sandbox Code Playgroud)

我想了解这意味着什么。“交错不是有益的”是否意味着数组索引不正确?

c++ vectorization llvm clang auto-vectorization

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

JAX 的 vmap 中的 in_axes 关键字

我试图使用vmap基于 JAX 文档的最小工作示例来了解 JAX 的自动矢量化功能。

我不明白如何in_axes正确使用。在下面的示例中,我可以设置in_axes=(None, 0)in_axes=(None, 1)导致相同的结果。为什么会这样?

为什么我必须使用in_axes=(None, 0)而不是类似的东西in_axes=(0, )

import jax.numpy as jnp
from jax import vmap


def predict(params, input_vec):
    assert input_vec.ndim == 1
    activations = input_vec
    for W, b in params:
        outputs = jnp.dot(W, activations) + b
        activations = jnp.tanh(outputs)
    return outputs


if __name__ == "__main__":

    # Parameters
    dims = [2, 3, 5]
    input_dims = dims[0]
    batch_size = 2

    # Weights
    params = list()
    for …
Run Code Online (Sandbox Code Playgroud)

auto-vectorization jax

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