0 / 0 / 0
Регистрация: 27.02.2013
Сообщений: 11
1

Механика оптимизации

28.06.2017, 12:00. Показов 996. Ответов 15
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Вопрос по работе компилятора. При определенных условиях он вырезает из обработчика прерываний куски кода. Хотелось бы понять, исходя из каких критериев. Например.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
void TC2_Handler()
{
  TC_GetStatus(TC0, 2);
  Serial.print("H1_____");
  Serial.println(Millis());
  uint32_t j=Millis();
  for (uint32_t i1=0; i1<30000000ul; i1++)
  {
    for (uint32_t i2=0; i2<30000000ul; i2++)
    {
      for (uint32_t i3=0; i3<30000000ul; i3++)
      {
        for (uint32_t i4=0; i4<30000000ul; i4++)
        {
          for (uint32_t i5=0; i5<30000000ul; i5++)
          {
            for (uint32_t i6=0; i6<30000000ul; i6++)
            {
              j++;
            }
          }
        }
      }
    }
  }
  Serial.print("j=");
  Serial.println(j);
  Serial.print("H2_____");
  Serial.println(Millis());
}
При вложенности циклов до i5 работает. Больше - нет (вырезает целиком весь кусок связанный с циклами). Как исправить, понимаю (volatile на переменную j). Разумеется, с volatile циклы работают в разы дольше. Точнее говоря, это в варианте с циклами i1-4 весь код связанный с циклами занимает всего лишь несколько машинных тактов. Я так понимаю, что уже на этапе компиляции идет расчет приращения значения j, и потом оно просто прибавляется к значению j. И когда из-за большого количества циклов предварительно рассчитанное значение j переполняется, компилятор выкидывает эту часть. Если что, оптимизация идет с ключиком -0s.

Собственно, вопрос: а что происходит на самом деле?
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
28.06.2017, 12:00
Ответы с готовыми решениями:

Механика функций C++
Здравствуйте нужна ваша помощь в ответе на некоторые вопросы низкоуровневого программирования: На...

Механика обобщённых функций
Здравствуйте! Подскажите, пожалуйста, явная функция swapp является перегрузкой или...

Механика работы условия if
В одном из тестов встертилось такое задание: что выведет программа? Вот код #include &quot;stdafx.h&quot;...

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

15
Форумчанин
Эксперт CЭксперт С++
8215 / 5045 / 1437
Регистрация: 29.11.2010
Сообщений: 13,453
28.06.2017, 12:23 2
Компилятор смотрит что вы написали бессмысленный код и выпиливает всё, что не изменит конечную логику работы, дабы вхолостую процессор не гонять.
volatile просто не даёт оптимизировать переменную.
0
0 / 0 / 0
Регистрация: 27.02.2013
Сообщений: 11
28.06.2017, 12:57  [ТС] 3
Я был бы полностью согласен с такой логикой работы, если бы не 2 строчки:
C++
1
2
uint32_t j=Millis(); //Начальное значение читается из какого-то регистра
Serial.println(j); //Полученное значение отправляется куда-то
А так получается, что компилятор "самовольно" удалил часть кода. Если бы не было второй строчки, код был бы действительно бессмысленным. А в существующей редакции он прямым образом влияет на результат.
0
Форумчанин
Эксперт CЭксперт С++
8215 / 5045 / 1437
Регистрация: 29.11.2010
Сообщений: 13,453
28.06.2017, 13:04 4
qaz0, так что мешает компилятору просто к j прибавить нужное число?
0
0 / 0 / 0
Регистрация: 27.02.2013
Сообщений: 11
28.06.2017, 13:12  [ТС] 5
Ничего. И это очень красивый пример оптимизации кода.

