加速图像处理的神器: INTEL ISPC 编译器迁移图像旋转算法 - 从 ISPC双精度到 ISPC单精度

Posted 帅的发光发亮

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了加速图像处理的神器: INTEL ISPC 编译器迁移图像旋转算法 - 从 ISPC双精度到 ISPC单精度相关的知识,希望对你有一定的参考价值。

从 ISPC双精度到 ISPC单精度

前面把原始的C代码转成了ISPC可编译的C代码,其中image_rotate_double_ispc函数里面的数据都是基于double双精度来运算的。我的电脑是支持AVX/AVX2指令集的,所以一次可以并发做4个double浮点的运算,理论上可以提升4倍的算力。

通过ISPC的编译,实际获得了3.74X倍的性能加速。

从上图YMM寄存器的宽度和浮点数据的宽度来看,YMM寄存器可以一次做8个单精float型数据的计算。这次就来试试把image_rotate_double_ispc函数里面的计算全部改为单精浮点运算,看看性能有多少提升。

代码改动

  1. 把所有的double替换成float
  2. 定义float常量的后缀是f, 定义double常量的后缀是d
#define M_PI_F 3.1415926535f
 
export void image_rotate_float_ispc(uniform const uint8 srcImg[], uniform uint8 dstImg[], uniform float center_x,uniform float center_y, uniform int Width, uniform int Height, uniform float RotateDegree)

	uniform float angle = (float)RotateDegree*M_PI_F / 180.0;
	uniform float alpha = cos(angle);
	uniform float beta = sin(angle);
	uniform float m[6];
 
	m[0] = alpha;
	m[1] = -beta;
	m[2] = (1.0 - alpha) * (float)center_x + beta * (float)center_y ;
	m[3] = beta;
	m[4] = alpha;
	m[5] = (1.0 - alpha) * (float)center_y - beta * (float)center_x;
 
	for (uniform int row = 0; row < Height; row++)
		foreach (col = 0 ... Width) 
			float x, y;
			int leftX, rightX, topY, bottomY;
			float w00, w01, w10, w11;
			float fxy;
 
			x = m[0] * (float)col + m[1] * (float)row + m[2];
			y = m[3] * (float)col + m[4] * (float)row + m[5];
 
			leftX = floor(x);
			topY = floor(y);
			rightX = leftX + 1.0;
			bottomY = topY + 1.0;
 
			w11 = abs(x - leftX)*abs(y - topY);
			w01 = abs(1.0 - (x - leftX))*abs(y - topY);
			w10 = abs(x - leftX)*abs(1 - (y - topY));
			w00 = abs(1.0 - (x - leftX))*abs(1.0 - (y - topY));
 
			if ((int)leftX >= 0 && (int)rightX < Width && (int)topY >= 0 && (int)bottomY < Height) 
				fxy = (float)srcImg[topY*Width+ leftX]*w00 +    
					  (float)srcImg[bottomY*Width+ leftX]*w01 +
					  (float)srcImg[topY*Width+ rightX]*w10 + 
					  (float)srcImg[bottomY*Width+ rightX]*w11;
 
				fxy = round(fxy);
				if (fxy < 0)
					fxy = 0;
				if (fxy > 255)
					fxy = 255;
 
				dstImg[row*Width+ col] = (uint8)(fxy);
			
			else
				dstImg[row*Width + col] = 0;
		;
;

代码对比

image_rotate_double_ispc()和image_rotate_float_ispc()

运行一下单精度计算版本的代码,运行时间: 761ms

性能提升

和image_rotate_double_ispc版本的性能提升

1148ms/761ms = 1.5X

和原始C代码的性能比对

4301ms/761ms = 5.65X

5.65X虽然和理论的8X有很大的差距,但是已经很满意了,毕竟这段代码写的时候没有考虑任何内存访问的优化,现在能有这个性能提升很好很暴力!!!

以上是关于加速图像处理的神器: INTEL ISPC 编译器迁移图像旋转算法 - 从 ISPC双精度到 ISPC单精度的主要内容,如果未能解决你的问题,请参考以下文章

加速图像处理的神器: INTEL ISPC编译器 迁移图像旋转算法 - ISPC单精度 从单核 到 多核

加速图像处理的神器: INTEL ISPC编译器 迁移图像旋转算法 - ISPC单精度 从单核 到 多核

加速图像处理的神器: INTEL ISPC编译器 迁移图像旋转算法 - ISPC单精度 从单核 到 多核

加速图像处理的神器: INTEL ISPC 编译器迁移图像旋转算法 - 从 ISPC双精度到 ISPC单精度

加速图像处理的神器: INTEL ISPC 编译器迁移图像旋转算法 - 从 ISPC双精度到 ISPC单精度

加速图像处理的神器: INTEL ISPC 编译器迁移图像旋转算法 - 从 ISPC双精度到 ISPC单精度