Re[16]: Производительность .Net на вычислительных задачах
От: Sinclair Россия https://github.com/evilguest/
Дата: 28.10.20 04:22
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Стек аудио-эффектов для гитары, например.

А нельзя композицию эффектов свести к композитному эффекту?

V>Т.е., даже если импульсная характеристика порождена не аналоговым процессом, а цифровым, то делается это примерно так:

V>- на некоей модели, оперирующей большой точностью, моделируется некая обработка сигнала;
V>- с этой модели снимается итоговая импульсная характеристика;
V>- в реалтайме затем происходит свёртка входного сигнала с импульсной характеристикой.
Хм. Это должно работать только с линейными фильтрами.
V>Суть в том, что "точная модель" оперирует большой разрядностью и кратной передискетизацией унутре, поэтому эта модель не работает в реалтайм, она используется один раз при вычислении IR.
Как-то это сложно. Непонятно, зачем вообще вся эта суперпередискретизация, если мы всё равно пропускаем через эту модель единичный сигнал, а на выход записываем коэффициенты в "финальной" дискретизации и разрядности.
V>Нелинейщина обычно проще. Это разного рода пороговые ф-ии, типа sqrt, log и т.д. и они часто реализованы через табличную аппроксимацию, т.е. практически бесплатны.
Ну, по сравнению с арифметикой даже они гораздо дороже. Как сделать табличную аппроксимацию в SIMD?

V>Компилятор Intel С++ разворачивает циклы именно при работе с SIMD в N=16, 32, ..., 128 раз.

В примерах, которые видел я, развёртки SIMD циклов от ICC ~ 2, от GCC — ~4. И это при простейшем коде цикла, где вроде бы и нагрузки на CPU на итерацию мало, и до пределов кэша коду ещё далеко.
V>Кеш данных 1-го уровня имеет в точности быстродействие файла регистров (и там и там косвенная адресация из-за ассоциативности, для кеша данных — с данными, для файла регистров — из-за переименований регистров, где внутренний файл регистров в несколько раз больше "публичного" его отображения).
Ну... хз. Всё равно юнитов исполнительных в одном ядре не очень много; даже если я разверну цикл 128 раз, никто мне не будет 128 пар сложений одновременно выполнять.

V>Другое дело, что там много инфы и она достаточно "муторная". ))

Ну вот в том-то и дело. Формально вроде бы интел и переходы предсказывает, и инструкции перемещает, а на практике — всё равно разница есть.
Вот то же предсказание переходов: по идее, проверка выхода за диапазон вообще не должна влиять на массивах размером в 33мегапиксела. Там же ровно всегда один и тот же бранч выбирается.
Ан нет — жрёт до 25% времени в скалярном варианте фильтра C4.
Вот и перемешивание инструкций — есть подозрение, что даже формальная независимость по данным не обеспечит идеальный тайминг; а ICC как раз их располагает с учётом знания устройства конвеера.
Впрочем, мне всё равно до этого далеко. Мой оптимизатор даже эвристическим назвать нельзя — он тупой табличный. В то время, как взрослые пацаны работают как минимум со стоимостями, т.е. рассматривают для любой комбинации операций разные варианты её кодирования в бинарь, и выбирают наиболее дешёвый.
Способность ещё и анализировать инструкции с точки зрения возможности наложения друг на друга — вообще космос по сравнению с тем, что уже сделано в linq2d.

V>Но для второго канала для рекурсивного фильтра надо подгрузить уже другие минус N отсчётов.

Почему другие-то? На выходе-то оба канала точно так же идут в памяти вместе: LRLRLRLRLR.

V>Соотв, кол-во отсчётов IR зависит от отношения частоты дискретизации / частоты фильтра и от заданной точности.

