Страницы

Поиск по вопросам

пятница, 15 марта 2019 г.

Оптимизация алгортима перебора пикселей WPF C#

Здравствуйте, есть метод получения массива яркостей из 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-х строчках кода вряд ли получится. Поэтому думайте как уменьшить число итераций.

Комментариев нет:

Отправить комментарий