Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Float-ядро для double операций
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
AlexeyT
Ожидаем поставку процессора с ядром Cortex-M4F с аппаратно реализованными операциями с плавающей точкой (32-битные float).

Точности float для некоторых наших вычислений недостаточно, приходится использовать 64-битный double.

Вопрос - есть ли способ использовать float-сопроцессор для операций формата double? Хотя бы для самых простых - сложение и вычитание?
scifi
Цитата(AlexeyT @ Nov 16 2013, 15:18) *
Вопрос - есть ли способ использовать float-сопроцессор для операций формата double? Хотя бы для самых простых - сложение и вычитание?

Нет.
fatlortroll
Цитата(AlexeyT @ Nov 16 2013, 15:18) *
Вопрос - есть ли способ использовать float-сопроцессор для операций формата double? Хотя бы для самых простых - сложение и вычитание?
Если не смутит ссылка на Хабр, то здесь достаточно подробно описаны внутренности чисел с плавающей точкой, и сразу станет ясно, отчего более короткие float не удастся приспособить под работу с double, которые длиннее их.
Rst7
QUOTE
Вопрос - есть ли способ использовать float-сопроцессор для операций формата double? Хотя бы для самых простых - сложение и вычитание?


Для только сложения и вычитания проще использовать long long. Без всяких float/double. Как бы значащих цифр больше, чем в double.
vlad_new
А я не знал что незяяяяя. Взял и включил сопр. В итоге на флоатах скорость поднялась в 12-15 раз, а на дублях в 3-4. sm.gif
AlexeyT
Цитата(vlad_new @ Nov 17 2013, 06:01) *
А я не знал что незяяяяя. Взял и включил сопр. В итоге на флоатах скорость поднялась в 12-15 раз, а на дублях в 3-4. sm.gif



Эвона как! А ассемблерный листинг можете выложить? Допустим, ассемблерная реализация:

double a=2.123456789012345, b=-5.123456789012345, res; res = a+b;

в двух вариантах - при включенном и выключенном сопроцессоре.
Меня вот никак не отпускает ощущение, что ДОЛЖНО float ядро хоть как-то ускорять операции double.
vlad_new
Цитата(AlexeyT @ Nov 17 2013, 11:14) *
Эвона как! А ассемблерный листинг можете выложить? Допустим, ассемблерная реализация:

double a=2.123456789012345, b=-5.123456789012345, res; res = a+b;

в двух вариантах - при включенном и выключенном сопроцессоре.
Меня вот никак не отпускает ощущение, что ДОЛЖНО float ядро хоть как-то ускорять операции double.

Код
//----------------------FPU OFF ----------------------------------------//

