首页 > 其他分享 >2024.4.9 AVX加速卷积part2

2024.4.9 AVX加速卷积part2

时间:2024-04-09 11:25:07浏览次数:18  
标签:__ kernel AVX2 2024.4 part2 set1 pd AVX

AVX加速卷积part2

重新构筑下昨天的想法:
问题:

源程序在O2下的执行时间:

经过AVX改进后的执行时间:

下面尝试在AVX2基础上改进:
AVX与AVX2的主要区别和改进:

向量整数指令:
AVX主要集中在浮点数运算上,提供了对256位宽SIMD(单指令多数据)向量的支持。
AVX2引入了向量整数运算的支持。这意味着,除了浮点运算外,AVX2还可以对256位的整数向量执行各种运算,这在处理图形、视频处理和数字信号处理等领域特别有用。
FMA(Fused Multiply-Add)指令:
虽然FMA指令首次出现在AVX中(作为AVX的扩展,称为FMA3),但AVX2进一步加强了对这些指令的支持。FMA指令可以在单个操作中完成乘法和加法,从而提高了计算的效率和准确性。
Gather指令:
AVX2引入了gather指令,这允许从非连续内存位置加载数据到一个寄存器中。这对于处理稀疏矩阵和不规则数据结构特别有用,因为它可以减少必须手动编码的复杂内存访问模式。
向量化的位操作:
AVX2增加了对向量位操作的支持,使得位级并行处理成为可能,这在某些算法中可以极大提高性能。
扩展的整数指令集:
AVX2通过扩展的整数指令集,提供了更多处理整数向量的能力,如增加、减少、乘法等操作。

FMA func.

// conv_avx2.cpp

bool Convolve1D_Ks5_F64_AVX(double* __restrict__ y, const double* __restrict__ x, const double* __restrict__ kernel, int64_t num_pts) {
    constexpr int64_t kernel_size = 5;
    constexpr int64_t ks2 = kernel_size / 2;

    // Ensure the input size is sufficient for the convolution operation
    if (num_pts < kernel_size) {
        return false;
    }

    // Load the convolution kernel into AVX2 registers
    __m256d k0 = _mm256_set1_pd(kernel[0]);
    __m256d k1 = _mm256_set1_pd(kernel[1]);
    __m256d k2 = _mm256_set1_pd(kernel[2]);
    __m256d k3 = _mm256_set1_pd(kernel[3]);
    __m256d k4 = _mm256_set1_pd(kernel[4]);

    // Perform convolution operations in chunks using AVX2
    for (int64_t i = ks2; i <= num_pts - kernel_size; i += 4) {
        // Load chunks of the input signal into AVX2 registers
        // std::cout << i << '\n';
        __m256d x0 = _mm256_loadu_pd(&x[i + 2]);
        __m256d x1 = _mm256_loadu_pd(&x[i + 1]);
        __m256d x2 = _mm256_loadu_pd(&x[i]);
        __m256d x3 = _mm256_loadu_pd(&x[i - 1]);
        __m256d x4 = _mm256_loadu_pd(&x[i - 2]);

        // Perform element-wise multiplication and sum the results
        __m256d y_val = _mm256_setzero_pd();
        y_val = _mm256_fmadd_pd(x0,k0,y_val);
        y_val = _mm256_fmadd_pd(x1,k1,y_val);
        y_val = _mm256_fmadd_pd(x2,k2,y_val);
        y_val = _mm256_fmadd_pd(x3,k3,y_val);
        y_val = _mm256_fmadd_pd(x4,k4,y_val);

        // Store the convolution results back to the output array
        _mm256_storeu_pd(&y[i], y_val);
    }

    // Handle the remainder of the elements that don't fit into a multiple of 4
    for (int64_t i = num_pts - ks2; i < num_pts; i++) {
        double result = 0.0;
        for (int64_t k = -ks2; k <= ks2; k++) {
            result += x[i - k] * kernel[k + ks2];
        }
        y[i] = result;
    }

    return true;
}

在AVX512指令集下进行改进:

// conv_avx512.cpp

bool Convolve1D_Ks5_F64_AVX512(double* __restrict__ y, const double* __restrict__ x, const double* __restrict__ kernel, int64_t num_pts) {
    constexpr int64_t kernel_size = 5;
    constexpr int64_t ks2 = kernel_size / 2;

    // Ensure the input size is sufficient for the convolution operation
    if (num_pts < kernel_size) {
        return false;
    }

    // Load the convolution kernel into AVX512 registers
    __m512d k0 = _mm512_set1_pd(kernel[0]);
    __m512d k1 = _mm512_set1_pd(kernel[1]);
    __m512d k2 = _mm512_set1_pd(kernel[2]);
    __m512d k3 = _mm512_set1_pd(kernel[3]);
    __m512d k4 = _mm512_set1_pd(kernel[4]);

    // Perform convolution operations in chunks using AVX512
    for (int64_t i = ks2; i <= num_pts - kernel_size; i += 8) { // Note: Change stride to 8 for AVX512
        // Load chunks of the input signal into AVX512 registers
        __m512d x0 = _mm512_loadu_pd(&x[i + 2]);
        __m512d x1 = _mm512_loadu_pd(&x[i + 1]);
        __m512d x2 = _mm512_loadu_pd(&x[i]);
        __m512d x3 = _mm512_loadu_pd(&x[i - 1]);
        __m512d x4 = _mm512_loadu_pd(&x[i - 2]);

        // Perform element-wise multiplication and sum the results
        __m512d y_val = _mm512_setzero_pd();
        y_val = _mm512_fmadd_pd(x0, k0, y_val);
        y_val = _mm512_fmadd_pd(x1, k1, y_val);
        y_val = _mm512_fmadd_pd(x2, k2, y_val);
        y_val = _mm512_fmadd_pd(x3, k3, y_val);
        y_val = _mm512_fmadd_pd(x4, k4, y_val);

        // Store the convolution results back to the output array
        _mm512_storeu_pd(&y[i], y_val);
    }

    // Handle the remainder of the elements that don't fit into a multiple of 8
    for (int64_t i = num_pts - ks2; i < num_pts; i++) {
        double result = 0.0;
        for (int64_t k = -ks2; k <= ks2; k++) {
            result += x[i - k] * kernel[k + ks2];
        }
        y[i] = result;
    }

    return true;
}

