Jump to content

    

запрягаем хлопцы кони...

2_kan35

в конкретно моем случае библиотка в контексте матричных вычислений не подходит:

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

2. ST либа имеет ограниченный набор функционала с матрицами

3. ST либа предлагает матрицы произвольной размерности, при малых размерностях будут потери на циклах и тд, прэтому 3x3 расписанные по компонентно быстрее будут работать.

4. Интерес представляет в ST либе табличные синусы и косинусы но их еще на соответствие стандарту нада проверить.

если мне потребуется матрицы большого размера то я опять же возьму шаблоны и также буду в операторном виде писать код. если по ТЗ код должен быть на С написан (глупости манагеров) то тогда ST либа может стать хорошим подспорьем. но в любом случае вещи то примитивные и скорее всего для конкретной задачи руками написаный функционал будет быстрее и короче.

все вышенаписанное не относится к функциям с фиксированной запятой и SIMD- поскольку для них компиллер не может автоматом ничего генерить о тут однозначно использовать либу от ST либо смотреть на нее и делать лучне и быстрее.

 

2_Xenia

>Скажите пожалуйста....

разумеется все сделано на классах, больше никак.

> Этот мой вопрос продиктован беспокойством по поводу "лишних" операций...

Ваше беспокойство совершенно понятно, еслибы Вы не беспокоилить бы такими вопросами то наверно не быть вам эмбеддером...

посуществу - да действительно, для перемножения матрицы на матрицу с присвоением ( A*=B ) нужен временный объект чтоб хранить промежуточные суммы и не портить элементы матрицы, с другой стороны не хочется создавать временный обхект и возюкатся с лишними копированиями . C++ в таких случаях задача решается передачей не по укателю или экземпляру объекта а по ссылке что снимает проблему копирования при передачи в функцию. если функция инлайн типа вообще нет никаой передачи параметров. Про аллокацию, все временые объекты создаются на стеке статически, это означает что размещение объекта это всеволишь суммирование указателя стека с числом равным размер объекта и вызов конструктора, а один конструктор мы оставляем пустым - он формально должен быть вызван по стандарту С++ но так как он пустой то и вызывать фактичеси ничего не надо что компиллер и делат! это подходящий случай какраз временых объектов.

таким образом no priblem. приходя к размышлениям о подобных вещах нада учитывать два факта - современный компиллер зело хитрожопый суслик, а если вы начнете ковырятся в оптимизаторах дерева кода промежуточного предствленя кода RTL то и восе поймете что в 99 процентах вас обманет и выдас код лучше (правдо это зависит от таргет платформы). второй факт - 99 процентов програмистов С++ не умеют им пользоватся. к сожалению для эффективного использования нада глубоко изучать рализацию заложенных методик а не то как писать классы и тд - а с этим проблема, мало кто этим занимается. например вопрос - где GCC кладет таблицу виртуальных функций? какова реализация вызова виртуальных методов. знание подобных вещей позволят безнаказанно юзать вещи на микроконтроллера с объемом ОЗУ несколько килобайт и плевать с большой башни на многочисленные стада верующих во сякие мифы про С++. чуваки делающие стандарт для С++ не такие тупые и очень отчетливо понимают что код возможно прийдется компилять для чайника или градусника.

довольно болтавни, давайте сравним код умножения матицы на вектор 3x3:

код:

asm  volatile( "mov r5,r5" );
asm  volatile( "mov r5,r5" );
x = A*x;
asm  volatile( "mov r5,r5" );
asm  volatile( "mov r5,r5" );

asm:

08000e18:   mov r5, r5
08000e1a:   mov r5, r5
08000e1c:   vmul.f32 s14, s3, s19
08000e20:   vmov.f32 s16, s4
08000e24:   vmov.f32 s18, s3
08000e28:   vfnms.f32 s16, s3, s23
08000e2c:   vfma.f32 s18, s4, s21
08000e30:   vfma.f32 s14, s4, s20
08000e34:   vfma.f32 s16, s17, s22
08000e38:   vfma.f32 s18, s17, s19
08000e3c:   vsub.f32 s17, s14, s17
08000e40:   mov r5, r5
08000e42:   mov r5, r5

прикол в том что в данном случае даже на стеке ничего не размещается - хватает регистров FPU...

