Здравствуйте, есть метод получения массива яркостей из BitmapSource для дальнейшего анализа:
public const float CoeffColor = ((float)100 / 255 * 3) / 10000;
//...
arrayPixelsImage = new byte[SizeArrayPixels];
source.CopyPixels(arrayPixelsImage, StriteImage, 0); //typeof(source) == BitmapSource
float[,] massBrightness = new float[WidthImage, HeightImage];
Parallel.For(0, WidthImage, x =>
{
for (int y = 0; y < HeightImage; y++)
{
int indx = y * WidthImage * 4 + 4 * x;
float brightness = (float)(arrayPixelsImage[indx] + arrayPixelsImage[indx + 1] + arrayPixelsImage[indx + 2]) * CoeffColor;
massBrightness[x, y] = brightness;
}
});
return massBrightness;
Интересует то, как можно его оптимизировать, в плане времени выполнения?
Ответ
Погонял алгоритм на fullHD jpeg'e. У меня на нём выходит чуть боле 2млн итераций суммарно.(внешний параллельный + внутренний) И тут, я боюсь оптимизировать особо не получится.
Примерные затраты по коду:
int indx = y * WidthImage * 4 + 4 * x; -25%
float brightness = (float)(arrayPixelsImage[indx] + arrayPixelsImage[indx + 1] + arrayPixelsImage[indx + 2]) * CoeffColor; -70%
massBrightness[x, y] = brightness;-3%
сам цикл -2%
Учитывая общее кол-во итераций не лишним будет отметить, что накладные расходы на создание нового таска на каждой итерации Parallel.For практически нивелируют выигрыш от использования распараллеливания при сравнении с последовательным циклом с таким же кол-вом итераций. Т.е. цикл с 2М итераций с тем же телом выполняется почти за то же кол-во тиков.
Резюмируя свои мысли по поводу оптимизации данного кода:
На C# вряд ли удастся достичь хотя бы 2-х кратного прироста производительности. Можно оптимизировать все вычисления и операции доступа/присвоения, но максимум, чего удастся добиться это 30% прироста на "удачном" прогоне по отношению к среднему результату до оптимизации. Если учесть что винда система отнюдь не реального времени то даже оптимизированный вариант может ( и достаточно часто будет) отрабатывать дольше чем средне время для не оптимизированного варианта.
Если нужно "лопатить" большие объёмы данных и по другому никак при этом выполняя на каждом кванте (единице данных) достаточно простые/быстрые операции то я рекомендую смотреть вам в сторону использования ресурсов GPU (OpenCL или CUDA)
Для всех остальных случаев я бы смотрел в сторону упрощения алгоритма или уменьшения числа операций. Например понижал бы разрешение изображения пока это не сильно сказывается на результате. Ощутимо упростить что-либо в этих 3-х строчках кода вряд ли получится. Поэтому думайте как уменьшить число итераций.
Комментариев нет:
Отправить комментарий