高效的使用搬运API
【优先级】高
【描述】使用搬运API时,应该尽可能地使用API的srcStride/dstStride/blockLen/blockCount等参数实现连续搬运或者固定间隔搬运,而不是使用for循环,二者效率差距极大。如下图示例,图片的每一行为16KB,需要从每一行中搬运前2KB,针对这种场景,使用srcStride/dstStride/blockLen/blockCount等参数可以达到一次搬完的效果,每次搬运32KB;如果使用for循环遍历每行,每次仅能搬运2KB。参考尽量一次搬运较大的数据块章节介绍的搬运数据量和实际带宽的关系,建议通过DataCopy包含srcStride/dstStride/blockLen/blockCount的接口一次搬完。
图1 待搬运数据排布
【反例】
// 搬运数据存在间隔,从GM上每行16KB中搬运2KB数据, 共16行 LocalTensor<float> tensorIn; GlobalTensor<float> tensorGM; ... constexpr int32_t copyWidth = 2 * 1024 / sizeof(float); constexpr int32_t imgWidth = 16 * 1024 / sizeof(float); constexpr int32_t imgHeight = 16; // 使用for循环,每次只能搬运2K,重复16次 for (int i = 0, i < imgHeight; i++) { DataCopy(tensorIn[i * copyWidth ], tensorGM[i*imgWidth], copyWidth); }
【正例】
LocalTensor<float> tensorIn; GlobalTensor<float> tensorGM; ... constexpr int32_t copyWidth = 2 * 1024 / sizeof(float); constexpr int32_t imgWidth = 16 * 1024 / sizeof(float); constexpr int32_t imgHeight = 16; // 通过DataCopy包含srcStride/dstStride/blockLen/blockCount的接口一次搬完 DataCopyParams copyParams; copyParams.blockCount = imgHeight; copyParams.blockLen = copyWidth / 8; // 搬运的单位为DataBlock(32Byte),每个DataBlock内有8个float copyParams.srcStride = (imgWidth - copyWidth ) / 8; // 表示两次搬运src之间的间隔,单位为DataBlock copyParams.dstStride = 0; // 连续写,两次搬运之间dst的间隔为0,单位为DataBlock DataCopy(tensorGM, tensorIn, copyParams);
父主题: 搬运优化