|
|
  |
Ассемблерная оптимизация маленького куска (порядка 10-15 инструкций) |
|
|
|
Feb 27 2016, 07:57
|
Гуру
     
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713

|
Цитата(Himmler @ Feb 27 2016, 13:41)  Примерно получается (если считать, что входное слово, 12-битная маска, адреса таблиц уже загружены,регистры сохранены, и таблиц всего 3 по 12/12/8 бит): Не понимаю - почему Вы выбрали 12/12/8, а не 11/11/10? Ведь первый вариант требует 16896 байт таблиц, в то время как 2-ой - только 10240.  Цитата(Himmler @ Feb 27 2016, 13:41)  ldr r1, [r4, r1]; загружаем младшие 12 бит (r4 был предварительно загружен и будет ещё многократно использоваться) ldr r2, [r5, r2, LSR #12]; загружаем средние 12 бит (r5 был предварительно загружен и будет ещё многократно использоваться) ldr r3, [r6, r0, LSR #24]; загружаем старшие 8 бит (r6 был предварительно загружен и будет ещё многократно использоваться) Забываете, что читаете не байты, а слова. Надо сдвинуть все индексы влево на 1 бит. Так что кол-во команд будет на 1 больше. И команды не LDR, а LDRH.
|
|
|
|
|
Feb 27 2016, 08:20
|
Участник

Группа: Участник
Сообщений: 17
Регистрация: 24-06-11
Пользователь №: 65 868

|
В моём случае не принципиально 10 килобайт или 16, а дискреты в 4 бита мне удобнее для пересчёта таблиц из их первоначального вида (где было 8 таблиц по 16 4-битных значений в каждой) Насчёт не байты, а слова - да, лопухнулся, написал как было раньше, когда было 4 однобайтовых таблицы. Сдвигать нужно на 1 бит индексы у двух таблиц, третья осталась однобайтовой. Только вот не понял, откуда ещё 1 команда, вроде же достаточно поменять на код вида Код ldr r1, [r4, r1, LSL#1]; загружаем младшие 12 бит (r4 был предварительно загружен и будет ещё многократно использоваться) ldr r2, [r5, r2, LSR #11]; загружаем средние 12 бит (r5 был предварительно загружен и будет ещё многократно использоваться) ldr r3, [r6, r0, LSR #24]; загружаем старшие 8 бит (r6 был предварительно загружен и будет ещё многократно использоваться)
Сообщение отредактировал Himmler - Feb 27 2016, 14:31
|
|
|
|
|
Feb 27 2016, 08:25
|
Гуру
     
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713

|
Вы упорно пишете LDR, хотя Вам надо грузить 16-битные слова Доп. команда добавляется если использовать 11/11/10 рассечение (нужно маскировать и сдвинуть старшие 10бит, а это не получится сделать сразу в LDRH). Ок, тогда оставим 12/12/8. Тогда получим: Код ;исх. данные: ;R0 - аргумент; ;R7 = 0x1FFE AND R1, R7, R0, LSL #1;получаем индекс*2 в первой таблице AND R2, R7, R0, LSR #12-1;получаем индекс*2 во второй таблице LDRH R1, [R4, R1];загружаем младшие 12 бит (r4 был предварительно загружен и будет ещё многократно использоваться) LDRH R2, [R5, R2];загружаем средние 12 бит (r5 был предварительно загружен и будет ещё многократно использоваться) LDRB R3, [R6, R0, LSR #24];загружаем старшие 8 бит (r6 был предварительно загружен и будет ещё многократно использоваться) ADD R1, R1, R2, LSL #12;собираем 3 куска в одно 32-битное слово ADD R1, R3, LSL #24
|
|
|
|
|
Feb 27 2016, 08:32
|
Участник

Группа: Участник
Сообщений: 17
Регистрация: 24-06-11
Пользователь №: 65 868

|
Опять же согласен, вгружать 32-битные слова неправильно.
То есть на данный момент 7 тактов. Больше нигде и ничего не срезать ?
|
|
|
|
|
Feb 28 2016, 00:15
|
Частый гость
 
Группа: Участник
Сообщений: 182
Регистрация: 16-10-15
Пользователь №: 88 894

|
LDRB R3, [R6, R0, LSR #24] - это наверное из другой вселенной. В скобках адрес, при этом модификации подвергается последний регистор в записи, и двигать (умножать) его можно исключительно в лево, и число для модификации от единицы до трёх, и чтение байта с такой модификацией - теряет смысл, ибо глюканёт на несоответствии объявленных границ выравнивания переменных и зарегистрированной командой. В целом трешь и угар, выдыхайте  .
Сообщение отредактировал AVI-crak - Feb 28 2016, 00:16
|
|
|
|
|
Feb 28 2016, 11:33
|
Участник

Группа: Участник
Сообщений: 17
Регистрация: 24-06-11
Пользователь №: 65 868

|
К сожалению прямо сейчас у меня железяки и полноценного ide под рукой нету, смогу только завтра проверить.
Но ARMSim#.191, onlinedisassembler.com и ARM instruction evaluator прекрасно переварили такой код, взаимно понимая друг друга и отлично ассемблируя/дизассемблируя результаты друг друга. В частности LDRB R3, [R6, R0, LSR #24] (машинный код E7D63C20) делает именно то, что задумывалось.
|
|
|
|
|
Mar 2 2016, 18:16
|
Участник

Группа: Участник
Сообщений: 17
Регистрация: 24-06-11
Пользователь №: 65 868

|
Извиняюсь за задержку, сегодня проверил код, погонял на разных входных данных - работает именно так, как нужно Код ;R0 - используется другим куском кода ;R1 - используется другим куском кода ;R2 - здесь храним кусок (12 бит) :R3 - здесь храним второй кусок (12 бит) ;R4 = in_data ;R5 = table_0_pointer = 0x4000 ;R6 = table_1_pointer = 0x6000 ;R7 = table_2_pointer = 0x3F00 ;R8 = mask (0x1FFE) ;R9-R14 - используется другим куском кода
AND R2, R8, R4, LSL #1 AND R3, R8, R4, LSR #11 LDRH R2, [R5, R2] LDRH R3, [R6, R3] LDRB R4, [R7, R4, LSR #24] ADD R2, R2, R3, LSL #12 ADD R2, R2, R4, LSL #24 Поглядел на весь код в целом - было бы очень хорошо сэкономить два регистра. Ну или хотя бы один. Предположительно, это можно как-нибудь сделать, не храня все три адреса в R5, R6 и R7, а храня один их них, а два других -вычисляя на лету. Но тут я столкнулся с тем, что LDRH не хочет делать сдвиги и суммирования, как это делают LDR и LDRB. Можно ли тут как-нибудь извернуться ? Разумеется, не увеличивая число инструкций.
|
|
|
|
|
Mar 3 2016, 16:38
|
Участник

Группа: Участник
Сообщений: 17
Регистрация: 24-06-11
Пользователь №: 65 868

|
Сегодня начал мерить производительность кода и познакомился с кучей неприятных сюрпризов архитектуры ARM.
Во-первых блокировка при загрузке байт/слов составляет не один такт, а два. Во-вторых все сдвиги, прилепленные к командам, совсем не бесплатные, и тоже добавляют блокировку на использование сдвигаемого регистра на один такт.
Возможно, есть что-то ещё, и в результате приведённый мной выше код работает правильно, но в два раза дольше, чем я ожидал.
Единственное, что сразу пришло на ум и чуть-чуть ускорило выполнение - перенос одной команды загрузки слова на пораньше. Но особой погоды это не сделало.
Поэтому актуален следующий вопрос:
Как можно изменить код (в том числе с добавлением команд и расходованием доп. регистров), чтобы уменьшить именно количество тактов при выполнении ?
|
|
|
|
|
Mar 4 2016, 09:37
|
Местный
  
Группа: Участник
Сообщений: 319
Регистрация: 27-09-07
Пользователь №: 30 877

|
Цитата(Himmler @ Mar 3 2016, 19:38)  Сегодня начал мерить производительность кода и познакомился с кучей неприятных сюрпризов архитектуры ARM.
Во-первых блокировка при загрузке байт/слов составляет не один такт, а два. Во-вторых все сдвиги, прилепленные к командам, совсем не бесплатные, и тоже добавляют блокировку на использование сдвигаемого регистра на один такт.
Возможно, есть что-то ещё, и в результате приведённый мной выше код работает правильно, но в два раза дольше, чем я ожидал.
Единственное, что сразу пришло на ум и чуть-чуть ускорило выполнение - перенос одной команды загрузки слова на пораньше. Но особой погоды это не сделало.
Поэтому актуален следующий вопрос:
Как можно изменить код (в том числе с добавлением команд и расходованием доп. регистров), чтобы уменьшить именно количество тактов при выполнении ? а развернуть цикл, и конвертировать паралельно 2 числа, может както уменьшить простои?
|
|
|
|
|
Mar 4 2016, 14:41
|
Частый гость
 
Группа: Участник
Сообщений: 182
Регистрация: 16-10-15
Пользователь №: 88 894

|
Цитата(Himmler @ Mar 3 2016, 23:38)  Сегодня начал мерить производительность кода и познакомился с кучей неприятных сюрпризов архитектуры ARM. Это наверное ваша команда чтения из памяти виновата LDRB R3, [R6, R0, LSR #24] У старенького arm926 - ядро ARM7TDMI, и его команды имеют чёткое описание http://www.gaw.ru/html.cgi/txt/doc/micros/...tmi/insruct.htmФормат чтения памяти : [Rn, +/-Rm, LSR #5bit_shift_imm] , но в реальности LSR-LSL - это пятый бит смещения, а нулевой бит просто не участвует в операции - и того 3 бита смещения. То-есть как у всех ARM чипов.
|
|
|
|
|
Mar 4 2016, 14:51
|
Гуру
     
Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136

|
Цитата(AVI-crak @ Mar 4 2016, 17:41)  У старенького arm926 - ядро ARM7TDMI Это что-то новенькое Цитата(AVI-crak @ Mar 4 2016, 17:41)  и его команды имеют чёткое описание Да. См. тут.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|