У меня есть алгоритм, который преобразует канал изображения Bayer в RGB. В моей реализации у меня есть один вложенный цикл for
, который итерации по каналу bayer, вычисляет индекс rgb из индекса bayer и затем устанавливает это значение пикселя из канала Bayer.
Главное отметить здесь, что каждый пиксель может быть рассчитан независимо от других пикселей (не полагается на предыдущие вычисления), и поэтому алгоритм является естественным кандидатом на параллелизацию. Однако вычисление основывается на некоторых предустановленных массивах, к которым все потоки будут доступны в одно и то же время, но не изменится.
Однако, когда я попытался распараллелить основной for
с MS cuncurrency::parallel_for
, я не получил повышения производительности. Фактически, для ввода размера 3264X2540, работающего по 4-ядерному процессору, нераспараллельная версия работала в ~ 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];
}
});
}