埋め込み式C関数の最適化

7102 ワード

0.はじめに


これは単純な関数の最適化であるが,コードの読みやすさと効率の総合的な考慮を体現している.
優秀なコードを書く方法を聞かれたら、「もう1版書く」と答えた.

1.バージョン1


リングbufferからデータを取り出し、構造体に配置します.bufferのデータはバイト毎に記憶するが、構造体の各セルデータはint 16である.
void GetDataFromMeas(int8_t *rawDataBuf, fftStruct *fftBufVx)
 {
    int8_t *src_ptr = rawDataBuf;  // pointer to raw data buffer.
    uint32_t i=0;
    int16_t volt[4] = {0,0,0,0};
 
    for(i = 0; i< LEN_NUM; i++)
    {
        volt[0] = *(int16_t *)src_ptr; // UL1
        src_ptr++;
        src_ptr++;
        volt[1] = *(int16_t *)src_ptr; // UL2
        src_ptr++;
        src_ptr++;
        volt[2] = *(int16_t *)src_ptr; // UL3
        src_ptr++;
        src_ptr++;
        volt[3] = *(int16_t *)src_ptr; // ULN
        src_ptr++;
        src_ptr++;
        *(fftBufVx->nL1_r + i) = (float32_t)(volt[0]-volt[3]);
        *(fftBufVx->nL1_i + i) = 0;
        *(fftBufVx->nL2_r + i) = (float32_t)(volt[1]-volt[3]);
        *(fftBufVx->nL2_i + i) = 0;
        *(fftBufVx->nL3_r + i) = (float32_t)(volt[2]-volt[3]);
        *(fftBufVx->nL3_i + i) = 0;
     }
 }

2.バージョン2


前回はどう見てもうるさいので、まずデータをバイトで取り出し、16ビットにつづって仮配列に入れ、最後に受信構造体配列に順番に書き込む.
データが16位である以上、なぜ8位で取り出さなければならないのか、これ以上はない.
修正後、コード行数が激減し、構造がより明確になります.
void GetDataFromMeas(int8_t *rawDataBuf, fftStruct *fftBufVx)
 {
    int16_t *src_ptr = (int16_t *)rawDataBuf;  // pointer to raw data buffer.
    uint32_t i=0;
    for(i = 0; i< LEN_NUM; i++)
    {
        *(fftBufVx->nL1_r + i) = (float32_t)(src_ptr[0]-src_ptr[3]); // UL1
        *(fftBufVx->nL1_i + i) = 0;
        *(fftBufVx->nL2_r + i) = (float32_t)(src_ptr[1]-src_ptr[3]); // UL2
        *(fftBufVx->nL2_i + i) = 0;
        *(fftBufVx->nL3_r + i) = (float32_t)(src_ptr[2]-src_ptr[3]); // UL3
        *(fftBufVx->nL3_i + i) = 0;
        
        src_ptr = src_ptr + 4;
     }
 }

3.バージョン3


ポインタのオフセットと配列の下付きスケールは本質的に一つのものであり,データ量はこのように大きく,アドレスオフセットの計算を省く操作を考慮し,配列の下付きスケールを直接参照することができる.
void GetDataFromMeas(int8_t *rawDataBuf, fftStruct *fftBufVx)
 {
    int16_t *src_ptr = (int16_t *)rawDataBuf;  // pointer to raw data buffer.
    uint32_t i=0;
    for(i = 0; i< LEN_NUM; i++)
    {
        fftBufVx->nL1_r[i] = (float32_t)(src_ptr[0]-src_ptr[3]); // UL1
        fftBufVx->nL1_i[i] = 0;
        fftBufVx->nL2_r[i] = (float32_t)(src_ptr[1]-src_ptr[3]); // UL2
        fftBufVx->nL2_i[i] = 0;
        fftBufVx->nL3_r[i] = (float32_t)(src_ptr[2]-src_ptr[3]); // UL3
        fftBufVx->nL3_i[i] = 0;

        src_ptr = src_ptr + 4
     }
 }

4.まとめ


インタフェースを変更しない場合は,関数の読みやすさと効率をできるだけ高め,コード産出効率と品質のバランスを徐々に把握する.止まらないで、次の版はもっといいです.