1、背景
STM32 MCU對25.6Kb數據進行壓縮,丟掉每個數據的低4位然后2個字節拼接為1個字節。發現處理耗時競達1ms以上,於是開始進行優化,最后達到200us的效果,提速5倍以上。
2、優化
2.1優化前
HAL_GPIO_WritePin(TestPB12_GPIO_Port, TestPB12_Pin, 1); #if (USE_BINNING) ImgCompressTo4Bit(img_ptr + PACKAGE_HEADER_SIZE, ImgSampBuf, IMG_SIZE); #else memcpy(img_ptr + PACKAGE_HEADER_SIZE, ImgSampBuf, IMG_SIZE); #endif HAL_GPIO_WritePin(TestPB12_GPIO_Port, TestPB12_Pin, 0);
該處理過程耗時1ms60us。
2.2 第一次優化
考慮到過多的for循環,會導致效率變低,於是一次處理4個字節。
/** * @brief compress a arrary with high 4bit and low 4bit. * @param[out] *pDst arrary to be filled * @param[in] *pSrc input arrary * @param[in] len src length * @return dst length. * */ int ImgCompressTo4Bit(uint8_t *pDst, uint8_t *pSrc, int srcLen) { /*loop Unrolling */ uint32_t dstLen = srcLen >> 1; uint32_t blkCnt = dstLen >> 2u; uint32_t halfOffset = dstLen; uint8_t * ptrHigh = pSrc; // high 4 bit uint8_t * ptrLow = pSrc + halfOffset; // low 4 bit while(blkCnt > 0u) { *pDst++ = ((*ptrHigh++) & 0xF0) | (((*ptrLow++) & 0xF0)>>4); *pDst++ = ((*ptrHigh++) & 0xF0) | (((*ptrLow++) & 0xF0)>>4); *pDst++ = ((*ptrHigh++) & 0xF0) | (((*ptrLow++) & 0xF0)>>4); *pDst++ = ((*ptrHigh++) & 0xF0) | (((*ptrLow++) & 0xF0)>>4); blkCnt--; } blkCnt = dstLen % 0x4u; while(blkCnt > 0u) { *pDst++ = ((*ptrHigh++) & 0xF0) | (((*ptrLow++) & 0xF0)>>4); blkCnt--; } return dstLen; }
優化后:一次處理4個數據時間為640us。如果進一步 一次處理8個數據,時間為600us。
2.3 第二次優化
考慮到MCU是32位機器,那么使用u32類型數據進行處理,可以提高效率。
int ImgCompressTo4Bit(uint8_t *pDst, uint8_t *pSrc, int srcLen) { /*loop Unrolling */ uint32_t dstLen = srcLen >> 1; uint32_t blkCnt = dstLen >> 2u; uint32_t halfOffset = dstLen; uint32_t * ptrHigh = (uint32_t*)pSrc; // high 4 bit uint32_t * ptrLow = (uint32_t*)(pSrc + halfOffset); // low 4 bit uint32_t * dst = (uint32_t*)pDst; while(blkCnt > 0u) { *dst++ = ((*ptrHigh++) & 0xF0F0F0F0) | (((*ptrLow++) & 0xF0F0F0F0)>>4); blkCnt--; } blkCnt = dstLen % (0x4u); while(blkCnt > 0u) { *dst++ = ((*ptrHigh++) & 0xF0F0F0F0) | (((*ptrLow++) & 0xF0F0F0F0)>>4); blkCnt--; } return dstLen; }
優化后速度達到240us。
2.4 第三次優化
同樣考慮降低for循環的次數,一次處理4個u32,實際上是16個字節的數據。
int ImgCompressTo4Bit(uint8_t *pDst, uint8_t *pSrc, int srcLen) { /*loop Unrolling */ uint32_t dstLen = srcLen >> 1; uint32_t blkCnt = dstLen >> 2u >> 2u; uint32_t halfOffset = dstLen; uint32_t * ptrHigh = (uint32_t*)pSrc; // high 4 bit uint32_t * ptrLow = (uint32_t*)(pSrc + halfOffset); // low 4 bit uint32_t * dst = (uint32_t*)pDst; while(blkCnt > 0u) { *dst++ = ((*ptrHigh++) & 0xF0F0F0F0) | (((*ptrLow++) & 0xF0F0F0F0)>>4); *dst++ = ((*ptrHigh++) & 0xF0F0F0F0) | (((*ptrLow++) & 0xF0F0F0F0)>>4); *dst++ = ((*ptrHigh++) & 0xF0F0F0F0) | (((*ptrLow++) & 0xF0F0F0F0)>>4); *dst++ = ((*ptrHigh++) & 0xF0F0F0F0) | (((*ptrLow++) & 0xF0F0F0F0)>>4); blkCnt--; } blkCnt = dstLen % (0x4u*0x4u); while(blkCnt > 0u) { *dst++ = ((*ptrHigh++) & 0xF0F0F0F0) | (((*ptrLow++) & 0xF0F0F0F0)>>4); blkCnt--; } return dstLen; }
優化后速度達到180--200us左右。
3、總結
基於c語法的優化:減少循環處理的次數。
基於芯片特性的優化:使用u32數據,提高處理效率。
經過3次簡單的優化,1ms60us的處理降低到200us實現原有的操作。