zoukankan      html  css  js  c++  java
  • STM32 MCU一次计算优化和提速

    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实现原有的操作。

  • 相关阅读:
    线性代数:矩阵行列式
    线性代数:逆变换
    线性代数:线性变换
    线性代数:零空间
    线性代数:向量乘法
    线性代数基础:向量组合
    线性代基础理论:向量
    线性代基础理论:矩阵
    SpringBoot 消费NSQ消息
    将Oracle中的数据放入elasticsearch
  • 原文地址:https://www.cnblogs.com/pingwen/p/11955978.html
Copyright © 2011-2022 走看看