記事ディレクトリ
プロジェクトのシナリオ:
推定された後処理ランタイムの最適化。
まず、最適化の前後での時間の比較を見てみましょう。
最適化前:
最適化後:
依然として大幅な改善が見られます。
問題の説明
モデル推論後に得られたデータの後処理には多大な時間がかかります。
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]
outputvtemp
outputsf
重复计算
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秒