ベイヤー画像チャンネルを RGB に変換するアルゴリズムがあります。私の実装ではfor
、ベイヤー チャネルを反復処理し、ベイヤー インデックスから RGB インデックスを計算し、ベイヤー チャネルからそのピクセルの値を設定する単一のネストされたループがあります。ここで注目すべき主な点は、各ピクセルは他のピクセルとは独立して計算できる (以前の計算に依存しない) ため、このアルゴリズムは自然に並列化の候補になるということです。ただし、計算は、すべてのスレッドが同時にアクセスするが変更されないいくつかのプリセット配列に依存します。
ただし、メインfor
を MSと並列化しようとするとcuncurrency::parallel_for
、パフォーマンスが向上しませんでした。実際、4 コア CPU で実行されるサイズ 3264X2540 の入力の場合、非並列バージョンは ~34 ミリ秒で実行され、並列バージョンは ~69 ミリ秒で実行されました (10 回の実行の平均)。実際に操作が並列化されていることを確認しました (タスク用に 3 つの新しいスレッドが作成されました)。
Intel のコンパイラを使用するとtbb::parallel_for
、ほぼ正確な結果が得られました。比較のために、ループC#
も使用したこのアルゴリズムの実装から始めたところ、parallel_for
ほぼ X4 のパフォーマンス向上が見られました (C++
この特定のタスクC++
ではシングルコアでも高速だったので選択しました)。
私のコードがうまく並列化できない理由は何ですか?
私のコード:
template<typename T>
void static ConvertBayerToRgbImageAsIs(T* BayerChannel, T* RgbChannel, int Width, int Height, ColorSpace ColorSpace)
{
//Translates index offset in Bayer image to channel offset in RGB image
int offsets[4];
//calculate offsets according to color space
switch (ColorSpace)
{
case ColorSpace::BGGR:
offsets[0] = 2;
offsets[1] = 1;
offsets[2] = 1;
offsets[3] = 0;
break;
...other color spaces
}
memset(RgbChannel, 0, Width * Height * 3 * sizeof(T));
parallel_for(0, Height, [&] (int row)
{
for (auto col = 0, bayerIndex = row * Width; col < Width; col++, bayerIndex++)
{
auto offset = (row%2)*2 + (col%2); //0...3
auto rgbIndex = bayerIndex * 3 + offsets[offset];
RgbChannel[rgbIndex] = BayerChannel[bayerIndex];
}
});
}