затычки из asm volatile( "mov r5,r5" ); нужны для того чтоб компиллер не смержил целочисленные инструкци спеерди и сзади идущие с собственно нас инрересуймыми. видимо компиллер чтото такое знает о кортексе чего я незнаю и пытается перемежать по возможности инструкции так чтоб шины и модули ЦПУ работали с пинимальными задержками. пибороми я не фексировал но возможно эта гипоза имеет основание быть.

 

зы. к компиллеру нада относится также как и к железу - как матчасти! а что клачики говорили - учи матчасть.

 

 

Share this post


Link to post
Share on other sites

Все вектора и матрицы передаются в функции указателями, так что не соглашусь по поводу запихивания многих параметров в стек. Я согласен на 100% в том, что заточенное под задачу наверняка оптимальнее универсального.

И нужно поставить точки над i - все эти функции написаны программистами ARM как собственно вся CMSIS библиотека (а то вы постоянно упоминаете ST - это не корректно). Что касается SIMD, то если посмотрите - они все реализованы как интринсики, и оптимизировать в них по сути нечего - остается только применять.

Share this post


Link to post
Share on other sites
Что касается SIMD, то если посмотрите - они все реализованы как интринсики, и оптимизировать в них по сути нечего - остается только применять.

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

 

предлагаю не уходить от темы - какие библиотеки и тд лучше ли хуже, вопрос который я пытаюсь тут поднять - какой хороший FPU когда он есть в наличии. библиотеки или их отсутствие пусть быдерет каждый сам, а вот с выбором использовать програмную плавучку(естественно случай с float) или FPU я думаю голосовать не прийдется :)

 

складывается впечатление что разделить радость от наличия FPU и его применения мне нескем, так сказать позитиф неочивиден.... но я всеравно рад!

 

 

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

Share this post


Link to post
Share on other sites
складывается впечатление что разделить радость от наличия FPU и его применения мне нескем, так сказать позитиф неочивиден.... но я всеравно рад!

Почему же. Вон, видео с дискретным косинус-преобразованием как попускает! Ето уже не жлобский фиксед поинт.

Share this post


Link to post
Share on other sites
по ходу дела буду делать решалку систем нелинейных уравненй, оно же нелинейный оптимизатор. ктонить использует сложные модели управляймой системы чтоб такое требовалось?

вот например (GMCD) в реальном времени

http://www.referun.com/n/algoritm-vyyavlen...schih-agregatov

Share this post


Link to post
Share on other sites
ну всетаки как интринсики! тоесть нада вызывать функции. я пытаюсь сказать что когда мы флотовые операции делаем мы операторы используем а не функции из библиотеки вызываем.

 

предлагаю не уходить от темы - какие библиотеки и тд лучше ли хуже, вопрос который я пытаюсь тут поднять - какой хороший FPU когда он есть в наличии. библиотеки или их отсутствие пусть быдерет каждый сам, а вот с выбором использовать програмную плавучку(естественно случай с float) или FPU я думаю голосовать не прийдется :)

 

складывается впечатление что разделить радость от наличия FPU и его применения мне нескем, так сказать позитиф неочивиден.... но я всеравно рад!

 

 

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

Hy интринсики по сути есть ассемблерные вставки как я считаю, может быть я и не прав, но в таком случае смысла в них нет.

По поводу радости от наличия FPU я могу с вами вместе ее разделить конечно, но все же если трезво рассуждать, то вряд ли он будет использоваться даже в каждом 10 проекте на STM32F4. Я считаю все эти FPU не более чем маркетингом, так как всем, кому он интересен как правило все равно не хватает мощности CortexM4F, а тем кому он нужен мало - и программным обойдутся в случае чего. Извините за отступление от вашей темы.

Share this post


Link to post
Share on other sites
Я считаю все эти FPU не более чем маркетингом, так как всем, кому он интересен как правило все равно не хватает мощности CortexM4F, а тем кому он нужен мало - и программным обойдутся в случае чего.

Мысля таким образом, "маркетингом" можно считать и умножение с делением - зачем они в железе, если и софтовой реализацией обойтись можно... :)

 

Share this post


Link to post
Share on other sites
Я считаю все эти FPU не более чем маркетингом, так как всем, кому он интересен как правило все равно не хватает мощности CortexM4F, а тем кому он нужен мало - и программным обойдутся в случае чего. Извините за отступление от вашей темы.

Может быть и можно было бы согласится, но есть ещё вопрос цены. Простой запрос на efind даёт цену для 207 от 216 рублей и в среднем 260, а на 407 от 221 и в среднем 320 рублей. И это не сравнивая данные по объёмам флэши, ногам и прочее.

