Здравствуйте коллеги. Итак сбылась мечта идиота - в микроконтроллерах появился 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
Вобщем бодро и жизнеутверждающе...
осталось дописать кватернионы и выложить на всеобщее обозрение.
если кому нужно плавучку вычислять - велком! подтянивайтесь...