Информация об изменениях

Сообщение Re[17]: Производительность .Net на вычислительных задачах от 02.11.2020 21:03

Изменено 02.11.2020 21:16 vdimas

Re[17]: Производительность .Net на вычислительных задачах
Здравствуйте, Sinclair, Вы писали:

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

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

До какой-то степени можно, конечно.
Это как минимизация выражений, распространение констант и т.д.
В общем, всё то, что входит в стадию бета-редукции у современных оптимизирующих компиляторов, с учётом предметной области вычислений.

И я одно время "пилил" именно подобное, но так и не допилил (всё надёюсь, что когда-нибудь будет чуть больше времени), бо именно эта область за вечер на коленке не взлетает, почему-то... ))
(в отличие от реализаций независимых эффектов и их простой композиции)
(и мне всё менее кажется, что "оно", действительно, надо)


V>>- с этой модели снимается итоговая импульсная характеристика;

V>>- в реалтайме затем происходит свёртка входного сигнала с импульсной характеристикой.
S>Хм. Это должно работать только с линейными фильтрами.

Разумеется, передаточная ф-ия by design служит для описания линейных (в операторной области) систем.
А IR — это представление передаточной ф-ии во временной области.

Т.е., этот подход работает для любой комбинации линейных операторов:
— линии задержки;
— интегрирование/дифференцирование;
— умножение и сложение амплитуды с константами;
— сумматоры сигналов, в т.ч. когда в аргументах идут обратные связи от других линейных вычислений этого же "блока".


V>>Суть в том, что "точная модель" оперирует большой разрядностью и кратной передискетизацией унутре, поэтому эта модель не работает в реалтайм, она используется один раз при вычислении IR.

S>Как-то это сложно. Непонятно, зачем вообще вся эта суперпередискретизация

Для эффектов навроде эха/реверберации/фленжеров/фейзеров и прочих эффектов на основе обратной связи с задержкой (особенно с переменной задержкой) почти всегда применяют всякие трюки для повышения кач-ва. Иначе эффект начинает иметь "металлические нотки" в звучании, вот как роботы говорят в старых фильмах — это накопление ошибок округления, которые при обратной связи многократно набегают друг на друга, что порождает гармоники обрабатываемого сигнала, которые, в свою очередь, интерферируют с частотой дискретизации.

Вариантов борьбы с этим хватает. Например, есть еще вариант вместо суровой передискретизации применять интерполяцию на линиях задержки, т.е. допустим мгновенная задержка на некоей линии задержки 0.0678345 сек (от балды), надо вычислить некий отсчёт. Вместо наивного нахождения индекса отсчёта в массиве как округления до целого умноженой частоты дискретизации на вещественное время, целевой отсчёт ищется по некоторому закону как интерполированный сигнал. В простейшем случае делается передискретизация всего лишь вдвое, затем неокруглённый отсчёт ищется через линейную интерполяцию по двум точкам. В более сложном виде пропускают через оператор передаточной ф-ии простейшего ФНЧ во временной области — это операция нахождения определённого интеграла, оно неплохо работает, когда в небольших пределах.

Понятное дело, что для наколенного "показать принцип" оно не требуется, но речь идёт о реальных боевых эффектах, где в последний десяток-другой лет кач-во электронной музыки (.е. электронных эффектов) вышло на весьма высокий уровень. "Наколенности" давно нет даже в бесплатных эффектах (любопытные могут поискать по "VST plugin").

Опять же, принцип "подсчитали в оффлайн сколь-угодно сложный эффект, а в онлайн используем IR" — он резко развязывает руки. Это примерно то же самое, что "память не ресурс", т.е. можно сурово передискретизировать сигнал, делать все вычисления в double64 или даже в double128, зато не париться с накоплением ошибок округления и интерферированием гармоник с частотой дискретизации (это всё будет в конце отфильтровано ФНЧ при обратной передискретизации). Оно позволяет использовать более простые алгоритмы, в т.ч. при передискретизации начинают хорошо работать сугубо численные методы, например, методы численного интегрирования и дифференцирования.
Численные методы просты, но неплохо работают при передискретизации на частоты, которые в несколько десятков раз, а лучше в сотню-другую выше максимально-интересующей обрабатываемой частоты, т.е. будет тебе не 48 кГц, а 4.8 Мгц, соответственно мантисса должна удлиниться примерно на 10 разрядов, плюс берём кол-во операций на один отсчёт, на каждую тысячу операций — опять плюс 10 разрядов мантиссы (для прикидки, простейший фильтр второго порядка — это 5-6 слагаемых многочлена) и т.д. и т.п.


