C++性能优化系列——3D高斯核卷积计算(十)合并多线程并行区

在上一篇 C++性能优化系列——3D高斯核卷积计算(八)3D高斯卷积 中,按照 X Y Z的顺序,依次计算每个维度的一维卷积。其代码实现中一个开辟了两个并行区,其中计算X Y 维度开辟一个并行区,计算Z 维度开辟一个并行区。本片基于可分离卷积的性质,按照 Z Y X 的顺序,计算每个维度的一维卷积。这样处理的可以将两个并行区合并成一个并行区,减少了一个并行区同步的操作。

代码实现

这里简单阐述一下实现思路:Z 维度的计算依次提取原始数据31层数据,并将每一层分别与卷积核的一个元素相乘,再将每一层的计算结果相加,得到目标结果(一层数据)。接下来,对这一层数据的X Y方向的计算通过复用之前实现的二维高斯卷积函数。
代码实现

void GaussSmoothCPU3DOptZYX(float* pSrc, int iDim[3], float* pKernel, int kernelSize[3], float* pDst, float* pBuffer)
	{
		int iSliceSize = iDim[1] * iDim[0];
		int nCenter = kernelSize[0] / 2;

#pragma omp parallel for num_threads(8) schedule(dynamic)
		for (int z = 0; z < (iDim[2] - kernelSize[0] + 1); z++)
		{
			float* pBuffSlice = pBuffer + (z + nCenter) * iSliceSize;
			float* pDstSlice = pDst + (z + nCenter) * iSliceSize;
			for (unsigned int kx = 0; kx < kernelSize[0]; kx++)
			{
				float* pSrcSlice = pSrc + (z + kx) * iSliceSize;
#pragma omp simd
				for (unsigned int iSliceIt = 0; iSliceIt < iSliceSize; ++iSliceIt)
				{
					pBuffSlice[iSliceIt] += pSrcSlice[iSliceIt] * pKernel[kx];
				}
			}
			int tid = omp_get_thread_num();
			memset(yBuf[tid], 0, sizeof(float) * iDim[0] * iDim[1]);
			Conv2D_Fuse(pBuffSlice, iDim, pKernel, kernelSize[0],yBuf[tid] , pDstSlice, NULL);
		}

	}

执行时间
16线程 dynamic调度

GaussSmoothCPU3DOptZYX cost Time(ms) 338.4

16线程 static调度

GaussSmoothCPU3DOptZYX cost Time(ms) 590

8线程 dynamic调度

GaussSmoothCPU3DOptZYX cost Time(ms) 230.9

从执行时间上可以看到:一个并行区通过使用超线程,速度并没有得到提升。

VTune分析性能问题

总体执行情况如下
在这里插入图片描述
说明:这里为了使执行时间稳定,重复调用函数30次。
在这里插入图片描述
性能瓶颈主要是访问L3 Cache与内存加载。
在这里插入图片描述
定位热点语句:计算Z 维度的乘加运算。
在这里插入图片描述
反馈的性能问题与程序的整体问题相对应。计算时每个线程在一次for迭代中分别要加载 432 * 432 *4 * 31 * 2 Byte 的数据,写432 * 432 * 4 * 31 Byte的数据,虽然连续访问内存,但是对同一块内存(432 * 432 * 4 Byte)写31次。访问内存模式导致内存性能瓶颈。
在这里插入图片描述
查看反汇编,这里编译器对循环做了2倍展开,CPI高的指令是fmadd 和movup的操作。这里fmadd一个操作数是从内存中加载,movup是将计算的结果写回内存。与前文分析的内容基本一致。
在这里插入图片描述
在这里插入图片描述

总结

本片通过改变三维卷积的计算维度顺序,将两个并行区合并成一个并行区。但同时,目前的实现方式存在明显的内存访问问题。该问题将在后续篇章中修复。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值