Jump to content

    
SII

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

Recommended Posts

Написал:

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

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

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites
12 минут назад, makc сказал:

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

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

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

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites
15 минут назад, jcxz сказал:

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

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

Share this post


Link to post
Share on other sites
1 час назад, makc сказал:

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

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

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

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

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

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

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

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

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

 

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

Share this post


Link to post
Share on other sites
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 такта

Share this post


Link to post
Share on other sites
8 минут назад, aaarrr сказал:

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

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

Share this post


Link to post
Share on other sites
1 hour ago, makc said:

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

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

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

Share this post


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

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

Share this post


Link to post
Share on other sites

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

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 такт, если "есть срабатывание" и код выходит из цикла

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.