浅谈C\C++代码优化中的一些小技巧

本文探讨了代码优化中的效率问题,从硬件加速(GPU、OpenMP、SSE)和软件加速(变量精简、去除冗余代码、快速算法)两方面介绍了提高代码运行效率的方法。

转自:http://blog.csdn.net/connor_lele/article/details/25566855

编写C\C++程序快两年,对于代码优化有很深的感触。个人认为,代码优化是一门很深的学问,而作为码农,我们总是在实践中不断更新自己对它的认识和理解。对于这个很大很深的问题,我只是根据自己的所学所见以及所悟来谈谈代码优化中的效率问题,希望对初学者有一些帮助,如有不对的地方还望指正。

一、定义

所谓代码优化是指在不改变程序运行结果的前提下,使最终生成的目标代码的运行时间更短,时空效率得到优化。这里,我结合自己的图像处理方面的一些经历谈谈如何如何减少运行时间、提高运行效率。个人认为主要包括硬件加速和软件加速两个方面。

二、硬件加速

顾名思义,硬件加速指的是充分利用计算机现有的的硬件资源编写代码,进而提高代码的运行效率。据我所知,常见的适合计算机的硬件加速方法有:GPU,OpenMP以及SSE。

GPU

GPU(Graphic Processing Unit)是图像处理器,它是显卡的大脑,早期主要用于电脑的2D\3D图形计算。随着科技的发展,GPU开始在并行计算等方面得到广泛的应用,其优势在于它包含很多小的独立处理单元,这些处理单元可以并行运算。这一特点决定了GPU相对于CPU而言在并行数据的处理上具有更大的优势,如图像处理中的计算梯度、反转灰度等运算。

关于GPU编程,首先需要硬件上的支持,即计算机需要有独立显卡,其次需要软件上的支持,即编程环境以及相应的GPU接口,如VS2008和NVIDIA的CUDA。CUDA是NVIDIA推出的一个GPU运算平台,我们可以理解API。一般而言,如果我们的电脑有独立显卡,在安装显卡驱动、CUDA开发包以及编程环境(如VS2008)之后,我们便可以在相应的工程项目中嵌入.cu格式的文件用于GPU编程。有关GPU编程的详细过程这里就不详细叙述了,感兴趣的同学可以参考CUDA提供的用户手册以及《GPU高性能编程CUDA实战》一书,前者比较详细,后者比较易懂。

OpenMP

百度百科的定义:OpenMP是由OpenMP Architecture Review Board牵头提出的,并已被广泛接受的,用于共享内存并行系统的多线程程序设计的一套指导性的编译处理方案(Compiler Directive),支持语言包括C语言、C++和Fortran等,适合并行处理的数据。

在VS2008下面使用OpenMP比较简单,我们需要将项目》配置属性》c/C++》语言下的OpenMP支持打开,并在工程项目中包含omp.h头文件,这样所建的项目便支持OpenMP了。

SSE

SSE(Streaming SIMD Extensions,单指令多数据流扩展)指令集是Intel在Pentium III处理器中率先推出的。由SSE部分和MMX部分组成。SSE部分负责处理浮点数,MMX 部分专门计算整数。SSE部分可以同时处理四个浮点数。VS2008下需要包含emmintrin.h头文件。举个例子,如需要计算向量中每个元素相乘的结果,其运算速度是原始方法的4倍。需要注意的是,SSE需要数组的首地址是16的整数倍。

  • 原始方法

    for(int i = 0; i < nSize; i++)
    {
        *pResult = (*pArray1)*(*pArray2);
        pArray1++; pArray2++; pResult++;
    }
  • SSE方法
    __m128 *p1 = (__m128*)pArray1;
    __m128 *p2 = (__m128*)pArray2;
    __m128 *p3 = (__m128*)pResult;
    for(int i = 0; i < nSize; i++)
    {
        *p3 = _mm_mul_ps(p1,p2);
        p1++; p2++; p3++;
    }

三、软件加速

个人认为,所谓的软件加速是值用最小的计算代价达到所需的目标,一般而言,软件加速需要对语言本身比较熟悉,同时需要了解相关问题的快速算法,这样才能够写出高效率的算法。这里,我结合自己写代码过程的体会从三个方面介绍一下软件加速的几种方法,包括变量、函数等方面的精简,去除冗余代码以及使用快速算法等。