执行结果:

标签:__,kernel,AVX2,2024.4,part2,set1,pd,AVX
From: https://www.cnblogs.com/jibinghu/p/18123498

相关文章

  • 2024.4.8 数据结构课件补题
    [AGC055B]ABCSupremacy令ABC分别为1,2,3,然后令\(s_i=(s_i-i)\textmod3\)且结果大于0。然后可以发现三种组合均为连贯的三个相同数。且可以自由移动。可以选择每遇到三个相同数就删掉,或者不断加入栈,如果栈顶三个数相同全部弹出。再比较剩下的数即可。#include<bits......
  • 云原生周刊:2024 年 K8s 基准报告 | 2024.4.8
    开源项目推荐ArgoCDImageUpdaterArgoCDImageUpdater是一个自动更新ArgoCD管理的Kubernetes工作负载容器镜像的工具。简而言之,它将跟踪ArgoCD应用程序资源上的注释指定的图像版本,并通过使用ArgoCDAPI设置参数覆盖来更新它们。目前,它仅适用于使用Kustomize......
  • 谢启鸿高等代数第四版习题7.7部分习题解析part2.以及部分第7章复习题
    7.7部分定理:以为特征值的K阶若当块个数为11.设n阶矩阵A的特征值全为1,求证:对任意的正整数K,与A相似。证明:=(易证故此处不再证明)而且的特征值全为1。的特征值为1的k阶若当块的个数为接下来只需证明相似于即可;即证明两者有相同的约当标准型.由书上7.8节的数学归纳可以知道......
  • 2024.4.8 pytorch框架初上手
    pytorchPyTorch是一个针对深度学习,并且使用GPU和CPU来优化的tensorlibrary(tensor库)中文文档:https://pytorch.org/resources梯度/导数计算#linear.pyimporttorchimportnumpyasnpx=torch.tensor(3,)w=torch.tensor(4.,requires_grad=True)b=t......
  • 2024.4.7 训练1(rating) Codeforces Global Round 25
    https://codeforces.com/contest/1951题解参考:https://zhuanlan.zhihu.com/p/691034931A题一开始的思路比较绕,wa很多发卡了半小时才过。hansun的思路比较硬直,他在极短的时间内过了Ahansun的题解:https://codeforces.com/contest/1951/submission/255262403我的想法是分奇偶情......
  • [护网必备]知攻善防实验室蓝队应急响应工具箱v2024.4
    前言蓝队工具箱是为打造一款专业级应急响应的集成多种工具的工具集,由真实应急响应环境所用到的工具进行总结打包而来,由ChinaRan404,W啥都学,清辉等开发者编写.把项目现场中所用到的工具连同环境一同打包,并实现“可移植性”“兼容性”“使用便捷”等优点。集成模块:“常用工具......
  • 日记 2024.4.7:子集卷积
    日记2024.4.7:子集卷积记号\(F(x)=\sum_{S\subseteq[n]}f_Sx^{S}\)是一个集合幂级数,其中\([n]=\{1,2,\cdots,n\}\),\(f_S\)是一个数组,然后写成像生成函数(其实是“形式幂级数”)的形式,\(x^S\)的这个指数是没意义的。FWT/FMT即两个集合幂级数的并、交、异或卷积运算。h......
  • 2024.4.7每日一题
    mysql1.创建索引idx_emp_no,查询emp_no为10005,使用强制索引forceindex(idx_emp_no)2.现在在last_update后面新增加一列名字为create_date,类型为datetime,NOTNULL,默认值为'000000:00:00'这里的默认值要写成,我还不知道为什么要这样default'2020-10-0100:00:00'java1......
  • 2024.4 做题纪要
    aaaaaaaaaaaaaaaaa大致是在成七集训,虽然挺多都是3月底的不过还是整一下。目录2024.3.30T2简单题2024.4.1T3木棍AGC059EGrid3-coloring2024.4.2T1斩首(Gym104901F)T3战争2024.4.5T3Text2024.4.7CF1707DPartialVirtualTreesCF1874EJellyfishandHack2024.3.30T2......
  • 2024.4.7
    2024.4.7【南天寂静亮星少,北落师门赛明灯。】Sunday二月三十<theme=oi-"search">A.填充单词题目描述小C认识很多单词,但是他并不喜欢其中的一些单词。具体地说,如果一个单词包含连续的3个元音字母,或连续的3个辅音字母,或者1个“L”字母都不包含的话,这个单词是不被小C喜......