Микроконтролери и електроника
http://mcu-bg.com/mcu_site/

float const -> double
http://mcu-bg.com/mcu_site/viewtopic.php?f=3&t=17703
Страница 1 от 2

Автор:  Цецо [ Пон Яну 11, 2021 5:50 pm ]
Заглавие:  float const -> double

Цитат:
int a,b;
a = 0.9 * a + 0.1 * b;


В горния израз компилатора(gcc) не следва ли да ползва double аритметика?

Автор:  miro_atc [ Пон Яну 11, 2021 6:01 pm ]
Заглавие:  Re: float const -> double

Така както си го дал най-вероятно е оптимизирал нещата и се учудвам, че не е останал само на int ;-)

реално имаш int на входа и int на изхода и може да се компилира просто като: (a*9 +b)/10 ;-)

Автор:  Цецо [ Пон Яну 11, 2021 6:14 pm ]
Заглавие:  Re: float const -> double

Не, оказа се, че има скрит -fsingle-precision-constant в тая версия на чибито, която ползваме. Което е грешка, оправил си го е човека в по-новите.

Ето тук е описано и що е грешка да се ползва тая опция, нарушава правилата на езика и може да доведе до кофти резултати при някой специфични математики:

https://github.com/ArduPilot/ardupilot/issues/5620

Автор:  miro_atc [ Пон Яну 11, 2021 6:16 pm ]
Заглавие:  Re: float const -> double

не знам, в случая ще е грешка ако компилаторът не го оптимизира ;-)

Автор:  Цецо [ Пон Яну 11, 2021 6:22 pm ]
Заглавие:  Re: float const -> double

Ми не го оптимизира. Тоест оптимизира нещо, но пак вика библиотеките за double сметки. Ако я няма въпросната опция. Ако я има вика библиотеките за float (или ползва FPU-то ако е налично).

Автор:  Цецо [ Пон Яну 11, 2021 6:26 pm ]
Заглавие:  Re: float const -> double

pPl->dc_ir и dc_ir са int32_t

gcc е версия 6 нещо си, желязото M4F, компилатора е конфигуриран с -mfloat-abi=hard -mfpu=fpv4-sp-d16

