|
запрягаем хлопцы кони..., немного результатов по юзанию FPU Cortex-M4F |
|
|
|
Nov 8 2012, 19:51
|

бессмертным стать можно тремя способами
    
Группа: Свой
Сообщений: 1 405
Регистрация: 9-05-06
Из: Москва
Пользователь №: 16 912

|
Здравствуйте коллеги. Итак сбылась мечта идиота - в микроконтроллерах появился FPU. прежде чем его эффективно использовать я решил потестить его и заодно потренироватся писать для него хороший код. была поставлена задача по быстрому нависать либу на C/C++ которая компилялась бы моей сборкой GCC в гожий код, цель - максимальная скорость. таким образом была сделана либа линейной алгебы векторов 3x1 матриц 3x3 и быстрые синусы и косинусы. линейная алгебра реализована на в виде класов чтоб можно былоюы использовать человеческие записис типа Код matrix m; vector vv(1,2,3), v; m.m00=1.2f; v.v0 = 0.3f .... v = !m*vv - v синусы на табличках во флеше. код написан так чтобы компиллер заинлайнил все что только возможно заинлайнить gcc версия 4.8.0 20121106 (experimental) (Klen's GNU package (KGP) for ARM/elf platform) ключи с чем все было собрано -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard -mthumb -Os -fomit-frame-pointer -finline-functions -ffunction-sections -fdata-sections -fgraphite -funroll-loops -flto запускалось на самодельной платке с STM32F405RGT6 мерялось таймером и измерения верифицировались осциллографом. проект состоит из FreeRTOS 7.3.0 запущены 4 задачки - одна тестовая с вычислениями вторая моргание светодиодом для контроля что не улетело в кору, третья - консоль, четвертая фоновая. прикручено TLSF. размеры мяса: section info: sec name size increase[%] .text 100208 0 (0.000000%) .data 40 0 (0.000000%) .bss 99664 0 (0.000000%) utilization: ram : 76.0681% 0 (0.000000%) flash: 9.56039% 0 (0.000000%) из них 86К флеша - это таблица синуса, флеша немеряно девать некуда..... док мы его теряем.. не сцать!! их у нас еще много!!! далее результаты - тип операции, время выполнения на двух частотах системного клока, исходный код на С/С++ и асм - то что вылезло из под компиллера. CODE
//----------------------------------------------------------------- m.inv() 0.500uS(168MHz) 0.336uS(250MHz)
asm volatile ( "mov r5,r5" ) ; rt_counter_start(hrt_count); asm volatile ( "mov r5,r5" ) ; m.inv(); asm volatile ( "mov r5,r5" ) ; rt_counter_stop(hrt_count); asm volatile ( "mov r5,r5" ) ;
080020c2: mov r5, r5 080020c4: mov.w r6, #1073741824 ; 0x40000000 080020c8: bl 0x8001244 <vPortEnterCritical()> 080020cc: ldr r1, [r6, #36] ; 0x24 080020ce: mov r5, r5 080020d0: vnmul.f32 s0, s23, s22 080020d4: vnmul.f32 s1, s23, s18 080020d8: vfma.f32 s0, s24, s17 080020dc: vfma.f32 s1, s16, s17 080020e0: vnmul.f32 s14, s16, s22 080020e4: vnmul.f32 s2, s0, s20 080020e8: vfma.f32 s14, s24, s18 080020ec: vfma.f32 s2, s21, s1 080020f0: vnmul.f32 s3, s19, s18 080020f4: vfma.f32 s2, s19, s14 080020f8: vnmul.f32 s4, s19, s22 080020fc: vdiv.f32 s15, s27, s2 08002100: vnmul.f32 s11, s20, s22 08002104: vfma.f32 s4, s21, s17 08002108: vfma.f32 s11, s21, s18 0800210c: vfma.f32 s3, s20, s17 08002110: vnmul.f32 s18, s19, s16 08002114: vnmul.f32 s22, s19, s24 08002118: vnmul.f32 s17, s20, s24 0800211c: vfma.f32 s18, s20, s23 08002120: vfma.f32 s22, s21, s23 08002124: vfma.f32 s17, s21, s16 08002128: vmul.f32 s19, s18, s15 0800212c: vnmul.f32 s23, s22, s15 08002130: vmul.f32 s21, s1, s15 08002134: vnmul.f32 s20, s3, s15 08002138: vnmul.f32 s24, s0, s15 0800213c: vmul.f32 s16, s4, s15 08002140: vmul.f32 s22, s14, s15 08002144: vnmul.f32 s18, s11, s15 08002148: vmul.f32 s17, s17, s15 0800214c: mov r5, r5 0800214e: ldr r7, [r6, #36] ; 0x24 08002150: ldr r2, [pc, #124] ; (0x80021d0 <TFPUTask::Code()+1676>) 08002152: subs r3, r7, r1 08002154: rsb r6, r8, r3 08002158: str r6, [r2, #0] 0800215a: bl 0x8001220 <vPortExitCritical()> 0800215e: mov r5, r5 //--------------------------------------------------------------------------------------------------------- m.det() 0.119uS(168MHz) 0.080uS(250MHz)
asm volatile ( "mov r5,r5" ) ; rt_counter_start(hrt_count); asm volatile ( "mov r5,r5" ) ; s0 = m.det(); asm volatile ( "mov r5,r5" ) ; rt_counter_stop(hrt_count); asm volatile ( "mov r5,r5" ) ;
0800284c: mov r5, r5 0800284e: bl 0x8001244 <vPortEnterCritical()> 08002852: mov.w r3, #1073741824 ; 0x40000000 08002856: ldr r0, [r3, #36] ; 0x24 08002858: mov r5, r5 0800285a: vneg.f32 s7, s16 0800285e: vmov.f32 s9, s24 08002862: vsub.f32 s1, s7, s23 08002866: vfma.f32 s9, s7, s17 0800286a: vneg.f32 s0, s1 0800286e: vsub.f32 s20, s0, s22 08002872: vfma.f32 s20, s9, s18 08002876: mov r5, r5 08002878: ldr r1, [r3, #36] ; 0x24 0800287a: ldr r4, [pc, #140] ; (0x8002908 <TFPUTask::Code()+1592>) 0800287c: subs r2, r1, r0 0800287e: rsb r5, r8, r2 08002882: str r5, [r4, #0] 08002884: bl 0x8001220 <vPortExitCritical()> 08002888: mov r5, r5 //--------------------------------------------------------------------------------------------------------- m /= z 0.190uS(168MHz) 0.128uS(250MHz)
asm volatile ( "mov r5,r5" ) ; rt_counter_start(hrt_count); asm volatile ( "mov r5,r5" ) ; m /= z ; asm volatile ( "mov r5,r5" ) ; rt_counter_stop(hrt_count); asm volatile ( "mov r5,r5" ) ;
0800285a: mov r5, r5 0800285c: mov.w r6, #1073741824 ; 0x40000000 08002860: bl 0x8001244 <vPortEnterCritical()> 08002864: ldr r2, [r6, #36] ; 0x24 08002866: mov r5, r5 08002868: vdiv.f32 s16, s22, s16 0800286c: vmul.f32 s18, s18, s16 08002870: vmul.f32 s21, s21, s16 08002874: vmul.f32 s28, s28, s16 08002878: vmul.f32 s17, s17, s16 0800287c: vmul.f32 s19, s19, s16 08002880: vmul.f32 s20, s20, s16 08002884: mov r5, r5 08002886: ldr r3, [r6, #36] ; 0x24 08002888: ldr r1, [pc, #204] ; (0x8002958 <TFPUTask::Code()+1672>) 0800288a: subs r0, r3, r2 0800288c: rsb r6, r8, r0 08002890: str r6, [r1, #0] 08002892: bl 0x8001220 <vPortExitCritical()> 08002896: mov r5, r5
//--------------------------------------------------------------------------------------------------------- m.solve(v) 0.619uS(168MHz) 0.416(MHz)
asm volatile ( "mov r5,r5" ) ; rt_counter_start(hrt_count); asm volatile ( "mov r5,r5" ) ; vv = m.solve(v); asm volatile ( "mov r5,r5" ) ; rt_counter_stop(hrt_count); asm volatile ( "mov r5,r5" ) ; det = rt_counter_us(hrt_count) ;
mov r5, r5 08002858: mov.w r7, #1073741824 ; 0x40000000 0800285c: bl 0x8001244 <vPortEnterCritical()> 08002860: ldr r2, [r7, #36] ; 0x24 08002862: ldr r3, [pc, #268] ; (0x8002970 <TFPUTask::Code()+1696>) 08002864: str r2, [r3, #0] 08002866: mov r5, r5 08002868: vneg.f32 s7, s16 0800286c: vsub.f32 s9, s7, s20 08002870: vmov.f32 s1, s21 08002874: vfma.f32 s1, s7, s26 08002878: vneg.f32 s0, s9 0800287c: vsub.f32 s2, s0, s25 08002880: vmov.f32 s14, #168 ; 0xa8 08002884: vfma.f32 s2, s1, s22 08002888: vmov.f32 s10, s23 0800288c: vdiv.f32 s4, s24, s2 08002890: vfma.f32 s10, s7, s22 08002894: vmul.f32 s15, s9, s4 08002898: vmul.f32 s8, s4, s14 0800289c: vmul.f32 s1, s1, s4 080028a0: vmul.f32 s5, s15, s19 080028a4: vmul.f32 s3, s8, s19 080028a8: vmul.f32 s2, s1, s19 080028ac: vmov.f32 s7, #172 ; 0xac 080028b0: vfma.f32 s5, s4, s17 080028b4: vldr s12, [pc, #188] ; 0x8002974 <TFPUTask::Code()+1700> 080028b8: vfma.f32 s3, s4, s7 080028bc: vsub.f32 s9, s21, s16 080028c0: vfma.f32 s2, s4, s20 080028c4: vmul.f32 s11, s10, s4 080028c8: vmul.f32 s6, s4, s12 080028cc: vmul.f32 s0, s9, s4 080028d0: vfma.f32 s5, s11, s17 080028d4: vfma.f32 s3, s6, s17 080028d8: vfma.f32 s2, s0, s17 080028dc: vstr s5, [r11] 080028e0: vstr s3, [r11, #4] 080028e4: vstr s2, [r11, #8] 080028e8: mov r5, r5 080028ea: ldr r0, [r7, #36] ; 0x24 080028ec: subs r1, r0, r2 080028ee: rsb r6, r8, r1 080028f2: str r6, [r3, #0] 080028f4: bl 0x8001220 <vPortExitCritical()> 080028f8: mov r5, r5 //--------------------------------------------------------------------------------------------------------- vsincos(a,sin,cos) 0.357uS(168MHz) 0.272uS(250MHz) arg=8.599 cos=-0.678717434 sin=0.734399676
asm volatile ( "mov r5,r5" ) ; rt_counter_start(hrt_count); asm volatile ( "mov r5,r5" ) ; vsincos ( arg , s0,s1) ; asm volatile ( "mov r5,r5" ) ; rt_counter_stop(hrt_count); asm volatile ( "mov r5,r5" ) ;
08002ed8: mov r5, r5 08002eda: mov.w r4, #1073741824 ; 0x40000000 08002ede: bl 0x80024b8 <vPortEnterCritical> 08002ee2: ldr r1, [r4, #36] ; 0x24 08002ee4: mov r5, r5 08002ee6: vmul.f32 s3, s16, s17 08002eea: vmov.f32 s9, s16 08002eee: vcvt.u32.f32 s4, s3 08002ef2: ldr r5, [pc, #188] ; (0x8002fb0 <TFPUTask::Code()+1156>) 08002ef4: vcvt.f32.u32 s7, s4 08002ef8: vfms.f32 s9, s7, s23 08002efc: vmul.f32 s13, s9, s22 08002f00: vmul.f32 s14, s13, s17 08002f04: vcvt.u32.f32 s15, s14 08002f08: vcvt.f32.u32 s12, s15 08002f0c: vmov r3, s15 08002f10: vfms.f32 s9, s12, s21 08002f14: add.w r0, r5, r3, lsl #3 08002f18: vldr s0, [r0] 08002f1c: vldr s6, [r0, #4] 08002f20: vmov.f32 s19, s0 08002f24: vmov.f32 s20, s6 08002f28: vfma.f32 s19, s6, s9 08002f2c: vfms.f32 s20, s0, s9 08002f30: mov r5, r5 08002f32: ldr r2, [r4, #36] ; 0x24 08002f34: subs r4, r2, r1 08002f36: ldr r1, [pc, #124] ; (0x8002fb4 <TFPUTask::Code()+1160>) 08002f38: subs r5, r4, r7 08002f3a: str r5, [r1, #0] 08002f3c: bl 0x8002494 <vPortExitCritical> 08002f40: mov r5, r5
//------------------------------------------------------------------------------- vcos(a) 0.177uS 0224us(250MHz) arg=8.599 cos=-0.519285738
asm volatile ( "mov r5,r5" ) ; rt_counter_start(hrt_count); asm volatile ( "mov r5,r5" ) ; s0 = vsin ( arg ) ; asm volatile ( "mov r5,r5" ) ; rt_counter_stop(hrt_count); asm volatile ( "mov r5,r5" ) ;
08002ee8: mov r5, r5 08002eea: mov.w r5, #1073741824 ; 0x40000000 08002eee: bl 0x80024b8 <vPortEnterCritical> 08002ef2: ldr r1, [r5, #36] ; 0x24 08002ef4: mov r5, r5 08002ef6: vmul.f32 s4, s16, s18 08002efa: vmov.f32 s12, s16 08002efe: vcvt.u32.f32 s7, s4 08002f02: ldr r2, [pc, #184] ; (0x8002fbc <TFPUTask::Code()+1168>) 08002f04: vcvt.f32.u32 s9, s7 08002f08: vfms.f32 s12, s9, s22 08002f0c: vmul.f32 s14, s12, s21 08002f10: vmov.f32 s15, s12 08002f14: vmul.f32 s0, s14, s18 08002f18: vcvt.u32.f32 s6, s0 08002f1c: vcvt.f32.u32 s5, s6 08002f20: vmov r3, s6 08002f24: vfms.f32 s15, s5, s20 08002f28: add.w r0, r2, r3, lsl #3 08002f2c: vldr s8, [r0, #4] 08002f30: vldr s17, [r0] 08002f34: vfma.f32 s17, s8, s15 08002f38: mov r5, r5 08002f3a: ldr r4, [r5, #36] ; 0x24 08002f3c: subs r5, r4, r1 08002f3e: ldr r1, [pc, #128] ; (0x8002fc0 <TFPUTask::Code()+1172>) 08002f40: rsb r4, r8, r5 08002f44: str r4, [r1, #0] 08002f46: bl 0x8002494 <vPortExitCritical> 08002f4a: mov r5, r5
Вобщем бодро и жизнеутверждающе... осталось дописать кватернионы и выложить на всеобщее обозрение. если кому нужно плавучку вычислять - велком! подтянивайтесь...
|
|
|
|
|
Nov 8 2012, 21:09
|
Гуру
     
Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521

|
Прошу прощения, не совсем в теме... Вроде st выкладывало свою либу... Что там совсем плохо? И ещё один вопрос. Мне в новом проекте придётся вовсю пользоваться плавучкой ... Правда там мелочи - всякие умножения/ деления, корни, возведения в степени (в том числе дробные) ну и логарифмы. Хотелось бы получить совместимый код с процом не имеющим плавучки. Я думаю, что всё без проблем должно работать и на 207, хотя на старте заложил 407. Тем не менее было бы любопытно посмотреть (раз уж есть такая возможность) разницу в производительности этих кристаллов на моей задаче. Поэтому хотелось бы написать максимально унифицированный исходник, при этом хотелось бы, чтобы 407 задействовал бы аппаратную плавучку. Пишу под IAR и, до этого я думал, что достаточно будет установить галочку "использовать плавучку".  Ну или, накройняк, подключать, по выбору, разные библиотеки и, соответственно, использовать разные вызовы ... Я в корне заблуждаюсь? Да, забыл, ещё фильтрацию придётся делать. Попробую на плавучке. Доложу.  Хотя и не скоро ... Финиш ближе к лету ...
|
|
|
|
|
Nov 8 2012, 22:29
|

бессмертным стать можно тремя способами
    
Группа: Свой
Сообщений: 1 405
Регистрация: 9-05-06
Из: Москва
Пользователь №: 16 912

|
2 _ Сергей Борщ 250 - это конечно разгон, квар 12мгц множители PLL_M =(12000000/ 1000000 ) PLL_N=500 PLL_P= 2 паралельно смотрел когдаж он глючить начнет, походу не начнет - при случае упирается наверно в шину флеша на чтение команд и константных данных, она проц наверно держит пока не выдаст то что поросили. но что характерно - рост линейный от частоы..... есть о чем подумать. не греется ... я думаю что на 250 может не вся переферия заработать. но уарт, таймеры, gpio работают без сбоев. есьть ощущение что еслиб не флеш то он бы и на 600мгц завелся бы, жрал бы наврно много.
2_SasaVitebsk Вы все правильно понимаете.- с разными ключами один и тотже код скомпилится с разным набором инстукций, в случае 207 будут вызваны програмные реализации из libm.a но чтото я не помню библиотек которые поиближались к потенциальной эффективности - все приходится напильником и зубиом рихтовать. в моем случае вызовов никаких не будет - все заинлайнено чтоб ихбавится потерь времени на работе со стеком и и на переходах.
по поводу ST мовской библиотке - там поддержка целочисленых вычисленй, как Вы наверно знаеете кроме FPU в ядро расширено SIMD инструкциями - вот про них в данном случае и песня.
можно будет просто сравнить скорость кода в результате - луший критерий, ну например калмановича и рикатичем пустить и посмотреть у кого такт системы быстрее будет. я все это ковыряю к тому что БИНС хочу построить - тут нужно много и обильно вращать вектора и интегрировать матричные уравнения - самое то чтоб нагрузить FPU, хотя честно говоря практика показала что и stm32f103 хватает - полоса пропускания реальной ситемы (самолет беспилотник автомобиль дерижбобель) ну на крайняк десятки герц, если они не в кого не впиливаются. стогерцового такта хватает для оценки состояния и управления. тут резервы скорости позволят применить в контуре более детальные модели управляймрго объекта.
|
|
|
|
|
Nov 9 2012, 16:13
|
Участник

Группа: Участник
Сообщений: 56
Регистрация: 3-12-04
Пользователь №: 1 307

|
Цитата(klen @ Nov 8 2012, 23:51)  //--------------------------------------------------------------------------------------------------------- m.solve(v) 0.619uS(168MHz) 0.416(MHz) очень любопытно будет посмотреть! а каким методом система решается?
|
|
|
|
|
Nov 9 2012, 16:40
|

Гуру
     
Группа: Модератор FTP
Сообщений: 4 479
Регистрация: 20-02-08
Из: Москва
Пользователь №: 35 237

|
Как-то тягостно мне оценить скорость работы плавучки по макро-задачам типа инвертирования матрицы...
Нельзя сообщить для несведующих, за сколько тактов выполняется там операция умножения (можно по даташиту)? А еще лучше - замерить, как быстро вычисляется скалярное произведение длинного вектора с самим собой. Скажем, вектор берем длиной в 1000 элементов, а вычисление повторяем сотни раз, чтобы в общем зачете заняло минуту-две. Тогда время реальной производительности на операциях умножения с накоплением будет определена с достаточной точностью.
Вся же остальная линейная алгебра, как бы она ни была привлекательна и практически полезна, в конечном итоге, зависит именно от этой операции умножения с накоплением. А потому реальные примеры из нее совершенно не нужны, а только запутывают.
P.S. А float-числа у него какой длины? Приведенные выше расчеты на 32-битных или 64-битных флоатах проводились?
|
|
|
|
|
Nov 9 2012, 17:08
|
;
     
Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509

|
Цитата(Xenia @ Nov 9 2012, 20:40)  Здесь всё, что интересует. Ага, еще Цитата(Xenia @ Nov 9 2012, 20:40)  Вся же остальная линейная алгебра, как бы она ни была привлекательна и практически полезна, в конечном итоге, зависит именно от этой операции умножения с накоплением. Благодаря команде vcvt можно выползать на fixed point, использовать mac-инструкции и вползать обратно в плавучку. Ну, и vmla - чистый float-mac, 3 такта...
Сообщение отредактировал _Pasha - Nov 9 2012, 17:14
|
|
|
|
|
Nov 9 2012, 17:34
|
Участник

Группа: Участник
Сообщений: 33
Регистрация: 29-06-10
Пользователь №: 58 196

|
вы тестировали те 64k памяти дополнительные? -flto вообще работает для Cortex-M4F? Также интересует -fgraphite и принципиальная возможность использования -fprofile-generate/-fprofile-use. libgomp.a можно для FreeRTOS заточить?
Сообщение отредактировал eisufu - Nov 9 2012, 17:45
|
|
|
|
|
Nov 10 2012, 09:32
|

бессмертным стать можно тремя способами
    
Группа: Свой
Сообщений: 1 405
Регистрация: 9-05-06
Из: Москва
Пользователь №: 16 912

|
serg_D >а каким методом система решается? самым тупым - для матрицы 3x3 расписана покомпонентно обратная матрица, потом умножение на вектор правых частей Xenia >за сколько тактов.. *, *-, *+ три такта, / и квадратый корень 14 тактов , остальное за 1 такт написать тест оказалось очень сложно, поскольку компиллер жеско все перекручивает и оптимизирует, на выходе не совсем то что ожидается, тут скорее всего реальный алгоритм нада проверять на разных машинках >float-числа у него какой длины? IEEE 754-1985 тоесть стандартный 32 флоат. >Я поняла там написанное так, что double float (64-битные) числа он умножать не умеет. Тогда действительно ему только с матрицами 3х3 работать... смотря для чего матрицы и как заполнять ее элементы. учитывая ошибки входных сигналов(датчики, шумы) обычно даже для относительно больших матриц можно так вычмсления провести чтоб матрицы были хорошо обусловлены. например базис поменять или масштаб. тут просто нужна ловкость рук и никакого мошенства. некоторые товарисщии на даблах применя их в тупую получают ошибки больше чем джедаи на флотах. 2_eisufu >вы тестировали те 64k памяти дополнительные? те 64k это какие ? в том что у меня запаяно ее 128К+64К если 64 - это дополнительный блок то нет, но могу. самому интересно. мне кажется разницы не будет. но проверим. > -flto вообще работает для Cortex-M4F? а якжо! тока он для всего работает независимо от ядра, тут много особенностей, он часто падает с диагностикой о внутренней ошибке но я выявил некоторые правила благодаря которым проект собирается с LTO, собсно представленные выше результаты были по коду с LTO >Также интересует -fgraphite чисто в принципе должно работать но нада проверять тестами какой асм вылазит, у меня графит всегда по умолчанию включен для проекта, а че оно дает или не дает я еще не исследовал. давайте вместе это выясним. тесты с "с неправильными цыклами" нужны. >принципиальная возможность использования -fprofile-generate/-fprofile-use к сожаления тут я ничео не могу сказать.... я пока даже механихма в ообщем инстументирования не вкуриваю, нада ковырять. > libgomp.a можно для FreeRTOS заточить? думаю что можно каминибудь костылями прикрученными к FreeRTOS и исходникам GCC и может быть даже не трудно, но!.... зачем, всеравно то одно вычислительное ядро имеется - смысла паралелние вычисления раскидывать по OMP задачкам на одном процессоре нет. если выродит арм микроконтроллеры с двумя и более ядрами то тогда наверно все зачешутся как код подятнуть под это. для linux+Cortex-A9/15 это стопудово работает, можно проверить. 2_MrAlex >Расширенный фильтр Калмана. Модель не линейная. Линеаризуется на каждом шаге. Интегрирование в самой простой форме использовали. Размерность матриц 4x4. гуд. тут то не в том как хорошо организовать вычисления на проце без FPU(Ваш случай с MSP) а в том что на Cortex-M4F получится это деать много раз быстрее при прочих условиях на равных тактовых. доделал кватерниончики - вращают вектора хорошо.. позтиф! цель достигнута - для высисление пространственных преобразований имеется полный набор операндов - vector3 matrix3 quat4, для экземпляров переопределены операторы теперь формулы можно из книжки брать и тупо писать в операторной форме: решение системы Код float z; vector b(1,2,3), x; matrix A(1,2,3,4,5,6,7,8,9);
x = !A*b; // решение системы z = b^a; // скалярное произведение b = a*b; // векторное произведение b = a*f + f*b - b/f; // мастабирование/ ссумирование векотров
quat Q; b.x=2; b.y=54; b.z-5.002; Q.set_axis( b , 0.5* M_PI ); // установка кватерниона на поаорот вокруг орта b на угол 90 градусов b = Q^b; // вычисление повернутого вектора
vector x,u,z; matrix I,F,B,H,K,P,Q,R;
while(1) { z = .... // измерение
x = F*x+B*u; // экстраполяция состояня P = F*P*(~F)+Q; // экстаоляция ошибок K=P*(~H) * !(H*P*(~H)+R); // вычислене коэф усиления x += K*(z-H*x); // корреция P = (I-K*H)*P; } цикл срасчетом фильта 3x3 выполняется за 5.05uS
|
|
|
|
|
Nov 10 2012, 10:01
|
Знающий
   
Группа: Участник
Сообщений: 537
Регистрация: 22-02-06
Пользователь №: 14 594

|
Цитата(klen @ Nov 9 2012, 02:29)  по поводу ST мовской библиотке - там поддержка целочисленых вычисленй, как Вы наверно знаеете кроме FPU в ядро расширено SIMD инструкциями - вот про них в данном случае и песня. Библиотека ST, а точнее ее часть - CMSIS DSP библиотека содержит функции для работы как с SIMD расширениями так и с FPU. Или мы говорим про разные библиотеки? Цитата The library installer contains prebuilt versions of the libraries in the Lib folder.
arm_cortexM4lf_math.lib (Little endian and Floating Point Unit on Cortex-M4) arm_cortexM4bf_math.lib (Big endian and Floating Point Unit on Cortex-M4) arm_cortexM4l_math.lib (Little endian on Cortex-M4) arm_cortexM4b_math.lib (Big endian on Cortex-M4) arm_cortexM3l_math.lib (Little endian on Cortex-M3) arm_cortexM3b_math.lib (Big endian on Cortex-M3) arm_cortexM0l_math.lib (Little endian on Cortex-M0) arm_cortexM0b_math.lib (Big endian on Cortex-M3)
|
|
|
|
|
Nov 10 2012, 14:07
|

Гуру
     
Группа: Модератор FTP
Сообщений: 4 479
Регистрация: 20-02-08
Из: Москва
Пользователь №: 35 237

|
Цитата(klen @ Nov 10 2012, 13:32)  vector b(1,2,3), x; matrix A(1,2,3,4,5,6,7,8,9);
x = !A*b; // решение системы z = b^a; // скалярное произведение b = a*b; // векторное произведение b = a*f + f*b - b/f; // масштабирование/ суммирование векторов Скажите пожалуйста, как это вы так хитрО определили vector и matrix (полагаю, что это классы), что над ними стали возможны матричные операции в алгебраической записи? Очень уж мне любопытно, хотя этот вопрос напрямую к теме не относится. Например, в записи y = A* bгде: y и b - вектора, A - матрица вы получаете промежуточный вектор результата произведения, и лишь только потом копируете его в y? Или все-таки исхитрились класть сразу на нужное место, обходя векторно-матричное копирование при выполнении операции присваивания? Этот мой вопрос продиктован беспокойством по поводу "лишних" операций аллокирования объекта для хранения промежуточного результата, его копирования при присвоении, и последующей деаллокации после использования. В обычной (не матричной) алгебре проблем с промежуточным результатом не возникает, т.к. для его хранения достаточно регистра или элемента стека. Но когда это вектор, а тем паче матрица, то с этим проблема немалая. Например, в операциях векторно-матричного сложения дополнительная операция копирования (чтение и запись в память на каждый элемент) занимает точти столько же времени, сколько само сложение. К сожалению, я не знаю достататочно элегантного способа узнать адрес y при выполнении операции умножения y = A* b, реализуемой определением оператора умножения в классе matrix. А неэлегантный способ сводится к выполнению операции умножения в операторе присваивания, но тогда оператор умножения должен выдавать ему "задание" с адресами (а то и вместе с типами) сомножителей. Короче говоря, как это у вас реализовано? P.S. Если такой отход от темы вы считаете недопустимым, то с благодарностью ознакомилась бы с вашим мнением в любой другой теме или личной переписке.
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|