S>если мы всё равно пропускаем через эту модель единичный сигнал, а на выход записываем коэффициенты в "финальной" дискретизации и разрядности.


Этот единичный сигнал будет затухать некоторое время.
Затухание получается на линиях задержки и на обратной связи и т.д. что выше описано.
Да и, сами рекурсивные фильтры являются свеобразной линией задержки.
Иногда для компенсации фазовой задержки вводят отрицательную задержку в сигнал, т.е. как бы входной сигнал берется из "будущего", а управляющее вычисленное воздействие (например, мгновенная амплитуда, управляющая АЧХ фильтра) — применяется к сигналу из "настоящего".

А да, самое главное.
Коэффициенты IR имеют понятный для любого хоббиста физический смысл — это просто отсчёты выходного сигнала.
(т.е., "планка входа" в тему минимальная)

Единичный сигнал пропускают через некую систему, на выходе имеем, грубо, WAV-файл, это и есть IR.
Теперь делаем свёртку входного сигнала с IR и ву-а-ля.

Свертка тоже понятна любому хоббисту — мы проигрываем WAV-файл IR с громкостью текущего отсчёта аудио, на следующем шаге к проигрываемому прибавляем опять этот же WAV файл с громкостью, равной следующему отсчёту и т.д., т.е. как бы в параллель "играет" столько "проигрывателей" WAV-файла IR, какова его длина.


V>>Нелинейщина обычно проще. Это разного рода пороговые ф-ии, типа sqrt, log и т.д. и они часто реализованы через табличную аппроксимацию, т.е. практически бесплатны.

S>Ну, по сравнению с арифметикой даже они гораздо дороже. Как сделать табличную аппроксимацию в SIMD?

Через a*x+b


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

S>В примерах, которые видел я, развёртки SIMD циклов от ICC ~ 2, от GCC — ~4. И это при простейшем коде цикла, где вроде бы и нагрузки на CPU на итерацию мало, и до пределов кэша коду ещё далеко.

В 2 раза развёртки циклов я не видел ни разу в ассемблерном виде в релизе.
От 16 до 128 с шагом в степень двойки видел.


V>>Кеш данных 1-го уровня имеет в точности быстродействие файла регистров (и там и там косвенная адресация из-за ассоциативности, для кеша данных — с данными, для файла регистров — из-за переименований регистров, где внутренний файл регистров в несколько раз больше "публичного" его отображения).

S>Ну... хз. Всё равно юнитов исполнительных в одном ядре не очень много; даже если я разверну цикл 128 раз, никто мне не будет 128 пар сложений одновременно выполнять.

Это не тот разворот, это ты имел ввиду в параллель когда вычисления.
Тут да, особо не разбежишься.

О чём говорил я — циклы разворачивают для экономии на обслуживании переменной цикла и соотв. ветвления.

S>Вот то же предсказание переходов: по идее, проверка выхода за диапазон вообще не должна влиять на массивах размером в 33мегапиксела. Там же ровно всегда один и тот же бранч выбирается.


От алгоритма ж зависит.
Если в алгоритме смещение x +/- 100, то на 100 точках в начале и в конце строки будет выход за границы изображения.

Но это применительно к 2D.
С 1D любопытней — выходов за границы быть не может.
Такая адресация делается на циклической линии задержки, длина которой не может быть меньше макс. амплитуды смещения по индексу, и тогда индекс любого отсчёта при смещении назад находится как (cursor + length — offset) % length. Например, было бы прикольно эту операцию сразу выполнить как "встроенный кирпичик" системы. На пальцах — 3.5 отсчёта назад — это x[cursor-3]*0.5+x[cursor-4]*0.5, 4.3 отсчёта назад — это x[cursor-4]*0.7+x[cursor-5]*0.3, где индекс условного cursor-offset вычисляется на циклической линии задержки как показал выше.

