モデル推論後処理 C++ コード最適化のケース

プロジェクトのシナリオ:

推定された後処理ランタイムの最適化。

まず、最適化の前後での時間の比較を見てみましょう。
最適化前:
ここに画像の説明を挿入します
最適化後:

依然として大幅な改善が見られます。


問題の説明

モデル推論後に得られたデータの後処理には多大な時間がかかります。

auto outputsf = pRealEngine->sampleProcess->outData;
    //postprogress

std::vector<float> outputvtemp; 
std::vector<std::vector<BoundingBox>> preds(pRealEngine->num_class); //class-bboxes
BoundingBox temp;
auto n = pRealEngine->modelout_len*pRealEngine->nc;
// int c=0;
for(auto i=0;i<n;i++){
    
    
    outputvtemp.push_back(outputsf[i]);
    if((i+1)%pRealEngine->nc==0) {
    
    
        if(outputvtemp[4]>pRealEngine->confidence_threshold){
    
    
            auto cx = outputvtemp[0];
            auto cy = outputvtemp[1];
            auto w = outputvtemp[2];
            auto h = outputvtemp[3];
            temp.x = std::max(int((cx-w/2)),0);
            temp.y = std::max(int((cy-h/2)),0);
            temp.w = std::min(int(w),int(pImgInfo->i32Width-temp.x));
            temp.h = std::min(int(h),int(pImgInfo->i32Height-temp.y));
            temp.cx = int((cx-w/2));
            temp.cy = int((cx-w/2));
            temp.confidence =  outputvtemp[4];
            temp.classid = getfclassid(outputvtemp);

            preds[temp.classid].push_back(temp);
        }
        outputvtemp.clear();
    } 
}	

原因分析:

不必要的数据复制:ベクトルに追加するoutputvtemp.push_back(outputsf[i])ために元のコードで使用されます。これには、メモリの再割り当てとデータのコピーが含まれます。このオーバーヘッドを回避するために、追加のベクトルを使用せずにループ内で配列に直接アクセスできますoutputsf[i]outputvtempoutputsf

重复计算cx - w/2: ループ内で計算され、cy - h/2複数の場所で再利用される値。これらの計算を条件の外側に移動して、二重計算を避けることができます。

复杂的条件判断: ループ内にいくつかの条件判定があります。たとえばif (outputvtemp[4] > pRealEngine->confidence_threshold)、これらの条件判定により実行時間が長くなる可能性があります。これらの条件判断が必要であることを確認し、可能であれば不必要な条件判断を最小限に抑えます。


解決:

auto outputsf = pRealEngine->sampleProcess->outData;
std::vector<std::vector<BoundingBox>> preds(pRealEngine->num_class); //class-bboxes
BoundingBox temp;
auto n = pRealEngine->modelout_len * pRealEngine->nc;
// int elements_per_output = 5; // 每个输出元素包含 5 个值

for (auto i = 0; i < n; i +=pRealEngine->nc)// elements_per_output) 
{
    
    
    float confidence = outputsf[i + 4];

    if (confidence > pRealEngine->confidence_threshold) 
    {
    
    
        auto cx = outputsf[i];
        auto cy = outputsf[i + 1];
        auto w = outputsf[i + 2];
        auto h = outputsf[i + 3];
        temp.x = std::max(int((cx - w / 2)), 0);
        temp.y = std::max(int((cy - h / 2)), 0);
        temp.w = std::min(int(w), int(pImgInfo->i32Width - temp.x));
        temp.h = std::min(int(h), int(pImgInfo->i32Height - temp.y));
        temp.cx = int((cx - w / 2));
        temp.cy = int((cy - h / 2));
        temp.confidence = confidence;
        // 将数组转换为 std::vector<float>
        std::vector<float> outputvtemp(outputsf + i, outputsf + i + pRealEngine->nc);
        
        // 调用 getfclassid 函数,并传递起始和结束索引
         temp.classid = getfclassid(outputvtemp); // 传递起始和结束索引

        preds[temp.classid].push_back(temp);
    }
}

まとめ

この記事は、私自身のプロジェクトで遭遇した実際的な問題であり、C++ 関連のプロジェクトを開始したばかりなので、ここに記録します。
C++ への道のりは長いです、さあ!
2023年9月9日 15時33分36秒

おすすめ

転載: blog.csdn.net/JulyLi2019/article/details/132777406
おすすめ