Перейти к содержанию
    

AT32F437: эффективность работы команд под WS0

В 12.08.2023 в 23:55, jcxz сказал:

Вот именно: 4 + 4 = 8   Первый класс школы, если что  :wink:

LDRD - это загрузка двух 32-битных слов (данные занимают 2 * 4 байта = 8 байт). Плюс сама команда 4 байта. 8 + 4 = 12 байт.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

29 минут назад, adnega сказал:

LDRD - это загрузка двух 32-битных слов (данные занимают 2 * 4 байта = 8 байт). Плюс сама команда 4 байта. 8 + 4 = 12 байт.

:wacko2:

Изначально я вам советовал применить команду:

14 часов назад, jcxz сказал:

Не хватает варианта с заменой этого на одну LDRD R5, R6, =0x40020418  :wink:

Но такая команда не скомпилится.

Я ошибся. Беру свои слова обратно. :vava:

 

PS: 8 байт должны занять:

LDR R5, =0x40020418
LDR R6, =0x40020418

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В 13.08.2023 в 01:01, jcxz сказал:

Но такая команда не скомпилится.

"=imm32" я понимаю как "[PC, label]". Команда "LDRD R5, R6, [PC, label]" компилируется, и листинг я приводил (данные лежат по метке "cc"):

80052bc: e9df 5604   ldrd  r5, r6, [pc, #16] ; 80052d0 <cc>
..
080052d0 <cc>: 
80052d0: 40020418  .word 0x40020418                                                                                                                           
80052d4: 40020418  .word 0x40020418 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В 13.08.2023 в 01:01, jcxz сказал:

PS: 8 байт должны занять:

LDR R5, =0x40020418
LDR R6, =0x40020418

Ммм..

; 20.4ns = 6t
; LDR   R5, =0x40020418                                                                                                                                        
800530a: 4d04        ldr r5, [pc, #16] ; (800531c <cc+0x3c>)                                                                                                   
; LDR   R6, =0x40020418                                                                                                                                        
800530c: 4e03        ldr r6, [pc, #12] ; (800531c <cc+0x3c>)

800531c: 40020418  .word 0x40020418

Да 8 байт. Но какой толк от второй команды, когда есть MOV ?

Пока делаю вывод, что у МК с WS0 для кода самая быстрая загрузка imm32 будет с использованием MOV/MOVT, но более расточительна по памяти.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

4 часа назад, adnega сказал:

Ммм..

; 20.4ns = 6t
; LDR   R5, =0x40020418                                                                                                                                        
800530a: 4d04        ldr r5, [pc, #16] ; (800531c <cc+0x3c>)                                                                                                   
; LDR   R6, =0x40020418                                                                                                                                        
800530c: 4e03        ldr r6, [pc, #12] ; (800531c <cc+0x3c>)

800531c: 40020418  .word 0x40020418

Да 8 байт. Но какой толк от второй команды, когда есть MOV ?

В данном случае - никакой. Это ведь был тест для сравнения разных вариантов загрузки.

4 часа назад, adnega сказал:

Пока делаю вывод, что у МК с WS0 для кода самая быстрая загрузка imm32 будет с использованием MOV/MOVT, но более расточительна по памяти.

Не факт. Если имеется последовательность:

LDR R0, [PC, #imm]   ;загрузка const из адреса PC+imm
LDR R1, [R2]

И последовательность, грузящая ту же константу, но с помощью с MOV/MOVT:

MOV  R0, #0x0418                                                                                                                   
MOVT R0, #0x4002
LDR  R1, [R2]

То первый вариант может на CM4+ выполниться за 3 или за 4 такта; а 2-й вариант = всегда 4 такта.

За счёт декодирования адреса второй LDR во время выполнения первой LDR (согласно тому документу, что я приводил выше). Хотя не уверен, в данном случае сработает конвееризация. Надо проверять.

Ну и размер у 1-го варианта меньше, а значит косвенно это тоже может увеличивать скорость.

4 часа назад, adnega сказал:

"=imm32" я понимаю как "[PC, label]". Команда "LDRD R5, R6, [PC, label]" компилируется

Я писал не про LDRD R5, R6, [PC, label], а про LDRD R5, R6, =imm32.

По крайней мере на IAR.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

У LDR(D) по описанию ARM последний операнд строго адрес в памяти. Транслятор IAR видимо не требует обязательного ввода квадратных скобок для адресов, типа режим MASM на х86. Хотя мне по душе режим TASM IDEAL, где за такое бьют по рукам.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Нашел ошибку у себя: задал частоту процессора вдвое меньше (144 против 288).

Но результаты исследования были очень полезны! Я поигрался с памятью, с оптимизацией и вот что получилось.

Попробовал поиграться с взятием из памяти - получилось улучшить. Пример (R0 = 0x20001A7C, R2 = 0x20001A80, R4 = 0x20001A84):

                 LDR R1, [R0]
                ADD R1, #0
                STR R1, [R0]
                
                LDR R3, [R2]
                ADD R3, #0
                STR R3, [R2]
                
                LDR R5, [R4]
                ADD R5, #0
                STR R5, [R4]

выполняется 49 нс (14 тактов), а последовательность

                LDR R1, [R0]
                LDR R3, [R2]
                LDR R5, [R4]
                
                ADD R1, #0
                STR R1, [R0]
                
                ADD R3, #0
                STR R3, [R2]
                
                ADD R5, #0
                STR R5, [R4]

выполняется 42 нс (12 тактов).
(Да, я мерил своим любимым GPIO, но все сходится). В принципе, разница невелика, но есть.

Да, AT действительно работает быстрее STM. Поэтому, если речь идет об оптимизации, то лучше, если будет длительная вычислительная цепочка.
Т.е. взял значения - и долго-долго обрабатываешь, потом кладешь.

Но, если говорить о целочисленных вычислениях, то взять значения особо-то и некуда - регистров всего 12. Иное дело обстоит с регистрами FPU - их 32.

Но AT работает быстрее! Так, я запустил весь алгоритм (без оптимизации!), и получилось, что эффективность возросла где-то на 30-40 % (собственно, пропорционально тактовой частоте - 288/216 МГц).

Выводы.
1. AT на Cortex-M4 работает быстрее во всех отношениях, чем STM на Cortex-M7.
2. Оптимизация при целочисленных вычислениях не имеет смысла - мало регистров, да и процесс, как правило, один.
3. Оптимизация при "плавучных" вычислениях даст превосходный результат, т.к. есть 32 FPU регистра.
4. Если программа, требующая быстрой работы (0WS), до 512 кБ, то не надо кэшировать ее, создавать системы управления памятью - она сама грузится в SRAM и работает быстро.
5. Цена где-то в 2-3 раза ниже у китайца.

Резюме: выбираю китайца AT32F437, всё закладываю под него. Но делаю так, чтобы можно было запаять STM32F745.

Всем спасибо!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

3 часа назад, dmitrykhom сказал:

                ADD R1, #0

Если бы вместо этого, написали бы: ADDS R1, #0, то было бы ещё лучше.

3 часа назад, dmitrykhom сказал:

1. AT на Cortex-M4 работает быстрее во всех отношениях, чем STM на Cortex-M7.

При одной и той же частоте CPU?

3 часа назад, dmitrykhom сказал:

2. Оптимизация при целочисленных вычислениях не имеет смысла

Не согласен. Не всё решается количеством регистров.

3 часа назад, dmitrykhom сказал:

3. Оптимизация при "плавучных" вычислениях даст превосходный результат, т.к. есть 32 FPU регистра.

Опять не факт. Команды FPU как правило - длиннее, и кроме того - часто их требуется больше, чем при аналогичных целочисленных вычислениях (условные вевтвления, преобразования к/от целочисленным значениям и т.п.).

Так что очень часто - как раз наоборот.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

3 часа назад, dmitrykhom сказал:

Но результаты исследования были очень полезны! Я поигрался с памятью, с оптимизацией и вот что получилось.

Весьма странные результаты у Вас получились...

Я сейчас проверил на STM32F4, код

LDR R1, [R0] ; +2
LDR R3, [R2] ; +1
LDR R5, [R4] ; +1

ADD R1, #0   ; +1
STR R1, [R0] ; +2

ADD R3, #0   ; +1
STR R3, [R2] ; +2

ADD R5, #0   ; +1
STR R5, [R4] ; +2

выполняется 13 тактов (смотрю CYCCNT). И это законно, ибо соответствует документации на Cortex-M4 (рядом подписал CPI).

Код

LDR R1, [R0] ; +2
ADD R1, #0   ; +1
STR R1, [R0] ; +2

LDR R3, [R2] ; +2
ADD R3, #0   ; +1
STR R3, [R2] ; +2

LDR R5, [R4] ; +2
ADD R5, #0   ; +1
STR R5, [R4] ; +2

выполняется 15 тактов, и это тоже законно, ибо соответствует растактовке (опять же, рядом подписал такты выполнения).

Я не понимаю, что Вы там измеряете, получая меньшее кол-во тактов. Очень вряд ли китайцы допилили Cortex-M4, сократив циклы.

Причем, я могу таких блоков инструкций наплодить весьма много, и результат будет пропорционален. А попробуйте и Вы - тоже будет кратно 14 тактам? Раз в 10 блок инструкций увеличьте.
 

Цитата

1. AT на Cortex-M4 работает быстрее во всех отношениях, чем STM на Cortex-M7.

Только за счет большей частоты. И только. У Cortex-M7 - многостадийный декодер с несколькими исполнительными конвейерами, что дает ему возможности внеочередного исполнения потока команд. Это может быть весьма эффективно, особенно, если компилятор прошаренный и умеет нормально тасовать команды.
 

Цитата

2. Оптимизация при целочисленных вычислениях не имеет смысла - мало регистров, да и процесс, как правило, один.
3. Оптимизация при "плавучных" вычислениях даст превосходный результат, т.к. есть 32 FPU регистра.

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

FPU регистры удобны только их наличием для разовой загрузки из памяти и обратно.
 

Цитата

5. Цена где-то в 2-3 раза ниже у китайца.

Ну это да. Хотя бывает, что можно урвать STM32 (если были заложены изначально в проект) по весьма неплохой цене.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

26 минут назад, Arlleex сказал:

Весьма странные результаты у Вас получились...

У Вас - тоже :wink2:

26 минут назад, Arlleex сказал:

Я сейчас проверил на STM32F4, код

LDR R1, [R0] ; +2
LDR R3, [R2] ; +1
LDR R5, [R4] ; +1

ADD R1, #0   ; +1
STR R1, [R0] ; +2

ADD R3, #0   ; +1
STR R3, [R2] ; +2

ADD R5, #0   ; +1
STR R5, [R4] ; +2

выполняется 13 тактов (смотрю CYCCNT). И это законно

Это странно. Так как при наличии write buffer, операции STR должны бы занимать по такту. У вашего МК нет WB?

Померил сейчас этот код на XMC4700 = 11 тактов. Т.е. - на 1 такт больше, чем должно быть (видимо влияние предвыборки или ещё чего).

26 минут назад, Arlleex сказал:

Код

LDR R1, [R0] ; +2
ADD R1, #0   ; +1
STR R1, [R0] ; +2

LDR R3, [R2] ; +2
ADD R3, #0   ; +1
STR R3, [R2] ; +2

LDR R5, [R4] ; +2
ADD R5, #0   ; +1
STR R5, [R4] ; +2

выполняется 15 тактов, и это тоже законно, ибо соответствует растактовке (опять же, рядом подписал такты выполнения).

На XMC4700 = 12 тактов. Что тоже законно, так как работает WB.  :unknw:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Да, каюсь:vava:. Ошибся в измерении. У меня тоже сейчас 11 тактов получилось.

Причем действительно 11 тактов, даже если наплодить этих блоков друг за другом и посмотреть, насколько изменяется CYCCNT. Ровно 11 тактов.

Видимо последний STR выполняется 2 такта, ибо добавление ADD R5, #0 в конце блока тоже дает 11 тактов.

А вот второй пример дает ровно 15 тактов. Добавление одного и того же куска кода прибавляет ровно по 15 тактов.

При этом включенный/отключенный prefetch buffer вообще не влияет на такты.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 час назад, Arlleex сказал:

А вот второй пример дает ровно 15 тактов.

Йес! :dance4: Значит XMC оказался круче! :bb:

:biggrin:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 минуты назад, jcxz сказал:

Йес! :dance4: Значит XMC оказался круче! :bb:

:biggrin:

Самое забавное, что я стал гуглить, не один ли я счастливый обладатель такой особенности - и нет, не один))

Оказывается, при чтении из обычной области ОЗУ, одиночный LDR в любом месте кода занимает 3 такта.

Если за LDR есть еще LDR - они конвейеризуются до 1 такта. Т.е. портянка типа

LDR
LDR
LDR

будет выполнена за 5 тактов:russian_ru:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

3 минуты назад, Arlleex сказал:

Оказывается, при чтении из обычной области ОЗУ, одиночный LDR в любом месте кода занимает 3 такта.

Разве? Вы же сами приводили растактовки для варианта 2, где написали "2 такта". Да и мои эксперименты на XMC4700 это подтверждают. Если бы отдельная LDR во втором тесте выполнялась за 3 такта, то одна из последующих за ней ADD или STR должны были выполниться за 0 тактов.  :vava:

Во-вторых - открываем тот документ, ссыль на который я приводил выше и читаем на стр.2:

Цитата

CORTEX-M4 INSTRUCTION TIMING 

— LDR R0,[R1,R5]; LDR R1,[R2]; LDR R2,[R3,#4] - normally 4 cycles total.

:unknw:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

7 минут назад, jcxz сказал:

Во-вторых - открываем тот документ, ссыль на который я приводил выше и читаем на стр.2:

:unknw:

Дак это для теоретически голого процессора в TRM на Cortex-M4 указаны такты.

А в реальном МК надо еще учитывать, что между памятью и процессором есть матрица шин, к которой еще и отладчик подключен и ему тоже надо уступать пользование System Bus (просто мне так проще было на коленке собрать "смотрелку" тактов).

Я интереса ради пробую LDR грузить из CCM-памяти (она висит на D-bus процессора, в обход матрицы шин) - LDR - 2 такта. А из SRAM-регионов - 3 такта на первый LDR.

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...