Учитывая, что как правило, серийность изделий разрабатываемых на просторах бывшего союза далека от массовости, а также, учитывая, что стоимость законченного изделия, как правило, не определятся стоимостью МК и комплектующих в частности, то вполне допустимо потратить лишних 2$ на такую фичу как FPU + доп флэш + 10-15% скорости. Особенно учитывая тенденции ...

 

Приведу пример из другой немного области, но сопоставимый. Разрабатывал девайс. Нужен был UART+DAC+ADC+мало ног. Поставил atmega88, цап сделал шимом, цифровой фильтр на целых числах долго просчитывал на разных моделях, несколько раз пересчитывал - добился приемлемого качества работы. Выпускается. Сейчас смотрю на stm32f100 - как хорошо на эту задачу ложится. ЦАП есть - не надо мутить, оперировать можно 32 битами, фильтр получится красивее, АЦП 12 бит. Думаю в целом устройство будет работать значительно устойчивее. Можно и частоту семплирования поднять. Несмотря на то, что качество АЦП у меги не лучшее, тем не менее при оцифровке 10 битами девайс работает устойчивее при помехах. Поэтому можно предположить, что перевод изделия на stm даст существенный выигрыш в качестве. Ну и цена практически одинаковая ... Конечно, сейчас уже перерабатывать не станут - всех всё устраивает, денег на это выделятся не будет, но всё же ...

Share this post


Link to post
Share on other sites

Столкнулся с трудностью.

Как разделить юзание FPU в прерывании и основном потоке с минимальным свопингом. По идее, надо плавучие регистры явно разделять. Что, снова ассемблер?

Share this post


Link to post
Share on other sites
Это уж точно их маркетинговый ход :)

Почему? Имхо, очень неплохо придумано. Для осей так вообще очень удобно.

Я пытаюсь понять, можно ли как-то вмешаться в GCC FPU register sheduling?

Сильно сомневаюсь. Может быть проще отказаться от плавучки в прерываниях, и пользовать её только в одном процессе? Тогда ничего не надо сохранять, сохраняется только контекст M3. Я так пробовал - отлично работает.

Share this post


Link to post
Share on other sites
Сильно сомневаюсь. Может быть проще отказаться от плавучки в прерываниях, и пользовать её только в одном процессе? Тогда ничего не надо сохранять, сохраняется только контекст M3. Я так пробовал - отлично работает.

Понятно, что в прерываниях ничего особо делать низзя. Но надо...

Было бы неплохо

register volatile float resw asm("S0");

Share this post


Link to post
Share on other sites

Разочарование сплошное. Проблема давно изящно решена, например, в i80386-ом - при переключении контекста меняется содержимое только РОН-ов, FPU не трогается и взводится специальный флажок. Если в новом контексте начинает использоваться FPU и этот спецфлажок установлен, то генерируется исключение, обработчик которого выполнит отложенную смену контекста FPU - сохранит старый и загрузит новый. А тут - при переключении контекста задачи RTOS старшие регистры s16-s31 нужно сохранить ручками в любом случае, даже если задача последний раз пользовалась FPU полчаса назад и может больше и не собирается дальше пользоваться. И новый контекст не грузится автоматически при попытке использования - значит изволь для новой задачи его также ручками загрузить.

Флажки-то в Cortex-M4F есть, но аппаратный способ смены контекста FPU "не доделан", а программного "по требованию", я так понял нету. ИМХО, на сегодняшний день такое решение для смены контекста FPU немного диковато, и не видится способа как эту "Lazy stacking feature" красиво встроить в переключатель контекста в RTOS. Или чего-то не так понял?

Upd: ну слегка корявый способ нашелся - при переключении контекста запрещать использование FPU через биты 11/10 в CPACR. Тогда при попытке использования FPU в новом контексте вылезет исключение UsageFault и можно будет ситуацию разрулить. Но при этом использование "Lazy stacking feature" все равно сомнительно.

Share this post


Link to post
Share on other sites

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

У меня в программе на STM32F405 в одном из прерываний используется float.

Флажек "Use FPU" разумеется стоит, без него (специально пробовал) все считается раз в 5 медленее.

Програма без ОС, в основной программе тоже кое-где есть float, хотя и довольно редко.

Нужно ли предпринимать какие-то шаги, для сохранения контекста FPU в прерываниях, или Keil с этим самостоятельно разберется и можно не переживать?

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this