RomaRoma
Jan 10 2014, 19:21
Добрый день/ночь!
Прошу помощи форумчан. Хочу использовать микроконтроллер для произведения большого объема вычислений, но не уверен в том, достаточна ли его мощность. Марка микроконтроллера еще не выбрана, скорее всего, на ядре ARM или Cortex.
Прошу счастливых владельцев микроконтроллеров на ядре ARM и/или AVR произвести замер времени выполнения простейшего вычисления с вещественными числами.
Покупать отладочную плату и программатор для этого слишком накладно.
Если производительности не хватит, буду вынужден использовать мощный РС под управлением ОС реального времени. Либо можно запараллелить несколько микроконтроллеров.
Детали кода значения не имеют, нужно просто ПРИМЕРНО оценить длительность вычислений с применением умножения и деления вещественных чисел. Желательно использовать real двойной точности (64 бит), но это не принципиально.
Заранее благодарен всем откликнувшимся!
Пример кода на псевдоязыке
//желательно использовать real двойной точности (64 бит), но это не принципиально
real a = 1;
real b = 1234.567;
//получить текущее значение системного время в мсек или мксек
int StartTime = getCurrentTime();
//рабочий цикл
for (int i=0; i<1000000; i++)
{ a = a + (real(i) / b );
b = b + 0.000001;
//на всякий пожарный
If (a>100000000) {a=1};
}
//итоговая длительность вычислений
int Dur = getCurrentTime() - StartTime;
//используем полученное значение, чтобы слишком умный компилятор не удалил неиспользуемые вычисления
//вместо Print можно сделать что угодно, лишь бы использовать значение!
//например, сохранить в EEPROM
Print(a);
megajohn
Jan 10 2014, 20:18
с максимальной оптимизацией по скорости получилось:
для CM3:( IAR DLIB )
250 572 180 тактов для float ( 32 бита )
347 571 190 тактов для double ( 64 бита )
для AVR: ( IAR DLIB )
1 725 881 000 тактов для float ( 32 бита )
3 697 655 000 тактов для double ( 64 бита )
A. Fig Lee
Jan 10 2014, 20:46
Цитата(megajohn @ Jan 10 2014, 15:18)

с максимальной оптимизацией по скорости получилось:
для CM3:( IAR DLIB )
250 572 180 тактов для float ( 32 бита )
* 72 MHz = 4 секунды примерно? Ы?
megajohn
Jan 10 2014, 20:53
Цитата(A. Fig Lee @ Jan 11 2014, 00:46)

* 72 MHz = 4 секунды примерно? Ы?
сам офигел. Смотрю дизасм, и вызываются либовские aeabi_i2d, __aeabi_ddiv, __aeabi_dadd, __aeabi_cdrcmple
RomaRoma
Jan 10 2014, 21:04
Цитата(megajohn @ Jan 10 2014, 23:53)

сам офигел. Смотрю дизасм, и вызываются либовские aeabi_i2d, __aeabi_ddiv, __aeabi_dadd, __aeabi_cdrcmple
Спасибо!
Уточню: такт - имеется в виду такт процессора? нет ли там какого-либо пересчета (кратности и т.д.).
То есть, действительно ли получается 250 млн тактов процессора / 72мгц = примерно 3,5 сек?
дальше, деление реализовано программно (через библиотеку)?
апппаратное деление бывает? или только в DSP?
megajohn
Jan 10 2014, 21:10
Цитата
Уточню: такт - имеется в виду такт процессора?
да.
Цитата
нет ли там какого-либо пересчета (кратности и т.д.).
пока не наблюдаю
Цитата
То есть, действительно ли получается 250 млн тактов процессора / 72мгц = примерно 3,5 сек?
вроде
Цитата
дальше, деление реализовано программно (через библиотеку)?
да
Цитата
апппаратное деление бывает?
бывает для целочисченных. Смотреть
ссылкудля плавучки ручками, с приведением мантис
Цитата
или только в DSP?
там может и есть. Поспрашивайте кто юзает CM4 или BF или прочее
mantech
Jan 11 2014, 05:40
Может имеет смысл глянуть в сторону STM32F407 или иже с ним (M4F) с аппаратным FPU и 168МГц?
Или обязательное условие double-вычисления?
ЗЫ. Может не совсем в тему, но тестировал на АВР и АРМе сишную вирт. задачу, так производительность арма раз в 15 быстрее (целочисленная 16 и 32х битная арифметика)
Тактовая авр 12МГц АРМ - 168..
AVR 8 разрядов, ARM 32. Понятно что производительность AVR на такой арифметике будет на порядки медленнее. AVR хорош для обрадотки 8-ми битных данных. Тексты, всякие протоколы на основе ASCII через UART и другие 8-ми битные порты. Ногами подрыгать тоже не плохо получается. Если нужны 64-бит вычисления то на AVR и смотреть не стоит.
stells
Jan 11 2014, 07:12
Цитата(slog @ Jan 11 2014, 11:04)

