你如何利用SIMD(如SSE/AVX)优化图像处理的性能?

SIMD优化问题

  • 1. SIMD 在图像处理中的优化方式
  • 2. 典型应用场景
  • 3. SIMD 的常见优化技巧
  • 4. 总结

利用 SIMD(Single Instruction, Multiple Data) 指令集(如 SSE/AVX/AVX2/AVX-512)优化图像处理的性能,可以极大地提升计算速度,减少 CPU 计算瓶颈。以下是具体的方法和示例:

1. SIMD 在图像处理中的优化方式

(1)SIMD 的原理
• 普通 CPU 处理方式:逐个像素计算(如 for 循环),每次只能处理一个数据。
• SIMD 处理方式:一次操作多个数据,例如 SSE 处理 4 个 32 位浮点数,AVX 处理 8 个 32 位浮点数,AVX-512 可处理 16 个 32 位浮点数。

2. 典型应用场景

1)灰度转换

RGB 图像转换为灰度图的公式:

Gray = 0.299 R + 0.587 G + 0.114 B

SIMD 优化代码(使用 AVX2):

#include <immintrin.h>  // 包含 AVX 指令集头文件
#include <opencv2/opencv.hpp>

void rgb_to_gray_avx(const cv::Mat& src, cv::Mat& dst) {
    int width = src.cols;
    int height = src.rows;
    dst.create(height, width, CV_8UC1);

    __m256 r_weight = _mm256_set1_ps(0.299f);
    __m256 g_weight = _mm256_set1_ps(0.587f);
    __m256 b_weight = _mm256_set1_ps(0.114f);

    for (int y = 0; y < height; ++y) {
        const uchar* src_ptr = src.ptr<uchar>(y);
        uchar* dst_ptr = dst.ptr<uchar>(y);

        for (int x = 0; x < width; x += 8) {  // AVX 处理 8 个像素
            __m256 r = _mm256_cvtepi32_ps(_mm256_cvtepu8_epi32(_mm_loadl_epi64((__m128i*)(src_ptr + x * 3 + 0))));
            __m256 g = _mm256_cvtepi32_ps(_mm256_cvtepu8_epi32(_mm_loadl_epi64((__m128i*)(src_ptr + x * 3 + 1))));
            __m256 b = _mm256_cvtepi32_ps(_mm256_cvtepu8_epi32(_mm_loadl_epi64((__m128i*)(src_ptr + x * 3 + 2))));

            __m256 gray = _mm256_add_ps(_mm256_add_ps(_mm256_mul_ps(r, r_weight), _mm256_mul_ps(g, g_weight)), _mm256_mul_ps(b, b_weight));

            __m256i gray_int = _mm256_cvtps_epi32(gray);
            __m128i gray_8bit = _mm_packus_epi32(_mm256_castsi256_si128(gray_int), _mm256_extractf128_si256(gray_int, 1));
            
            _mm_storel_epi64((__m128i*)(dst_ptr + x), gray_8bit);
        }
    }
}

优化点:
• AVX2 一次处理 8 个像素,相比普通 for 循环,可以加速 8 倍。
• 使用 _mm256_mul_ps 进行浮点运算,提高吞吐量。

(2)高斯滤波

普通高斯滤波

G ( x , y ) = ∑ i = − 1 1 ∑ j = − 1 1 w ( i , j ) ⋅ I ( x + i , y + j ) G(x,y) = \sum\limits_{i=-1}^{1} \sum\limits_{j=-1}^{1} w(i,j) \cdot I(x+i, y+j) G(x,y)=i=11j=11w(i,j)I(x+i,y+j)

SIMD 优化思路
• 使用 SSE/AVX 加载多个像素点。
• 并行计算加权和,避免逐像素遍历。

SIMD 代码示例(AVX2 版本):

void gaussian_blur_avx(const cv::Mat& src, cv::Mat& dst) {
    int width = src.cols;
    int height = src.rows;
    dst.create(height, width, CV_8UC1);

    float kernel[3] = {0.25f, 0.5f, 0.25f}; // 高斯核
    __m256 k0 = _mm256_set1_ps(kernel[0]);
    __m256 k1 = _mm256_set1_ps(kernel[1]);
    __m256 k2 = _mm256_set1_ps(kernel[2]);

    for (int y = 1; y < height - 1; ++y) {
        for (int x = 1; x < width - 1; x += 8) {  // 8 个像素并行
            __m256 p0 = _mm256_cvtepi32_ps(_mm256_cvtepu8_epi32(_mm_loadl_epi64((__m128i*)&src.at<uchar>(y-1, x-1))));
            __m256 p1 = _mm256_cvtepi32_ps(_mm256_cvtepu8_epi32(_mm_loadl_epi64((__m128i*)&src.at<uchar>(y, x-1))));
            __m256 p2 = _mm256_cvtepi32_ps(_mm256_cvtepu8_epi32(_mm_loadl_epi64((__m128i*)&src.at<uchar>(y+1, x-1))));

            __m256 sum = _mm256_add_ps(_mm256_add_ps(_mm256_mul_ps(p0, k0), _mm256_mul_ps(p1, k1)), _mm256_mul_ps(p2, k2));

            __m256i result = _mm256_cvtps_epi32(sum);
            __m128i result_8bit = _mm_packus_epi32(_mm256_castsi256_si128(result), _mm256_extractf128_si256(result, 1));

            _mm_storel_epi64((__m128i*)&dst.at<uchar>(y, x), result_8bit);
        }
    }
}