V>В реальности это от нескольких десятков отсчётов, до нескольких тысяч, чаще всего в пределах нескольких сотен для низких порядков фильтра (до ~8 порядков).
V>Для ревербераторов+эха длина IR может составлять секунды, умножай на частоту дискретизации.
Омг. То есть мы говорим о ~10^6 отсчётов. Да, тут есть шанс вылететь за кэш.
С другой стороны, тут никакой мотивации для linq нету. Все фильтры устроены одинаково — тупо свёртка IR с входом и выходом. Один раз пишем оптимальную функцию; можно её специализировать для пяти-шести вариантов аппаратуры — и вперёд, на танки.

V>Исходники есть, можно подключить гитару и играть. ))

V>Могу переслать куда-нить.
Пересылай. Хотя я скорее гитару подключу к готовой железке
V>Можно.
V>Вернее, нужно, чтобы стимулировать желание экспериментировать задёшево. ))
Пока непонятно. То есть понятно, что можно давать, скажем, описывать частотный фильтр его графиком, а потом конвертировать это в IR при помощи Фурье. (Я такие штуки видел ещё в 1980х, вряд ли кого чем-то тут можно удивить).
И вообще, если мы всё сводим к IR, то любой фильтр — это просто набор чиселок. Ну, или функция от N аргументов, которая порождает этот набор чиселок.
Что тут можно придумать, кроме того, что уже сто лет как придумано?

V>ОК, это была инфа — эксперименты/рассчёты ИИ делают сегодня в основном на Питоне.

V>Т.е., в реальных железках работают уже плюсы с вычисленными на Питоне коэф. сетки.
Ну, для ML уже есть кому экспериментировать. https://devblogs.microsoft.com/dotnet/using-net-hardware-intrinsics-api-to-accelerate-machine-learning-scenarios/
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re: Производительность .Net на вычислительных задачах
От: кубик  
Дата: 28.10.20 05:00
Оценка:
Привет,

Я счел эту задачу подходящей для того что б подтянуть ассеиблер с SSE.
Переделал первый цикл (for for) на SSE и получил 20% прирост скорости. Собираюсь переделать всю sauvolaBinarize
Даже в твоем случае если double заменить на float (а так можно без потери смысла?) то С++ убыстряется на ~ 3%.
Re[15]: Производительность .Net на вычислительных задачах
От: Sinclair Россия https://github.com/evilguest/
Дата: 28.10.20 08:59
Оценка:
Здравствуйте, Sinclair, Вы писали:
S>Ну, критерий истины — замеры. Ща прикручу тесты, можно будет развлекаться переписыванием кода, и заменами компиляторов.
Привинтил тесты.
Проверяется запуском в студии, либо из командной строки — см. https://github.com/evilguest/linq2d/blob/master/.github/workflows/dotnet-core.yml
Бенчмаркнуться можно из командной строки при помощи
cd Linq2d.Benchmarks
dotnet run -c Release --no-build --filter "*"


Результаты замеров в облаке:
Intel Xeon Platinum 8171M CPU 2.60GHz, 1 CPU, 2 logical and 2 physical cores
.NET Core SDK=3.1.403
  [Host] : .NET Core 3.1.9 (CoreCLR 4.700.20.47201, CoreFX 4.700.20.47203), X64 RyuJIT

Job=InProcess  Toolchain=InProcessEmitToolchain  

|             Method |      FileName |      Mean |    Error |   StdDev | Ratio | RatioSD |
|------------------- |-------------- |----------:|---------:|---------:|------:|--------:|
|              CppC4 | p00743.bmp.gz |  47.14 ms | 0.490 ms | 0.458 ms |  0.38 |    0.00 |
|          NaturalC4 | p00743.bmp.gz | 321.79 ms | 3.111 ms | 2.758 ms |  2.62 |    0.03 |
|           UnsafeC4 | p00743.bmp.gz | 122.62 ms | 1.104 ms | 0.979 ms |  1.00 |    0.00 |
|             LinqC4 | p00743.bmp.gz |  62.87 ms | 0.823 ms | 0.770 ms |  0.51 |    0.01 |
| LinqC4VectorCached | p00743.bmp.gz |  51.53 ms | 0.603 ms | 0.535 ms |  0.42 |    0.01 |


