标签: auto-vectorization

为什么 GCC 生成有条件执行 SIMD 实现的代码?

以下代码生成的程序集在使用-O3. 为了完整起见,代码始终在 GCC 13.2 中执行 SIMD,而从不在 clang 17.0.1 中执行 SIMD。

#include <array>

__attribute__((noinline)) void fn(std::array<int, 4>& lhs, const std::array<int, 4>& rhs)
{
    for (std::size_t idx = 0; idx != 4; ++idx) {
        lhs[idx] = lhs[idx] + rhs[idx];
    }
}
Run Code Online (Sandbox Code Playgroud)

这是Godbolt 中的链接

这是 GCC 12.3 的实际汇编(使用 -O3):

fn(std::array<int, 4ul>&, std::array<int, 4ul> const&):
        lea     rdx, [rsi+4]
        mov     rax, rdi
        sub     rax, rdx
        cmp     rax, 8
        jbe     .L2
        movdqu  xmm0, XMMWORD PTR [rsi]
        movdqu  xmm1, XMMWORD PTR [rdi]
        paddd …
Run Code Online (Sandbox Code Playgroud)

c++ gcc simd auto-vectorization

24
推荐指数
1
解决办法
1116
查看次数

简单的getter/accessor防止矢量化 - gcc bug?

考虑修复的这个最小实现vector<int>:

constexpr std::size_t capacity = 1000;

struct vec 
{
    int values[capacity];
    std::size_t _size = 0;    

    std::size_t size() const noexcept 
    { 
        return _size; 
    }

    void push(int x) 
    {
        values[size()] = x;
        ++_size;
    }
};
Run Code Online (Sandbox Code Playgroud)

鉴于以下测试用例:

vec v;
for(std::size_t i{0}; i != capacity; ++i) 
{
    v.push(i);
}

asm volatile("" : : "g"(&v) : "memory");
Run Code Online (Sandbox Code Playgroud)

编译器生成非向量化程序集:godbolt.org上的实例

godbolt截图 - 非矢量化


如果我做出以下任何改变......

  • values[size()] - > values[_size]

  • 添加__attribute__((always_inline))size()

...然后编译器生成矢量化程序集:godbolt.org上的实例

godbolt截图 - 矢量化


这是一个gcc bug吗?或者有一个原因可以解释为什么一个简单的访问器size()会阻止自动矢量化,除非always_inline明确添加?

c++ optimization performance gcc auto-vectorization

14
推荐指数
1
解决办法
330
查看次数

为什么编译器在这里错过矢量化?

考虑以下valarray类:

#include <stdlib.h>

struct va
{
    void add1(const va& other);
    void add2(const va& other);

    size_t* data;
    size_t  size;
};

void va::add1(const va& other) {
    for (size_t i = 0; i < size; ++i) {
        data[i] += other.data[i];
    }
}

void va::add2(const va& other){
    for (size_t i = 0, s = size; i < s; ++i) {
        data[i] += other.data[i];
    }
}
Run Code Online (Sandbox Code Playgroud)

add2函数针对不同的编译器(MSVC、Clang、GCC、ICC)进行了向量化,而add1并非如此。参见https://godbolt.org/z/c61qvrrbv

这是通过潜在的别名来解释的:编译器无法证明所指向的元素之一data不是其size本身。

data然而,和指向的元素也可能存在重叠other.data。对于 MSVC,这些元素和指针本身可能存在别名,因为它没有利用严格别名规则。这适用于add1 …

c++ vectorization strict-aliasing compiler-optimization auto-vectorization

14
推荐指数
1
解决办法
456
查看次数

为什么矢量化对于几乎相同的代码表现不同?

以下是执行相同操作的自由函数,但在第一种情况下,循环不是矢量化的,但在其他情况下它是.这是为什么?

#include <vector>

typedef std::vector<double> Vec;

void update(Vec& a, const Vec& b, double gamma) {
    const size_t K = a.size();
    for (size_t i = 0; i < K; ++i) { // not vectorized
        a[i] = b[i] * gamma - a[i];
    }
}

void update2(Vec& a, const Vec& b, double gamma) {
    for (size_t i = 0; i < a.size(); ++i) { // vectorized
        a[i] = b[i] * gamma - a[i];
    }
}