На -О2
Цитат:
pPl->dc_ir = 0.9 * pPl->dc_ir + 0.1 * dc_ir;
801a8d0: f8d4 0090 ldr.w r0, [r4, #144] ; 0x90
801a8d4: f7f5 fe96 bl 8010604 <__aeabi_ui2d>
801a8d8: a37d add r3, pc, #500 ; (adr r3, 801aad0 <pl_process+0x350>)
801a8da: e9d3 2300 ldrd r2, r3, [r3]
801a8de: f7f5 ff07 bl 80106f0 <__aeabi_dmul>
801a8e2: 4680 mov r8, r0
801a8e4: 4650 mov r0, sl
801a8e6: 4689 mov r9, r1
801a8e8: f7f5 fe8c bl 8010604 <__aeabi_ui2d>
801a8ec: a37a add r3, pc, #488 ; (adr r3, 801aad8 <pl_process+0x358>)
801a8ee: e9d3 2300 ldrd r2, r3, [r3]
801a8f2: f7f5 fefd bl 80106f0 <__aeabi_dmul>
801a8f6: 4602 mov r2, r0
801a8f8: 460b mov r3, r1
801a8fa: 4640 mov r0, r8
801a8fc: 4649 mov r1, r9
801a8fe: f7f5 fd45 bl 801038c <__adddf3>
801a902: f7f6 f935 bl 8010b70 <__aeabi_d2uiz>
801a906: 4603 mov r3, r0
801a908: 9003 str r0, [sp, #12]
801a90a: f8c4 3090 str.w r3, [r4, #144] ; 0x90


на -О0

Цитат:
pPl->dc_ir = 0.9 * pPl->dc_ir + 0.1 * dc_ir;
801fca2: 9b0e ldr r3, [sp, #56] ; 0x38
801fca4: f8d3 3090 ldr.w r3, [r3, #144] ; 0x90
801fca8: 4618 mov r0, r3
801fcaa: f7f0 fcab bl 8010604 <__aeabi_ui2d>
801fcae: a372 add r3, pc, #456 ; (adr r3, 801fe78 <pl_analyze+0x288>)
801fcb0: e9d3 2300 ldrd r2, r3, [r3]
801fcb4: f7f0 fd1c bl 80106f0 <__aeabi_dmul>
801fcb8: 4603 mov r3, r0
801fcba: 460c mov r4, r1
801fcbc: 4625 mov r5, r4
801fcbe: 461c mov r4, r3
801fcc0: 980b ldr r0, [sp, #44] ; 0x2c
801fcc2: f7f0 fc9f bl 8010604 <__aeabi_ui2d>
801fcc6: a36e add r3, pc, #440 ; (adr r3, 801fe80 <pl_analyze+0x290>)
801fcc8: e9d3 2300 ldrd r2, r3, [r3]
801fccc: f7f0 fd10 bl 80106f0 <__aeabi_dmul>
801fcd0: 4602 mov r2, r0
801fcd2: 460b mov r3, r1
801fcd4: 4620 mov r0, r4
801fcd6: 4629 mov r1, r5
801fcd8: f7f0 fb58 bl 801038c <__adddf3>
801fcdc: 4603 mov r3, r0
801fcde: 460c mov r4, r1
801fce0: 4618 mov r0, r3
801fce2: 4621 mov r1, r4
801fce4: f7f0 ffe4 bl 8010cb0 <__aeabi_d2uiz>
801fce8: 4602 mov r2, r0
801fcea: 9b0e ldr r3, [sp, #56] ; 0x38
801fcec: f8c3 2090 str.w r2, [r3, #144] ; 0x90


На -О0 -fsingle-precision-constant

Цитат:
pPl->dc_ir = 0.9 * pPl->dc_ir + 0.1 * dc_ir;
801fbd2: 9b0e ldr r3, [sp, #56] ; 0x38
801fbd4: f8d3 3090 ldr.w r3, [r3, #144] ; 0x90
801fbd8: ee07 3a90 vmov s15, r3
801fbdc: eef8 7a67 vcvt.f32.u32 s15, s15
801fbe0: ed9f 7a6b vldr s14, [pc, #428] ; 801fd90 <pl_analyze+0x270>
801fbe4: ee27 7a87 vmul.f32 s14, s15, s14
801fbe8: 9b0b ldr r3, [sp, #44] ; 0x2c
801fbea: ee07 3a90 vmov s15, r3
801fbee: eef8 7a67 vcvt.f32.u32 s15, s15
801fbf2: eddf 6a68 vldr s13, [pc, #416] ; 801fd94 <pl_analyze+0x274>
801fbf6: ee67 7aa6 vmul.f32 s15, s15, s13
801fbfa: ee77 7a27 vadd.f32 s15, s14, s15
801fbfe: eefc 7ae7 vcvt.u32.f32 s15, s15
801fc02: ee17 2a90 vmov r2, s15
801fc06: 9b0e ldr r3, [sp, #56] ; 0x38
801fc08: f8c3 2090 str.w r2, [r3, #144] ; 0x90

Автор:  HCL [ Пон Яну 11, 2021 7:20 pm ]
Заглавие:  Re: float const -> double

А онзи се оплаквахте, че на питона версиите му били досадни.... :D

Автор:  Цецо [ Пон Яну 11, 2021 7:25 pm ]
Заглавие:  Re: float const -> double

Е не, тука проблема се оказа в междинния слой. Компилатора се държи адекватно, правилата са стриктни и си ги спазва.

Автор:  palavrov [ Пон Яну 11, 2021 7:48 pm ]
Заглавие:  Re: float const -> double

miro_atc написа:
не знам, в случая ще е грешка ако компилаторът не го оптимизира ;-)

Проблемът е, че 0.1 и 0.9 нямат точно представяне с floating point числа (без значение дали е float или double) и съответно при някои числа ще има разлика с оптимизираният код (ако например го оптимизра до (a*9 +b)/10)

Tакива оптимизации са работа на задклавиатурното устройство, работата на компилатора е стриктно да следва каквото му е подадено като сорс и да оптимизира само там където няма да има странични ефекти.

Аз бих го "оптимизирал" и като (a*7+b)>>3 за да избягам от делението, но само ако това не се отразява на съответния алгоритъм.

Автор:  Цецо [ Пон Яну 11, 2021 8:57 pm ]
Заглавие:  Re: float const -> double

Абе за оптимизациите е ясно. Въпроса беше - дробна константа, без спецификатор не се ли приема за double? И ако да, що при мен не се случваше. Намери се обяснението.

Автор:  bateAz [ Вто Яну 12, 2021 12:26 am ]
Заглавие:  Re: float const -> double

miro_atc написа:
....

реално имаш int на входа и int на изхода и може да се компилира просто като: (a*9 +b)/10 ;-)


Понеже съм запознат с проблема, да си кажа и аз. Добре, че компилаторът не го е оптимизирал, защото резултатът щеше да е грешен. а*9 щеше да препълни размера на типа ( 32 битов без знак е ) и катеричките нямаше да са това, което изглеждат.

Автор:  miro_atc [ Вто Яну 12, 2021 10:50 am ]
Заглавие:  Re: float const -> double

bateAz написа:
Добре, че компилаторът не го е оптимизирал, защото резултатът щеше да е грешен.


Е те затова падат ракетите ;-)

Те това би трябвало да не препълва:
(a*9LL +b)/10LL

За по-оптимална компилация може и така:

Код:
long long ll;

ll = a;
ll += ll << 3;
ll += b;
return ll / 10;

Автор:  bateAz [ Вто Яну 12, 2021 10:58 am ]
Заглавие:  Re: float const -> double

miro_atc написа:
...
Те това би трябвало да не препълва:
(a*9LL +b)/10LL

...


Това е ясно. За предишното говорехме.

Автор:  palavrov [ Вто Яну 12, 2021 12:31 pm ]
Заглавие:  Re: float const -> double

miro_atc написа:
За по-оптимална компилация може и така:

Код:
long long ll;

ll = a;
ll += ll << 3;
ll += b;
return ll / 10;

Що зорлен го мъчиш компилатора да се чуди какво си имал в предвид. И кода ти става по труден за четене. Такава оптимизация е платформо зависима, т.е. на процесори които имат хардуерно умножение (т.е. почти всички модерно 16, 32, 64 битово) ще е по бързо да се изпълни една инструкция за умножение отколкото две (преместване и събиране). Модерните компилатори ще се оправят достатъчно добре с оптимизиране на такива сметки там където може и има смисъл. Като бонус ако смениш процесора с друг компилатора ще оптимизира за него, докато ако направиш такава оптимизация му вързваш ръцете винаги да ползва преместване и събиране.

Автор:  miro_atc [ Вто Яну 12, 2021 1:25 pm ]
Заглавие:  Re: float const -> double

palavrov написа:
Такава оптимизация е платформо зависима


Така е... Някой ден подобни оптимизации излизат през носа, играл съм го и тоя филм.
От друга страна, ако човек работи на определена платформа... както да речем аз последните 20г. може да се каже, че сме вече почти женени ;-)
Та в такива случаи, когато по никакъв начин не се очаква генерална смяна си позволявам да се съобразя с конкретната платформа. И само с нея ;-)
В случая хардуерно умножение има, но е 32 битово. И което е още по-зле за 64-бит аритметика се разчита на стандартните библиотеки, демек вика се функция с всичките произтичащи негативи от това. Аз даже се учудвам, че по-горе има float аритметики директно без викане на __eabi_.... Или newlib са го пипнали (не знам аз не го ползвам и следя). Но при всички случаи 64-бит шифтване е по-бързо и позволява съчетание със събирането. То и при умножението има multiply and accumulate, обаче ще стане още по-грозно като код.
А другия проблем специално при GCC че не е много гъвкав с типовете. Разчита ти да му ги укажеш, а аз обикновено избягвам в сорса да има двуумене какъв тип трябва да се ползва. Говоря за изрази където трябва да се прецени дали какъв тип са аргументите и какъв тип резултата и т.н. Примерно в случая делението може да е 64 бит /32 бит, което е значително по-бързо от 64/64. Но не съм сигурен в израз дали GCC няма да му хрумне нещо друго, затова - на парче ;-)

Страница 1 от 2 Часовете са според зоната UTC + 2 часа [ DST ]
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/