C++性能调优
基于C++语言,记录CPU平台上的性能调优过程
USST_Coder
这个作者很懒,什么都没留下…
展开
-
C++性能优化系列——矩阵转置(一)访问内存顺序带来的性能差异
矩阵转置代码实现说明:实现两种矩阵转置方法,其中测试平台9900k,为了让程序执行时间足够长,重复执行代码1024次。矩阵尺寸1024*1024。将矩阵按照128X128分块转置处理。每个块内部分别按照方式 按行索引读取和按列索引写 与 按列索引读和按行索引写 实现,即方法一 写行连续,方法二 读连续。int main(int argc, char* argv[]){#define NROW 1024#define NCOL 1024#define NSLICE NROW*NCOL#defin原创 2020-07-27 15:45:07 · 3015 阅读 · 2 评论 -
C++性能优化系列——矩阵转置(二)循环分块优化缓存访问
在上一篇博客 CPU性能优化系列——矩阵转置(一)访存方式造成的性能差异 中,为了说明CPU缓存一致性算法对写内存和读内存的差异,只是单纯构造一个内存操作对称的矩阵转置实现方式,其中分块与内存访问的步长并非是最合理的。本篇将基于上一篇博客的实现方式,根据L1 Data Cache的结构,对访问缓存方式做进一步优化。代码实现...原创 2020-07-31 11:15:13 · 4766 阅读 · 2 评论 -
C++性能优化系列——矩阵转置(三)内存填充避免缓存抖动
在上一篇博客 CPU性能优化系列——矩阵转置(二)循环分块优化缓存访问 中通过循环分块方法,分析并优化了缓存的访问,使性能得到提升。同时通过VTune抓包分析了代码执行情况。看起来Cache命中情况很好。可实际缓存真的没有优化空间了吗?也不见得。本篇根据《深入理解计算机系统》中缓存篇介绍的映射规则,在缓存映射方面做进一步优化。以分块优化版本为Base,通过对pSource数据进行内存填充处理,使pSource的访问内存映射不集中在一个缓存组中,避免缓存抖动问题。优化后执行情况:1024 * 1024原创 2020-08-05 15:58:34 · 1405 阅读 · 0 评论 -
C++性能优化系列——矩阵转置(四)OpenMP并行计算
C++版本c++版本并行化实现unsigned char* pSource; pSource = (unsigned char*)malloc(sizeof(unsigned char) * NREALCOL * NROW); for (int irow = 0; irow < NROW; ++irow) { memset(pSource + irow * NREALCOL, irow % 256, sizeof(unsigned char) * NREALCOL);//按照字节原创 2020-08-05 16:24:19 · 2066 阅读 · 0 评论 -
C++性能优化系列——矩阵转置(五)Intrinsic函数详解
本篇详细介绍编译器提供Intrinsic函数的具体功能,为下一篇通过Intrinsic函数实现矩阵转置做铺垫。Intrinsic函数详解__m128i _mm_unpacklo_epi8 (__m128i a, __m128i b)#include <emmintrin.h>Instruction: punpcklbw xmm, xmmCPUID Flags: SSE2DescriptionUnpack and interleave 8-bit integers from the原创 2020-07-27 19:14:09 · 3750 阅读 · 0 评论 -
C++性能优化系列——矩阵转置(六)Intrinsic转置实现与Core Bound优化
namespace TTranspose {#define NROW 1024#define NCOL 1024#define NSLICE 1024*1024#define REPEAT 1024//#define REPEAT 1 void Verify(unsigned char* pSource, unsigned char* pTarget) { for (int i = 0 ; i < NSLICE; ++i) { if (pSource[i] != pTa原创 2020-07-20 15:34:23 · 1344 阅读 · 0 评论 -
C++性能优化系列——矩阵转置(七)Intrinsic 内存预取与OpenMP多线程并行化
上一篇CPU性能优化系列——矩阵转置(六)Intrinsic转置实现与Core Bound优化中通过Intrinsic 实现了矩阵转置功能,同时针对寄存器使用导致的spilling问题,对每次处理的数据块尺寸进行调整。本篇将基于之前的优化版本,在内存访问方面与多线程并行化方面做进一步优化。内存访问优化上一篇中主要针对寄存器使用问题优化代码,未针对内存访问问题 L3 Latency做处理。考虑Advance2版本中对内存访问的模式,写内存操作是连续执行的,读内存操作是交叉执行的。因此加载内存方式导致该问题原创 2020-08-18 17:08:55 · 1178 阅读 · 0 评论 -
C++性能优化系列——矩阵转置(八)IPP转置API性能测试
本篇记录Intel 高性能计算函数库IPP中的转置函数ippiTranspose_8u_C1R的执行情况,方便性能优化系列篇中转置实现做性能对比。函数说明解释来自IPP2018发布文档。Intel® Integrated Performance Primitives Developer Reference, Volume 2: Image Processing函数APIIPPAPI(IppStatus, ippiTranspose_8u_C1R, ( const Ipp8u* pSrc, int原创 2020-08-20 15:38:27 · 1270 阅读 · 0 评论 -
C++性能优化系列——3D高斯核卷积计算(一)滑动窗口法
滑动窗口法是最容易理解的计算卷积的方法。通过滑动窗口法计算卷积,简单来说就是将卷积核的锚点在它有效的范围内(能够与矩阵计算的所有锚点位置组成的点集)移动,并依次计算和新目标矩阵。滑窗法做高斯核卷积维度信息int kernelSize[3] = { 31,31,31 };int iDim[3] = { 432,432,457 };代码实现void GaussSmoothCPU3DNaive(float* pSrc, int iDim[3], float* pKernel, int kernelS原创 2020-08-20 17:42:44 · 1039 阅读 · 1 评论 -
C++性能优化系列——3D高斯核卷积计算(二)FMA向量化计算一维卷积
高斯核的卷积计算是可分离的,即高斯核的每一个维度可以分开处理。因此,一维卷积计算成为了实现3D高斯卷积的基础。一维卷积计算的性能直接影响了整个程序的性能。本篇将实现一维卷积功能,同时引出ICC编译器对多层嵌套循环场景的向量化优化倾向的调查结果。公用函数这里为了增加结果的稳定性,重复执行#define CONVREPEAT 100000测试函数int TestConv1D(int index) { const int SRCSize = 432; const int KERNELSize原创 2020-08-21 17:55:02 · 2183 阅读 · 0 评论 -
C++性能优化系列——3D高斯核卷积计算(三)IPP计算一维卷积
本篇通过Intel高性能计算库IPP中的卷积计算API实现一维卷积,并记录程序耗时情况,同时与 性能优化系列(CPU)——3D高斯核卷积计算(三)FMA向量化计算一维卷积 中只通过编译器向量化版本对比性能。功能实现代码实现:void Conv1d_IPP(float* pSrc, int iLength, float* pKernel, int kernelSize, float* pDst) { IppEnum funCfg = (IppEnum)(ippAlgAuto); int buf原创 2020-08-27 14:53:42 · 1243 阅读 · 0 评论 -
C++性能优化系列——3D高斯核卷积计算(四)Intrinsic实现一维卷积与循环展开
基于 性能优化系列(CPU)——3D高斯核卷积计算(三)FMA向量化计算一维卷积 中实现,本文用Intrinsic实现向量化的一维卷积计算。代码实现void Conv1D_Ins_Cmb(float* pSrcLine, int iLength, float* pKernel, int kernelSize, float* pDst,float* pSimdKernel) { int iConvSize = iLength - kernelSize + 1; float* pDstTemp原创 2020-09-17 11:53:30 · 800 阅读 · 0 评论 -
C++性能优化系列——3D高斯核卷积计算(五)2D卷积分离计算
高斯卷积核具有可分离的性质,因此可以通过以下方法计算二维高斯卷积:构造一个一维高斯卷积核,将原始二维矩阵分别以行主序与列主序,与一维卷积核做卷积计算,得到的结果就是目标二维高斯卷积的结果。本篇按照上述描述的思路实现了可分离的二维高斯卷积计算,并在此基础上对计算的过程分解与重构,挖掘实现的并行性。基线版二维高斯卷积为了让运行时间更加稳定,增加函数的执行次数至1000#define CONV2DREPT 1000这里对代码实现功能做一下简单的说明。原始矩阵维度432 * 432,维度定义为x和y。高斯原创 2020-08-29 15:22:13 · 1428 阅读 · 0 评论 -
C++性能优化系列——3D高斯核卷积计算(六)交换维度计算2D卷积
在 C++性能优化系列——3D高斯核卷积计算(五)2D卷积计算 中,基于可分离卷积的性质,先计算x维度卷积,再将y维度卷积计算过程打乱并重组,完成了两个维度的向量化计算。本篇以先计算y维度卷积,后计算x维度卷积的顺序计算2D高斯卷积。代码实现代码实现void Conv2D_Fuse(float* pSrcSlice, int iDim[2], float* pKernel, int iKernelSize, float* pBuffer, float* pDstSlice,float* pSimdKe原创 2020-09-19 11:31:32 · 435 阅读 · 0 评论 -
C++性能优化系列——3D高斯核卷积计算(七)Intrinsic实现2D高斯卷积
本篇基于 C++性能优化系列——3D高斯核卷积计算(六)交换维度计算2D卷积 中2D高斯卷积的计算逻辑,通过Intrinsic函数实现相同的功能并对比性能差异。代码实现先用指令实现对x维度的计算void Conv2D_Fuse_InstructX(float* pSrcSlice, int iDim[2], float* pKernel, int iKernelSize, float* pBuffer, float* pDstSlice,float* pSimdKernel) { //combi原创 2020-09-19 14:28:07 · 372 阅读 · 0 评论 -
C++性能优化系列——3D高斯核卷积计算(八)3D高斯卷积
本篇基于可分离卷积的性质,按照 X Y Z的顺序,依次计算每个维度的一维卷积。代码实现因为是按照X Y Z的计算顺序,因此只能够在计算X维度的卷积时,复用之前实现的一维卷积计算函数。Y维度的计算是将一个Z平面上的二维数据中每行与卷积核中一个点相乘,并将31个点的卷积核计算出的结果累加至一行,更新到中间缓存的目标位置。Z维度的计算是将一个Z平面的二维数据和卷积核中的一个点相乘,并将31个点的卷积核计算出的结果累加至一个二维平面,更新到结果的目标位置。这里对Y 和 Z维度的计算都是通过编译器ICC实现向量化原创 2020-09-30 14:35:26 · 1650 阅读 · 0 评论 -
C++性能优化系列——3D高斯核卷积计算(九)3D高斯卷积OpenMP Task优化内存访问
本篇基于 C++性能优化系列——3D高斯核卷积计算(八)3D高斯卷积中的代码实现的计算逻辑,通过OepnMP的Task特性,优化Z维度卷积计算中内存性能瓶颈。(本篇只优化内存访问问题,不保证总执行时间会提升)。代码实现void GaussSmoothCPU3DBase_Task(float* pSrc, int iDim[3], float* pKernel, int kernelSize[3], float* pDst, float* pBuffer) { int iSliceSize = iD原创 2020-09-30 17:44:09 · 514 阅读 · 0 评论 -
C++性能优化系列——3D高斯核卷积计算(十)合并多线程并行区
void GaussSmoothCPU3DOptZYX(float* pSrc, int iDim[3], float* pKernel, int kernelSize[3], float* pDst, float* pBuffer) { //计算结果正确 //执行时间 16 dynamic GaussSmoothCPU3DOptZYX cost Time(ms) 338.4 //16 static GaussSmoothCPU3DOptZYX cost Time(ms) 590 //原创 2020-10-19 17:57:10 · 729 阅读 · 0 评论 -
C++性能优化系列——3D高斯核卷积计算(十一)优化内存访问模式
void GaussSmoothCPU3DOptZYXSplitZIntrinsic(float* pSrc, int iDim[3], float* pKernel, int kernelSize[3], float* pDst, float* pBuffer) { //计算结果正确 //16 thread dynamic GaussSmoothCPU3DOptZYXSplitZIntrinsic cost Time(ms) 145.8 int iSliceSize = iDim[1] *原创 2020-10-20 00:51:26 · 514 阅读 · 0 评论 -
C++性能优化系列——3D高斯核卷积计算(十二)Intrinsic实现
void GaussSmoothCPU3DOptZYXSplitZIntrinsic(float* pSrc, int iDim[3], float* pKernel, int kernelSize[3], float* pDst, float* pBuffer) { //计算结果正确 //16 thread dynamic GaussSmoothCPU3DOptZYXSplitZIntrinsic cost Time(ms) 145.8 int iSliceSize = iDim[1] *原创 2020-10-20 14:34:14 · 489 阅读 · 2 评论