void update3(Vec& a, size_t K, const Vec& b, …
Run Code Online (Sandbox Code Playgroud)

c++ sse vectorization visual-studio auto-vectorization

13
推荐指数
1
解决办法
448
查看次数

在什么条件下.NET JIT编译器执行自动矢量化?

新的RyuJIT编译器是否曾生成向量(SIMD)CPU指令,何时?

附注:System.Numerics命名空间包含允许显式使用Vector操作的类型,这些操作可能会也可能不会生成SIMD指令,具体取决于CPU,CLR版本,JITer版本,是否直接编译为本机代码.这个问题具体是关于何时非矢量代码(例如在C#或F#中)将产生SIMD指令.

.net simd vectorization auto-vectorization ryujit

12
推荐指数
1
解决办法
1104
查看次数

整数向量化精度/整数除法精度是否依赖于 CPU?

我尝试对 16 位整数 ARGB 通道的 64 位颜色的预乘进行矢量化。

我很快意识到,由于缺乏加速整数除法支持,我需要将我的值转换为float并显式使用一些 SSE2/SSE4.1 内在函数以获得最佳性能。尽管如此,我还是想保留非特定的通用版本作为后备解决方案(我知道它目前比某些普通操作慢,但它将提供未来可能的改进的兼容性)。

但是,在我的机器上结果不正确。

一个非常小的重现:

// Test color with 50% alpha
(ushort A, ushort R, ushort G, ushort B) c = (0x8000, 0xFFFF, 0xFFFF, 0xFFFF);

// Minimal version of the fallback logic if HW intrinsics cannot be used:
Vector128<uint> v = Vector128.Create(c.R, c.G, c.B, 0u);
v = v * c.A / Vector128.Create(0xFFFFu);
var cPre = (c.A, (ushort)v[0], (ushort)v[1], (ushort)v[2]);

// Original color:
Console.WriteLine(c); // prints (32768, 65535, 65535, 65535)

// Expected …
Run Code Online (Sandbox Code Playgroud)

c# precision simd vectorization auto-vectorization

11
推荐指数
0
解决办法
151
查看次数

cython boundscheck = True比boundscheck = False快

请考虑以下最小示例:

#cython: language_level=3, boundscheck=False, wraparound=False, initializedcheck=False, cdivision=True
cimport cython
from libc.stdlib cimport malloc

def main(size_t ni, size_t nt, size_t nx):
    cdef:
        size_t i, j, t, x, y
        double[:, :, ::1] a = <double[:ni, :ni, :nx]>malloc(ni * ni * nx * sizeof(double))
        double[:, :, ::1] b = <double[:nt, :ni, :nx]>malloc(nt * ni * nx * sizeof(double))
        size_t[:, :, ::1] best = <size_t[:nt, :ni, :nx]>malloc(nt * ni * nx * sizeof(size_t))
        size_t mxi
        double s, mxs
    for t in range(nt):
        for j …
Run Code Online (Sandbox Code Playgroud)

cython auto-vectorization

10
推荐指数
1
解决办法
1672
查看次数

为什么gcc autovectorization对3x3的卷积矩阵不起作用?

我已经为卷积矩阵实现了以下程序

#include <stdio.h>
#include <time.h>

#define NUM_LOOP 1000
#define N 128   //input or output dimention 1
#define M N     //input or output dimention 2
#define P 5 //convolution matrix dimention 1 if you want a 3x3 convolution matrix it must be 3
#define Q P     //convolution matrix dimention 2
#define Csize P*Q   
#define Cdiv  1     //div for filter 
#define Coffset 0   //offset 

//functions
void unusual(); //unusual implementation of convolution
void naive();
//data
unsigned short int input[N][M] __attribute__(( aligned(32))); // input …
Run Code Online (Sandbox Code Playgroud)

c x86 gcc compiler-optimization auto-vectorization

10
推荐指数
1
解决办法
363
查看次数

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

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
查看次数

std::min 与使用 #pragma GCC 优化(“O3”)的三元 gcc 自动矢量化

我知道“为什么我的编译器要这样做”不是最好的问题类型,但这个问题对我来说真的很奇怪,我很困惑。

我原以为这std::min()与手写的三元相同(可能还有一些编译时模板的东西),并且在正常使用时似乎可以编译为相同的操作。但是,当尝试使“最小和总和”循环自动向量化时,它们似乎不一样,如果有人能帮我找出原因,我会很高兴。这是一个产生问题的小示例代码:

#pragma GCC target ("avx2")
#pragma GCC optimize ("O3")

#include <cstdio>
#include <cstdlib>
#include <algorithm>

#define N (1<<20)
char a[N], b[N];

int main() {
    for (int i=0; i<N; ++i) {
        a[i] = rand()%100;
        b[i] = rand()%100;
    }

    int ans = 0;
    #pragma GCC ivdep
    for (int i=0; i<N; ++i) {
        //ans += std::min(a[i], b[i]);
        ans += a[i]>b[i] ? a[i] : b[i];
    }
    printf("%d\n", ans);
}
Run Code Online (Sandbox Code Playgroud)

gcc 9.3.0用编译命令编译它g++ -o test test.cpp -ftree-vectorize -fopt-info-vec-missed -fopt-info-vec-optimized -funsafe-math-optimizations …

c++ optimization gcc compiler-optimization auto-vectorization

9
推荐指数
1
解决办法
222
查看次数