|                  Method | WHalf |      FileName |       Mean |    Error |   StdDev | Ratio | RatioSD |
|------------------------ |------ |-------------- |-----------:|---------:|---------:|------:|--------:|
|             SafeSauvola |     5 | p00743.bmp.gz | 1,806.3 ms |  6.15 ms |  5.13 ms |  1.69 |    0.01 |
|     UnsafeSauvolaScalar |     5 | p00743.bmp.gz | 1,068.0 ms |  8.79 ms |  7.79 ms |  1.00 |    0.00 |
|              CppSauvola |     5 | p00743.bmp.gz |   573.0 ms |  3.60 ms |  3.01 ms |  0.54 |    0.00 |
|       LinqSauvolaVector |     5 | p00743.bmp.gz | 1,313.3 ms |  7.65 ms |  7.16 ms |  1.23 |    0.01 |
|       LinqSauvolaScalar |     5 | p00743.bmp.gz | 1,638.8 ms | 17.83 ms | 16.68 ms |  1.53 |    0.02 |
| CachedLinqSauvolaVector |     5 | p00743.bmp.gz |   687.8 ms |  4.95 ms |  4.39 ms |  0.64 |    0.01 |
| CachedLinqSauvolaScalar |     5 | p00743.bmp.gz | 1,016.4 ms |  6.32 ms |  5.60 ms |  0.95 |    0.01 |
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[2]: Производительность .Net на вычислительных задачах
От: Sinclair Россия https://github.com/evilguest/
Дата: 28.10.20 12:17
Оценка:
Здравствуйте, кубик, Вы писали:
К>Переделал первый цикл (for for) на SSE и получил 20% прирост скорости.
Сравниваешь с AVX2?
К>Даже в твоем случае если double заменить на float (а так можно без потери смысла?) то С++ убыстряется на ~ 3%.
Не, давай не будем заменять на float. Если это делать, то надо во всём коде его систематически заменять — и в c# тоже. Не то, чтобы это было долго, но лучше, чтобы все были в равных условиях.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[3]: Производительность .Net на вычислительных задачах
От: кубик  
Дата: 29.10.20 02:42
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Здравствуйте, кубик, Вы писали:

К>>Переделал первый цикл (for for) на SSE и получил 20% прирост скорости.
S>Сравниваешь с AVX2?
А что , уже переписали на асме или просто опцию компилятора добавили ? Я что то не заметил.
Re[4]: Производительность .Net на вычислительных задачах
От: Sinclair Россия https://github.com/evilguest/
Дата: 29.10.20 03:26
Оценка:
Здравствуйте, кубик, Вы писали:
К>А что , уже переписали на асме или просто опцию компилятора добавили ? Я что то не заметил.
Добавил -march=native.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[3]: Производительность .Net на вычислительных задачах
От: кубик  
Дата: 29.10.20 10:32
Оценка:
К>>Даже в твоем случае если double заменить на float (а так можно без потери смысла?) то С++ убыстряется на ~ 3%.
S>Не, давай не будем заменять на float. Если это делать, то надо во всём коде его систематически заменять — и в c# тоже. Не то, чтобы это было долго, но лучше, чтобы все были в равных условиях.

Ну можно размер картинки считать кратным чему либо типа 4,8,16?
Это хобби, не хочу возится с некратными размерами.
Re[4]: Производительность .Net на вычислительных задачах
От: Sinclair Россия https://github.com/evilguest/
Дата: 29.10.20 11:53
Оценка:
Здравствуйте, кубик, Вы писали:

К>>>Даже в твоем случае если double заменить на float (а так можно без потери смысла?) то С++ убыстряется на ~ 3%.

S>>Не, давай не будем заменять на float. Если это делать, то надо во всём коде его систематически заменять — и в c# тоже. Не то, чтобы это было долго, но лучше, чтобы все были в равных условиях.

К>Ну можно размер картинки считать кратным чему либо типа 4,8,16?

