Re[17]: Производительность .Net на вычислительных задачах
От: Sinclair Россия https://github.com/evilguest/
Дата: 03.11.20 10:47
Оценка: 2 (1)
Здравствуйте, кубик, Вы писали:
К>На моем тесте с asm более чем 2 раза быстее С++. Вызываю 10 раз подряд c4filter на рандомном массиве размером 10,000 x 10,000 и беру разницу GetTickCount64. Выделение памяти и иниц. массива не входят в измерения.
К>А в таблице ты делаешь вывод что он чуть чуть обгоняет. Мне не понятно методика теста и в какую колонку смотреть. Я не математик.
Методика теста очень простая: берём grayscale изображение размером 33 мегапиксела и скармливаем его в разные варианты кода, вычисляя для него фильтр C4.
Во всех вариантах исходный массив уже выделен; выделение массива результата (размером в ~130 мегабайт) в замер времени входит, но выполняется для всех измерений на стороне дотнета.

Замеры делаются при помощи benchmarkdotnet.org — он вызывает каждого из кандидатов столько раз, сколько нужно для уверенной оценки.
Точнее, делается так: замеряется время работы m вызовов подряд (m подбирается в зависимости от времени работы однократного вызова; для таких тяжёлых операций, как у нас, оно в диапазоне от 2 до 6), и замер повторяется многократно.
Из замеренного времени вычитается время прогона такого же цикла, только с вызовом пустого метода.
Перед началом измерений выполняется несколько прогревочных прогонов, не входящих в результат — чтобы прогреть все кэши и проинициализировать всякие оптимизационные структуры, и замерять производительность "стабильного" случая.
Загрузка изображения с диска делается один раз, до начала серии замеров, и в замеры не входит.
Во все вызовы передаётся физически один и тот же массив в качестве входного; выходной массив — каждый раз разный.

Смотреть надо в колонки Mean и Ratio.
Mean — это среднее время работы каждого из вариантов. Ratio — это отношение Mean к так называемой baseline реализации — в нашем случае это рукопашный скалярный unsafe код на C#.
Error — это погрешность измерения, линейно связана со среднеквадратичным измерением.

Вот, смотрим: С++ окучивает 33 мегабайта в среднем за 120.5 миллисекунд. Это 90% от времени работы скалярного unsafe-кода на шарпе. До того, как я смог включить в нём векторизацию, справлялся за ~140 миллисекунд.
Твой ассемблерный вариант окучивает тот же массив за 101 миллисекунду. А linq2d справляется за 93.


Вообще, BDN отдаёт больше результатов — в том числе и отброшенные экстремальные значения, и признаки мультимодальности (обычно мультимодальность означает, что есть какой-то скрытый параметр, и часть исполнений идёт по одному пути, а часть — по другому. Например, сборка мусора может случиться, а может не случиться во время исполнения кода). Но главный результат — вот в виде такой таблички.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.