超线程对多线程并行化的影响 Myth丶恋晨 2022-12-11 12:16 136阅读 0赞 本篇基于 [C++性能优化系列——3D高斯核卷积计算(八)3D高斯卷积][C_3D_3D] 中的代码实现,测试超线程对多线程并行性的影响。 ### 代码实现 ### 测试平台支持8核16线,具体信息参考 [C++性能优化系列——百倍加速比的矩阵转置性能调优][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线程** ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3lhbjMxNDE1_size_16_color_FFFFFF_t_70_pic_center] 热点语句 ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3lhbjMxNDE1_size_16_color_FFFFFF_t_70_pic_center 1] **16线程** ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3lhbjMxNDE1_size_16_color_FFFFFF_t_70_pic_center 2] 热点语句 ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3lhbjMxNDE1_size_16_color_FFFFFF_t_70_pic_center 3] 从函数执行结果和VTune性能分析可以看到: 1)并行区开辟8个线程总的执行速度快,线程执行的效率更高,线程创建后一直在进行有效的计算 2)并行区开辟16个线程总的执行速度慢,线程执行效率低,线程在有效计算的中间夹杂着大量的等待时间 3)对于两个版本的热点语句,由于开辟16线程的并行区同一时刻总的访问内存数量加倍,因此造成了内存性能瓶颈更为突出。 因为超线程技术本身是复用相同的物理核心,当前场景每个线程执行的功能类似,因此使用超线程时,两个线程使用同一个物理核心上的同一个执行部件,同时内存压力加倍,造成线程等待。 ### 结论 ### 对于类似本篇中的代码实现,线程功能类似,负载较小,同时已经有明确的内存问题时,通过使用超线程技术,并不一定得到更好的加速比,因此在选择超线程时,需要根据具体的代码实现随机应变。 [C_3D_3D]: https://blog.csdn.net/yan31415/article/details/108880264 [C]: https://blog.csdn.net/yan31415/article/details/107876678 [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3lhbjMxNDE1_size_16_color_FFFFFF_t_70_pic_center]: /images/20221123/4343dfcd191e4a188989e51bf79c9c16.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3lhbjMxNDE1_size_16_color_FFFFFF_t_70_pic_center 1]: /images/20221123/159a979d63524443912c0ba80de414e4.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3lhbjMxNDE1_size_16_color_FFFFFF_t_70_pic_center 2]: /images/20221123/bb7c355adf3445e6b265ec5ef5e252ed.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3lhbjMxNDE1_size_16_color_FFFFFF_t_70_pic_center 3]: /images/20221123/7d689302092e432ba1a396be2109f863.png
还没有评论,来说两句吧...