优化点:
• 通过 _mm256_mul_ps 进行 SIMD 并行加权计算。
• 适用于 高斯模糊、均值滤波等卷积操作。

3. SIMD 的常见优化技巧

1.	使用对齐内存(如 _mm_malloc 或 alignas(32)),避免 内存访问未对齐 导致的性能下降。
2.	数据预取(Prefetching),减少 Cache Miss。
3.	循环展开(Loop Unrolling),减少 分支预测失败。
4.	减少分支(Branchless Programming),例如使用 _mm256_blendv_ps() 进行 条件运算。

4. 总结

在这里插入图片描述

使用 SIMD(SSE/AVX) 优化图像处理,不仅能显著提升性能,还能降低 CPU 负载,尤其适用于 工业检测、实时图像处理、深度学习预处理 等领域。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/969855.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Guava学习(一)

避免使用Null值 在程序开发中&#xff0c;特别是涉及到集合的场景&#xff0c;90%都不允许null值的存在&#xff0c;特别是null值存在歧义&#xff0c;当使用ConcurrentMap是为了并发安全不允许将null值作为key&#xff0c;但是普通map允许null值为key&#xff0c;当null作为k…

springboot026在线文档管理系统

版权声明 所有作品均为本人原创&#xff0c;提供参考学习使用&#xff0c;如需要源码数据库配套文档请移步 www.taobysj.com 搜索获取 技术实现 开发语言&#xff1a;Javavue。 框架&#xff1a;后端spingboot前端vue。 模式&#xff1a;B/S。 数据库&#xff1a;mysql。 开…

Linux——stdio

一、基本概念 文件: 一组相关数据的集合 文件名: 01.sh //文件名 流&#xff1a; 流是指数据在程序或系统中的流动方式。在Linux中&#xff0c;数据流通常通过文件描述符&#xff08;File Descriptors&#xff09;进行管理。文件描述符是一个非负整数&#xff0c;用…

解决 paddle ocr 遇到 CXXABI_1.3.13 not found 的问题

ImportError: /lib/x86_64-linux-gnu/libstdc.so.6: version CXXABI_1.3.13 not found (required by /home/hum/anaconda3/envs/ipc/lib/python3.11/site-packages/paddle/base/libpaddle.so) 通过命令检查 strings /lib/x86_64-linux-gnu/libstdc.so.6|grep CXXABI 而实际上我…

【物联网】电子电路基础知识

文章目录 一、基本元器件1. 电阻2. 电容3. 电感4. 二极管(1)符号(2)特性(3)实例分析5. 三极管(1)符号(2)开关特性(3)实例6. MOS管(产效应管)(1)符号(2)MOS管极性判定(3)MOS管作为开关(4)MOS管vs三极管7. 门电路(1)与门(2)或门(3)非门二、常用元器件…

LLM论文笔记 5: CodeT: Code Generation with Generated Tests

Arxiv日期&#xff1a;2022.7.21机构&#xff1a;Microsoft 关键词 代码补全测试自生成&#xff08;提出&#xff09;Inference 核心结论 1. 更多的测试用例通常可以提高代码大模型的性能&#xff0c;但当测试用例数量达到一定阈值后&#xff0c;性能提升效果减弱 2. 只考虑…

Nginx--日志(介绍、配置、日志轮转)

前言&#xff1a;本博客仅作记录学习使用&#xff0c;部分图片出自网络&#xff0c;如有侵犯您的权益&#xff0c;请联系删除 一、Nginx日志介绍 nginx 有一个非常灵活的日志记录模式&#xff0c;每个级别的配置可以有各自独立的访问日志, 所需日志模块 ngx_http_log_module 的…

网络营销新宠:http代理ip为广告投放精准定位保驾护航

在当今数字化时代&#xff0c;网络营销已成为企业推广产品和服务、提升品牌影响力的重要手段。而在众多的网络营销工具中&#xff0c;http代理ip正逐渐崭露头角&#xff0c;成为广告投放精准定位的得力伙伴&#xff0c;为广告投放保驾护航。 http代理ip在广告投放中发挥着多方面…

Python Pandas(7):Pandas 数据清洗

