Форум РадиоКот https://radiokot.ru/forum/ |
|
Наткнулся на какой то баг компилятора? https://radiokot.ru/forum/viewtopic.php?f=59&t=156052 |
Страница 1 из 1 |
Автор: | V2oD2o [ Пн июл 09, 2018 09:36:48 ] |
Заголовок сообщения: | Наткнулся на какой то баг компилятора? |
C8T6, 72Мгц, внешний кварц, CMSIS без каких либо надстроек, g++ имеется прерывание 4мкс, он же счетчик для событий + необходимо некоторые данные обновлять \ считать почему то скобки очень сильно влияют на время выполнения прерывания, например если условно: a = (((b * 10) + (c / 60)) - 1) * 5; - прерывание будет выполняться 5.184135 мкс а вот такая конструкция: x = b * 10; y = c / 60; a = x + y - 1; a *= 5; не будет влиять на время прерывания, т.е. время прерывания чётко 4.000000мкс что компилятору там могло в голову ударить ? |
Автор: | ARV [ Пн июл 09, 2018 09:55:29 ] |
Заголовок сообщения: | Re: Наткнулся на какой то баг компилятора? |
V2oD2o писал(а): a = (((b * 10) + (c / 60)) - 1) * 5; ну а если записать "естественно", без лишних скобок:a = (b*10 + c/60 - 1) * 5;? что будет?
|
Автор: | Мурик [ Пн июл 09, 2018 10:04:27 ] |
Заголовок сообщения: | Re: Наткнулся на какой то баг компилятора? |
Какие типы переменных? Float или Double среди них есть? Результат первой и второй конструкции идентичен или отличается? Оптимизация по скорости включена? |
Автор: | V2oD2o [ Пн июл 09, 2018 10:29:55 ] |
Заголовок сообщения: | Re: Наткнулся на какой то баг компилятора? |
V2oD2o писал(а): a = (((b * 10) + (c / 60)) - 1) * 5; ну а если записать "естественно", без лишних скобок:a = (b*10 + c/60 - 1) * 5;? что будет?Пример условный, но закономерность именно такая, всё считаешь в одной строке - лаг по времени прерывания, разделяешь - все нормально Добавлено after 2 minutes 18 seconds: Какие типы переменных? Float или Double среди них есть? Результат первой и второй конструкции идентичен или отличается? Оптимизация по скорости включена? C8T6 не имеет FPU, в первом посте указал что только CMSIS без всяких надстроек т.е. никаких извращений с float на цельночисленном камне, тип данных uint16_t или 32_t - ситуация одинаковая, оптимизации пробовал разных уровней - результат малоотличим Данные снимал анализатором, в прерывании ->ODR ^= и смотрел на интервалы прерывания И еще, для понимания - калькуляция там не одна, их с десяток наберется, за пределы результирующей длины слова - не вылезает, по отладчику перепроверено несколько раз |
Автор: | Reflector [ Пн июл 09, 2018 10:35:45 ] |
Заголовок сообщения: | Re: Наткнулся на какой то баг компилятора? |
ну а если записать "естественно", без лишних скобок:a = (b*10 + c/60 - 1) * 5;? что будет? А есть варианты? Твоя программа разбора выражений со скобками и без могла выдавать разные результаты? V2oD2o, такое выражение целиком за пол мкс должно считаться, даже без оптимизации будет не на много больше, причем в таком случае медленнее должен быть вариант с промежуточными переменными, так что весьма вероятно баг где-то в другом месте. |
Автор: | V2oD2o [ Пн июл 09, 2018 10:40:11 ] |
Заголовок сообщения: | Re: Наткнулся на какой то баг компилятора? |
ну а если записать "естественно", без лишних скобок:a = (b*10 + c/60 - 1) * 5;? что будет? А есть варианты? Твоя программа разбора выражений со скобками и без могла выдавать разные результаты? V2oD2o, такое выражение целиком за пол мкс должно считаться, даже без оптимизации будет не на много больше, причем в таком случае медленнее должен быть вариант с промежуточными переменными, так что весьма вероятно баг где-то в другом месте. выражение условное, там несколько десятков расчётов завязанные на разные временные события и внешние прерывания, основная масса расчетов ведётся по данным ADC через DMA - 4 канала попробую сформировать вечером реальный пример, на котором можно увидеть "у себя" описанную проблему результат - всегда одинаковый, просто разбивание строки со скобками убирает проблему полностью, таймер начинает считать нормально |
Автор: | Siarzhuk [ Пн июл 09, 2018 11:37:48 ] |
Заголовок сообщения: | Re: Наткнулся на какой то баг компилятора? |
тип данных uint16_t или 32_t - ситуация одинаковая В многострочном варианте промежуточный результат явно приводится к типу присваиваемых переменных, в однострочном - нет. Проверьте, интересу ради, вариант a = (uint_16t)(((uint_16t)(b * 10) + (uint_16t)(c / 60)) - 1) * 5; Кроме того, теоретически, операции "перемножение" и "домножение" имеют разное количество аргументов - и компилятор вполне может решить пользоваться разными инструкциями буде такие в его распоряжении на рассматриваемой платформе. А сгенерированный ASM код наверняка неидентичен - может туда глянуть? |
Автор: | V2oD2o [ Пн июл 09, 2018 13:00:32 ] |
Заголовок сообщения: | Re: Наткнулся на какой то баг компилятора? |
тип данных uint16_t или 32_t - ситуация одинаковая В многострочном варианте промежуточный результат явно приводится к типу присваиваемых переменных, в однострочном - нет. Проверьте, интересу ради, вариант a = (uint_16t)(((uint_16t)(b * 10) + (uint_16t)(c / 60)) - 1) * 5; Кроме того, теоретически, операции "перемножение" и "домножение" имеют разное количество аргументов - и компилятор вполне может решить пользоваться разными инструкциями буде такие в его распоряжении на рассматриваемой платформе. А сгенерированный ASM код наверняка неидентичен - может туда глянуть? На работе к сожалению нет возможности objdump сделать, дома по-любому буду построчно разбирать и бряки делать на каждом шагу, вчера ночью только наткнулся на этупроблему, особо времени не было разбираться Насчет приведения к типам - хорошая идея, попробую вечером |
Автор: | Мурик [ Пн июл 09, 2018 13:03:29 ] |
Заголовок сообщения: | Re: Наткнулся на какой то баг компилятора? |
Эту строку. Код: a = (((b * 10) + (c / 60)) - 1) * 5; GCC компилировал так (все переменные uint32_t).Код: // a = (((b * 10) + (c / 60)) - 1) * 5; Эти строки. 080004AC ldr r1, [pc, #64] ; (0x80004f0 <main+116>) 080004B0 add.w r2, r2, r2, lsl #2 080004B4 umull r1, r3, r1, r3 080004B8 lsrs r3, r3, #5 080004BA add.w r3, r3, r2, lsl #1 080004BE add.w r3, r3, r3, lsl #2 080004C2 subs r3, #5 Код: x = b * 10; скомпилировались в такой код. y = c / 60; a = x + y - 1; a *= 5; Код: // x = b * 10;
080004B0 add.w r2, r2, r2, lsl #2 // y = c / 60; 080004AC ldr r1, [pc, #64] ; (0x80004f0 <main+116>) 080004B4 umull r1, r3, r1, r3 080004B8 lsrs r3, r3, #5 // a = x + y - 1; 080004BA add.w r3, r3, r2, lsl #1 080004BE subs r3, #1 // a *= 5; 080004C0 add.w r3, r3, r3, lsl #2 |
Автор: | V2oD2o [ Пн июл 09, 2018 13:12:03 ] |
Заголовок сообщения: | Re: Наткнулся на какой то баг компилятора? |
Эту строку. Код: a = (((b * 10) + (c / 60)) - 1) * 5; GCC компилировал так (все переменные uint32_t).Код: // a = (((b * 10) + (c / 60)) - 1) * 5; Эти строки. 080004AC ldr r1, [pc, #64] ; (0x80004f0 <main+116>) 080004B0 add.w r2, r2, r2, lsl #2 080004B4 umull r1, r3, r1, r3 080004B8 lsrs r3, r3, #5 080004BA add.w r3, r3, r2, lsl #1 080004BE add.w r3, r3, r3, lsl #2 080004C2 subs r3, #5 Код: x = b * 10; скомпилировались в такой код. y = c / 60; a = x + y - 1; a *= 5; Код: // x = b * 10; 080004B0 add.w r2, r2, r2, lsl #2 // y = c / 60; 080004AC ldr r1, [pc, #64] ; (0x80004f0 <main+116>) 080004B4 umull r1, r3, r1, r3 080004B8 lsrs r3, r3, #5 // a = x + y - 1; 080004BA add.w r3, r3, r2, lsl #1 080004BE subs r3, #1 // a *= 5; 080004C0 add.w r3, r3, r3, lsl #2 Уровень оптимизации какой ? Судя по строке 080004C2 subs r3, #5 - что то пошло не так |
Автор: | Мурик [ Пн июл 09, 2018 13:12:51 ] |
Заголовок сообщения: | Re: Наткнулся на какой то баг компилятора? |
-Ofast. Необязательно для всего проекта. Можно только для нужной функции. |
Автор: | V2oD2o [ Пн июл 09, 2018 13:14:25 ] |
Заголовок сообщения: | Re: Наткнулся на какой то баг компилятора? |
-Ofast. Необязательно для всего проекта. Можно только для нужной функции. Обновил пред коммент, откуда там? 080004C2 subs r3, #5 |
Автор: | Reflector [ Пн июл 09, 2018 13:36:43 ] |
Заголовок сообщения: | Re: Наткнулся на какой то баг компилятора? |
откуда там? 080004C2 subs r3, #5 Современные компиляторы очень умные, в данном случае он раскрыл скобки(b * 50 + c / 12 - 5), заменил деление умножением, умножение заменил сдвигами и сложением, более того т.к. из-за целочисленного деления результат упрощенного выражения может быть другим, то было предусмотрено и это. Так что не нужно искать баги у компилятора, ищи баги у себя |
Автор: | dosikus [ Пн июл 09, 2018 17:11:17 ] |
Заголовок сообщения: | Re: Наткнулся на какой то баг компилятора? |
V2oD2o , покажите полносттю обработчик прерывания таймера. Особенно интересует сброс флага... |
Автор: | V2oD2o [ Вт июл 10, 2018 09:20:24 ] |
Заголовок сообщения: | Re: Наткнулся на какой то баг компилятора? |
V2oD2o , покажите полносттю обработчик прерывания таймера. Особенно интересует сброс флага... Там все в порядке, проект рабочий, после доработок, не сразу, но было замечено увеличение времени отсчета по таймеру примерно х1.8 - х2, т.е. событие по 10мс, выполнялось в 18.5064мс Добавлено after 7 minutes 45 seconds: тип данных uint16_t или 32_t - ситуация одинаковая В многострочном варианте промежуточный результат явно приводится к типу присваиваемых переменных, в однострочном - нет. Проверьте, интересу ради, вариант a = (uint_16t)(((uint_16t)(b * 10) + (uint_16t)(c / 60)) - 1) * 5; Кроме того, теоретически, операции "перемножение" и "домножение" имеют разное количество аргументов - и компилятор вполне может решить пользоваться разными инструкциями буде такие в его распоряжении на рассматриваемой платформе. А сгенерированный ASM код наверняка неидентичен - может туда глянуть? "Дело было не в бобине" - и действительно, приведение к типам дало прирост, очень ощутимый, было 18мс вместо 10мс, перевёл все расчеты на u32_t (в 16 не влезу) - стало 13.3мс, добавил -O3 - и увидел заветные 10мс, пробовал нагрузить еще всякими вычислениями, даже гораздо более сложными и считать их каждый тик, а не по событию - проблема решилась, каждый тик ровно 5.000 мкс, спасибо за наводку! Что интересно -Ох без использования однотипных данных - почти ничего не давало |
Автор: | dosikus [ Вт июл 10, 2018 15:10:05 ] |
Заголовок сообщения: | Re: Наткнулся на какой то баг компилятора? |
Особенно интересует сброс флага... И все же, многие влетали на эти грабли сбрасывая флаг в конце распухшего прерывания... |
Автор: | V2oD2o [ Вт июл 10, 2018 15:15:59 ] |
Заголовок сообщения: | Re: Наткнулся на какой то баг компилятора? |
Особенно интересует сброс флага... И все же, многие влетали на эти грабли сбрасывая флаг в конце распухшего прерывания... Да, я не исключение, проходили |
Страница 1 из 1 | Часовой пояс: UTC + 3 часа |
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group http://www.phpbb.com/ |