在线编程在线课堂在线测评Anycodes在线编程

编程论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

How to use bs4??
本帖最后由 carry0987 于
Double Queue 问题描述 : The new founded Balkan Investment Group Bank (
John 问题描述 : Little John is playing very funny game
linux-command Linux命令大全搜索工具,内容包含Linux命令
Coati 是一款跨平台的代码查看工具,适用于 C/C++ 和 Java。商业软件。特性:1. 索引
系统可承载海量并发,消息收发确认机制 保障消息必达 系统采用动态智
全平台视频监控,支持安卓苹果以及pcweb,支持海康大华等主流dvr,全部源码以及文档 单聊、群聊、商
如何访问类的私有属性? 下面以 TPathData 为例,
问题:从 XE4 以来,Firemonkey 曲线绘图在移动平台不平滑的问题一直令人诟病,提交到官方的 QC 也是族繁不及备载,官方似乎有意的
操作数据库(RODBC)   odbcConnect(dsn, uid="", p
数据模式:mode函数显示任何对象的模式。常见的单个的
系统可承载海量并发,消息收发确认机制 保障消息必达 系统采用动态智
RabbitMQ与PHP(一) 项
Iease团队扩编预备中,盼望能有Ruby或者java工程师加盟。全职兼职都可以。有爱好的伴侣请与我接洽。 邮件:i
ruby 怎么设置装备摆设GTK2,求教指导下!
#include #include #include #include using namespace std; int main() {
标题如图所示: 有n盏灯,编号1~n。一开端灯都是关着的
成熟的消息收发确认机制,支持万人大群 支持开发自定义的消息sdk接口,扩展性超强 支持单/
成熟的消息收发确认机制,支持万人大群 支持开发自定义的消息sdk接口,扩展性超强 支持单/
1. 注意列表和集合的区别 set 列表表现形式: list_1
Ajax   Ajax即“Asynchronous Javascript And
大师好,我比来在做布谷鸟优
分辨提取A和B图像Harris角点,接下来须要对

[C++分享] 程序性能优化

[复制链接]
发表于 2016-4-11 19:00:57 | 显示全部楼层 |阅读模式
  在硬件资源昂贵的时代,编程人员非常注重程序的性能,以期望用尽可能少的硬件资源完成尽可能多的事情。随着科技的发展,
摩尔定律的魔力使得硬件资源已越来越便宜,速度也越来越快,似乎性能已不是编程人员所需关注的事情了。然而在一个竞争
与发展的时代,软件的功能越来越复杂,用户的操作体验越来越重要,而且竞争越来越激烈,谁能以更优势的价格,更好的操
作体验,完成更多更复杂的事情,谁就将在激烈竞争中胜出。因而软件的性能优化必将一直是软件领域所要关注的内容之一。
虽然软件的性能优化贯穿了设计与编码的整个过程,本文也将从设计与编码两个层次对性能优化进行分析。本文还将从CPU、内
存、磁盘、网络四个方面描述性能问题分析的过程。
2.设计出来的性能
1)系统架构
        控制流与数据流?减少不必要的模块
2)程序结构
        多线程程序
                锁的粒度、各种锁/信号量的性能对比
        共享内存通信
        降低灵活性以获取高性能。
        减少不必要的重复判断(SHTTP/HTTP)
3)接口设计
        好的接口给予使用者充分的灵活性
4)数据结构与算法
        Linux内存管理,数量小时使用链表
       
3.编码的艺术
        1)内存访问与文件
                减少new/delete或malloc/free操作减少换页
                减少文件打开与关闭操作
                减少文件读写次数(减少系统调用)
        2)减少不必要的运算
                消除重复运算
                循环中的运算
                最忙的循环放在里面
        3)语言及库函数特性的利用
                if与case语句
                构造与析构
                宏与内联函数
                迟缓型计算
                减少临时变量
                缓存字符串的长度
                不必要的memset
        4)硬件特性的利用
                字节对齐
                移位与乘除2
                性能热点用汇编实现