(на остальное потом)
Re[17]: Производительность .Net на вычислительных задачах
Здравствуйте, Sinclair, Вы писали:

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

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

До какой-то степени можно, конечно.
Это как минимизация выражений, распространение констант и т.д.
В общем, всё то, что входит в стадию бета-редукции у современных оптимизирующих компиляторов, с учётом предметной области вычислений.

И я одно время "пилил" именно подобное, но так и не допилил (всё надёюсь, что когда-нибудь будет чуть больше времени), бо именно эта область за вечер на коленке не взлетает, почему-то... ))
(в отличие от реализаций независимых эффектов и их простой композиции)
(и мне всё менее кажется, что "оно", действительно, надо)


V>>- с этой модели снимается итоговая импульсная характеристика;

V>>- в реалтайме затем происходит свёртка входного сигнала с импульсной характеристикой.
S>Хм. Это должно работать только с линейными фильтрами.

Разумеется, передаточная ф-ия by design служит для описания линейных (в операторной области) систем.
А IR — это представление передаточной ф-ии во временной области.

Т.е., этот подход работает для любой комбинации линейных операторов:
— линии задержки;
— интегрирование/дифференцирование;
— умножение и сложение амплитуды с константами;
— сумматоры сигналов, в т.ч. когда в аргументах идут обратные связи от других линейных вычислений этого же "блока".


V>>Суть в том, что "точная модель" оперирует большой разрядностью и кратной передискетизацией унутре, поэтому эта модель не работает в реалтайм, она используется один раз при вычислении IR.

S>Как-то это сложно. Непонятно, зачем вообще вся эта суперпередискретизация

Для эффектов навроде эха/реверберации/фленжеров/фейзеров и прочих эффектов на основе обратной связи с задержкой (особенно с переменной задержкой) почти всегда применяют всякие трюки для повышения кач-ва. Иначе эффект начинает иметь "металлические нотки" в звучании, вот как роботы говорят в старых фильмах — это накопление ошибок округления, которые при обратной связи многократно набегают друг на друга, что порождает гармоники обрабатываемого сигнала, которые, в свою очередь, интерферируют с частотой дискретизации.

Вариантов борьбы с этим хватает. Например, есть еще вариант вместо суровой передискретизации применять интерполяцию на линиях задержки, т.е. допустим мгновенная задержка на некоей линии задержки 0.0678345 сек (от балды), надо вычислить некий отсчёт. Вместо наивного нахождения индекса отсчёта в массиве как округления до целого умноженой частоты дискретизации на вещественное время, целевой отсчёт ищется по некоторому закону как интерполированный сигнал. В простейшем случае делается передискретизация всего лишь вдвое, затем неокруглённый отсчёт ищется через линейную интерполяцию по двум точкам. В более сложном виде пропускают через оператор передаточной ф-ии простейшего ФНЧ во временной области — это операция нахождения определённого интеграла, оно неплохо работает, когда в небольших пределах.

Понятное дело, что для наколенного "показать принцип" оно не требуется, но речь идёт о реальных боевых эффектах, где в последний десяток-другой лет кач-во электронной музыки (.е. электронных эффектов) вышло на весьма высокий уровень. "Наколенности" давно нет даже в бесплатных эффектах (любопытные могут поискать по "VST plugin").

Опять же, принцип "подсчитали в оффлайн сколь-угодно сложный эффект, а в онлайн используем IR" — он резко развязывает руки. Это примерно то же самое, что "память не ресурс", т.е. можно сурово передискретизировать сигнал, делать все вычисления в double64 или даже в double128, зато не париться с накоплением ошибок округления и интерферированием гармоник с частотой дискретизации (это всё будет в конце отфильтровано ФНЧ при обратной передискретизации). Оно позволяет использовать более простые алгоритмы, в т.ч. при передискретизации начинают хорошо работать сугубо численные методы, например, методы численного интегрирования и дифференцирования.
Численные методы просты, но неплохо работают при передискретизации на частоты, которые в несколько десятков раз, а лучше в сотню-другую выше максимально-интересующей обрабатываемой частоты, т.е. будет тебе не 48 кГц, а 4.8 Мгц, соответственно мантисса должна удлиниться примерно на 10 разрядов, плюс берём кол-во операций на один отсчёт, на каждую тысячу операций — опять плюс 10 разрядов мантиссы (для прикидки, простейший фильтр второго порядка — это 5-6 слагаемых многочлена) и т.д. и т.п.


