速度取决于算法
同样的事情,方法不一样,效果也不一样。比如,汽车引擎,可以让你的速度超越马车,却无法超越音速;涡轮引擎,可以轻松超越音障,却无法飞出地球;如果有火箭发动机,就可以到达火星。代码的运算速度取决于以下几个方面:0 算法本身的复杂度,比如MPEG比JPEG复杂,JPEG比BMP图片的编码复杂。1 CPU自身的速度和设计架构 2 CPU的总线带宽 3 您自己的代码的写法

我们一个图象模式识别的项目,需要将RGB格式的彩色图像先转换成黑白图像。图像转换的公式如下:
Y = 0.299 * R + 0.587 * G + 0.114 * B;
图像尺寸640*480*24bit,RGB图像已经按照RGBRGB顺序排列的格
式,放在内存里面了。
例如,将这个喷火的战斗机引擎,转换为右边的黑白图片
我已经悄悄的完成了第一个优化
以下是输入和输出的定义:
#define XSIZE 640
#define YSIZE 480
#define IMGSIZE XSIZE*YSIZE
Typedef struct RGB
{
unsigned char R;
unsigned char G;
unsigned char B;
}RGB;
struct RGB in[IMGSIZE] //需要计算的原始数据
Unsigned char out[IMGSIZE] //计算后的结果
看得出来优化在
哪里吗?
我已经悄悄的完成了第一个优化
#define XSIZE 640
#define YSIZE 480
#define IMGSIZE XSIZE*YSIZE
Typedef struct RGB
{
unsigned char R;
unsigned char G;
unsigned char B;
}RGB;
struct RGB in[IMGSIZE] //需要计算的原始数据
Unsigned char out[IMGSIZE] //计算后的结果
优化原则:
图像是一个2D数组,我用一个1维数组来存储。
编译器处理1维数组的效率要高过2维数组
先写一个代码
Y = 0.299 * R + 0.587 * G + 0.114 * B;
Void calc_lum()
{int I;
for(i=0;i{double r,g,b,y;
unsigned char yy;
r=in[i].r; g=in[i].g; b=in[i].b;
y=0.299*r+0.587*g+0.114*b;
yy=y; out[i]=yy;
}
}
这大概是能想得出来的最简单的写法了,实在看不出有什么毛病,好
了,编译一下跑一跑吧。
第一次试跑Void calc_lum()
{int I;
for(i=0;i{double r,g,b,y;
unsigned char yy;
r=in[i].r; g=in[i].g; b=in[i].b;
y=0.299*r+0.587*g+0.114*b;
yy=y; out[i]=yy;
}
}
这个代码分别用VC6.0和GCC编译,生成2个版本,分别在PC上和
我的embedded system上面跑。
速度多少?说出来吓死你!
第一次试跑的成绩
在PC上,由于存在硬件浮点处理器,CPU
频率也够高,计算速度为20秒
我的embedded system ,没有以上2个
优势,浮点操作被编译器分解成了整数运
算,运算速度为120秒左右
这只是一副图像的运算速度!!
去掉浮点运算
上面这个代码还没有跑,我已经知道会很慢了,因为这其中有大量
的浮点运算。只要能不用浮点运算,一定能快很多。
Y = 0.299 * R + 0.587 * G + 0.114 * B;
那这个公式怎么能用定点的整数运算替代呢?
0.299 * R可以如何化简?
Y = 0.299 * R + 0.587 * G + 0.114 * B;
Y=D+E+F;
D=0.299*R;
E=0.587*G;
F=0.114*B;
我们就先简化算式D吧!
RGB的取值范围都是0~255,都是整数,只是这个系数比较麻烦,
不过这个系数可以表示为:
0.299=299/1000
所以D=(R*299)/1000
Y=(R*299)/1000+(G*587)/1000+(B*114)/1000
再简化为:
Y=(R*299+G*587+B*114)/1000
这一下,能快多少呢?
化简后的成绩
Embedded system
上的速度45秒
PC上的速度2秒
0.299 * R进一步化简
Y=(R*299+G*587+B*114)/1000
这个式子好像还有点复杂,可以再砍掉一个除法运算。
前面的算式D可以这样写:
0.299=299/1000=1224/4096
所以D=(R*1224)/4096
Y=(R*1224)/1000+(G*2404)/4096+(B*467)/4096
再简化为:
Y=(R*1224+G*2404+B*467)/4096
这里的/4096除法,因为它是2的N次方,所以可以用移位操作替
代,往右移位12bit就是把某个数除以4096了
Y = 0.299 * R + 0.587 * G + 0.114 * B
Y=(R*1224+G*2404+B*467)/4096
Void calc_lum()
{int I;
for(i=0;i{int r,g,b,y;
r=1224*in[i].r; g=2404*in[i].g; b=467*in[i].b;
y=r+g+b;
y=y>>12; //这里去掉了除法运算
out[i]=y;
}
}
这个代码编译后,又快了20%
0.299 * R进一步化简
还是太慢!
虽然快了不少,还是太慢了一些,
20秒处理一幅图像,地球人都不能
接受!
但是目前这个式子好像优化到极限
了,要想突破音障,只能拆掉活塞
发动机,安装蜗轮引擎!
仔细端详一下这个式子!
仔细端详一下这个式子!
RGB的取值有文章可做,RGB的取值永远都大于等于0,小于等于
255,我们能不能将D,E,F都预先计算好呢?然后用查表算法计
算呢?
我们使用3个数组分别存放DEF的256种可能的取值,然后。。。
Y = 0.299 * R + 0.587 * G + 0.114 * B;
Y=D+E+F;
D=0.299*R;
E=0.587*G;
F=0.114*B;
查表数组初始化
Int D[256],E[256],F[256]; //查表数组
Void table_init()
{int I;
for(i=0;i<256;i++)
{D[i]=i*1224; D[i]=D[i]>>12;
E[i]=i*2404; E[i]=E[i]>>12;
F[i]=i*467; F[i]=F[i]>>12;
}
}
Y = 0.299 * R + 0.587 * G + 0.114 * B;
Y=D+E+F;
D=0.299*R;
E=0.587*G;
F=0.114*B;
使用查表数组
Y = 0.299 * R + 0.587 * G + 0.114 * B;
Y=D+E+F;
D=0.299*R;
E=0.587*G;
F=0.114*B;
Void calc_lum()
{int I;
for(i=0;i{int r,g,b,y;
r=D[in[i].r]; g=E[in[i].g]; b=F[in[i].b]; //查表
y=r+g+b;
out[i]=y;
}
}
突破音障!
这一次的成绩把我吓出一身冷汗,执行时间居然从30秒一下提高到
了2秒!在PC上测试这段代码,眼皮还没眨一下,代码就执行完了。
一下提高15倍,爽不爽?
还能再
快吗? 120

45秒
30秒
2秒
下一
程,几
秒?
很多embedded sysytem 的32bitCPU,都至少有2个ALU,能不
能让2个ALU都跑起来?
Void calc_lum()
{int I;
for(i=0;i{int r,g,b,y;
r=D[in[i].r]; g=E[in[i].g]; b=F[in[i].b]; //查表
y=r+g+b;
out[i]=y;
}
} Void calc_lum()
{int I;
for(i=0;i{int r,g,b,y, r1,g1,b1,y1;
r=D[in[i].r]; g=E[in[i].g]; b=F[in[i].b]; //查表
y=r+g+b;
out[i]=y;
r1=D[in[i+1].r]; g1=E[in[i+1].g]; b1=F[in[i+1].b]; //查表
y1=r1+g1+b1;
out[i+1]=y1;
}
}
踩足油门,向2马赫进军!
并行计算
2个ALU处理的数据不能有数据依赖,也就是说:
某个ALU的输入条件不能是别的ALU的输出,这样
才可以并行
给第一个ALU执行给第二个ALU执行
一次并行处理2组数据
所以这里一次加2
Void calc_lum()
{int I;
for(i=0;i{int r,g,b,y, r1,g1,b1,y1;
r=D[in[i].r]; g=E[in[i].g]; b=F[in[i].b]; //查表
y=r+g+b;
out[i]=y;
r1=D[in[i+1].r]; g1=E[in[i+1].g]; b1=F[in[i+1].b]; //查表
y1=r1+g1+b1;
out[i+1]=y1;
}
}
这一次的成绩是:
加足燃料,进军3马赫!
Int D[256],E[256],F[256]; //查表数组
Void table_init()
{int I;
for(i=0;i<256;i++)
{D[i]=i*1224; D[i]=D[i]>>12;
E[i]=i*2404; E[i]=E[i]>>12;
F[i]=i*467; F[i]=F[i]>>12;
}
}
看看这个代码,
到这里,似乎已经足够快了,但是我们反复实验,发现,还有办法再快!
可以将
Int D[256],E[256],F[256]; //查表数组
更改为:
Unsigned short D[256],E[256],F[256]; //查表数组
这是因为编译器处理int类型和处理unsigned
short类型的效率不一样
再改动一下
Unsigned short D[256],E[256],F[256]; //查表数组
Inline Void calc_lum()
{int I;
for(i=0;i{int r,g,b,y, r1,g1,b1,y1;
r=D[in[i].r]; g=E[in[i].g]; b=F[in[i].b]; //查表
y=r+g+b;
out[i]=y;
r1=D[in[i+1].r]; g1=E[in[i+1].g]; b1=F[in[i+1].b]; //查表
y1=r1+g1+b1;
out[i+1]=y1;
}
}
将函数声明为inline,这样编译器就会将其
嵌入到母函数中,可以减少CPU调用子函
数所产生的开销
这2个小小的改进带来的效益!
现在,我们已经达到了客户的要求!
其实,我们还可以飞出地球的!
如果加上以下措施,应该还可以更快:
•把查表的数据放置在CPU的高速数据CACHE
里面
•把函数calc_lum()用汇编语言来写
其实,CPU的潜力是很大的
•不要抱怨你的CPU,记住一句话:“只要功率足
够,砖头都能飞!”
•同样的需求,写法不一样,速度可以从120秒
变化为0.5秒,说明CPU的潜能是很大的!看你

如何去挖掘。

原文:http://blog.chinaunix.net/uid-20806919-id-132246.html

C++编程优化——让你的代码飞起来相关推荐

  1. C 语言编程 — 结构化程序流的汇编代码与 CPU 指令集

    目录 文章目录 目录 文章目录 为什么要保留汇编语言 顺序程序流 条件程序流 循环程序流 函数调用栈的工作原理 文章目录 <C 语言编程 - GCC 工具链> <C 语言编程 - 程 ...

  2. L1-015 跟奥巴马一起画方块 (15分) 美国总统奥巴马不仅呼吁所有人都学习编程,甚至以身作则编写代码,成为美国历史上首位编写计算机代码的总统。2014年底,为庆祝“计算机科学教育周”正式启动,奥

    美国总统奥巴马不仅呼吁所有人都学习编程,甚至以身作则编写代码,成为美国历史上首位编写计算机代码的总统.2014年底,为庆祝"计算机科学教育周"正式启动,奥巴马编写了很简单的计算机代 ...

  3. 郁金香汇编代码注入怎么写看雪_世界黑客编程大赛冠军的汇编代码 你见过吗?...

    前几天发布了一篇"雷军22年前写的汇编代码"的文章,引起网友的热议.有人说汇编是最牛逼的编程语言,没有之一.汇编语言确实厉害,不知道你有没有见过世界黑客编程大赛冠军的作品? 雷军编 ...

  4. 计算机算法对程序设计的作用,算法计算机论文,关于数学算法对计算机编程优化相关参考文献资料-免费论文范文...

    导读:本论文主要论述了算法计算机论文范文相关的参考文献,对您的论文写作有参考作用. (重庆人文科技学院 理工学院数学系,重庆 401572) 摘 要:数学算法是一种将很多问题进行归纳总结,然后采用统一 ...

  5. 英特尔多核平台编程优化大赛报告

    前言 本次优化使用的CPU是Intel Xeon 5130 主频为2.0GHz 同Intel酷睿2一样是基于Core Microarchitecture 的双核处理器.本次优化在Intel的工具帮助下 ...

  6. HighNewTech:来到了21世纪的第3个十年,各行业数字化迫在眉睫,全民编程也势不可挡。但,问题来了,编程,一定需要写代码么?那么,传说中的iVX工具,与编程到底又有什么暧昧关系?

    High&NewTech:来到了21世纪的第3个十年,各行业数字化迫在眉睫,全民编程也势不可挡.但,问题来了,编程,一定需要写代码么?那么,传说中的iVX工具,与编程到底又有什么暧昧关系? 导 ...

  7. 【笔记】编程的原则:改善代码质量的101个方法

    代码必然被修改 Code will be changed 代码不是写完就结束了,它在日后必然会被修改.没有写完就扔的一次性代码. 在编写代码的时候,我们应将"代码会被修改"这一点作 ...

  8. 公开“英特尔多核平台编程优化大赛”优化报告及源代码

    公开"英特尔多核平台编程优化大赛"优化报告及源代码 本系列文章欢迎转载.打印.分发等,但不可用于商业用途,任何时候必须保留全文完整,并声明转载自恋花蝶的博客(http://blog ...

  9. 切割优化模型可以用c语言编程不,数学算法对计算机编程优化研究

    数学算法是一种以数学模型为基础的理论知识,能够对计算机编程中的问题进行归纳总结和统一计算,以提高逻辑应用的效率,它是计算机编程的基础.计算机编程是从数学模型开始的,首先要根据具体问题进行抽象,以建立一 ...

最新文章

  1. postgresql 子查询_PostgreSQL子事务及性能分析
  2. html转义字符对照表
  3. 批量(导入导出)迁移AD中的用户信息和密码到新环境中,同时保持用户在MOSS中的权限【addusers,ldifde,copypwd,UserInfo,tp_SystemID】...
  4. 以太坊DAPP[2]-×××-react框架与web3实例
  5. python 打包文件
  6. Python for i in range ()用法详解
  7. 在android studio中创建Hello-JNI工程
  8. MySQL中left join、right join与inner join的区别
  9. vsco怎么两个滤镜叠加_PS插件 VSCO滤镜137款预设安装使用教程
  10. uva 11714——Blind Sorting
  11. php 彩票系统,hsyl12141511 一套完整的PHP版彩票系统 - 下载 - 搜珍网
  12. UItextField 的属性
  13. 【自学系列一】HTML5大前端学习路线+视频教程(完整版)
  14. 游戏筑基开发之测试篇2(C语言)
  15. 通达信、东方财富神奇九转指标计算公式,代码实现
  16. Ubuntu升级glibc
  17. Excel 技术篇-使用excel启用宏提示:“可能是因为该宏在此工作簿中不可用,或者所有的宏都被禁用“问题解决方法
  18. vue 头像 上传 裁剪
  19. python import文件后 core dumped_python numpy包调用core dumped、Linux VDSO机制
  20. kodi 缓存文件夹_如何将Kodi图稿与视频存储在同一文件夹中

热门文章

  1. php比较函数代码,php字符串比较函数
  2. 高中计算机考试编程题,2020年高中信息技术模块测试卷5(算法与程序设计) 信息技术试题(PDF版无答案)...
  3. matlab中如何区分两幅图的亮度_高中历史教学中利用老地图设计习题的尝试
  4. java51_Java运行 Unsupported major.minor version 51.0 错误
  5. html 文字不可选择,有没有办法在HTML页面上使文本无法选择?
  6. 程序员多数性功能不行_从面试官角度观察到的程序员技能瓶颈,同时给出突破瓶颈的建议...
  7. ubuntu nginx php-fpm mysql_Ubuntu下安装Nginx,PHP5(及PHP-FPM),MySQL
  8. 水文特点是什么意思_一级建造师是什么意思?一级建造师报考指南
  9. 前Oracle首席工程师怒喷:MySQL 是“超烂的数据库”,建议考虑 PostgreSQL
  10. 每日一皮:都 0202 年了,我怎么可能被骗呢?