变量、函数等方面的精简
  • 用尽量小的数据类型

    能用bool型变量不用char型;能用char型变量不用int型,虽然有时不同数据类型的运算速度可能相同;如,在表示图像数据时,由于图像数据一般为0-255之间,对其进行的大部分运算也都在0-255之间,这时我们只需使用uchar型即可。

  • 减少运算强度

    尽量使用移位、取余运算代替乘法、除法等; 如b=a/4可替代为b=a>>2,b=a%4可替代为b=a&3,b=3*a可替代为b=a<<1+a。

    避免不必要的整数除法; 如avg=sum/w/h可替代为avg=sum/(w*h)。

    使用增量和减量操作符; 如a=a+1可替代为a++。

  • 循环优化

    拆解小循环,即不要将一些可列举的情况写成循环,特别是该小循环嵌套在大循环中情况。

    switch语句中概率较大的情况放在靠前的位置。

  • 使用内联函数

去除冗余代码

所谓的去除冗余代码是指程序在不知不觉中进行了很多重复的运算,而这些重复运算其实可以通过巧妙的安排进行避免。这里说两个图像处理中常见的方法:查找表和积分图。

  • 查找表

    所谓的查找表比较通俗的说法就是已经赋好值的数组。当我们在程序中需要用到查找表中的某种情况时,只需要调用相应的数组元素即可,如计算图像的梯度。正常情况下,我们计算完一个像素点水平方向和垂直方向的差值dx和dy之后,通过公式sqrt(dx*dx+dy*dy)和atan2(dy,dx)便可分别得到梯度的幅值和方向。但是,这种方法存在很大的冗余,它需要频繁地调用开方函数和反正切函数,而这个代价是很大的。仔细想想,由于像素值属于[0,255],那么dx和dy便属于[-255,255],其情况是可列举的。如果我们把所有(dx,dy)对应的梯度的幅值和方向提前计算好,并放到一个数组构成查找表,那么当给定一个像素点的dx和dy,我们只需要索引到其对应的数组元素即可。相对于原始方法而言,这样能够大大地减少运算量,提高代码效率。

  • 积分图

    积分图指计算图像中每个像素点对应的左上角像素值之和。最直观的方法可能是依次遍历每个像素点,然后计算该像素点左上角的像素值之和。这种方法虽然简单、直观,但是计算复杂,没有利用当前已有像素点和的信息。这里,给一种简单,有效的方法,它充分利用了当前已有像素点和的信息。

    for(i = 0; i < w; i++)
    {
        offset = i;
        pResult[offset] = (int)data[offset];
        for(j = 1; j < h; j++)
        {
            offset += w;
            pResult[offset] = pResult[offset-w]+(int)data[offset];
        }
    }
    for(j = 0; j < h; j++)
    {
        offset = j*w;
        pResult[offset] = (int)data[offset];
        for(i = 1; i < w; i++)
        {
            offset++;
            pResult[offset] += (int)data[offset];
        }
    }

    可见,积分图的计算是有技巧的。那么积分图有什么用了,其实积分图的出现本身也是为了加快一些问题的运算速度,如大量计算图像中局部区域的像素和。

使用已有的快速算法

许多问题(例如查找、排序以及傅里叶变换等)其实在学术界都有相应的快速算法,我们所需要做的其实就是搜索,常见问题的快速算法可能baidu一下就能搞定,对于一些特定的问题,我们可能需要google出相应的论文,并根据论文思想编写相应的快速算法。下面简要地列举查找、排序以及傅里叶变换等问题的快速算法。

  • 查找

    包括二分查找、分块查找以及哈希查找等。

  • 排序

    包括快速排序、堆排序以及归并排序等。

  • 傅里叶变换

    可以用fft实现,目前比较最快的fft算法开发包应该是fftw,matlab应该用的就是这个开发包。

总结

个人感觉硬件加速相对而言简单,对于个人能力要求相对于较低,但是可能需要一定的硬件成本,而软件加速需要时间和知识的积累,对于个人能力要求较高,但是不需要烧钱。至于效果,硬件加速和软件加速属于两种不同方法,我们需要根据实际情况判断那种方法更适合,例如,很多时候我们花费了很大的精力进行代码优化后的速度还比不上简单GPU加速后的速度。