0x08000512 4E93      LDR           r6,[pc,#588] ; @0x08000760
0x08000514 6AB2      LDR           r2,[r6,#0x28]
0x08000516 6AF3      LDR           r3,[r6,#0x2C]
0x08000518 6A30      LDR           r0,[r6,#0x20]
0x0800051A 6A71      LDR           r1,[r6,#0x24]
0x0800051C F003F89B  BL.W          __aeabi_dadd (0x08003656)
0x08000520 6330      STR           r0,[r6,#0x30]
0x08000522 6371      STR           r1,[r6,#0x34]

//----------------------FPU ON -----------------------------------------//
0x08000522 4D94      LDR           r5,[pc,#592] ; @0x08000774
0x08000524 ED950B0A  VLDR          d0,[r5,#0x28]
0x08000528 EC532B10  VMOV          r2,r3,d0
0x0800052C ED950B08  VLDR          d0,[r5,#0x20]
0x08000530 EC510B10  VMOV          r0,r1,d0
0x08000534 F003F841  BL.W          __aeabi_dadd (0x080035BA)
0x08000538 EC410B10  VMOV          d0,r0,r1
0x0800053C ED850B0C  VSTR          d0,[r5,#0x30]


Вот пришлось посидеть и понять почему у меня ускорение произошло. Просто у меня кучка всякой математики и некоторые ее части производились во флоуте ( ну где дубль не нужен был),
вот поэтому прога и ускорилась в 3-4 раза. Так что народ прав. В чистом виде для дубля сопр бесполезен. Но при грамотном смешевании дубля и флоута эффект будет.

SII
Как видим, для деления вызывается подпрограмма, что и следовало ожидать: не может 32-разрядный ППЗ выполнять 64-разрядные операции. Ускорение же, возможно, произошло не только из-за смеси операций (32- и 64-разрядных), но и из-за повышения частоты процессора, если тестирование без ППЗ производилось на физически другом процессоре. Например, если ядро Cortex-M3 (без ППЗ) работало на частоте 60 МГц, а ядро Cortex-M4F (с ППЗ) -- на 180 МГц, то последнее, грубо говоря, будет в 3 раза быстрее на любых операциях именно за счёт роста частоты.

Цитата(AlexeyT @ Nov 17 2013, 11:14) *
Меня вот никак не отпускает ощущение, что ДОЛЖНО float ядро хоть как-то ускорять операции double.


Ну, потратьте время на изучение матчасти -- и тогда поймёте, что никак оно не ускорит и не может ускорить в принципе.
etoja
Цитата(AlexeyT @ Nov 16 2013, 15:18) *
Ожидаем поставку процессора с ядром Cortex-M4F с аппаратно реализованными операциями с плавающей точкой (32-битные float).


Странно. STM32F415, STM32F303 без очереди везде.

Вы в своём алгоритме скобки правильно расставьте и иногда масштабирование делайте. Так работают алгоритмы цифровой обработки сигналов .
Возможно компилятор gcc часть этой работы сделает и сам при включенной оптимизации.
Golikov A.
число дабл - это мантисса + порядок.
если его разложить на 2 числа

младшая часть мантисы и порядок
и старшая часть мантисы и увеличенный порядок

то есть как бы число и уточнение, это позволит уменьшить длину мантисы

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

я в чем то не прав?

AlexeyT
Цитата(etoja @ Nov 18 2013, 16:19) *
Вы в своём алгоритме скобки правильно расставьте и иногда масштабирование делайте. Так работают алгоритмы цифровой обработки сигналов .


Разрешите не понять?



Цитата(Golikov A. @ Nov 18 2013, 21:33) *
число дабл - это мантисса + порядок.
если его разложить на 2 числа

младшая часть мантисы и порядок
и старшая часть мантисы и увеличенный порядок

то есть как бы число и уточнение, это позволит уменьшить длину мантисы

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

я в чем то не прав?



Во-во! Вот и я надеялся найти подсказку по алгоритму представления double числа в виде какой-то комбинации двух float. Как, например, операции для __int64 представляются в виде комбинаций обычных 32-битных int.
jcxz
Цитата(Golikov A. @ Nov 18 2013, 23:33) *
я в чем то не прав?

В математике.
То что Вы сказали, переведите на математический язык (формулами).
И поймёте почему.
Golikov A.
ну вот так как-то
(А+B ) * (D + C) = AD + BD + AC + BC
с этим я надеюсь все согласятся


далее мне кажется что число вида (для простоты будем оперировать целыми)
11112222 всегда можно представить в виде 1111 * 10000 + 2222

(A*B *C * D) == A*C*B*D

если число вида 1111 * 10000 считать А = 1111, B = 10000, то мы получаем
арифметику с числами 1111 2222 - половинного порядка, и выравнивание порядков и суммирование

я не утверждаю что все действия при перемножении даблов раскладываются в действия с флотами, мне просто кажется что часть действий при перемножении даблов может быть ускорена при наличии флоат умножителя. Правда не знаю будет ли выигрыш от работы с флотами или легче сразу все сводить к перемножению целых...
jcxz
Цитата(Golikov A. @ Nov 19 2013, 14:32) *
ну вот так как-то
(А+B ) * (D + C) = AD + BD + AC + BC
с этим я надеюсь все согласятся

Не согласятся.
У вас число в экспоненциальной форме - это не умножение, а возведение в степень.
ну-ка разложите:
Код
(A+B)^(N+M)
(где: ^ - операция возвдения в степень) в сумму

PS: Да и поймите - даже если вы найдёте способ, то это будет soft-преобразование double->float, потом будет float операция (или несколько) и обратное soft-преобразование float->double.
У вас всё равно 2 операции с double с soft-эмуляцией. Однозначно это будет медленее чем одна операция с double с soft-эмуляцией.
SII
Цитата(Golikov A. @ Nov 19 2013, 12:32) *
ну вот так как-то


Ещё раз: изучите матчасть. А заодно повторите школьный курс математики, чтобы вспомнить, что такое экспоненциальное представление чисел.

Цитата(jcxz @ Nov 19 2013, 12:50) *
ну-ка разложите:
Код
(A+B)^(N+M)
(где: ^ - операция возвдения в степень) в сумму


У Вас описка: поскольку речь идёт об умножении, то
Код
A^N * B^M = (A*B)^(N+M)

Впрочем, сути дела это не меняет.

Для тех, кому всё ещё непонятно: при выполнении умножения чисел с плавающей запятой их мантиссы перемножаются, а порядки -- складываются. Чтобы выполнить умножение мантисс, умножитель должен обладать соответствующей разрядностью, ну а ППЗ, предназначенный для обработки лишь чисел одинарной точности, никак не сможет умножить мантиссы чисел с двойной точности: у него банально не хватит разрядности. Кстати говоря, то же самое относится к программной реализации операций с плавающей запятой: если для перемножения мантисс чисел одинарной точности достаточно лишь одной инструкции 32-разрядного целочисленного умножения, которая у ARMов есть, то для перемножения мантисс чисел двойной точности подходящей инструкции уже нет, и приходится выполнять умножение кусками, суммируя частичные произведения.

В общем, наличие ППЗ одинарной точности абсолютно бесполезно, если необходимо выполнять вычисления с двойной точностью: он не может помочь ничем.
Golikov A.
я не ошибся, я имел ввиду другое

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

Хотя ваша правда, легче уже сразу переходить к перемножению мантис в целочисленной арифметике, чем мутить такое.
DASM
Цитата(SII @ Nov 19 2013, 14:18) *
если для перемножения мантисс чисел одинарной точности достаточно лишь одной инструкции 32-разрядного целочисленного умножения, которая у ARMов есть, то для перемножения мантисс чисел двойной точности подходящей инструкции уже нет

ARM разные бывают, стоит уточнить. У ARMv6 хардворный дабл есть.
SII
Цитата(DASM @ Nov 19 2013, 14:43) *
ARM разные бывают, стоит уточнить. У ARMv6 хардворный дабл есть.


Кажется, мы говорим о разных вещах: Вы о наличии ППЗ, обрабатывающего не только 32-разрядные, но и 64-разрядные вещественные числа, а я -- о программной реализации вещественной арифметики с помощью команд обработки целых чисел, т.е. без ППЗ. Для того, чтобы выполнить умножение мантисс вещественных чисел двойной точности, требуется команда умножения, операндами которой являются 64-разрядные числа. Реально мантисса, конечно, меньше -- если память не изменяет, 52 бита -- но в любом случае 32-разрядное умножение здесь не годится, а команд, умножающих более крупные целые числа, ни у каких ARMов нет.
Golikov A.
а я о теоретической применимости 32 битного флотовского умножителя для ускорения 64 битной дабловской арифметики...%)
SII
В третий раз повторяю: изучите матчасть, а заодно и математику. Никакого "флотовского умножителя" в природе не существует. Для выполнения операций с вещественными числами используются схемы сложения, умножения, деления и сдвига целых чисел, не имеющие никаких принципиальных отличий от аналогичных узлов, предназначенных для выполнения целочисленной арифметики. Более того, разрядность у вычислительных блоков ППЗ, поддерживающего лишь вещественную арифметику одинарной точности, меньше, чем у аналогичных блоков основного процессора. Например, обычный целочисленный умножитель в основном процессоре позволяет умножить два 32-разрядных целых числа с получением 64-разрядного результата, а пресловутый умножитель в ППЗ, который никакой не "флотовый", а опять-таки самый что ни на есть обычный целочисленный -- лишь два 24-разрядных целых числа (поскольку мантисса вещественных чисел одинарной точности содержит 24 бита). То же самое относится и к другим схемам.

Может быть, теоретически удалось бы извернуться и использовать ППЗ одинарной точности для обработки чисел двойной точности, вот только реализация всего этого будет принципиально такой же, как на целочисленном процессоре без всякого ППЗ, только намного более муторной. Например, для умножения кусков мантисс вещественных чисел двойной точности (размер 53 бита) в любом случае придётся мантиссы разбивать на части и выполнять умножение по кусочкам, а потом складывать промежуточные результаты. На 32-разрядном умножителе основного процессора потребуется 4 операции умножения (32*32 бита с 64-разрядным результатом), а на 24-разрядном умножителе ППЗ -- целых 25 (12*12 бит с 24-разрядным результатом), т.е. даже по одному умножению ППЗ будет проигрывать основному процессору более чем в шесть раз. А ведь требуются ещё сдвиги и сложения, которые на ППЗ реализовать тоже сложней, чем на основном процессоре (если вообще удастся такое сделать -- тут надо думать). Так что такая реализация арифметики двойной точности на ППЗ одинарной точности будет во много медленней, чем её реализация на основном процессоре -- и, что весьма интересно, при этом никакие "плавающие" возможности ППЗ реально использовать невозможно, они лишь мешают.
Golikov A.
ну вот теперь понятно...

а 32 битный умножитель целых, дает 64 бита?

int32_t A;
int32_t B;
int64_t Result;

всегда писал Result = (int64_t)A * (int64_t)B, и тем самым заставлял проц делать сразу все в 64 битах и за несколько тактов. То есть мне стоило писать Result = A * B? или такую хитрость только явным ассемблером получить можно?



Сергей Борщ
QUOTE (Golikov A. @ Nov 20 2013, 10:05) *
всегда писал Result = (int64_t)A * (int64_t)B, и тем самым заставлял проц делать сразу все в 64 битах и за несколько тактов. То есть мне стоило писать Result = A * B?
Вы и ваш компилятор делали так, как и надо делать согласно стандарта языка. Если включить оптимизатор, то хороший компилятор должен выкинуть лишние операции и оставить лишь [32]*[32]=[64]
SII
Цитата(Golikov A. @ Nov 20 2013, 11:05) *
а 32 битный умножитель целых, дает 64 бита?


Физически -- да, умножение 32-разрядных чисел даст 64-разрядный результат. Однако удастся ли "в лоб" использовать это на языке высокого уровня (на Си, в частности), я не знаю. На ассемблере ручками -- всегда пожалуйста sm.gif
Golikov A.
в лоб без оптимизации
[32]*[32]
дает [32]....
имеется ввиду
Result = A * B,
а Result = (int64_t)A * (int64_t)B,
без оптимизации дает больше команд чем просто 32 на 32 умножение, а с оптимизацией я чет не допер посмотреть...
Сергей Борщ
QUOTE (Golikov A. @ Nov 20 2013, 14:40) *
без оптимизации дает больше команд чем просто 32 на 32 умножение, а с оптимизацией я чет не допер посмотреть...
Без оптимизации получаете ровно то, что просите. Без оптимизации, как и просите.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.