Сообщение Производительность .Net на вычислительных задачах от 21.10.2020 2:52
Изменено 21.10.2020 6:20 Sinclair
Производительность .Net на вычислительных задачах
Мой доклад успешно прошёл. Запись я обещал не выкладывать до середины ноября, да и не особо там чего смотреть.
Хочу поделиться самой зрелищной частью: сравнение производительности разных способов реализации вычислительно-интенсивного кода.
Вот график, который сравнивает разные способы посчитать бинаризацию по Sauvola 7184019.1 для изображения в 33 мегапиксела (время в ms):
Участники:
Итого: гарантированно безопасный код на C# работает быстрее небезопасного кода на C#, и сравнимо с небезопасным кодом на С++.
В более простом случае, с фильтром C4, вот такой вот linq2d код объезжает С++ на обеих платформах:
Вот C4 по тому же изображению размером 33МП:
Весь код, включая бенчмарки — в репозитории https://github.com/evilguest/linq2d
Выводы, как грится, каждый может сделать сам.
Хочу поделиться самой зрелищной частью: сравнение производительности разных способов реализации вычислительно-интенсивного кода.
Вот график, который сравнивает разные способы посчитать бинаризацию по Sauvola 7184019.1 для изображения в 33 мегапиксела (время в ms):
Участники:
- Naive — простая реализация на C#, на основе двумерных массивов
Unsafe — реализация на С# с прямой манипуляцией указателями (fixed)
С++ — реализация на С++, внешняя dll, в неё делаем вызов. Стоимостью маршалинга одного указателя на фоне сотен миллисекунд обработки можно пренебречь.
Linq — честная реализация на linq2d, которая на каждое вычисление фильтра строит код трансформации с нуля
Cached Linq — реализация на linq2d, один раз (за пределами измерений) строит код трансформации и сохраняет его в делегат Func<byte[,], byte[,]>. Замеряется стоимость вычисления фильтра Sauvola при помощи этого сохранённого делегата.
Итого: гарантированно безопасный код на C# работает быстрее небезопасного кода на C#, и сравнимо с небезопасным кодом на С++.
В более простом случае, с фильтром C4, вот такой вот linq2d код объезжает С++ на обеих платформах:
private static Func<byte[,], int[,]> _c4 =
(from d in new byte[0,0]
select (d[-1, 0] + d[1, 0] + d[0, -1] + d[0, 1])/4).Transform;
public static void int[,] C4(byte[,] data) => _c4(data);
Вот C4 по тому же изображению размером 33МП:
Весь код, включая бенчмарки — в репозитории https://github.com/evilguest/linq2d
Выводы, как грится, каждый может сделать сам.
Производительность .Net на вычислительных задачах
Мой доклад успешно прошёл. Запись я обещал не выкладывать до середины ноября, да и не особо там чего смотреть.
Хочу поделиться самой зрелищной частью: сравнение производительности разных способов реализации вычислительно-интенсивного кода.
Вот график, который сравнивает разные способы посчитать бинаризацию по Sauvola (2D-Linq и оптимизация цифровых фильтров) для изображения в 33 мегапиксела (время в ms):
Участники:
Итого: гарантированно безопасный код на C# работает быстрее небезопасного кода на C#, и сравнимо с небезопасным кодом на С++.
В более простом случае, с фильтром C4, вот такой вот linq2d код объезжает С++ на обеих платформах:
Вот C4 по тому же изображению размером 33МП:
Весь код, включая бенчмарки — в репозитории https://github.com/evilguest/linq2d
Выводы, как грится, каждый может сделать сам.
Хочу поделиться самой зрелищной частью: сравнение производительности разных способов реализации вычислительно-интенсивного кода.
Вот график, который сравнивает разные способы посчитать бинаризацию по Sauvola (2D-Linq и оптимизация цифровых фильтров) для изображения в 33 мегапиксела (время в ms):
Участники:
- Naive — простая реализация на C#, на основе двумерных массивов
Unsafe — реализация на С# с прямой манипуляцией указателями (fixed)
С++ — реализация на С++, внешняя dll, в неё делаем вызов. Стоимостью маршалинга одного указателя на фоне сотен миллисекунд обработки можно пренебречь.
Linq — честная реализация на linq2d, которая на каждое вычисление фильтра строит код трансформации с нуля
Cached Linq — реализация на linq2d, один раз (за пределами измерений) строит код трансформации и сохраняет его в делегат Func<byte[,], byte[,]>. Замеряется стоимость вычисления фильтра Sauvola при помощи этого сохранённого делегата.
Итого: гарантированно безопасный код на C# работает быстрее небезопасного кода на C#, и сравнимо с небезопасным кодом на С++.
В более простом случае, с фильтром C4, вот такой вот linq2d код объезжает С++ на обеих платформах:
private static Func<byte[,], int[,]> _c4 =
(from d in new byte[0,0]
select (d[-1, 0] + d[1, 0] + d[0, -1] + d[0, 1])/4).Transform;
public static void int[,] C4(byte[,] data) => _c4(data);
Вот C4 по тому же изображению размером 33МП:
Весь код, включая бенчмарки — в репозитории https://github.com/evilguest/linq2d
Выводы, как грится, каждый может сделать сам.