AVR 8 разрядов, ARM 32. Понятно что производительность AVR на такой арифметике будет на порядки медленнее.
http://ru.wikipedia.org/wiki/AVR32
Цитата(megajohn @ Jan 10 2014, 23:18)

с максимальной оптимизацией по скорости получилось:
Можете сам исходный файл показать? Тогда можно будет на разных контроллерах проверить.
ZASADA
Jan 11 2014, 09:01
+1. кидайте законченный код, запущу на авр32 60 мгц
но вообще за счет более высокой тактовой частоты должны выигрывать ARMы с FPU
megajohn
Jan 11 2014, 09:14
Цитата(ViKo @ Jan 11 2014, 12:11)

Можете сам исходный файл показать? Тогда можно будет на разных контроллерах проверить.
дык автар дал же, ну вот
Код
void test(void)
{
#define TT double
// #define TT float
TT a = 1.0;
TT b = 1234.567;
for ( int i = 0; i < 1000000; i++ )
{
a = a + (TT(i) / b );
b = b + 0.000001;
if( a > 100000000 ) a = 1;
}
LPC_TIM0->TCR = (u32)a;
// PORTA = ((int)a) & 0x0F;
}
проверял в симуляторах ( реальной железки не было под рукой ).
для AVR делал max_i = 1000; для CM3 max_i = 100000; и умножал результат.
RomaRoma
Jan 11 2014, 14:04
спасибо всем откликнувшимся
Цитата(megajohn @ Jan 11 2014, 12:14)

проверял в симуляторах ( реальной железки не было под рукой ).
можно ли отталкиваться от этих цифр, которые дал симулятор?
точность порядка +-50% меня вполне устраивает
На что в первую очередь нужно обращать внимание для увеличения производительности ARM (кроме увеличения такт. частоты): наличие аппаратного FPU?
Есть ли заметная (в несколько раз) разница в производительности между различными семействами - ARM9, ARM11, Cortex и т.д., или в принципе они равнозначны, и нужно только выбрать макс. так частоту и аппаратный FPU?
M_Andrey
Jan 12 2014, 12:03
Цитата(megajohn @ Jan 10 2014, 23:18)

для AVR: ( IAR DLIB )
1 725 881 000 тактов для float ( 32 бита )
3 697 655 000 тактов для double ( 64 бита )
В железе: ATMega128 16MHz, замеры времени по TIMER1 плюс прерывание по его переполнению для увеличения разрядности.
float
Time (10000) = 0x00000063 C069 0,4085825625 сек
Time (100000) = 0x000003B3 6C89 3,8806485625 сек
Time (1000000) = 0x0000230D 2135 36,7539393125 сек
double
Time (10000) = 0x00000942 3A67 9,7084544375 сек
Time (100000) = 0x00005AF5 3CA3 95,3763301875 сек
Time (1000000) = 0x0003887D 262C 948,42531475 сек
RomaRoma
Jan 12 2014, 15:58
Цитата(M_Andrey @ Jan 12 2014, 15:03)

В железе: ATMega128 16MHz, замеры времени по TIMER1 плюс прерывание по его переполнению для увеличения разрядности.
float
Time (10000) = 0x00000063 C069 0,4085825625 сек
Time (100000) = 0x000003B3 6C89 0,8806485625 сек
Time (1000000) = 0x0000230D 2135 36,7539393125 сек
double
Time (10000) = 0x00000942 3A67 9,7084544375 сек
Time (100000) = 0x00005AF5 3CA3 95,3763301875 сек
Time (1000000) = 0x0003887D 262C 948,42531475 сек
спасибо.
цифры заставили задуматься, что что-то я не там ищу....Значит мощный x86, и никаких альтернатив
ZASADA
Jan 12 2014, 16:07
дсп еще не щупали.
megajohn
Jan 12 2014, 18:15
Цитата(M_Andrey @ Jan 12 2014, 16:03)

