AVX 指令集并行技术优化中值滤波

简介: AVX 指令集并行技术优化中值滤波

利用 AVX 向量化技术优化的中值滤波

代码和注释如下:

void medianFilterAVX(int height, int width, unsigned char *__restrict src, unsigned char *__restrict  dst)
{
  // 注意是从 1 开始
    for(int i = 1; i < height - 1; i++)
    {
        int j;
    // 4字节*8 = 32
        for(j = 1; j < width - 1 - 32; j += 32)
        {
            __m256i a[9]; // 3*3 的领域
            a[0] = _mm256_loadu_si256((__m256i *)(src + i * width + j)); // 非对齐模式加载8 个 int 型
            a[1] = _mm256_loadu_si256((__m256i *)(src + i * width + j + 1));
            a[2] = _mm256_loadu_si256((__m256i *)(src + i * width + j - 1));
            a[3] = _mm256_loadu_si256((__m256i *)(src + (i + 1) * width + j));
            a[4] = _mm256_loadu_si256((__m256i *)(src + (i + 1) * width + j + 1));
            a[5] = _mm256_loadu_si256((__m256i *)(src + (i + 1) * width + j - 1));
            a[6] = _mm256_loadu_si256((__m256i *)(src + (i - 1) * width + j));
            a[7] = _mm256_loadu_si256((__m256i *)(src + (i - 1) * width + j + 1));
            a[8] = _mm256_loadu_si256((__m256i *)(src + (i - 1) * width + j - 1));
      // 因为只要知道中值就好(a[4])
            for( int ji = 0; ji < 5; ji++)
            {
                for( int k = ji + 1; k < 9; k++)
                {
          // 逐字节的比较(32个字节)
                    __m256i large = _mm256_max_epu8(a[ji], a[k]);
                    __m256i small = _mm256_min_epu8(a[ji], a[k]);
                    a[ji] = small;
                    a[k] = large;
                }
            }
            _mm256_storeu_si256((__m256i *)(dst + i * width + j), a[4]);// 非对齐模式存储8 个 int 型
        }
    // 不能被 32 整除的部分
        for(int je = j; je < width - 1; je++)
        {
            unsigned char a[9];
            a[0] = src[i * width + je];
            a[1] = src[i * width + je + 1];
            a[2] = src[i * width + je - 1];
            a[3] = src[(i + 1) * width + je];
            a[4] = src[(i + 1) * width + je + 1];
            a[5] = src[(i + 1) * width + je - 1];
            a[6] = src[(i - 1) * width + je];
            a[7] = src[(i - 1) * width + je + 1];
            a[8] = src[(i - 1) * width + je - 1];
            for( int ji = 0; ji < 5; ji++)
            {
                for( int jj = ji + 1; jj < 9; jj++)
                {
                    unsigned char large = std::max<unsigned char>(a[ji], a[jj]);
                    unsigned char small = std::min<unsigned char>(a[ji], a[jj]);
                    a[ji] = small;
                    a[jj] = large;
                }
            }
            dst[i * width + je] = a[4];
        }
    }
    // 边界处理:直接拷贝
    for( int i = 0; i < width; i++)
    {
        dst[i] = src[i];
        dst[(height - 1)*width + i] = src[(height - 1) * width + i];
    }
    for(int i = 0; i < height; i++)
    {
        dst[i * width] = src[i * width];
        dst[i * width + width - 1] = src[i * width + width - 1];
    }
}

入口函数:

cv::Mat input = imread("micky.png", cv::IMREAD_GRAYSCALE);
cv::Mat scale;
cv::resize(input, scale, cv::Size(3200, 3200));// 为了使得优化效果更明显
int width = scale.cols;
int height = scale.rows;
cv::Mat output = cv::Mat(cv::Size(width, height), CV_8UC1, cv::Scalar(0));
Timer timer;
//meanFilter(scale.data, output.data, width, height);
medianFilter(height, width, scale.data, output.data);
timer.rlog("时间");
timer.restart();
medianFilterAVX(height, width, scale.data, output.data);
timer.rlog("时间");

