图形图像处理-之-彩色转化到灰度的速度优化

               图形图像处理-之-彩色转化到灰度的速度优化
                   HouSisong@GMail.com  2009.02.08

tag:灰度算法,速度优化,定点数优化,MMX,SSE,SSE2,CPU缓存优化

摘要:
  彩色转化到灰度的速度优化文章包括图形图像处理简单Demo框架和灰度转换的实
现及其速度优化,并演示其使用SIMD指令集的优化;
   本篇文章将第一次提供完整的可以编译的图像处理完整项目代码;
   (以后会用这个框架逐步改写以前的图形图像处理文章)

正文:  
  为了便于讨论,这里只处理32bit的ARGB颜色;代码使用C++;使用的编译器为vc2008;
(经过测试代码也可以在DevC++和xcode下编译通过) 测试使用的CPU为AMD64x2 4200+(2.33G);

速度测试说明:
  只测试内存数据到内存数据的ARGB32颜色的灰度转化;
  测试图片是800*600; fps表示每秒钟的帧数,值越大表示函数越快;

A: 图形图像处理简单Demo框架
   
  我以前写的图形图像处理方面的blog文章都没有完整的可以编译运行的代码,
而仅仅列出了关键的核心代码;经常有网友看了我的文章,但因为不能实际运行看看,
从而对代码的理解不深,也不能把代码移植到自己的项目中使用; 所以决定为我的图形
图像处理系列blog文章建立一个简单的小型的框架;我把它命名为hGraphic32,
它会尽量的小,演示为主,仅支持ARGB32颜色,能够加载和保存bmp图片文件,能够在
多个编译器和平台下编译和运行;
   现在就下载完整项目源代码吧:  完整项目源代码


  <hGraphic32>文件夹里的文件说明:
    "hColor32.h"  : 里面定义了32bitARGB颜色类型Color32,它占用4字节,代表一个颜色;
        TPixels32Ref是图像数据区的描述信息,可以把它理解为一个"指针",指向了Color32构成的像素区;
        IPixels32Buf是图像数据区接口,用于描述一个图像的缓冲区;
    "hPixels32.h" : 里面定义了TPixels32类,它实现了IPixels32Buf接口,用于申请和管理一块内存像素;
    "hStream.h"   : 里面定义了IInputStream输入流接口;
        IBufInputStream数据区输入流接口,继承自IInputStream;
        TFileInputStream文件输入流类,它实现了IBufInputStream接口;
        IOutputStream输出流接口;
        TFileOutputStream文件输出流类,它实现了IOutputStream接口;
     "hBmpFile.h" : 里面定义了TBmpFile类,它负责加载bmp和保存bmp;
     "hGraphic32.h" 文件include了上面的*.h头文件,所以使用的时候,只要#include "hGraphic32.h"就可以了

B: 灰度转化项目
  所有的转换和测试代码都在"ColorToGray/ColorToGray.cpp"文件中(带有main函数的命令行程序);
  "ColorToGray/win_vc/ColorToGray.sln"是windows系统下的vc2008项目文件(测试的时请设定调试运行目录为"..");
  "ColorToGray/win_DevC++/ColorToGray.dev"是windows系统下的DevC++项目文件;
  "ColorToGray/macosx_xcode/ColorToGray.xcodeproj"是macosx系统下的xcode项目文件;
  你也可以自己建立项目,包含ColorToGray.cpp文件和<hGraphic32>文件夹下的所有文件,就可以编译了;

C: 灰度转化公式和代码实现
  文章中用的灰度公式: Gray = R*0.299 + G*0.587  + B*0.114;
 
代码实现:



//速度测试
//==============================================================================
// colorToGray_float           145.49 FPS


D: 将浮点运算转化为定点数(整数)运算
    



//速度测试
//==============================================================================
// colorToGray_int16           355.33 FPS


E: 做一个简单的循环代码展开



//速度测试
//==============================================================================
// colorToGray_int16_expand4   413.22 FPS


F: 一个特别的版本
   在高级语言范围内进行单条指令多数据流计算,减少需要的乘法量;
在乘法运算代价比较高昂的cpu上应该效果不错; (x86上速度可能慢)


//速度测试
//==============================================================================
// colorToGray_int8_opMul      387.97 FPS


G: 内联汇编的MMX实现版本
   注意:这里的MMX代码都只支持x86CPU(奔腾MMX以上CPU);
   在x64下不再有MMX寄存器,而应该使用SEE的XMM寄存器;
   而且在x64模式下vc2008编译器还没有提供内联汇编的直接支持,而必须使用函数指令方式的实现;
   GCC编译器也支持内联汇编模式,但是汇编语法不同,请参考相应的说明;




//速度测试
//==============================================================================
// colorToGray_MMX             590.84 FPS


H: 优化写缓冲的内联汇编的MMX实现版本
  该版本相应于上面的MMX版本只改写了两句:
   一是写内存的movq [edx+ecx*4],mm0 改成了 movntq [edx+ecx*4],mm0 绕过缓存
   二是函数结束的时候调用sfence刷新写入
  完整代码如下:





//速度测试
//==============================================================================
// colorToGray_MMX2            679.50 FPS


I: 使用MMX函数指令方式的实现
  MMX/SSE等特殊指令除了内联汇编来使用外,也可以使用函数指令方式的实现,从而在多种
编译器下都可以使用SIMD相关指令,可移植性也会好很多;
  但现在看来,vc对此的优化还不够,还可能遇到编译器的实现bug;
  (可以考虑使用intel的编译器编译这些代码,感觉优化能力很不错)




//速度测试
//==============================================================================
// colorToGray_MMX_mmh         508.69 FPS



 优化写缓冲的使用MMX函数指令方式的实现




//速度测试
//==============================================================================
// colorToGray_MMX2_mmh        540.78 FPS


J:把测试成绩放在一起:


//CPU: AMD64x2 4200+(2.33G)  800*600 to 800*600
//==============================================================================
// colorToGray_float           145.49 FPS
// colorToGray_int16           355.33 FPS
// colorToGray_int16_expand4   413.22 FPS
// colorToGray_int8_opMul      387.97 FPS
// colorToGray_MMX             590.84 FPS
// colorToGray_MMX2            679.50 FPS
// colorToGray_MMX_mmh         508.69 FPS
// colorToGray_MMX2_mmh        540.78 FPS


ps:用SSE的浮点指令的版本/用SSE2整数指令的版本/利用SSE3的水平加指令等的实现版本有机会时再补充
ps:SIMD特殊指令集的使用框架请参见我的<YUV视频格式到RGB32格式转换的速度优化 中篇>一文,从而
根据CPU对指令集的支持情况动态的调用最优的实现函数版本;

评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值