S>если мы всё равно пропускаем через эту модель единичный сигнал, а на выход записываем коэффициенты в "финальной" дискретизации и разрядности.


Этот единичный сигнал будет затухать некоторое время.
Затухание получается на линиях задержки и на обратной связи и т.д. что выше описано.
Да и, сами рекурсивные фильтры являются свеобразной линией задержки.
Иногда для компенсации фазовой задержки вводят отрицательную задержку в сигнал, т.е. как бы входной сигнал берется из "будущего", а управляющее вычисленное воздействие (например, мгновенная амплитуда, управляющая АЧХ фильтра) — применяется к сигналу из "настоящего".

А да, самое главное.
Коэффициенты IR имеют понятный для любого хоббиста физический смысл — это просто отсчёты выходного сигнала.
(т.е., "планка входа" в тему минимальная)

Единичный сигнал пропускают через некую систему, на выходе имеем, грубо, WAV-файл, это и есть IR.
Теперь делаем свёртку входного сигнала с IR и ву-а-ля.

Свертка тоже понятна любому хоббисту — мы проигрываем WAV-файл IR с громкостью текущего отсчёта аудио, на следующем шаге к проигрываемому прибавляем опять этот же WAV файл с громкостью, равной следующему отсчёту и т.д., т.е. как бы в параллель "играет" столько "проигрывателей" WAV-файла IR, какова его длина.


V>>Нелинейщина обычно проще. Это разного рода пороговые ф-ии, типа sqrt, log и т.д. и они часто реализованы через табличную аппроксимацию, т.е. практически бесплатны.

S>Ну, по сравнению с арифметикой даже они гораздо дороже. Как сделать табличную аппроксимацию в SIMD?

Через a*x+b


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

S>В примерах, которые видел я, развёртки SIMD циклов от ICC ~ 2, от GCC — ~4. И это при простейшем коде цикла, где вроде бы и нагрузки на CPU на итерацию мало, и до пределов кэша коду ещё далеко.

В 2 раза развёртки циклов я не видел ни разу в ассемблерном виде в релизе.
От 16 до 128 с шагом в степень двойки видел.


V>>Кеш данных 1-го уровня имеет в точности быстродействие файла регистров (и там и там косвенная адресация из-за ассоциативности, для кеша данных — с данными, для файла регистров — из-за переименований регистров, где внутренний файл регистров в несколько раз больше "публичного" его отображения).

S>Ну... хз. Всё равно юнитов исполнительных в одном ядре не очень много; даже если я разверну цикл 128 раз, никто мне не будет 128 пар сложений одновременно выполнять.

Это не тот разворот, это ты имел ввиду в параллель когда вычисления.
Тут да, особо не разбежишься.

О чём говорил я — циклы разворачивают для экономии на обслуживании переменной цикла и соотв. ветвления.

S>Вот то же предсказание переходов: по идее, проверка выхода за диапазон вообще не должна влиять на массивах размером в 33мегапиксела. Там же ровно всегда один и тот же бранч выбирается.


От алгоритма ж зависит.
Если в алгоритме смещение x +/- 100, то на 100 точках в начале и в конце строки будет выход за границы изображения.

Но это применительно к 2D.
С 1D любопытней — выходов за границы быть не может.
Такая адресация делается на циклической линии задержки, длина которой не может быть меньше макс. амплитуды смещения по индексу, и тогда индекс любого отсчёта при смещении назад находится как (cursor + length — offset) % length. Например, было бы прикольно эту операцию сразу выполнить как "встроенный кирпичик" системы. На пальцах (для линейной аппроксимации) 3.5 отсчёта назад — это x[cursor-3]*0.5+x[cursor-4]*0.5, 4.3 отсчёта назад — это x[cursor-4]*0.7+x[cursor-5]*0.3, где индекс условного cursor-offset вычисляется на циклической линии задержки как показал выше.

(на остальное потом)