和串行版本的比较结果如下:提升了将近 19 倍

image.png

目录
相关文章
|
1月前
|
算法 计算机视觉 开发者
|
7月前
|
缓存 测试技术 数据中心
【计算机架构】计算 CPU 动态功耗 | 集成电路成本 | SPEC 基准测试 | Amdahl 定律 | MIPS 性能指标
【计算机架构】计算 CPU 动态功耗 | 集成电路成本 | SPEC 基准测试 | Amdahl 定律 | MIPS 性能指标
290 0
|
8月前
|
Docker Windows 容器
cpu不支持avx指令集怎么办
如果CPU不支持AVX指令集,可以考虑以下两种解决方案: 更新BIOS版本:在某些情况下,更新BIOS版本可能会支持AVX指令集。可以联系电脑厂商或者查阅相关教程进行BIOS更新。 更换支持AVX指令集的CPU:如果更新BIOS版本后仍不支持AVX指令集,那么可以考虑更换支持AVX指令集的CPU。可以根据自己的需求和预算选择适合的CPU。 另外,如果在tf1.6以后的官方的tf包都是用AVX编译的,而电脑的CPU不支持AVX指令集,那么可以考虑使用Docker来配置运行环境。但需要注意,Docker在Windows上配置稍显繁琐,并需要配置虚拟机等其他东西。 总的来说,如果不支持AVX指令
2007 0
|
16天前
|
并行计算 算法 C#
C# Mandelbrot和Julia分形图像生成程序更新到2010-9-14版 支持多线程计算 多核处理器
此文档是一个关于分形图像生成器的介绍,作者分享了个人开发的M-J算法集成及色彩创新,包括源代码和历史版本。作者欢迎有兴趣的读者留言交流,并提供了邮箱(delacroix_xu@sina.com)以分享资源。文中还展示了程序的发展历程,如增加了真彩色效果、圈选放大、历史记录等功能,并分享了几幅精美的分形图像。此外,还提到了程序的新特性,如导入ini文件批量输出图像和更新一批图片的功能。文档末尾附有多张程序生成的高分辨率分形图像示例。
|
缓存 openCL 算法
关于实现Halcon算法加速的基础知识(2)(多核并行/GPU)
关于实现Halcon算法加速的基础知识(多核并行/GPU)
2757 0
关于实现Halcon算法加速的基础知识(2)(多核并行/GPU)
|
1月前
|
存储 编译器 数据处理
CPU架构和指令集
不同的CPU架构通常使用不同的指令集。每种CPU架构都有其自己的一组特定的机器指令,这些指令用于执行计算机程序。不同的CPU架构之间的指令集是不兼容的,这意味着编写的程序通常需要根据目标CPU的架构进行编译或汇编,以确保它们能够在该CPU上正确运行。 一些常见的CPU架构包括:
|
机器学习/深度学习 人工智能 并行计算
深度学习设计的衍射处理器并行计算数百个变换
深度学习设计的衍射处理器并行计算数百个变换
深度学习设计的衍射处理器并行计算数百个变换
不同CPU指令的指令集密度
不同CPU指令的指令集密度
110 0
不同CPU指令的指令集密度
|
存储 机器学习/深度学习 编译器
MNN卷积性能提升90%!ARMv86正式投用
ARMv86指令集新增了通用矩阵乘指令与bf16的支持,这些指令理论性能是ARMv82sdot的2倍;使用这些指令实现int8/bf16矩阵乘能够带来显著的性能提升。本文使用ARMv86的新增指令对MNN的ConvInt8和MatMul算子进行实现,最高得到了大约90%的性能提升。
730 0
MNN卷积性能提升90%!ARMv86正式投用
|
算法 安全 程序员
关于实现Halcon算法加速的基础知识(1)(多核并行/GPU)
关于实现Halcon算法加速的基础知识(多核并行/GPU)
1133 0
关于实现Halcon算法加速的基础知识(1)(多核并行/GPU)