В железе: ATMega128 16MHz, замеры времени по TIMER1 плюс прерывание по его переполнению для увеличения разрядности.
float Time (1000000) = 0x0000230D 2135 36,7539393125 сек
double Time (1000000) = 0x0003887D 262C 948,42531475 сек
чойта странно, при double получилось 15 174 805 036 тактов, при float - 588 063 029 тактов. Смущает кратность в 26 раз.
M_Andrey
Jan 12 2014, 19:12
Цитата(megajohn @ Jan 12 2014, 21:15)

чойта странно, при double получилось 15 174 805 036 тактов, при float - 588 063 029 тактов. Смущает кратность в 26 раз.
Все вопросы к компилятору:
Нажмите для просмотра прикрепленного файла Нажмите для просмотра прикрепленного файла
megajohn
Jan 12 2014, 19:21
Цитата(M_Andrey @ Jan 12 2014, 23:12)

Все вопросы к компилятору:
ну а где D_ADD_L11, D_DIV_L11, SL2D_L11 ?
M_Andrey
Jan 12 2014, 19:58
Ужесточил типы, теперь между double и float разница 8-9-и кратная!
float
Time (10000) = 00000107 BA45 1,0802283125 сек
Time (100000) = 00000A49 CDB9 10,7880595625 сек
Time (1000000) = 0000661C 332D 107,0702588125 сек
double
Time (10000) = 000007AD AF87 8,0514484375 сек
Time (100000) = 00005F37 60E0 99,84155 сек
Time (1000000) = 0003B3B0 8E95 993,7246493125 сек
megajohn
Jan 12 2014, 20:05
Цитата(M_Andrey @ Jan 12 2014, 23:58)

Ужесточил типы, теперь между double и float разница 8-9-и кратная!
float Time (1000000) = 0000661C 332D 107,0702588125 сек
double Time (1000000) = 0003B3B0 8E95 993,7246493125 сек
Чой та я в шоке. Что вообще за компилятор ?
теперь у вас увеличилось время для float почти в три раза, но стало близко к моему с 1% ошибкой ( 1 713 124 141 vs 1 725 881 000 )
но double долго считается по отношению к коду сгенеренному в IAR.
Ruslan1
Jan 12 2014, 22:49
PIC32, 80 MHz (оптимизация средненькая, такую дает бесплатный вариант лицензии MPLAB-C32 компилятора )
CODE
typedef long double f64;
typedef unsigned int u32;
volatile f64 a = 1;
volatile f64 b = 1234.567;
int main(void)
{
u32 i;
//рабочий цикл
for (i=0; i<1e6; i++)
{
a = a + ((f64)i / b );
b = b + 0.000001;
//на всякий пожарный
if (a>100000000) a = 1;
}
return 0;
}
510024595 машинных циклов
6.375307 секунд
Если 32-битные вычисления
Код
typedef float f64;
415782614 мц
5.197283 секунд
M_Andrey
Jan 13 2014, 08:52
Цитата(megajohn @ Jan 12 2014, 23:05)

Чой та я в шоке. Что вообще за компилятор ?
IAR C/C++ Compiler for AVR 5.50.0 (5.50.0.50277)C:\Program Files\IAR EW 5.5\avr\bin\iccavr.exe
14.04.2010 16:14:06, 11579392 bytes
Full DLIB - \avr\LIB\DLIB\dlAVR-3s-ec_mul-64-f.r90
CODE
#define cycle 1000000L
#define TT double
//#define TT float
TT test(void)
{
TT a = (TT)1.0;
TT b = (TT)1234.567;
for (long i = 0; i < cycle; i++)
{
a = a + ( (TT)i / b );
b = b + (TT)0.000001;
if (a > (TT)100000000.0) a = (TT)1.0;
}
return(a);
}
ZASADA
Jan 13 2014, 11:02
avr32 60MHz i = 1 000 000
без оптимизации
double 7,544 сек
float 3,177 сек
на макс оптимизации
double 6,904 сек
float 208 мсек
A. Fig Lee
Jan 13 2014, 13:37
Цитата(ZASADA @ Jan 13 2014, 06:02)

avr32 60MHz i = 1 000 000
без оптимизации
double 7,544 сек
float 3,177 сек
на макс оптимизации
double 6,904 сек
float 208 мсек
208 миллисекунд?
Примерно 12 циклов на операцию?
Чегото слишком оптимистично..
12 миллионов циклов супротив майкрочиповских 500 миллионов?
Не верится..
Это в симуляторе?
ZASADA
Jan 13 2014, 14:01
на реальной плате
причем double не особо круто соптимизировало.
A. Fig Lee
Jan 13 2014, 14:12
Цитата(ZASADA @ Jan 13 2014, 09:01)