К>Это хобби, не хочу возится с некратными размерами.
В принципе можно, но тогда придётся подправить тесты.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re: Производительность .Net на вычислительных задачах
От: omgOnoz  
Дата: 29.10.20 12:35
Оценка: -1
Здравствуйте, Sinclair, Вы писали:

А как же java / scala паралельные коллекции и т.п. которые из-под коробки юзают многопоточность?

Голые циклы в 2020 году как бы не очень...
Отредактировано 29.10.2020 12:36 omgOnoz . Предыдущая версия .
Re[2]: Производительность .Net на вычислительных задачах
От: Sinclair Россия https://github.com/evilguest/
Дата: 29.10.20 15:23
Оценка:
Здравствуйте, omgOnoz, Вы писали:
O>А как же java / scala паралельные коллекции и т.п. которые из-под коробки юзают многопоточность?
Ничего про это не знаю. Начнём с того, что в java в принципе нет многомерных массивов. А также нет value-типов и нормальных генериков; то есть сделать обёртку вокруг линейного массива, которая будет переводить item(i, j) в item[i*w+j], придётся для каждого типа отдельно.
Насколько там возможно получить аналог Expression<T> для анализа — х.з.

O>Голые циклы в 2020 году как бы не очень...

А где в linq2d голые циклы?
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[3]: Производительность .Net на вычислительных задачах
От: omgOnoz  
Дата: 29.10.20 18:17
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Ничего про это не знаю. Начнём с того, что в java в принципе нет многомерных массивов.

Многомерный массив всегда можно представить в виде обычного массива.

S>А также нет value-типов и нормальных генериков; то есть сделать обёртку вокруг линейного массива, которая будет переводить item(i, j) в item[i*w+j], придётся для каждого типа отдельно.

В скале это можно. Даже есть перегрузка операторов.
S>А где в linq2d голые циклы?
я так называю ... for i for j
Отредактировано 29.10.2020 18:26 omgOnoz . Предыдущая версия .
Re[5]: Производительность .Net на вычислительных задачах
От: кубик  
Дата: 30.10.20 03:24
Оценка:
К>>Ну можно размер картинки считать кратным чему либо типа 4,8,16?
К>>Это хобби, не хочу возится с некратными размерами.
S>В принципе можно, но тогда придётся подправить тесты.

А можешь сказать почему у тебя в c4filter output это int. На мой взгляд достаточно word
Re[4]: Производительность .Net на вычислительных задачах
От: Sinclair Россия https://github.com/evilguest/
Дата: 30.10.20 09:38
Оценка:
Здравствуйте, omgOnoz, Вы писали:
S>>Ничего про это не знаю. Начнём с того, что в java в принципе нет многомерных массивов.
O>Многомерный массив всегда можно представить в виде обычного массива.
Наверное, можно. Ну, я на java ничего не писал почти 20 лет.
S>>А также нет value-типов и нормальных генериков; то есть сделать обёртку вокруг линейного массива, которая будет переводить item(i, j) в item[i*w+j], придётся для каждого типа отдельно.
O>В скале это можно. Даже есть перегрузка операторов.
Ок, а дальше что? Как будет выглядеть этот EDSL на джаве или, скажем, на скале?

S>>А где в linq2d голые циклы?

O>я так называю ... for i for j
Ну, ок. И где в linq2d for i for j?
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[6]: Производительность .Net на вычислительных задачах
От: Sinclair Россия https://github.com/evilguest/
Дата: 30.10.20 09:40
Оценка:
Здравствуйте, кубик, Вы писали:

К>А можешь сказать почему у тебя в c4filter output это int. На мой взгляд достаточно word

Для упрощения кода. Просто в дотнете нет никакой арифметики ни на byte, ни на word — есть только на int и на long.
Поэтому когда мы складываем byte + byte, получается сразу int, а к word придётся кастить руками.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[5]: Производительность .Net на вычислительных задачах
От: Ночной Смотрящий Россия  
Дата: 30.10.20 20:32
Оценка: +1 -1
Здравствуйте, a_g_99, Вы писали:

