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

Генитальная оптимизация

Написал:

volatile bool  Busy;
....

while ( Busy ) ;

На оптимизации -O3 в Кейле получаю:

0x000015C8 782C      LDRB          r4,[r5,#0x00]
0x000015CA B134      CBZ           r4,0x000015DA
0x000015CC 782F      LDRB          r7,[r5,#0x00]
0x000015CE B127      CBZ           r7,0x000015DA
0x000015D0 782F      LDRB          r7,[r5,#0x00]
0x000015D2 B117      CBZ           r7,0x000015DA
0x000015D4 782F      LDRB          r7,[r5,#0x00]
0x000015D6 2F00      CMP           r7,#0x00
0x000015D8 D1F6      BNE           0x000015C8

Вот интересно, с какого перепугу компилятор разворачивает цикл, который ничего не делает, кроме как тупо ждёт изменение значения переменной?..

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


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

Скорее всего чтобы более эффективно загрузить конвейер и уменьшить задержку выхода из цикла ценой некоторого раздувания кода.

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


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

если в этом и есть какой-то смысл, - среднее количество тактов реакции на изменение значения Busy будет меньше

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


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

12 минут назад, makc сказал:

Скорее всего чтобы более эффективно загрузить конвейер и уменьшить задержку выхода из цикла ценой некоторого раздувания кода.

Скорее - наоборот: это уменьшит задержку невыхода из цикла (между проверками пока условие выхода не выполнено). Так как исполненная команда условного перехода выполняется дольше неисполненной. Задержку выхода этот код как раз скорее увеличит (или оставит прежней - смотря как считать).

Но имхо - причина всё же не в этом, а просто это - глюк оптимизатора. Сталкивался с чем-то подобным и в IAR.

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


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

У меня в этом проекте вообще мистика :) На -O0 или -O1 -- всё нормально. При -O2 или -O3 на дисплей цвета выводятся инвертированными. Естественно, стал разбираться, и первое, что обнаружил -- в буфере информация корректная. А сам вывод у меня по DMA идёт, так что вроде бы изменяться значения ну никак не могут (тем более, что картинка на своих местах и т.п. -- а значит, команды дисплею выдаются корректно, а выдача-то производится тем же самым DMA!). Вот сейчас малым ходом ползу и разбираюсь, во что компилятор превратил мой быдлокод...

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


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

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

Скорее - наоборот: это уменьшит задержку невыхода из цикла (между проверками пока условие выхода не выполнено). Так как исполненная команда условного перехода выполняется дольше неисполненной. Задержку выхода этот код как раз скорее увеличит (или оставит прежней - смотря как считать).

Задержка выхода из цикла это время от входа в цикл до выхода из него. Соответственно чтобы этого достичь нужно уменьшить время между проверками. Переход в конце цикла перегружает конвейер и увеличивает время между проверками, чтобы этого избежать компилятор продублировал чтение-сравнение-переход и тем  самым несколько снизил задержки, т.к. перезагрузка конвейера стала выполняться в 4 раза реже. Почему "наоборот"?

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


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

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

Задержка выхода из цикла это время от входа в цикл до выхода из него.

Нет. Это задержка от момента установления условия выхода, до собственно выхода.

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

Переход в конце цикла перегружает конвейер и увеличивает время между проверками

В любом случае - в случае CBZ то же самое происходит при срабатывании условия: перегрузка конвеера (более длинное выполнение команды при выполнившемся переходе).

Если время между проверками внутри цикла = T1, время от последней проверки до выхода = T2.

1. То в случае такой оптимизации: T2>T1.

2. Обычный цикл: T1>T2.

В среднем время от установления сигнала, до выхода будет = T1/2+T2. Здесь как видно T2 влияет сильнее, а в первом случае оно больше.

 

PS: А вообще конечно на ARM работать в суперлупе - не комильфо. Давно следовало перейти на ОС.  :unknw:

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


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

1 hour ago, jcxz said:

Если время между проверками внутри цикла = T1, время от последней проверки до выхода = T2.

1. То в случае такой оптимизации: T2>T1.

2. Обычный цикл: T1>T2.

В среднем время от установления сигнала, до выхода будет = T1/2+T2. Здесь как видно T2 влияет сильнее, а в первом случае оно больше.

ничего не понятно.

код в примере имеет 4 части:

  1. время при срабатывании - 3 такта, время без срабатывания - 2 такта, => время от установления сигнала - (3 в первый раз и 4-6 во все остальные разы) тактов,
  2. время при срабатывании - 3 такта, время без срабатывания - 2 такта, => время от установления сигнала - (3-5) тактов,
  3. время при срабатывании - 3 такта, время без срабатывания - 2 такта, => время от установления сигнала - (3-5) тактов,
  4. время при срабатывании - 3 такта, время без срабатывания - 4 такта, => время от установления сигнала - (3-5) тактов

таким образом, в среднем время от установления сигнала, до выхода будет стремиться к (5+4+4+4)/4=4,25 тактов при том что, если использовать только последнюю часть кода, в среднем время от установления сигнала, до выхода будет 5 такта

P.S. добавил в расчет джиттер. в любом случае в среднем имеем ускорение на 0,75 такта

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


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

1 hour ago, jcxz said:

на ARM работать в суперлупе - не комильфо

 И где же здесь суперлуп-то?

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


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

8 минут назад, aaarrr сказал:

 И где же здесь суперлуп-то?

Видимо имелось в виду блокирующее ожидание. Обычно так делают, когда где-то есть этот самый суперлуп.

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


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

1 hour ago, makc said:

Обычно так делают, когда где-то есть этот самый суперлуп.

Так часто делают, например, при инициализации периферии или ожидании заведомо быстрой реакции от неё.

Делать вывод об отсутствии ОС, на мой взгляд, совершенно безосновательно.

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


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

2 часа назад, 1113 сказал:
  1. время при срабатывании - 3 такта, время без срабатывания - 2 такта, => время от установления сигнала - (3 в первый раз и 4-6 во все остальные разы) тактов

Ничего не понятно...  :umnik2: Что такое "время при срабатывании" и "время без срабатывания"? И почему они такие?

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


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

первые три блока состоят из двух команд

0x000015C8 782C      LDRB          r4,[r5,#0x00]
0x000015CA B134      CBZ           r4,0x000015DA

первая исполняется 1 такт и загружает в R4 проверяемое значение, вторая исполняется 1 такт если "нет срабатывания" и код не выходит из цикла, и 2 такта, если "есть срабатывание" и код выходит из цикла

 

последний блок состоит из трех команд

0x000015D4 782F      LDRB          r7,[r5,#0x00]
0x000015D6 2F00      CMP           r7,#0x00
0x000015D8 D1F6      BNE           0x000015C8

первая исполняется 1 такт и загружает в R7 проверяемое значение, вторая исполняется 1 такт и тестирует R7 на 0, устанавливая по результату регистр статуса и третья исполняется 2 такта если "нет срабатывания" и код не выходит из цикла, и 1 такт, если "есть срабатывание" и код выходит из цикла

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


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

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

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

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

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

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

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

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

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

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