на реальной плате
причем double не особо круто соптимизировало.
a ассемблерный код есть посмотреть?
ZASADA
Jan 13 2014, 14:39
Цитата
800036E0 mov R8, 0
800036E2 movhi R7, 0x3f80
800036E6 sub R8, -1
800036E8 cp.w R8, 1000000
800036EC breq 0x8000370e
800036EE cop CP0, CR9, CR0, CR8, 12
800036F2 cop CP0, CR7, CR9, CR5, 14
800036F6 cop CP0, CR0, CR7, CR6, 24
800036FA brvs 0x80003702
800036FE brle 0x800036e6
80003702 movhi R7, 0x3f80
80003706 sub R8, -1
думаю гдето дурит, слишком сильно ускоряет вычисление даже при включение минимальной оптимизации
M_Andrey
Jan 13 2014, 14:41
Кстати, если посмотреть в float числа:
1234.567 = 0x449A 5225
1234.567001 = 0x449A 5225
и только
1234.5671 = 0x449A 5226
и компилятор наверное об этом знает
Ruslan1
Jan 13 2014, 14:41
Цитата(ZASADA @ Jan 13 2014, 16:01)

на реальной плате
причем double не особо круто соптимизировало.
Такое ощущение, что там Ваш никнейм приключился

И оно "соптимизировало" переменные, так как они больше нигде не используются. или цикл "соптимизировало".
Попробуйте их объявить как volatile, ну или посмотрите что там в a и в b после выполнения.
neiver
Jan 13 2014, 14:47
Попробовал на Stm32f407 с использованием аппаратной плавающей точки, получилось 28000000 тактов процессора на 1000000 (миллион) итераций цикла - 28 тактов на итерацию.
Для double нет аппаратной поддержки и результат куда печальнее 1117999516 тактов, ~1118 тактов на итерацию.
Компилятор arm-none-eabi-gcc 4.7.3.
ZASADA
Jan 13 2014, 15:28
а не сокращает, я его после цикла распечатываю =)
наибольший эффект дает ключ -ffast -math, без него при минимальной оптимизации float = 1,992 сек
быстродействие победил =).
b принималось за константу
заменил на
Код
b = b + 0.001;
итоговый результат
без оптимизации float = 3,256 сек
после оптимизации float = 2,64 сек
результаты вычислений в обоих случаев одинаковы, т.е. ничего в цикле не сокращается
RomaRoma
Jan 14 2014, 07:57
всем спасибо
тема закрыта
вижу, что на микроконтроллере такие задачи не решить
megajohn
Jan 14 2014, 08:21
Цитата(RomaRoma @ Jan 14 2014, 11:57)

вижу, что на микроконтроллере такие задачи не решить
теоретически, вам нужен microcontroller with double-precision FPU
это только в ARM9.
к примеру у NXP значится
LPC3180 This CPU coprocessor provides full support for single-precision and double-precisionили искать другие контроллеры с ядром
VFP9-S
Цитата(neiver @ Jan 13 2014, 17:47)

Попробовал на Stm32f407 с использованием аппаратной плавающей точки, получилось 28000000 тактов процессора на 1000000 (миллион) итераций цикла - 28 тактов на итерацию.
Мне кажется, вы ошиблись в 10 раз. Сам пробовал, в симуляторе.
С вашего позволения, предлагаю тест, который 1000 раз вычисляет число Пи (по формуле каких-то трех мудрецов). Тогда можно будет удостовериться, что программа работает правильно.
Код
typedef float tt;
// typedef double tt;
volatile tt pi;
for (int n = 1000; n--; ) {
pi = 4.0 / 1 - 2.0 / 4 - 1.0 / 5 - 1.0 / 6;
for (int i = 1; i < 8; i++) {
tt i8 = i * 8;
tt p = 4 / (i8 + 1) - 2 / (i8 + 4) - 1 / (i8 + 5) - 1 / (i8 + 6);
for (int j = i; j > 0; j--) {
p /= 16;
}
pi += p;
}
}
return pi;
float pi = 3.14159274 (ошибка связана с недостаточной точностью float формата при расчетах)
double pi = 3.141592653589
Keil, STM32, -O3 -Otime, симулятор, тактов на один цикл:
STM32F207: float = 4506, double = 8125
STM32F407, no use FPU: float = 4506, double = 8125
STM32F407, use FPU: float = 662, double = 10094
Последняя цифра меня удивила. Видимо, использование FPU STM32 для double в Keil недоработано.
Цитата(RomaRoma @ Jan 14 2014, 11:57)