__>вообще идея говорения что си щарп, пхп, вижуал бэсик и тп быстрее С++ это как то с душком не правда ли? Отдает какой то граничащей с безумием продажностью. Или клиническим идиотизмом


Подгорело знатно.
... << RSDN@Home 1.3.17 alpha 5 rev. 62>>
Re[8]: Производительность .Net на вычислительных задачах
От: ути-пути Россия  
Дата: 30.10.20 23:11
Оценка:
Здравствуйте, kaa.python, Вы писали:

KP>Высокий уровень оптимизации вообще мало где нужен


Так вроде область ясно очерчена в заголовке темы.
Переубедить Вас, к сожалению, мне не удастся, поэтому сразу перейду к оскорблениям.
Re[7]: Производительность .Net на вычислительных задачах
От: кубик  
Дата: 31.10.20 05:01
Оценка: 3 (1)
S>Для упрощения кода. Просто в дотнете нет никакой арифметики ни на byte, ни на word — есть только на int и на long.
S>Поэтому когда мы складываем byte + byte, получается сразу int, а к word придётся кастить руками.

Но у нас воспрос не простоты, а производительности... Надеюсь ты в докладе осветил этот недостаток

Переписаная на SSE с AVX c4_filter с WORD в 3-4 раза быстрее чем C++ (старенький VS 2008, проц Xeon старенький)

А с int в 2 раза быстрее чем C++

Результаты сверял.

в c4_filter я заменил только главный цикл. Думаю этого достаточно.
Так как Xeon у меня старый, инетересно, как моя функа (она тоже наивная, переписана с твоей) посчитает на новых и посоревнуется с современным оптимизатором?

Update: нашел gcc современный с -march=native и -mtune=native и -O2 так же как и VS 2008.
Он ничего не векторизировал в асме. Как я и ожидал. Если б так было б, то можно на пенсию было собираться.
Отредактировано 31.10.2020 6:34 кубик . Предыдущая версия . Еще …
Отредактировано 31.10.2020 5:39 кубик . Предыдущая версия .
Re[8]: Производительность .Net на вычислительных задачах
От: Sinclair Россия https://github.com/evilguest/
Дата: 31.10.20 11:57
Оценка:
Здравствуйте, кубик, Вы писали:

К>Результаты сверял.


К>в c4_filter я заменил только главный цикл. Думаю этого достаточно.

Да, конечно.
К>Так как Xeon у меня старый, инетересно, как моя функа (она тоже наивная, переписана с твоей) посчитает на новых и посоревнуется с современным оптимизатором?
Отлично, ждём pull request.
К>Update: нашел gcc современный с -march=native и -mtune=native и -O2 так же как и VS 2008.
К>Он ничего не векторизировал в асме. Как я и ожидал. Если б так было б, то можно на пенсию было собираться.

Хм, странно.
Я вот тут вижу какую-то векторизацию внутреннего цикла:
https://godbolt.org/z/Gq6Gce
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[9]: Производительность .Net на вычислительных задачах
От: кубик  
Дата: 31.10.20 13:23
Оценка:
S>Хм, странно.
S>Я вот тут вижу какую-то векторизацию внутреннего цикла:

да, вижу. Я пробовал с O2, а оно появляется при O3. Думаю что оптимизатору мало хинтов что б сделать красиво.
Я тебе послал файлик. Более чем в 2 раза быстрее на выровненых данных.
Re[10]: Производительность .Net на вычислительных задачах
От: Sinclair Россия https://github.com/evilguest/
Дата: 01.11.20 06:40
Оценка:
Здравствуйте, кубик, Вы писали:
К>да, вижу. Я пробовал с O2, а оно появляется при O3. Думаю что оптимизатору мало хинтов что б сделать красиво.
К>Я тебе послал файлик. Более чем в 2 раза быстрее на выровненых данных.
Ок, файлик получил, сейчас разберусь, как это собрать.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.