Отговори на тема  [ 25 мнения ]  Отиди на страница Предишна  1, 2
STM32 и масив във флаша? 
Автор Съобщение
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Пет Ное 12, 2004 3:38 pm
Мнения: 9103
Местоположение: Chicago, IL
Мнение Re: STM32 и масив във флаша?
Че тя разликата между двата варианта е само в две инструкции, до колкото виждам и не би трябвало да има чак такова забавяне - все пак говорим само за няколко цикъла разлика.
Дали пък няма някаква връзка с това, на който точно адрес е разположена таблица, т.е. как са подравнени данните?


Нед Юли 22, 2012 11:09 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Нед Юни 10, 2007 2:22 pm
Мнения: 6492
Местоположение: София
Мнение Re: STM32 и масив във флаша?
Без да съм се вглеждал в кода (т.е. само гледайки цялата страница наведнъж) не
изглежда да е от компилатора, и деленето си го прави в шифт и т.н.

Изглежда просто дотам са му силиците на процесора, всеки 20-ина uS прекъсване
му идват вповече или нещо такова. Може би може да се оптимизира де, то да преполови
циклите човек и може би е решен проблемът.

_________________
-------------------
www.tgi-sci.com
-------------------
http://www.flickr.com/photos/didi_tgi/


Нед Юли 22, 2012 11:20 pm
Профил WWW
Ранг: Новодошъл
Ранг: Новодошъл

Регистриран на: Чет Яну 04, 2007 12:43 am
Мнения: 178
Мнение Re: STM32 и масив във флаша?
От дисасемблера се вижда, че варианта с таблицата се различава само с две инструкции. Може би просто си достигнал пределната производителност на този чип и малко допълнително забавяне скапва работата.
Евентуално може да опиташ да "изцедиш" още малко производителност, ако преобразуваш всички операции в 32-битови - тогава няма да се налага да се "отсича" горната половина на резултата с допълнителна инструкция. Но печалбата може би ще е нищожна.
Друг трик за ускоряване е inline-ване на циклите - вместо цикъл с осем итерации, например, може да използваш линеен код, за да избегнеш изпразването на конвейра при преходите. Разбира се, кодът ще нарастне доста, но само в критичната си част.
Предполагам, че всички тонове се обработват в рамките на едно прекъсване (т.е. няма многократно влизане и излизане в рамките на един тик от 1/48000).
Също, ако използваш интензивно DMA, той "краде" цикли от ядрото при опит да се достъпи една и съща памет и това може допълнително да намалява производителността.
И наистина, добре е да измериш колко време ти отнема обработката на прекъсването. Тогава би могъл и да оцениш как влияят различните промени в кода върху времето за изпълнение.


Нед Юли 22, 2012 11:25 pm
Профил
Ранг: Почетен член
Ранг: Почетен член

Регистриран на: Съб Май 27, 2006 12:37 pm
Мнения: 647
Местоположение: с. Згалево
Мнение Re: STM32 и масив във флаша?
Ето новите тестове:
Направих промяна в програмката, 2 прости функции, с единствената разлика че в едната се ползва индекса в изчислението на семпъла, а в другата със същия интдекс се вади от таблицата и взетото от таблицата се ползва вече за изчисление на семпъла.

Пускам по 1 000 000 извиквания на функциите и гледам до къде е стигнал таймера...

Изводи:
При първия вариант без участието на масива таймера стига до 678.
При втория вариант, с участие на масива, таймера стига до 867, което е около 128% от първия резултат.
Е сега въпроса е много ли е малко ли е???

Отделно в реалния код, през време на тая цялата работа SDIO модула чете с DMA от картата, ама то е с по-нисък приоритет, така че горния код не би трябвало да се прекъсва от нищо. Отделно дето ДМА-то пише в рама а не във флаша, така че не би трябвало да има значение.
Като цяло - явно падането на производителността с близо 30% ми идва много та от там и проблемите...

Следващия въпрос е, дали има някакъв начин да се оптимизират малко нещата.
Това което открих е, че мога да направя променлива от тип u16 в която да сложа стойността на o->envelope_position.hi.hi. Да правя всичко с тая променлива и накрая да върна стойността пак в o->envelope_position.hi.hi. По тоя начин свалям показанието на таймера от 867 на 825, ама пак няма да ми е достатъчно...


