Pull to refresh

Comments 27

Собственно, тема-то осталась не раскрыта: вы прекрасно объяснили работу алгоритма, но не объяснили, чем он для вас так важен :)

Сам алгоритм мы могли наблюдать в компьютерах 70-80-х, микрокалькуляторах, в libcordic в Linux, факт. (интересно, как работали FPU типа 80287, 80387)

CORDIC - это последний шанс. Т.е. если у нас нет мат. сопроцессора, чтобы вызвать готовые тригонометрические функции, если нет памяти, чтобы держать таблицу значений или нам нужен синус или тангенс на полном периоде а не только на углах меньше 20, где их можно аппроксимировать линейной функцией. Вот тогда уже да, CORDIC вытаскивают из запылившегося ящика.

Ну не то, чтобы вытаскивают. Если надо крохотного размера, быстро и дешёво вычислять (например, векторное управление BLDC с частотой сотни кГц), можно взять микроконтроллер с аппаратным CORDIC. ( https://brushless.zone/stm32g4-cordic-vs-sinf-for-motor-control/ ). Хотя в нем и на таблицы памяти хватает и FPU есть, но это, всё равно, дольше.

Одно плохо - stm32g431 сложно в РФ купить за адекватные деньги

Аппаратный будет быстрее выборки по таблице? Не знаю как реализован на stm CORDIC, но в целом скорость вычисления зависит от разрядности, т.е. если мы хотим получить 16-битное значение, то должны ждать 16 тактов.

Я проверял скорость вычисления синуса на STM32G474. Там в регистр аргумента записывается угол, после чего в регистре состояния нужно ждать появления бита готовности. Я в цикле ожидания инкрементировал переменную чтобы узнать да сколько циклов вычислится синус. Так вот, количество циклов равно нулю! То есть бит готовности появляется практически сразу.

Тут такое.... В STM32G474 база Cortex-M4F, - соответственно в списке инструкций FPU синуса нет.... Совсем нет. Убеждаемся.

Что вы там намерили - ну, по крайней мере непонятно.

А в модуле Cordic - все-таки 29 циклов. Проверять - на ассемблере.

Конечно нет, так же как нет регистра состояния и бита готовности. Я писал про модуль CORDIC, который есть в этом микроконтроллере. И про его быстродействие. И проверять это можно на чём угодно.

И проверять это можно на чём угодно.

Ну, дело хозяйское. Странно конечно, что у вас как-то сильно быстрее работает, чем указано в описании модуля, - но может у вас такой специфичный контроллер или еще что-то влияет....

Таймером проверяется а не переменной.

С практической точки зрения важно лишь через какое время после записи угла будет готов результат.

Собственно я именно об этом. 170 нс.

Без цифр cycnt из dwt я бы тоже не поверил. Учитывая какую дичь иногда выдают компиляторы

Смотря как у вас подключена память. Если есть мегабайт встроенной – хорошо, если снаружи болтается и обращение занимает от 3 тактов, высчитать может быть быстрее

Выборка по таблице - это несколько операций сравнения (хоть и двоичным поиском) для поиска соседей, а потом ещё несколько float-операций для интерполяции.

Помню неск лет назад в одном проекте драйвера BLDC на stm32f4xx использовали как раз табличный метод, коллеги оценивали гарантированную частоту обработки в 32 кГц

На STM32x4 есть есть FPU, и фиксированная запятая работает в итоге медленнее, чем плавающая. Ну и памяти там валом, чтобы хранить таблицы, а потом (если вдруг надо очень точно) интерполировать между соседними точками...

Ну тут такая ситуация. Там где используется STM32 обычно хватает просто таблицы и CORDIC просто не нужен. Но там где он нужен, уже STM32 не вывозит. Это какой-нибудь широкий FFT, который скорее всего будет имплементирован на FPGA и в такой ситуации просто не будет столько памяти хранить комплексные коэффициенты. Тут уже надо считать коэффициенты на лету.

Ну, все-же sinf() работает несколько подольше 29 циклов.....

По поиску в большой таблице, которая находится у Бога на куличках (8 к значений во внешнем ОЗУ/ПЗУ) - думаю, что тоже будет дольше 29 циклов (честно признаюсь - не проверял....). Так-что вариант фактически безальтернативный по скорости для данного контроллера (ну, если устраивает "приблизительность" и фиксточка).

FPU-то там есть, но синуса нет. А библиотечная функция в итоге работает медленнее, чем CORDIC. И, как было справедливо замечено, float - это костыль, который программисты используют когда до конца не понимают алгоритм. Ведь результат вычисления синуса нужен в конечном итоге для записи в таймер очередного значения ШИМ, или для регистров другой периферии, но в любом случае это будет целое. Тогда зачем нужны лишние преобразования?

Костыль, но тянуть 64-и-более-разрядные вычисления из-за большого динамического диапазона (например в модемах) - дорогое удовольствие. И постоянно следить, чтобы разрядности хватало... На FPGA - понятное дело, а на MCU более 32 разрядов жутко медленно, float работает за 1 такт. Если тригонометрия табличная, то взять значение - тоже единицы тактов

Напрасно Вы так про "запылившийся ящик". Применение CORDIC не ограничено вычислениями элементарных функций. Напомню, что Волдер/Меджитт называли этот метод методом псевдоповоротов вектора. Например, сейчас этот метод широко используется в ФАР для фазирования и весовой суммирования, причём он удобен для построения конвейерного процессора формирования ДН. А "вектор" может быть не обязательно двумерный. Вся быстрая матричная арифметика, связанная с преобразование базовой системы координат делается на этом алгоритме, список просто бесконечно - там просто не паханое поле... А Вы про "ящик". Я думаю, что Вы пересмотрит Ваше отношение.

В самом начале же написано:

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

Важным свойством этого алгоритма является то, что за 1 итерацию получается 1 точная двоичная цифра результата, что дает возможность построения 1-разрядных вычислительных структурах = сравнение-сдвиг

А что там с аппроксимацией полиномом? Если привести значение угла в диапазон от -pi/2 до pi/2, то можно использовать полином не очень большой степени. Или он будет всё же медленнее вышеописанного способа?

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

Тут важно то, что CORDIC очень хорошо ложится на FPGA, которая, по своей сути, является схемой, а не процессором. И в таком применении альтернатив у него практически нет. Поставить память, в которой держать значения, например, для 256 углов? А если нужно большее разрешение/точность? Пристроить к памяти автомат, который делает интерполяцию?

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

Sign up to leave a comment.