всем спасибо
тема закрыта
вижу, что на микроконтроллере такие задачи не решить
на всякий случай - есть микроконтроллеры с поддержкой double FPU
например LPC3xxx (ARM9+FPU)
также у renesas-а есть SH-2|3|4 семейство с 64бит FPU у них и по целым числам получше чем у ARM-ов - может есть и не BGA корпуса
если BGA не смущает, то imx
то есть, микроконтроллеры бывают разные, можно к ПК (типа на атоме Ж

по скорости вычислений приблизиться
Цитата(ViKo @ Jan 14 2014, 14:06)

Последняя цифра меня удивила. Видимо, использование FPU STM32 для double в Keil недоработано.

ну я сам лудить/паять, в тонкую математику не лезу, но наши математики, когда им предлагаю взять замечательный проц без FPU или с 32х битным FPU (что для даблов одноикственно) сразу же с негодованием отвергают и приблизительно такими же соотношениями мотивируют
Добавлю к списку еще MCU на Cortex-R4F, такие тоже есть, например TMS570 и RM4 (например RM48L930), они тоже имеют в составе дабл плавучку (VFPv3), еще ренесас - SuperH ядро, там тоже она есть.
A. Fig Lee
Jan 14 2014, 16:23
Цитата(ViKo @ Jan 14 2014, 05:06)

С вашего позволения, предлагаю тест, который 1000 раз вычисляет число Пи (по формуле каких-то трех мудрецов). Тогда можно будет удостовериться, что программа работает правильно.
Код
typedef float tt;
// typedef double tt;
volatile tt pi;
for (int n = 1000; n--; ) {
pi = 4.0 / 1 - 2.0 / 4 - 1.0 / 5 - 1.0 / 6;
for (int i = 1; i < 8; i++) {
tt i8 = i * 8;
tt p = 4 / (i8 + 1) - 2 / (i8 + 4) - 1 / (i8 + 5) - 1 / (i8 + 6);
for (int j = i; j > 0; j--) {
p /= 16;
}
pi += p;
}
}
return pi;
float pi = 3.14159274 (ошибка связана с недостаточной точностью float формата при расчетах)
double pi = 3.141592653589
Keil, STM32, -O3 -Otime, симулятор, тактов на один цикл:
STM32F207: float = 4506, double = 8125
STM32F407, no use FPU: float = 4506, double = 8125
STM32F407, use FPU: float = 662, double = 10094
Последняя цифра меня удивила. Видимо, использование FPU STM32 для double в Keil недоработано.

для сравнения:
Mac OS X 10.9.1 i7-2.2 GHz:
gcc -O3
10,000,000 cycles
float -
real 0m1.322s
user 0m1.316s
sys 0m0.004s
double -
real 0m2.073s
user 0m2.067s
sys 0m0.004s
ZASADA
Jan 14 2014, 16:45
могу завтра на авр32 запустить=)
A. Fig Lee
Jan 14 2014, 17:24
Цитата(ZASADA @ Jan 14 2014, 11:45)

могу завтра на авр32 запустить=)
ждемс..
ZASADA
Jan 15 2014, 07:56
итак вычисление числа Пи, код ViKo
AVR32, 60MHz, живое железо
float
без оптимизации
cycles= 6 738 017 time=112.3 мсек pi=3.141592741013
с безопасной оптимизацией
cycles= 2 936 003 time=48.90 мсек pi=3.141592741013
оптимизация с ускоренным вычислением float
cycles= 442 001 time=7.37 мсек pi=3.141327857971 - кривое значение в мелких разрядах, зато быстро =)
double
без оптимизации
cycles= 16 482 018 time=274.7 мсек pi=3.141592653589
с безопасной оптимизацией
cycles= 11 361 996 time=189.4 мсек pi=3.141592653589
оптимизация с ускоренным вычислением float
cycles= 11 813 997 time=196.9 мсек pi=3.141592653589 - даже чуть медленнее чем с обычными библиотеками float, но точность не пострадала
mantech
Jan 15 2014, 09:22
Цитата(ZASADA @ Jan 15 2014, 11:56)

итак вычисление числа Пи
Ну дак к чему пришли? Может у кого есть желание сбацать сводную табличку, в процентном выражении от типа проца?
Для просмотра полной версии этой страницы, пожалуйста,
пройдите по ссылке.