4.性能分析工具-callgrind
        valgrind系列工具因为免费,所以在linux系统上面最常见。callgrind是valgrind工具里面的一员,它的主要功能是模拟cpu的cache,能够计算多
级cache的有效、失效次数,以及每个函数的调用耗时统计。
        callgrind的实现机理(基于外部中断)决定了它有不少缺点。比如,会导致程序严重变慢、不支持高度优化的程序、耗时统计的结果误差较大等,
更多的外部工具有oprofile,gprof,tprof,Rational Quantify and Intel VTune       
5.编译器参数的优化
        大家要记住的是,编译器绝对比想象的要强大的多。编写编译器的人大都是十年、几十年代码编写经验的科学家!你能简单想到的,他们都已经想
到过了。普通的编译器,可以支持大部分已知的优化策略以及多媒体指令。至于哪个编译器更好,大部分人的观点是:intel。Intel毕竟是最优秀的
cpu提供者,他们的编译器考虑了很多cpu的特性,跑的更快。但目前intel编译器有一些比较弱智的地方,即它只识别自己的cpu,不是自己的cpu,
就认为是最差的i386-i686机器,从而不能在amd等平台上面支持sse功能。我们在linux上面写代码,一般更加喜欢流行的编译器,比如gcc。
        Gcc的优点是它更新快,开源,bug修改迅速。正因为他更新快,所以它能够支持部分C03的规范。
        5.1 gcc支持的优化技术
                1) 函数内联
                函数调用的过程是:压入参数到堆栈、保护现场、调用函数代码、恢复现场。当一个函数被大量调用的时候,函数调用的开销特别巨大。函数内
联是指把这些开销都去除,而直接调用代码。函数内联的不好之处是难以调试,因为函数实际上已经不存在了。
                2) 常量预先计算
                        a = b + 1000 * 8
                        对于这段代码,程序会预先计算b + 1000 * 8,从而变成:
                        a = b+  8000
                3) 相同子串提取
                        a=(b+1)*(b+1)
                        这里,b+1需要计算2次,可以只用计算一次:
                        tmp=b+1
                        a=tmp*tmp
                4) 生存周期分析
                        这是一个比较高级的技术。假设有代码:
                        a=b+1
                        c=a+1
                        在执行的时候,因为第二句依赖第一句,所以2句是线性执行。
                        但编译器其实可以知道,c就是等于b+2,所以代码变成:
                        a=b+1
                        c=b+2
                        这样,这2句就没有任何关系来了,执行的时候,cpu可以并行执行它们。
                5) 清除跳转
                        看如下代码:
                        int func()
                        {
                                int ret = 0;
                                if(xxx)
                                        ret=5;
                                else if(yyy)
                                        ret=6;
                                return ret;
                        }
                        当条件xxx满足的时候,程序还会跳到下面执行,但其实是没有必要的。编译器会把它变成:
                        int func()
                        {
                                if(xxx)
                                        return 5;
                                else if(yyy)
                                        return 6;
                        }
                6) 循环展开
                        循环由几个部分组成:计数器赋值、计算器比较、跳转。每次循环,后面2步都是必须的消耗。把循环内的代码拷贝多份,可以大大减少
循环的次数,节约后面2步的耗时。参考:
                        for(int counter = 0; counter < 4; count++)
                                xxx;
                        可以变成:
                                xxx;
                                xxx;
                                xxx;
                                xxx;
                        编译器不仅仅可以展开普通循环,它还能展开递归函数。原理是一样的,递归其实是一个不定长的借用了堆栈的循环。
                7) 循环内常量移除
                        for(int idx=0;idx<100;idx++)
                                a[idx]=a[idx]*b*b;
                        因为b*b在循环体内的值固定(常量),所以代码可以变成:
                        tmp=b*b;
                        for(int idx=0;idx<100;idx++)
                        a[idx]=a[idx]*tmp;
                8) 并行计算
                        大家都知道,现代cpu支持超流水线技术,同时可以执行多条语句。多条语句能否同时执行的限制是不能互相依赖。编译器会自动帮我们把