数据清洗是对一些没有用的数据进行处理的过程。很多数据集存在数据缺失、数据格式错误、错误数据或重复数据的情况&#xff0c;如果要使数据分析更加准确&#xff0c;就需要对这些没有用的数据进行处理。数据清洗与预处理的常见步骤&#xff1a; 缺失值处理&#xff1a;识别并…

CodeGPT + IDEA + DeepSeek,在IDEA中引入DeepSeek实现AI智能开发

CodeGPT IDEA DeepSeek&#xff0c;在IDEA中引入DeepSeek 版本说明 建议和我使用相同版本&#xff0c;实测2022版IDEA无法获取到CodeGPT最新版插件。&#xff08;在IDEA自带插件市场中搜不到&#xff0c;可以去官网搜索最新版本&#xff09; ToolsVersionIntelliJ IDEA202…

数字电路-基础逻辑门实验

基础逻辑门是数字电路设计的核心元件&#xff0c;它们执行的是基本的逻辑运算。通过这些基本运算&#xff0c;可以构建出更为复杂的逻辑功能。常见的基础逻辑门包括与门&#xff08;AND&#xff09;、或门&#xff08;OR&#xff09;、非门&#xff08;NOT&#xff09;、异或门…

常见的IP地址分配方式有几种:深入剖析与适用场景‌

在数字互联的世界里&#xff0c;IP地址如同网络世界的“门牌号”&#xff0c;是设备间通信的基础。随着网络技术的飞速发展&#xff0c;IP地址的分配方式也日趋多样化&#xff0c;以适应不同规模、不同需求的网络环境。本文将深入探讨当前主流的几种IP地址分配方式&#xff0c;…

【C语言】C语言 停车场管理系统的设计与实现(源码)【独一无二】

&#x1f449;博__主&#x1f448;&#xff1a;米码收割机 &#x1f449;技__能&#x1f448;&#xff1a;C/Python语言 &#x1f449;专__注&#x1f448;&#xff1a;专注主流机器人、人工智能等相关领域的开发、测试技术。 系列文章目录 目录 系列文章目录一、设计要求二、设…

【现代深度学习技术】深度学习计算 | GPU

【作者主页】Francek Chen 【专栏介绍】 ⌈ ⌈ ⌈PyTorch深度学习 ⌋ ⌋ ⌋ 深度学习 (DL, Deep Learning) 特指基于深层神经网络模型和方法的机器学习。它是在统计机器学习、人工神经网络等算法模型基础上&#xff0c;结合当代大数据和大算力的发展而发展出来的。深度学习最重…

蓝桥杯备考:贪心算法之纪念品分组

P1094 [NOIP 2007 普及组] 纪念品分组 - 洛谷 这道题我们的贪心策略就是每次找出最大的和最小的&#xff0c;如果他们加起来不超过我们给的值&#xff0c;就分成一组&#xff0c;如果超过了&#xff0c;就把大的单独成一组&#xff0c;小的待定 #include <iostream> #i…

【Elasticsearch】Mapping概述

以下是Elasticsearch中提到的关于Mapping的各模块概述&#xff1a; --- 1.Dynamic mapping&#xff08;动态映射&#xff09; 动态映射是指Elasticsearch在索引文档时&#xff0c;自动检测字段类型并创建字段映射的过程。当你首次索引一个文档时&#xff0c;Elasticsearch会根…

java商城解决方案

数字化时代&#xff0c;电子商务已成为企业拓展市场的重要渠道。对于想要建立在线商店的企业来说&#xff0c;选择正确的技术堆栈至关重要。 Java作为一种成熟且广泛使用的编程语言&#xff0c;为构建购物中心提供了强大的功能和灵活性。 商城Java源码&#xff1a;商城开发的核…

SSM开发(十二) mybatis的动态SQL

目录 一、为什么需要动态SQL? Mybatis 动态 sql 是做什么的? 二、多种动态 SQL 元素 三、示例 1、model定义 2、数据库定义 3、UserMapper接口及UserMapper.xml内容定义 if标签 choose/when/otherwise 标签 foreach标签 trim 标签 四、动态SQL注意 一、为什么需…

HCIA项目实践---OSPF的知识和原理总结

9.5 OSPF 9.5.1 从哪些角度评判一个动态路由协议的好坏&#xff1f; &#xff08;1&#xff09;选路佳&#xff08;是否会出环&#xff09; OSPF 协议采用链路状态算法&#xff0c;通过收集网络拓扑信息来计算最短路径&#xff0c;从根本上避免了路由环路的产生。 &#xff08…

HCIA项目实践---OSPF的基本配置

9.5.12 OSPF的基本配置 &#xff08;所搭环境如上图所示&#xff09; A 先配置IP地址 (先进入路由器R1的0/0/0接口配置IP地址&#xff0c;再进入环回接口配置IP地址) &#xff08;配置R2路由器的0/0/0和0/0/1以及环回接口的IP地址&#xff09; &#xff08;置R3路由器的0/0/0接…