代码下载链接: https://pan.quark.cn/s/a4b39357ea24 全球数据治理的发展趋势; 数据合规相关的法规标准以及重点案例的收集; 数据安全领域的标准与产业应用实践; 数字转型时代中数据流转所面临的风险控制; 运用人工智能技术进行的大数据安全保障; 各类厂商提供的数据安全防护措施; 完整的数据治理总体方案; 针对数据安全的治理解决方案; 【行业权威机构推荐】数据安全治理的建设指导手册; 企业数据防止信息泄露的体系化咨询服务完整资料; 阿里云在大数据安全方面的实践经验分享; 大数据安全等级保护过程中遇到的挑战及应对策略; 以风险为基础的数据完整性管理实践指导文件; 数据安全管理的相关法规条例; CSA组织发布的大数据安全与隐私保护手册中文翻译版本; GDPR框架下的数据合规性要求; 通过数据资产管理视角探讨数据安全监管; 大数据安全治理的汇编资料(共计四篇); 大数据安全的相关标准规范; 大数据应用场景中的隐性隐私安全隐患; 大数据应用环境下的隐私保护及风险控制技术; 数字化时代背景下的隐私保护策略; 等级保护2.0标准下的数据安全解决方案; 国际上通用的数据管理能力成熟度评估模型; 华为公司在大数据安全管理方面的实践经验; 企业数据安全能力体系框架_数据安全能力成熟度模型的构建与实际应用; 企业数据管理领域的理论知识和实践操作; 从零开始构建企业数字化运营全流程白皮书; 数据安全领域的权威白皮书; 数据安全能力建设的实施指导手册; 数据安全治理领域的白皮书及配套演示文稿; 数据安全治理的具体实施方案; 数据安全的多维度综合防御体系; 数据跨境传输的安全解决方案; 数据安全治理的技术支撑架构; 金融行业数据安全治理模型及实践案例; 涵盖但...
内容概要:本报告系统分析了2026年上半年AI引擎生成式优化(GEO优化)行业的发展现状与趋势,涵盖用户规模、商业生态、市场规模、技术演进及认知偏差等核心维度。数据显示,头部大模型月活用户快速增长,豆包、通义千问、DeepSeek等平台在用户基数与场景融合方面表现突出;GEO专业服务市场规模已达30亿元,预计下半年将翻倍增长。报告指出,用户消费决策正从传统搜索向“AI探索+搜索验证”双轨模式转变,企业入驻加速,行业进入规模化部署期。同时,随着豆包、千问等平台推进交易闭环建设,GEO优化正从内容曝光迈向交易转化,技术业态全面升级。然而,行业普遍存在“重技术轻结果”“过程与目的倒置”等认知偏差,亟需回归营销本质,推动结果前置。; 适合人群:品牌企业营销负责人、数字营销服务商、AI技术从业者及关注生成式AI商业化落地的研究人员。; 使用场景及目标:①帮助企业理解GEO优化在AI时代营销体系中的定位与价值;②指导企业制定以业务结果为导向的GEO布局策略;③助力服务商构建可衡量、可持续的GEO服务框架;④把握交易闭环趋势下的技术升级方向。; 阅读建议:此资源以行业洞察与趋势预判为核心,强调业务目标与技术实施的统一,建议读者结合自身行业特性与用户决策路径,重点关注效果衡量体系构建与平台生态适配性,避免陷入纯技术操作误区,推动GEO优化真正服务于品牌增长。
内容概要:本文聚焦于低惯量电力系统中构网型变流器的先进控制策略,系统复现并深入分析了基于IEEE 9节点混合拓扑的四种关键控制方法——下垂控制、虚拟同步机控制(VSM)、匹配控制以及可调度虚拟振荡器控制(dVOC)的电磁暂态仿真模型,全部通过Simulink平台实现。研究构建了高保真的仿真系统,全面对比不同控制策略在动态响应速度、系统稳定性、抗干扰能力及并网性能等方面的优劣,旨在揭示其在高比例新能源接入背景下维持电网稳定运行的作用机制。该工作不仅具备扎实的理论基础,更具有突出的工程应用价值,为新型电力系统的控制器设计、参数优化与稳定性评估提供了可靠的仿真依据和技术参考。; 适合人群:面向电力系统、电力电子、自动化等相关专业的研究生、科研人员及工程技术人员,尤其适合从事新能源并网、微电网控制、构网型变流器研发以及希望复现高水平SCI论文仿真实验的专业人士;要求读者具备良好的电力系统理论基础和熟练的MATLAB/Simulink操作技能。; 使用场景及目标:① 深入掌握构网型变流器在低惯量系统中的建模方法与核心控制原理;② 系统性对比下垂控制、VSM、dVOC等前沿控制策略的动态特性和稳定性表现差异;③ 精确复现权威期刊论文中的电磁暂态仿真结果,有效支撑高水平科研论文撰写、课题申报与项目验收;④ 为实际工程应用中构网型变流器的选型、参数整定与控制策略优化提供一个可验证、可扩展的仿真测试平台。; 阅读建议:建议结合所提供的完整Simulink模型与配套资源,严格按照文档目录结构循序渐进地学习,重点剖析每种控制策略的模块化实现细节、控制器参数设置及仿真工况配置,务必动手修改参数、运行仿真并分析结果,以深化对控制机理的理解,并在此基础上开展二次开发与创新性研究。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值