Жораев Тимур Юлдашевич @TimurZhoraev
Доцент института МПСУ им. Л. Н. Преснухина
Information
- Rating
- 1,108-th
- Location
- Москва, Москва и Московская обл., Россия
- Date of birth
- Registered
- Activity
Specialization
Hardware Engineer, Research Scientist
Senior
From 300,000 ₽
Applied math
Software development
Code Optimization
C
Assembler
Python
Algorithms and data structures
Object-oriented design
Multiple thread
Verilog HDL
Просто воспоминания, что не менее увлекательный был процесс перебора от 0 до N ради поиска чего-то необычного кроме рэзета и сессии ТР-ДОСа, особенно если был музыкальный сопроцессор, те самые AY в довесок. А с PEEK/POKE можно было составить свою первую прогу на асме в машинных кодах, записать её на ленту. Плюс различные фишки связанные с бордером. Не только стандартные цвета загрузчика M/C/B/Y но и кастомные. Плюс различные утилиты для быстрой загрузки когда высокий битрейт превращал звук в шипение. Не говоря уже про эксперименты с circle/draw, когда круги рисовались заливкой треугольниками в динамике, как целая игра.
Да, это отдельная история из разряда ++ *, особенно если имеются флажки насыщения в процессорах ЦОС (причём переключаемые динамически в любой момент) вместо переполнения и прочие UB. Это скорее компромисс между комитетом ISO/ANSI, имеющимся исторически сложившимся железом и пожеланиями пользователей. В этом случае используются только математические конструкции или алгоритмическое ветвление без UB, в остальном - только intrinsics и прочие штуки вне стандарта. Хотя бывает и так что char = 16 бит на C[5,2]000 DSP-шках. Плюс арифметический-двоичный сдвиг влево-вправо с учётом и без учёта знака и системы (дополнительный, прямой) особенно там где совсем простое железо. Вообщем лучшие гарантии даёт именно стандарт где математика явно прописана и все ограничения с ней связанные 127+1=-128
PS. Кстати стандарт языка это очень сильная позиция, которая, скорее всего превалирует перед включением Rust в ядро Linux например и другими не стандартизированными вроде Python/Perl/Java/JS и др.
Скорее всего речь уже идёт не строгих языках а фактически тех которые имеют характер описания и разметки. Вообщем эра текстовых редакторов уровня перевод строки и возврат каретки 0D0A ◙♪ с виртуальной машиной, определяемой первой двадцаткой управляющих символов ASCII уходит в прошлое, и то, что мы видим на экране есть результат отображения уже обработанного абстрактного синтаксического дерева. В этом случае ИИ тренируется уже не на слова/мнемоники а на представление алгоритма, данных в виде соответствующего дерева. Любой компилятор неявно содержит в себе модель вычислителя как на HDL-языке с разметкой количества тактов, целостности кэша, работы с аппаратурой.
Не мене увлекательная игра была с randomize usr 0 или randomize usr 15616. Кстати тот самый редактор Бэйсика FOR a=1 to � с мигающим вопросиком это фактически то что так не хватает современным IDE.
Да, также можно дополнить обработкой факторизацией и схемой Горнера общей формулы самого фильтра как суммы взвешенных отсчётов, в этом случае оптимизация может проводится уже в пространстве состояний по отсчётам (z⁻¹), например, сохраняя промежуточные значения в регистрах/памяти и далее уже применяя арифметические сдвиги в нужных местах. Ещё вдобавок решив проблему динамического диапазона и нормировки по ходу вычислений, что-то вроде (x₋₁+x₋₂)/2 = (2x₋₁+x₋₂)/2-x₋₁/2, чтобы не потерять разряды, особенно для полосовых фильтров и прочих высокодобротных штуковин.
Да действительно там есть инструкция MUL которая позволяет делать 16*16=16 за 9 тактов плюс ret и 16*16=32 за 17 тактов. Тут же говорится о том чтобы вообще не использовать данную инструкцию, например на каком-нибудь Attiny где умножение занимает сотни библиотечных тактов ну или знаменитый Z80. Интерес в том числе представляет в принципе подобного рода оптимизация на основе фиксированных значений коэффициентов, включая, например, возможную реализацию "гладкой" функции активации для нейрона с оптимальной для градиентного метода (производная есть сама функция) формой что-то вроде 1/(1+2^-x) - логистическая, с 2 вместо экспоненты, тогда алгоритм будет заключаться в сдвиге на заданное количество разрядов согласно старшей единице в операнде.
В данном случае речь идёт о расчёте коэффициентов фильтра, равным степени двойки, при которых он заведомо будет упрощён по количеству операций. Конечно же если компилятор достаточно "умный", то в коде выше можно вместо >>1 написать /2 или возможно даже int(a*0.5) и он оптимизирует, но лучше не рисковать и указать явную операцию << или >>, она практически выглядит как intrinsic-инструкция в коде, в этом случае язык С выглядит как "аппаратно-независимый ассемблер". Плюс в указанном методе без изменения структуры фильтра можно дискретным образом изменять полосу пропускания. Хотя, это если имеется инструкция ASR/ASL на заданное количество бит (Barrel shifter), в архитектуре AVR, например, сдвиг происходит только на один бит без параметра. CIC фильтр также требует большой динамический диапазон для вычислений вида ∞-∞ из-за наличия каскада интеграторов, в предлагаемом варианте этот диапазон ограничен лишь старшим разрядом.
Вообще говоря выглядит как хороший полуфабрикат для генерации чего бы то ни было с использованием некоего PerlScript-а, который штампует заголовочники с #embed. Потенциально настроечно-конфигурационные макросы и CMAKE будут хорошенько пересмотрены. На очереди встроенный Bison-Flex и Regexp как вишенка.
Ну тогда получается 2 вида квантования - по времени (что скорее образно и не вполне корректно) и по уровню, когда сигнал принимает значение соответствующее разрядной сетки (не обязательно линейной с шагом 2^-N, например для float с мантиссой и экспонентой она нелинейная, зато большой динамический диапазон).
Примерно тоже самое, но только с фиксированной частотной характеристикой без параметра + использование временных переменных состояния. Скорее всего это тоже самое, для 2-го порядка. В этом случае используется 3 точки, например на 0й частоте, Найквиста и какая-либо выделенная частота, при которой коэффициенты кратны степени двойки. Например, мнимая часть в этой точке равна нулю (полосовой) или обе одновременно (режекторный). Как раз там возникают те самые "рысканья", для первого порядка - статическая ошибка как сказано в статье. Однако, можно последовательно соединить ФНЧ и ФВЧ чтобы получить полосовой в некоторой мере, и тут уже возможны варианты. Ну а далее схема Горнера и прочие алгебраические преобразования чтобы вынести необходимые степени двойки за скобки и использовать переменные состояния.
Есть ещё более "хитрые" способы, заключающиеся в применении метода Ньютона-Рафсона, у того же Техаса, который для C2000 с фиксированной запятой реализует деление с уточнением по таблице, вычисление синусов-косинусов по таблице с интерполяцией рядом Тейлора в окрестности заданной табличной точки (описание вроде в sprc993), ну и конечно же CORDIC. Логарифмический масштаб скорее для количественного описания, здесь же отображение качественных характеристик, не имеющих промежуточных значений, да и на частоте Найквиста значение точно равняется нулю, там логарифм убегает в -∞.
Согласен, возможен вариант частота выборки, частота следования отсчётов, частота семплирования. Частота квантования скорее образно, исходя из рисунка.
Хотя бывает так что MUL на некоторых архитектурах, особенно на DSP считается даже быстрее, за такт, чем побитовые операции ASR-ASL, особенно если операнды потоком выбираются из памяти с автоматическим пост-инкрементом указателя. Другое дело мелкие микроконтроллеры и ПЛИС, где аппаратный умножитель - это целый блок по уровню интеграции не уступающий регистровому файлу и логике, и там где его нет конечно же будет существенный выигрыш, тем более что контроллеры наоборот, более заточены на двоичку чем на сигналку.
Стиль результатов промтов и ПРОМТ в публикации мелькает согласен я. Вот бы ещё какой-нибудь редактор который позволяет быстро подписывать рисунки с привязкой "прилипанием" к графику в растре, или векторный удобный редактор, наподобие S-Plan, желательно под Linux и опенсорс.
Этот нуль необходим для создания большой постоянной времени, например, для устранения постоянной составляющей. Данный метод имеет дискретный набор АЧХ/ФЧХ характерных для заданной степени двойки. Можно также рассчитать значение частоты среза по уровню, но там появятся арксинусы-косинусы из-за дискретной ПФ. Точное значение можно получить из скрипта выше в Maxima, путём FcabA^2;solve(%=L^2,f); после соответствующего выражения. Также, это не только ФНЧ но и ФВЧ (0 на f=0 и 1 на частоте Найквиста), режекторный/полосовой и более высокого порядка с эффективным вычислением на основе предложенного метода.