Прикачени файлове:
Коментар на файл: асемблера
3.jpg
3.jpg [ 276.25 KiB | Прегледано 2403 пъти ]
Коментар на файл: кода на самите функции
2.jpg
2.jpg [ 92.59 KiB | Прегледано 2403 пъти ]
Коментар на файл: Тестовия код, който вика функциите.
1.jpg
1.jpg [ 142 KiB | Прегледано 2403 пъти ]
Пон Юли 23, 2012 11:32 am
Профил WWW
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Нед Сеп 26, 2004 4:11 pm
Мнения: 3750
Местоположение: София
Мнение Re: STM32 и масив във флаша?
Не съм се задълбавал в кода, но някои неща не ми харесаха:
1. Пипането в таблица е придружено от индексиране, като индексът е поинтър->структура ( в общия случай размерът й НЕ е 2^N ) . елемент от структура . елемент от структура. ТОВА се изчислява БАВНО.
2. Някои хватки не са ми ясни: инициализираш локалната променлива value с някаква стойност и на следващия ред я коригираш ( с контстантна поправка ).
3. Не знам IAR колко е умен, но може да се наложи ти да му "подскажеш", че /65536 може да се направи със заигравка с поинтерите. Тук обаче е важно какво ти е ядрото : малък индианец или голям индианец. Е, няма да може да е "register".
4. Ти от цялата структура "о" ( Четох за историята на О ) ползваш само едно елементче, на която май 2 пъти му се изчислява адресът. Не може ли да подадеш като аргумент това, а не адреса на цялята структура. Това е малко грозно, но когато се гонят скорости се правят компромиси. Като алтернативен вариант вътре във функцията можеш да си сметнеш поинтър към "елементчето" и да го ползваш него.


Пон Юли 23, 2012 12:02 pm
Профил ICQ
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Нед Фев 26, 2006 6:52 pm
Мнения: 11266
Местоположение: Добрич
Мнение Re: STM32 и масив във флаша?
juzisound написа:
Ето новите тестове:


баси толкова ли е трудно да си направиш анализ, а?

викане на процедура (BL ...) ти е 3 клока
връщане (BX LR) ти е 3 клока.
четене ти е 2+WS клока (за RAМ WS=0)
записа ти е 1+WS (за RAМ WS=0)
всичко останало ти е 1 клок.

Първата процедура ти е 3+2+1+1+(2+WS) + 1+1+1+1+3 = 16+WS
Втората 3+2+1+1+(2+WS)+(2+WS)+(2+WS)+1+1+1+1+3 = 20+3*WS.

Към това добавяш цикъла.. не си дал дизасемблер. Ако е оптимизиран ще е един декремент (1клок) + преход (3клока) общо 4 клока. Ако не е оптимизиран може да е сравнение с регистър + инкремент + преход = 5 клока. Ако изобщо не е оптимизиран ще има и зареждане на регистъра още 2 клока.

Нека да приемем че цикъла е оптимизран т.е. 4 клока, тогава:
при 0 WS имаш 20 срещу 24 клока т.е. 120% както ти смяташ процентите....
при 1 WS имаш 21 срещу 27 клока т.е. 128%
при 2 WS имаш 22 срещу 30 клока т.е. 136%

Може да сметнеш % и при различни оптимизации на цикъла, но при всички случаи се получава че флаша ти е 1WS, a не 2...

Останалите изводи се надявам сам да може да си ги направиш, но очевидно нямаш никакво претоварване на флаша.... Просто така си работят нещата!


Пон Юли 23, 2012 12:38 pm
Профил
Ранг: Почетен член
Ранг: Почетен член

Регистриран на: Съб Май 27, 2006 12:37 pm
Мнения: 647
Местоположение: с. Згалево
Мнение Re: STM32 и масив във флаша?
Това за value не го гледай. Важното е че е еднакво и за двата случая. Примерите не са реален код. Оставил съм някои основни операции с value примерно, не за друго, ами щото инак компилатора прави хитрини в асемблера ако ги няма. В оригиналния код тия функции са много много по-големи и правят много повече неща...

Индекса o->envelope_position.hi.hi е един вид 32 битова променлива, която нараства с определена скорост, ама за индексиране се ползват само горните 16 бита. Един вид акумулатор...

Относно делението на /65536 - обърни внимание, че value е от тип SIGNED 32. Не знам дали за сигнед става с ротация или с взимане на горните битове... Тоест пробвал съм и знам че НЕ става с ротация.

