有趣的网站有哪些推荐,企业网站建设前期规划,国内新闻最新5条,电子商务网站建设及维护本文主要介绍如何优化您自己的CODE#xff0c;实现软件的加速。我们一个图象模式识别的项目#xff0c;需要将RGB格式的彩色图像先转换成黑白图像。图像转换的公式如下#xff1a; Y 0.299 * R 0.587 * G 0.114 * B 图像尺寸640*480*24bit#xff0c;RGB图像已经按照RGB…本文主要介绍如何优化您自己的CODE实现软件的加速。我们一个图象模式识别的项目需要将RGB格式的彩色图像先转换成黑白图像。图像转换的公式如下 Y 0.299 * R 0.587 * G 0.114 * B 图像尺寸640*480*24bitRGB图像已经按照RGBRGB顺序排列的格式放在内存里面了。以下是输入和输出的定义 #define XSIZE 640
#define YSIZE 480
#define IMGSIZE XSIZE * YSIZEtypedef struct RGB
{unsigned char R;unsigned char G;unsigned char B;}RGB;
struct RGB in[IMGSIZE]; //需要计算的原始数据
unsigned char out[IMGSIZE]; //计算后的结果 优化原则图像是一个 2D数组我用一个一维数组来存储。编译器处理一维数组的效率要高过二维数组。 第一步先写一个代码 void calc_lum()
{int i;for(i 0; i IMGSIZE; 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 G * 587 B * 114) / 1000 这一下能快多少呢 Embedded system上的速度为 45秒 PC上的速度为 2秒 0.299 * R可以如何化简 Y 0.299 * R 0.587 * G 0.114 * B;
Y (R * 299 G * 587 B * 114) / 1000; 这个式子好像还有点复杂可以再砍掉一个除法运算。前面的算式D可以这样写 0.299299/10001224/4096 所以 D (R * 1224) / 4096 Y(R*1224)/4096(G*2404)/4096(B*467)/4096 再简化为 Y(R*1224G*2404B*467)/4096 这里的/4096除法因为它是2的N次方所以可以用移位操作替代往右移位12bit就是把某个数除以4096了。 void calc_lum()
{int i;for(i 0; i IMGSIZE; 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%。虽然快了不少还是太慢了一些20秒处理一幅图像。 查表方式 我们回到这个式子 Y 0.299 * R 0.587 * G 0.114 * B;
YDEF;
D0.299*R;
E0.587*G;
F0.114*B; RGB的取值有文章可做 RGB的取值永远都大于等于 小于等于 255我们能不能将 D E F都预先计算好呢然后用查表算法计算呢我们使用 3个数组分别存放 DEF的 256种可能的取值然后...... 查表数组初始化 int D[256],F[256],E[256];
void table_init( ){int i;for(i0;i256;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;}
}void calc_lum(){int i;for(i 0; i IMGSIZE; 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倍爽不爽 继续优化.很多embedded system的32bit CPU都至少有2个ALU能不能让2个ALU都跑起来 void calc_lum(){int i;for(i 0; i IMGSIZE; i 2){ //一次并行处理2个数据int r,g,b,y,r1,g1,b1,y1;r D[in[i].r];//查表 //这里给第一个ALU执行g E[in[i].g];b F[in[i].b];y r g b;out[i] y;r1 D[in[i 1].r];//查表 //这里给第二个ALU执行g1 E[in[i 1].g];b1 F[in[i 1].b];y r1 g1 b1;out[i 1] y;}
} 2个 ALU处理的数据不能有数据依赖也就是说某个 ALU的输入条件不能是别的 ALU的输出这样才可以并行。这次成绩是 1秒。查看这个代码: int D[256],F[256],E[256]; //查表数组
void table_init(){int i;for(i0;i256;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],F[256],E[256]; //查表数组 更改为 unsigned short D[256],F[256],E[256]; //查表数组 这是因为编译器处理int类型和处理unsigned short类型的效率不一样。再改动 inline void calc_lum(){int i;for(i 0; i IMGSIZE; i 2){ //一次并行处理2个数据int r,g,b,y,r1,g1,b1,y1;r D[in[i].r];//查表 //这里给第一个ALU执行g E[in[i].g];b F[in[i].b];y r g b;out[i] y;r1 D[in[i 1].r];//查表 //这里给第二个ALU执行g1 E[in[i 1].g];b1 F[in[i 1].b];y r1 g1 b1;out[i 1] y;}
} 将函数声明为 inline这样编译器就会将其嵌入到母函数中可以减少 CPU调用子函数所产生的开销。这次速度 0.5秒。 其实我们还可以飞出地球的如果加上以下措施应该还可以更快 1) 把查表的数据放置在 CPU的高速数据 CACHE里面 2)把函数 calc_lum()用汇编语言来写 .其实 CPU的潜力是很大的, 1) 不要抱怨你的 CPU记住一句话“只要功率足够砖头都能飞” 2)同样的需求写法不一样速度可以从 120秒变化为 0.5秒说明 CPU的潜能是很大的看你如何去挖掘。 RGB到YUV的转换算法做以总结。 Y 0.299R 0.587G 0.114B U -0.147R - 0.289G 0.436B V 0.615R - 0.515G - 0.100B #deinfe SIZE 256
#define XSIZE 640
#define YSIZE 480#define IMGSIZE XSIZE * YSIZEtypedef struct RGB{unsigned char r;unsigned char g;unsigned char b;}RGB;struct RGB in[IMGSIZE];
unsigned char out[IMGSIZE * 3]; unsigned short Y_R[SIZE],Y_G[SIZE],Y_B[SIZE],U_R[SIZE],U_G[SIZE],U_B[SIZE],V_R[SIZE],V_G[SIZE],V_B[SIZE]; //查表数组
void table_init(){int i;for(i 0; i SIZE; i){Y_R[i] (i * 1224) 12; //YY_G[i] (i * 2404) 12; Y_B[i] (i * 467) 12;U_R[i] (i * 602) 12; //UU_G[i] (i * 1183) 12; U_B[i] (i * 1785) 12;V_R[i] (i * 2519) 12; //VV_G[i] (i * 2109) 12; V_B[i] (i * 409) 12;}
} inline void calc_lum(){int i;for(i 0; i IMGSIZE; i 2) { out[i] Y_R[in[i].r] Y_G[in[i].g] Y_B[in[i].b]; //Yout[i IMGSIZE] U_B[in[i].b] - U_R[in[i].r] - U_G[in[i].g]; //Uout[i 2 * IMGSIZE] V_R[in[i].r] - V_G[in[i].g] - V_B[in[i].b]; //V out[i 1] Y_R[in[i 1].r] Y_G[in[i 1].g] Y_B[in[i 1].b]; //Yout[i 1 IMGSIZE] U_B[in[i 1].b] - U_R[in[i 1].r] - U_G[in[i 1].g]; //Uout[i 1 2 * IMGSIZE] V_R[in[i 1].r] - V_G[in[i 1].g] - V_B[in[i 1].b]; //V}
} 这种算法应该是非常快的了. 转载请注明出处http://blog.csdn.net/songzitea/article/details/10474207