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

目录
相关文章
网站备案工信部短信核验操作流程
阿里云网站备案工信部短信核验操作流程,网站备案通过阿里云初审后后提交到管局,需要进行工信部短信核验
1402 0
网站备案工信部短信核验操作流程
|
7月前
|
运维 安全 数据建模
阿里云数字证书管理服务免费版和收费版SSL证书区别、收费标准、申请及部署教程参考
阿里云数字证书管理服务提供多种SSL证书类型和品牌,适用于不同规模的网站,包括但不限于电商、小型企业、大型企业或个人等。阿里云SSL证书有收费版的也有免费版的,有的新手用户由于是初次在阿里云申请SSL证书,可能不是很清楚免费版证书的申请和部署流程,本文为以图文形式为大家展示阿里云免费版SSL证书最新的申请及部署教程,以供参考。
|
11月前
|
传感器 物联网 开发工具
低功耗蓝牙和 Wi-Fi 哪个成本更低
低功耗蓝牙和Wi-Fi在成本上各有优势。低功耗蓝牙芯片成本较低,功耗更小,适合简单数据传输;而Wi-Fi传输速率高,但芯片成本和功耗相对较高,适用于复杂网络环境。具体选择需根据应用场景决定。
|
调度 C语言
深入浅出:C语言线程以及线程锁
线程锁的基本思想是,只有一个线程能持有锁,其他试图获取锁的线程将被阻塞,直到锁被释放。这样,锁就确保了在任何时刻,只有一个线程能够访问临界区(即需要保护的代码段或数据),从而保证了数据的完整性和一致性。 线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位。一个进程可以包含一个或多个线程,而每个线程都有自己的指令指针和寄存器状态,它们共享进程的资源,如内存空间、文件句柄和网络连接等。 线程锁的概念
712 1
|
存储 SQL 数据库
数据库技术探索:基础架构、应用场景与未来展望
一、引言 数据库技术是信息时代的基石,为企业和组织提供了数据存储、检索、分析和管理的核心支撑
|
负载均衡 算法 网络协议
SLB基本概念
SLB基本概念
822 3
|
存储 算法 Shell
C++项目实战-多进程(一篇文章)(一)
C++项目实战-多进程(一篇文章)(一)
377 0
|
分布式计算 关系型数据库 Hadoop
使用Sqoop将数据从Hadoop导出到关系型数据库
使用Sqoop将数据从Hadoop导出到关系型数据库
|
存储 NoSQL Linux
Linux调试工具GDB(2)
Linux调试工具GDB(2)
286 0