Относно o->envelope_position.hl.hi, няма по ефективен метод от извличане на стойност в променлива, и ползване на тая променлива вместо o->envelope_position.hi.hi. В реалния код o->envelope_position.hl.hi не се манипулира самостоятелно като 16 битова стойност. Всички манипулации са върху целия акумулатор o->envelope_position.all, което е цялата 32 битова променлива.


Пон Юли 23, 2012 12:47 pm
Профил WWW
Ранг: Почетен член
Ранг: Почетен член

Регистриран на: Съб Май 27, 2006 12:37 pm
Мнения: 647
Местоположение: с. Згалево
Мнение Re: STM32 и масив във флаша?
miro_atc написа:

Може да сметнеш % и при различни оптимизации на цикъла, но при всички случаи се получава че флаша ти е 1WS, a не 2...

Останалите изводи се надявам сам да може да си ги направиш, но очевидно нямаш никакво претоварване на флаша.... Просто така си работят нещата!


Флаша със сигурност е на 2 цикъла. Извадка от кода:

// Enable Prefetch Buffer
FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);

// Flash 2 wait state
// FLASH_Latency_0 - zero wait state, if 0 < SYSCLK . 24 MHz
// FLASH_Latency_1 - one wait state, if 24 MHz < SYSCLK . 48 MHz
// FLASH_Latency_2 - two wait states, if 48 MHz < SYSCLK . 72 MHz
FLASH_SetLatency(FLASH_Latency_2);

Предполагам че Prefetch Buffer-а има намеса в твоите сметки да изглежда че е само 1.

А иначе, че просто така си работят нещата е най-лошия възможен вариант... :(
Така се надявах аз да съм го омазал някъде...


Пон Юли 23, 2012 12:57 pm
Профил WWW
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Нед Сеп 26, 2004 4:11 pm
Мнения: 3750
Местоположение: София
Мнение Re: STM32 и масив във флаша?
Ако не е голям секрет, може да опитаме да оптимизираме нещата на нивото "С".


Пон Юли 23, 2012 1:04 pm
Профил ICQ
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Нед Фев 26, 2006 6:52 pm
Мнения: 11266
Местоположение: Добрич
Мнение Re: STM32 и масив във флаша?
Мда забравил съм WS при префетча, т.е. влизане/излизане ти е 3 + 2*WS, в цикъла също имаш един преход...
т.е. при оптимизиран цикъл едната процедура е 20 + 4*WS, другата е 24+6*WS т.е. 28 срещу 36 клока (пак 128%)

Ако знаеш колко ти е таймера може да го провериш... Едната процедура при 1 млн итерации трябва да се изпълни за около 380 mS, другата точно половин секунда.

juzisound написа:
Така се надявах аз да съм го омазал някъде...


е не... по-добрият вариант е да знаеш как работят ;-)

Реално имаш процесор дето на 72MHz може да направи 72 милиона умножения, хайде нека да са 36 милиона щото умножението може да е 2 клока. Но като го вкараш това в процедура и цикъл падаш на половин милион. А в реална ситуация споменаваше прекъсвания, там овърхеда е още по-голям.

Разбира се, няма как да стане проца да прави само сметки, сметки... трябва да се прави и черната работа, т.е. да се зареждат/извеждат данни и т.н. Но е важно да разбереш какво точно може да се прави бързо и какво те бави. Пак ще повторя - от 30 милиона операции с лекота падаш под 0.3 т.е. 100 пъти разлика между теория и практика.
Опитай се да не го накъсваш. По възможност (не ти знам алгоритмите) пробвай да зареждаш с load multiple вместо с единични load. Съответно в едно влизане в процедура смятай няколко семпъла, а не един. Идеята е да разхвърлиш овърхеда не на една полезна операция, а на група операции...


Пон Юли 23, 2012 1:27 pm
Профил
Покажи мненията от миналия:  Сортирай по  
Отговори на тема   [ 25 мнения ]  Отиди на страница Предишна  1, 2

Кой е на линия

Потребители разглеждащи този форум: 0 регистрирани и 6 госта


Вие не можете да пускате нови теми
Вие не можете да отговаряте на теми
Вие не можете да променяте собственото си мнение
Вие не можете да изтривате собствените си мнения
Вие не можете да прикачвате файл

Търсене:
Иди на:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group.
Designed by ST Software for PTF.
Хостинг и Домейни