代码效率优化

本文通过逐步优化RGB到YUV颜色空间转换的过程,展示了如何有效地提升算法性能。包括数据类型选择、运算优化、并行处理等技术手段。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近我们的项目有计算性能瓶颈,需要在1s内完成400次8192点的FFT,所以优化就成重中之重
那我们的代码运行的速度和哪些因素相关那?
1.算法本身的复杂程度,这一点最为重要,这个层面的优化可以最大程度的减少算法的复杂度
2.平台的运算速度,多核、dsp、gpu、vpu的使用会使算法这对应的平台上速度大大加快
3.特殊的运算单元,有些特殊的运算单元支持超带宽存取,有的甚至达到256bit甚至512bit,有的还支持多位运算数同时运算
4.存储器存取方式
5.当然最重要还是你写的代码
为了方便演示,我这里使用一个图像处理的例子,不能用定位算法啊,这涉及保密了,哈哈
我这里用的例子是将RPG格式图像YUV
为了验证算法的可行性我们先用matlab做下模拟
原图
这里写图片描述

clear;
clc;
RGB = imread('mi.jpg');
R = RGB(:,:,1);
G = RGB(:,:,2);
B = RGB(:,:,3);
x = size(RGB,1);
y = size(RGB,2);
 
% RGB2YUV
Y = 0.299*R + 0.587*G + 0.114*B;
U = -0.147*R- 0.289*G + 0.436*B;
V = 0.615*R - 0.515*G - 0.100*B;
YUV = cat(3, Y, U, V);
figure; 
imshow(YUV);

这里写图片描述
我是直接在pc上跑的,每次优化的效果可能不明显,因为我的pc配置太高了,哈哈哈
下面是c的实现,为了方便我直接从matlab导出数据放到数组中,在这过程中我也做了一次优化了,就是把二位的图像放在以为数组中存储,cpu处理一维数组的速度比多维数组速度快

#include <stdio.h>
#include <stdlib.h>
#include "R.h"
#include "G.h"
#include "B.h"
#define LEN 0xAB900  //540 * 1280

void rgb2yuv_opti(int *R, int *G, int *B, int *Y, int *U, int *V)
{
	long i;
	for (i = 0; i < LEN; ++i)
	{
		Y[i] = 0.299 * R[i] + 0.587 * G[i] + 0.114 * B[i];
		U[i] = -0.147 * R[i] - 0.289 * G[i] + 0.436 * B[i];
		V[i] = 0.615 * R[i] - 0.515 * G[i] - 0.100 * B[i];
	}
}
void main()
{
	int *Y = (int *)malloc(LEN * sizeof(int));
	int *U = (int *)malloc(LEN * sizeof(int));
	int *V = (int *)malloc(LEN * sizeof(int));
	struct timeval start, end;
	gettimeofday( &start, NULL );

	rgb2yuv_opti(R, G, B, Y, U, V);

	gettimeofday( &end, NULL );
	int timeuse = 1000000 * ( end.tv_sec - start.tv_sec ) + end.tv_usec - start.tv_usec;
	printf("time: %d us\n", timeuse);//微秒
}

time:25221 us
第一次优化
1.因为因为图像深度都是0-255之间的,所以把int改成unsigned short
2.机器对浮点数运算速度比较慢,所以我们把小数改成整数

int rgb2yuv_opti(unsigned short *R, unsigned short *G, unsigned short *B, unsigned short *Y, unsigned short *U, unsigned short *V)
{
	long long i;
	for (i = 0; i < LEN; ++i)
	{
		Y[i] = (299 * R[i] + 587 * G[i] + 114 * B[i])/1000;
		U[i] = (-147 * R[i] - 289 * G[i] + 436 * B[i])/1000;
		V[i] = (615 * R[i] - 515 * G[i] - 100 * B[i])/1000;
	}
}

哈哈 时间缩短了接近一半 time: 14038 us
第二次优化
1.因为 299/1000 约等于 1224/4096(这样会稍微的丢失精度),然后出操作用>>替代 /

int rgb2yuv_opti(unsigned short *R, unsigned short *G, unsigned short *B, unsigned short *Y, unsigned short *U, unsigned short *V)
{
	long long i;
	for (i = 0; i < LEN; ++i)
	{
		Y[i] = (1224 * R[i] + 2404 * G[i] + 467 * B[i])>>12;
		U[i] = (-602 * R[i] - 1183 * G[i] + 1785 * B[i])>>12;
		V[i] = (2519 * R[i] - 2109 * G[i] - 409 * B[i])>>12;
	}
}

时间有所短了一些 time: 11876 us
第三次优化
1.充分利用CPU中的三个ALU并行计算

int rgb2yuv_opti(unsigned short *R, unsigned short *G, unsigned short *B, unsigned short *Y, unsigned short *U, unsigned short *V)
{
	long long i;
	for (i = 0; i < LEN; i += 3)
	{
		Y[i] = (1224 * R[i] + 2404 * G[i] + 467 * B[i])>>12;
		U[i] = (-602 * R[i] - 1183 * G[i] + 1785 * B[i])>>12;
		V[i] = (2519 * R[i] - 2109 * G[i] - 409 * B[i])>>12;

		Y[i+1] = (1224 * R[i+1] + 2404 * G[i+1] + 467 * B[i+1])>>12;
		U[i+1] = (-602 * R[i+1] - 1183 * G[i+1] + 1785 * B[i+1])>>12;
		V[i+1] = (2519 * R[i+1] - 2109 * G[i+1] - 409 * B[i+1])>>12;

		Y[i+2] = (1224 * R[i+2] + 2404 * G[i+2] + 467 * B[i+2])>>12;
		U[i+2] = (-602 * R[i+2] - 1183 * G[i+2] + 1785 * B[i+2])>>12;
		V[i+2] = (2519 * R[i+2] - 2109 * G[i+2] - 409 * B[i+2])>>12;
	}
}

时间进一步缩短 time: 9530 us

到这里我优化的演示就到这里吧,其实我们fft算法中用到的优化方法比这个要多得多比如说:
1.查表法,我们将很多固定的数据事先算好放到表中,使用宏定义也是这个道理,这个方法优化特别明显
2.把经常调用的函数用inline定义,这样函数会被放到内存,中加快速度
3.把经常用到的内存区域mmap到内存中,提高速度
4.充分利用硬件资源,我们的dsp支持最大256位数据存取,可以8个数同时乘加操作等等

源码放在这里
https://download.youkuaiyun.com/download/bin_zhang1/10530464

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

叶与花语

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值