超线程对多线程并行化的影响

本篇基于 C++性能优化系列——3D高斯核卷积计算(八)3D高斯卷积 中的代码实现,测试超线程对多线程并行性的影响。

代码实现

测试平台支持8核16线,具体信息参考 C++性能优化系列——百倍加速比的矩阵转置性能调优。为了避免重复调用函数带来的多线程测试结果的干扰,这里只对函数调用一次。

并行区开辟8线程

void GaussSmoothCPU3DBase_OneParallelRegion(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 num_threads(8)
		{
#pragma omp for schedule(dynamic)
			for (int z = 0; z < (iDim[2]); z++)
			{
				{
					float* pSrcSlice = pSrc + z * iSliceSize;
					float* pBuffSlice = pBuffer + z * iSliceSize;
					memset(pBuffSlice, 0, iSliceSize * sizeof(float));
					for (int y = 0; y < iDim[1]; y++)
					{
						float* pSrcLine = pSrcSlice + y * iDim[0];
						float* pDstLine = pBuffSlice + y * iDim[0];
						Conv1D_Opt_Cmb(pSrcLine, iDim[0], pKernel, kernelSize[0], pDstLine);
					}
					for (int y = 0; y < (iDim[1] - kernelSize[0] + 1); y++)
					{
						float* pDstLine = pSrcSlice + (y + nCenter) * iDim[0];
						memset(pDstLine, 0, iDim[0] * sizeof(float));
						for (int kx = 0; kx < kernelSize[0]; kx++)
						{
							float* pSrcLine = pBuffSlice + (y + kx) * iDim[0];
#pragma omp simd aligned(pSrcLine, pDstLine)
							for (int i = 0; i < iDim[0]; i++)
							{
								pDstLine[i] += pSrcLine[i] * pKernel[kx];
							}
						}
					}
				}
			}

#pragma omp for schedule(dynamic)
			for (int z = 0; z < (iDim[2] - kernelSize[0] + 1); z++)
			{
				{
					float* pDstSlice = pDst + (z + nCenter) * iSliceSize;
					memset(pDstSlice, 0, iSliceSize * sizeof(float));
					for (int kx = 0; kx < kernelSize[0]; kx++)
					{
						float* pSrcSlice = pSrc + (z + kx) * iSliceSize;
#pragma omp simd
						for (int i = 0; i < iSliceSize; ++i)
						{
							pDstSlice[i] += pKernel[kx] * pSrcSlice[i];
						}
					}
				}

			}
		}

	}

执行时间

GaussSmoothCPU3DBase_OneParallelRegion cost Time(ms) 246

并行区开辟16线程
代码实现

void GaussSmoothCPU3DBase_OneParallelRegion(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 num_threads(16)
		{
#pragma omp for schedule(dynamic)
			for (int z = 0; z < (iDim[2]); z++)
			{
				{
					float* pSrcSlice = pSrc + z * iSliceSize;
					float* pBuffSlice = pBuffer + z * iSliceSize;
					memset(pBuffSlice, 0, iSliceSize * sizeof(float));
					for (int y = 0; y < iDim[1]; y++)
					{
						float* pSrcLine = pSrcSlice + y * iDim[0];
						float* pDstLine = pBuffSlice + y * iDim[0];
						Conv1D_Opt_Cmb(pSrcLine, iDim[0], pKernel, kernelSize[0], pDstLine);
					}
					for (int y = 0; y < (iDim[1] - kernelSize[0] + 1); y++)
					{
						float* pDstLine = pSrcSlice + (y + nCenter) * iDim[0];
						memset(pDstLine, 0, iDim[0] * sizeof(float));
						for (int kx = 0; kx < kernelSize[0]; kx++)
						{
							float* pSrcLine = pBuffSlice + (y + kx) * iDim[0];
#pragma omp simd aligned(pSrcLine, pDstLine)
							for (int i = 0; i < iDim[0]; i++)
							{
								pDstLine[i] += pSrcLine[i] * pKernel[kx];
							}
						}
					}
				}
			}

#pragma omp for schedule(dynamic)
			for (int z = 0; z < (iDim[2] - kernelSize[0] + 1); z++)
			{
				{
					float* pDstSlice = pDst + (z + nCenter) * iSliceSize;
					memset(pDstSlice, 0, iSliceSize * sizeof(float));
					for (int kx = 0; kx < kernelSize[0]; kx++)
					{
						float* pSrcSlice = pSrc + (z + kx) * iSliceSize;
#pragma omp simd
						for (int i = 0; i < iSliceSize; ++i)
						{
							pDstSlice[i] += pKernel[kx] * pSrcSlice[i];
						}
					}
				}

			}
		}

	}

执行时间

GaussSmoothCPU3DBase_OneParallelRegion cost Time(ms) 384

VTune分析线程性能

8线程

在这里插入图片描述
热点语句
在这里插入图片描述

16线程
在这里插入图片描述
热点语句
在这里插入图片描述

从函数执行结果和VTune性能分析可以看到:
1)并行区开辟8个线程总的执行速度快,线程执行的效率更高,线程创建后一直在进行有效的计算
2)并行区开辟16个线程总的执行速度慢,线程执行效率低,线程在有效计算的中间夹杂着大量的等待时间
3)对于两个版本的热点语句,由于开辟16线程的并行区同一时刻总的访问内存数量加倍,因此造成了内存性能瓶颈更为突出。
因为超线程技术本身是复用相同的物理核心,当前场景每个线程执行的功能类似,因此使用超线程时,两个线程使用同一个物理核心上的同一个执行部件,同时内存压力加倍,造成线程等待。

结论

对于类似本篇中的代码实现,线程功能类似,负载较小,同时已经有明确的内存问题时,通过使用超线程技术,并不一定得到更好的加速比,因此在选择超线程时,需要根据具体的代码实现随机应变。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值