Есть только одна проблема: если это число переполняется в момент его расчета компилятором, то оно не учитывается в дальнейшем (НЕ прибавляется или прибавляется 0 вместо какого-то другого числа).
0
4817 / 2278 / 287
Регистрация: 01.03.2013
Сообщений: 5,947
Записей в блоге: 28
28.06.2017, 14:31 6
Дело в том, что по мнению писателей компиляторов / оптимизаторов, сама задача съедания тактов процессора не рассматривается. Более того - компилятор не гарантирует код, выполняющийся строго определенное число тактов. Считается, что чем быстрее - тем лучше, и тупые циклы для паузы, результаты которых потом не используются, оптимизатор запросто может выкинуть. Мы вообще потеряли контроль за тактами, когда перешли от чистого асма на компиляторы. Поэтому - или дружить с компилятором через волатиле, или писать асм-вставки
0
Заблокирован
28.06.2017, 21:21 7
Цитата Сообщение от qaz0 Посмотреть сообщение
что происходит на самом деле?
Что-то странное.
0
18822 / 9826 / 2401
Регистрация: 30.01.2014
Сообщений: 17,260
29.06.2017, 12:22 8
Цитата Сообщение от qaz0 Посмотреть сообщение
Есть только одна проблема: если это число переполняется в момент его расчета компилятором, то оно не учитывается в дальнейшем (НЕ прибавляется или прибавляется 0 вместо какого-то другого числа).
Лучше, наверное, объяснить всем здесь физический смысл этого кода, чего хотелось добиться им.
Тогда будет понятно как тут помочь.
0
4817 / 2278 / 287
Регистрация: 01.03.2013
Сообщений: 5,947
Записей в блоге: 28
29.06.2017, 15:54 9
Как начинающий телепат, могу предположить, что пациент пишет кот, который вызывается в обработке прерывания Тайм-Каунтера № 2. А в нем он вместо того, чтобы быстро сделать что надо и выйти в основной поток выполнения, крутит 200 вложенных циклов, сжигая драгоценные такты, в которых 100500^100500 раз инкрементирует локальную переменную жи, которую на счастье горе оптимизатора пытается вывести в конце безобразия. Скорее всего жи у него переполняется неоднократно, и на месте вменяемого оптимизатора я бы заинкрементил на число итераций всех 200 циклов по модуля максимального уинта32, ибо остальные циклы с т.з. оптимизатора бессмысленны. Ну и в то, что все это добро успевает выполниться до следующего тика таймера-каунтера и очередного прерывания, в результате чего не забивается очередь необработанных прерываний (в зависомости от камня), я тоже не особо верю
0
Заблокирован
29.06.2017, 18:05 10
Цитата Сообщение от _Ivana Посмотреть сообщение
жи у него переполняется неоднократно
Беззнаковые числа не переполняются.
0
4817 / 2278 / 287
Регистрация: 01.03.2013
Сообщений: 5,947
Записей в блоге: 28
29.06.2017, 22:33 11
Цитата Сообщение от daun-autist Посмотреть сообщение
Беззнаковые числа не переполняются.
Пиши еще.
1
Велосипедист...
353 / 220 / 73
Регистрация: 15.12.2015
Сообщений: 785
29.06.2017, 23:49 12
Цитата Сообщение от _Ivana Посмотреть сообщение
Пиши еще.
Грубо

Цитата Сообщение от daun-autist Посмотреть сообщение
Беззнаковые числа не переполняются.
Переполняются. Поведение описано стандартом, в отличие от знаковых, что ведет к UB ( или ID? ).
0
Неэпический
17869 / 10634 / 2054
Регистрация: 27.09.2012
Сообщений: 26,736
Записей в блоге: 1
30.06.2017, 06:44 13
Captain Maxee, не будет UB.
0
Вездепух
Эксперт CЭксперт С++
11688 / 6367 / 1723
Регистрация: 18.10.2014
Сообщений: 16,050
30.06.2017, 08:40 14
Цитата Сообщение от qaz0 Посмотреть сообщение
если это число переполняется в момент его расчета компилятором, то оно не учитывается в дальнейшем
С чего вы взяли? Если бы j было знаковым, то компилятор имел бы право перекроить код вообще как угодно и выкинуть что угодно, ибо поведение не определено. А так как в вашем случае j - беззнаковое, т.е. поведение вполне определено, то компилятор может просто заранее предсказать, на сколько поменяется значение j в результате работы этих ваших циклов. Вполне может быть (я не проверял) что все эти ваши циклы в итоге вообще не меняют значения j. Вот компилятор их и выкидывает нафиг.
1
Заблокирован
30.06.2017, 10:53 15
Цитата Сообщение от _Ivana Посмотреть сообщение
Пук.
Ну а что от тебя ещё ожидать?
Цитата Сообщение от Captain Maxee Посмотреть сообщение
Переполняются.
И тут ты такой подкрепляешь свои слова цитатой из стандарта.
0
Велосипедист...
353 / 220 / 73
Регистрация: 15.12.2015
Сообщений: 785
30.06.2017, 17:42 16
Croessmah, а что будет?
Помнится мне, что поведение описано только для беззнаковых :0

Добавлено через 1 час 48 минут
Цитата Сообщение от daun-autist Посмотреть сообщение
И тут ты такой подкрепляешь свои слова цитатой из стандарта.
Фактически, я был неправ, что подтверждает стандарт:
A computation involving unsigned operands can never overflow, because a result that cannot be represented by the resulting unsigned integer type is reduced modulo the number that is one greater than the largest value that can be represented by the resulting type.
Ошибся из-за недопонимания термина переполнение. Я хотел донести, что при таком коде:
C
1
unsigned var = UINT_MAX + 1;
UB не будет.
0
30.06.2017, 17:42
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
30.06.2017, 17:42
Помогаю со студенческими работами здесь

Методы оптимизации
Здравствуйте, прошу помочь,кто может написать программу для решения задачи используя 2 метода...

Документация по флагам оптимизации
Подскажите мануал, документацию, гайд по флагам оптимизации. Желательно на русском. А то у меня...

Курсовая. Методы оптимизации
https://www.cyberforum.ru/attachments/402404d1400795723 Помогите чем сможете Заранее спасибо

MinGW и странности оптимизации
Долго бился, почему банальная строка for(;isLButtonDown();){} не работает как надо, а уходит на...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
16
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru