MPC-BE forum

MPC-BE => Обсуждение / Discussion => Тема начата: Aleksoid1978 от 15 октября 2016, 05:35:33

Название: Аудио-конвертер - оптимизация.
Отправлено: Aleksoid1978 от 15 октября 2016, 05:35:33
Вот решил заняться данным вопросом и попробовать для конвертации использовать SSE инструкции.
Пока реализовал самое необходимое(как по мне) преобразование - float to 32bit integer. Почему именно с этого начал и решили что самое необходимое - да потому что для большинства аудио-форматов ffmpeg(Lossy - с потерями) выдает во float. Встроенный WASAPI вывод в режиме Exclusive для этого случая будет переводить в 32 bit integer.
Вот тестовый билд - https://yadi.sk/d/qVohJjYswsgci

Что нужно - погонять на различных источниках - музыка/фильмы, особенно с высокой громкостью - и сравнить качество звучания, отсутствие дефектов/щелчков, в сравнении с SVN версией.

Чтобы использовался встроенный механизм конвертации типов - надо чтобы входные/выходные данные отличались только форматом, вот примерно как на скрине:
(http://s019.radikal.ru/i601/1610/1c/45058158c6d0.png)

P.S. Если что - то 24bit [padded] - это тоже 32bit Integer.

По скорости - сравнивать время обработки одного сэмпла конечно же нет смысла. Я для тестов это делал 10000(чтобы можно было ощутить разницу) - sse оптимизированная функция примерно в 15-17 раз быстрее. Тут даже дело не в самой скорости - а в уменьшении использовании процессорного времени, чтобы должно положительно сказываться на работе аудио-рендерера.

Для заинтересованных лиц патч - https://yadi.sk/d/IIufo59lwp7F9
[merge_posts_bbcode]Добавлено: 2016-10-15 12:35:33[/merge_posts_bbcode]

Обновил ссылку на тестовый билд - добавил 32 bit Integer to float, ну и ссылку на патч.
Обновил ссылку на тестовый билд - добавил float to 16bit Integer, ну и ссылку на патч.
Обновил ссылку на тестовый билд - добавил 16 bit Integer to float, ну и ссылку на патч.

Думаю на этом хватит. Хотя можно еще будет добавить float to 24 bit integer(у меня такой режим поддерживает Creative X-Fi, для Shared режима.) Но этот режим практически не используется - поэтому можно пока отложить.
Название: Аудио-конвертер - оптимизация.
Отправлено: V0lt от 15 октября 2016, 07:28:49
Немного о том, как работает наш конвертер int<->float и почему он вообще такой.

Рассмотрим случай int16->float и float->int16

Исходные данные.
Для int16 имеем диапазон -32768..+32767.
Для float имеем диапазон -1,0..+1,0.
Нули для int16 и float совпадают.

Видим, что максимальное значение по модулю 32768

Текущий алгоритм (без доп. округления)
value_float = (float)value_int16 / 32768; // -1,0..+0,999969
value_int16 = (value_float <= -1,0) ? -32768
            : (value_float >= 0,999969) ? 32767
            : value_float * 32768;
Это очень строгий алгоритм и  в принципе его можно слегка видоизменить, если взять за максимум 32767.

Модифицированный алгоритм (без доп. округления)
value_float = (float)value_int16 / 32767; // -1,000031..+1,0
value_int16 = (value_float < -1,0) ? -32768
            : (value_float >= 1,0) ? 32767
            : value_float * 32767;
Я ждал от него мизерный прирост скорости, но получил даже некоторое замедление.

Алгоритм int32->double->int32 получает аналогично. Корректность проверяется просто - выход равен входу.
Название: Аудио-конвертер - оптимизация.
Отправлено: Aleksoid1978 от 15 октября 2016, 08:12:26
Проверил свой алгоритм float -> int32 -> float - выход равен входу. Не проверял int32 -> float -> int32, на уверен что результат будет аналогичный.
[merge_posts_bbcode]Добавлено: 2016-10-15 15:12:26[/merge_posts_bbcode]

В ближайшее время  сделаю для преобразования int16 <-> float.
Название: Аудио-конвертер - оптимизация.
Отправлено: V0lt от 15 октября 2016, 10:29:32
Цитата: Aleksoid1978Не проверял int32 -> float -> int32, на уверен что результат будет аналогичный.
Увы, но не будет.
Название: Аудио-конвертер - оптимизация.
Отправлено: Aleksoid1978 от 15 октября 2016, 12:57:14
По поводу float -> int16 - прирост по скорости вообще от 25 до 30 раз(сравнивал на 10000 операциях).
Название: Аудио-конвертер - оптимизация.
Отправлено: V0lt от 15 октября 2016, 14:28:19
Заливай патч на 16-бит, погоняю.

Только мне непонятно про 10000. У меня обычный алгоритм на 65536 преобразований туда и обратно выполняется за 0 мс. Приходилось еще один цикл поверх накладывать, чтобы цифры появились.
Название: Аудио-конвертер - оптимизация.
Отправлено: Aleksoid1978 от 16 октября 2016, 08:48:23
10000 - преобразований одного пакета, а не одного элемента данных :)
И тут прирост именно при обработке пакета данных а не одного элемента. Для float <-> int32 за одни раз обрабатывается 4 элемента. А для float <-> int16 - сразу 8 элементов.

P.S. Обновил билд и патч, окончательно - теперь работают все заявленные преобразования.
[merge_posts_bbcode]Добавлено: 2016-10-16 14:46:47[/merge_posts_bbcode]

Так, если никто не хочет или не может проверить - то я в ближайшее время заливаю в SVN. Лично проверил все случаи - все корректно работает.

[merge_posts_bbcode]Добавлено: 2016-10-16 15:48:23[/merge_posts_bbcode]

Единственная просьба - у кого есть старое железо, с CPU без SSE2 - проверить работу.
Название: Аудио-конвертер - оптимизация.
Отправлено: V0lt от 16 октября 2016, 10:19:48
Плохо чего-то оптимизация работает.

Оригинал
convert int16 to float
completed in 187 ms.

convert int16 to float
completed in 2153 ms.

checking
The test is successful.

С оптимизацией.
convert int16 to float SSE
completed in 1358 ms.

convert int16 to float SSE
completed in 1466 ms.

checking
WARNING: -7210 != 32767
Verification failed!

Нет заявленного быстрее в N раз, да еще и ошибки странные делает.
Название: Аудио-конвертер - оптимизация.
Отправлено: Aleksoid1978 от 16 октября 2016, 10:53:51
Что и как ты тестировал ?? Опиши. Ну и по поводу проверки(где у тебя WARNING выдает) ??

P.S. Я надеюсь ты проверял не просто на преобразовании одного элемента ??
Название: Аудио-конвертер - оптимизация.
Отправлено: V0lt от 16 октября 2016, 11:10:29
Убрал возможность оптимизации цикла компилятором.
Оригинал.
convert int16 to float
completed in 4010 ms.

convert int16 to float
completed in 13197 ms.

checking
The test is successful.
Оригинал без доп. округления
convert int16 to float
completed in 3994 ms.

convert int16 to float
completed in 9875 ms.

checking
The test is successful.
SSE
convert int16 to float SSE
completed in 1388 ms.

convert int16 to float SSE
completed in 1482 ms.

checking
The test is successful.
Ошибка ушла (походу был баг компилятора при оптимизациях SSE на циклах с константной длиной). Получил ускорение примерно x3 и x6.
Название: Аудио-конвертер - оптимизация.
Отправлено: V0lt от 16 октября 2016, 11:31:45
Цитата: Aleksoid1978Что и как ты тестировал ?? Опиши.
float содержит 24 бита для числа и 8 бит для степени. Соотвественно в него без проблем должно поместиться 16-битное целое и при правильном подходе ничего не потеряется.

Для проверки генерирую массив из 65536 элементов со значениями от -32768 до 32767. И такой же массив для float и еще одного int16.
Далее произвожу преобразования массивов int16->float->int16 в количестве 100000, ибо точность GetTickCount() оставляет желать лучшего.
Затем сравниваю 1 и 3 массивы, они должны полностью совпадать.
[merge_posts_bbcode]Добавлено: 2016-10-16 11:31:45[/merge_posts_bbcode]

Для int32->float->int32 такой подход конечно не прокатит. Но в целом качественно сравнить два метода по старшим битам можно.
Название: Аудио-конвертер - оптимизация.
Отправлено: Aleksoid1978 от 16 октября 2016, 11:36:48
1 - я для сравнения пользовался не GetTickCount(), а нашу функцию GetPerfCounter() / 10000.
2 - я сравнивал(на скорость) не искусственно созданный массив из 65536 - а пакет идущий от декодера. И вот его прогонял 10000 раз.
Название: Аудио-конвертер - оптимизация.
Отправлено: V0lt от 16 октября 2016, 11:43:23
1. Не принципиально.
2. При правильно поставленном тесте искусственно созданный массив ничем не отличается от пакета идущий от декодера. Там и там кусок памяти. Только вот в массиве можно проверить все интересные значения, а пакете с этим сложнее.
Название: Аудио-конвертер - оптимизация.
Отправлено: Aleksoid1978 от 16 октября 2016, 12:41:13
Ну вот у меня выходила разница для float to int16 - 25-30 раз прирост. Обратно не проверял.

То что float -> int16 быстрее чем int16 -> float - это понятно, для перевода int16 -> float с помощью simd надо сперва 8x16 перевести в 2 по 4x32, потом уже во float.

P.S. Проверил int16 -> float, на 8192 элементах. 100000 прогонов.
Без sse - 1100 - 1150 мс
с sse - 135-140 мс
[merge_posts_bbcode]Добавлено: 2016-10-16 19:17:24[/merge_posts_bbcode]

Ну в любом случае вывод какой - мое нововведение очень даже имеет место быть :)

[merge_posts_bbcode]Добавлено: 2016-10-16 19:41:13[/merge_posts_bbcode]

Проверил преобразование float -> int16 -> float - теряются/меняются только после 5 - 6 знака после запятой. Что в принципе и логично.
Название: Аудио-конвертер - оптимизация.
Отправлено: V0lt от 16 октября 2016, 20:30:34
Проверка float->int16->float имеет мало смысла. Тем более сравнивать знаки после запятой. Знаешь сколько достоверных значащих цифр у float? Будешь удивлен. :)
Надо целые сравнивать.
[merge_posts_bbcode]Добавлено: 2016-10-16 20:30:34[/merge_posts_bbcode]

Мне в патче непонятно следующая строкаstatic const __m128 __32bitMin = _mm_set_ps1((float)INT24_MAX / INT24_PEAK);Опечатка?
Название: Аудио-конвертер - оптимизация.
Отправлено: Aleksoid1978 от 17 октября 2016, 00:13:08
Нет, все верно.
[merge_posts_bbcode]Добавлено: 2016-10-17 07:13:08[/merge_posts_bbcode]

Если взять INT32MAX/INT32PEAK - то для float получим округление к 1.0