看起来单线程执行的代码,变成并行计算,参考:
                        d=a+b;
                        e=a+d+f;
                        可以变成:
                        tmp=a+f;
                        d=a+b;
                        e=d+tmp;
                9) 表达式简化
                当年笔者在学习《离散数学》和《数字电路》的时候,总被眼花缭乱的布尔运算简化题目难倒。gcc终于让我松了一口气。参考:
                        !a && !b
                        这句需要3步执行,但变成:
                        !(a || b)
                        只需要2步执行。
        5.2 gcc重要优化选项
                1) 内联
                 -finline-small-functions
                内联比较小的函数。-O2选项可以打开。
                 -findirect-inlining
                间接内联,可以内联多层次的函数调用。-O2选项可以打开。
                 -finline-functions
                内联所有可以内联的函数。-O3选项可以打开。
                 -finline-limit=N
                可以进行内联的函数的最小代码长度。注意,这里是伪代码,不是真实代码长度。伪代码是编译器经过处理后的代码。带inline等标志的函数,默认
300行代码即可内联,不带的默认50行代码。和这个相关的选项是max-inline-insns-single和max-inline-insns-auto。
                 max-inline-insns-recursive-auto
                内联递归函数时,函数的最大代码长度。
                 large-function-insns、large-function-growth、large-unit-insns等
                函数内联的副作用是它导致代码变多,程序变长。这里的几个参数可以控制代码的总长度,避免编译后出现巨大的程序,影响性能和浪费资源。
                2) -fomit-frame-pointer
                不采用标准的ebp来记录堆栈指针,节省了一个寄存器,并且代码会更短。但据说在某些机器上面会导致debug模式出错。实际测试表明,在gcc4.2.4以
下,O2和O3都无法打开这个选项。
                3) -fwhole-program
                把代码当做一个最终交付的程序来编译,即明确指定了不是编译库。这个时候,编译器可以使用更多的static变量,来加快程序速度。
                4) mmx/ssex/avx
                多媒体指令,主要支持向量计算。一般来说,-march=i686、-mmx、-msse、-msse2是目前机器都支持的指令。
                除了基本的多媒体支持外,gcc编译器还支持-ftree-vectorize,这个选项告诉编译器自动进行向量化,也是-O3支持的选项。
                多说几句。在平常的使用中,多媒体指令不是很常见(除非游戏)。如果你有几个位表(bitset),它们需要进行各种位操作的话,多媒体指令还是挺有效果滴。
        5.3 gcc大杀器-profile driven optimize
                这是比较晚才出现的技术。其基本原理是:根据实际运行情况,缩短hot路径的长度。编译器通过加入各种计数器来监控程序的运行,然后根据计算出来
的实际访问路径情况,来分析hot路径,并且缩短其长度。根据gcc开发者的说法,这种技术可以提高20-30%的运行效率。
                其使用方式为:
                 编译代码,加上-fprofile-generate选项
                 到正式环境一段时间
                 当程序退出后,会产生一个分析文件
                 利用这个分析文件,加上-fprofile-use,重新编译一次程序
                举个例子来说:
                a=b*5;
                如果编译发现b经常等于10,那么它可以把代码变成:
                a=50;
                if(b != 10)
                a=b*5;
                从而在大多数情况下,避免了乘法消耗。
        5.4 gcc支持的优化属性(__attribute__)
                 aligned
                可以设置对齐到64字节,和cpu的cache line看齐
                 fastcall
                如果函数调用的前面2个参数是整数类型的话,这个选项可以用寄存器来传递参数,而不是用常规的堆栈
                 pure
                函数是纯粹的函数,任何时刻,同样的输入,都会有同样的输出。可以很方便依据概率来优化它。
        5.5 gcc其他优化技术
                 #pragma pack()
                对齐到一个字节,节省内存
                 __builtin_expect
                直接告诉编译器表达式最可能的结果,方便优化
                 编译带debug信息的小文件
                以下代码能够大大减少编译后程序大小,同时保留debug信息。其原理是外链一个带debug的版本。
                g++ tst.cpp -g -O2 -pipe
                copy a.out a.gdb
                strip --strip-debug a.out
                objcopy --add-gnu-debuglink=a.gdb a.out
6.算法是核心
        算法是程序的核心,一个程序的好坏,大部分是看起算法的好坏。对于一般的程序员来讲,我们无法改变系统和库的调用,只能根据
规则来使用它们,我们可以改变的是我们自己核心代码的算法。
        算法能够十倍甚至百倍的提高程序性能。如快排和冒泡排序,在上千万规模的时候,后者比前者慢几千倍。
        通常情况下,有如下一些领域的算法:
        A)常见数据结构和算法
        B)输入输出
        C)内存操作
        D)字符串操作
        E)加密解密、压缩解压
        F)数学函数               
        总上所述:性能问题通常体现在四个方面:CPU、内存、磁盘、网络几个方面。解决方法可以是修改代码甚至程序结构以更充分的利用现有资源,
也可以是增加相应的硬件以增加资源供给。



上一篇:第三章 数据处理
下一篇:算法学习(二) 全排列问题的非递归算法——模拟堆栈
在线编程(http://www.anycodes.cn)&编程论坛(http://www.52exe.cn)感谢您的支持!
回复

使用道具 举报

发表于 2016-4-16 06:09:36 | 显示全部楼层
支持,不过有些没看懂,系统内存少占用就把程序的各个部分分割运行,不就行了&hellip;&hellip;
来自苹果客户端来自苹果客户端
哎...今天够累的,来自客户端的签到
回复 支持 反对

使用道具 举报

发表于 2016-5-31 17:48:10 | 显示全部楼层
支持在线编程
在线编程(http://www.anycodes.cn)&编程论坛(http://www.52exe.cn)感谢您的支持!
回复 支持 反对

使用道具 举报

发表于 2016-8-4 17:04:06 | 显示全部楼层
AAAAAAAAAAAAAAAAAAAAAAAA
在线编程(http://www.anycodes.cn)&编程论坛(http://www.52exe.cn)感谢您的支持!
回复 支持 反对

使用道具 举报

发表于 2016-10-15 10:14:38 | 显示全部楼层
楼主炸了,管理疯了
在线编程(http://www.anycodes.cn)&编程论坛(http://www.52exe.cn)感谢您的支持!
回复 支持 反对

使用道具 举报

发表于 2016-11-20 03:56:27 | 显示全部楼层
标准的十五字有木有,没有
在线编程(http://www.anycodes.cn)&编程论坛(http://www.52exe.cn)感谢您的支持!
回复 支持 反对

使用道具 举报

发表于 2016-11-20 20:17:36 | 显示全部楼层
我.....
在线编程(http://www.anycodes.cn)&编程论坛(http://www.52exe.cn)感谢您的支持!
回复 支持 反对

使用道具 举报

发表于 2017-1-14 18:34:55 | 显示全部楼层
..................
在线编程(http://www.anycodes.cn)&编程论坛(http://www.52exe.cn)感谢您的支持!
回复 支持 反对

使用道具 举报

发表于 2017-2-14 09:34:46 | 显示全部楼层
装逼被雷劈
在线编程(http://www.anycodes.cn)&编程论坛(http://www.52exe.cn)感谢您的支持!
回复 支持 反对

使用道具 举报

发表于 2017-3-1 04:07:08 | 显示全部楼层
写的真心挺不错的
在线编程(http://www.anycodes.cn)&编程论坛(http://www.52exe.cn)感谢您的支持!
回复 支持 反对

使用道具 举报

发布主题 上个主题 下个主题 快速回复 返回列表 官方QQ群
在线客服
客 服 中 心
群 机 器 人
网站二维码
收 起 客 服

QQ|Archiver|手机版|小黑屋|Anycodes ( ICP14002806Anycodes在线编程

GMT+8, 2018-11-22 01:12 , Processed in 2.060587 second(s), 95 queries .

Powered by Anycodes

© 2001-2013 吉林市群龙科技有限公司 Inc.

快速回复 返回顶部 返回列表