-
- Есть небольшая, критичная в моём случае, разница времени выполнения Moлoдoй кoллeгa(70 знак., 28.04.2022 19:57)
- Если время критично, пишите на ассемблере, или возьмите другой чип.
) - AПM(29.04.2022 14:22)
- Причём тут ассемблер? Операция p=p->next это одна ассемблерная
команда (для ARM) и любой компилятор cделает её на изи. Вопрос в
размещении данных во flash. - VladislavS.(29.04.2022 15:05)
- вообще вопрос в алгоритме, который критичен к лишней ассемблерной
команде. - Mahagam(29.04.2022 16:14)
- Странный вопрос. Есть контроллер, который справляется, пусть даже и
на пределе, с поставленной задачей. Предлагается заменить его на
более производительный чтобы был запас в эту одну ассемблерную
команду? - VladislavS.(29.04.2022 16:51)
- задача, где требуется ШИМ по чёткому расписанию решается либо контроллером c DMA, либо на плис. походу, контроллер изначально выбран неверно. - Mahagam(29.04.2022 17:12)
- там, походу, дело в неравномерности обращений. задача изначально
неясная. - Mahagam(29.04.2022 16:54)
- Да какая разница, какой там алгоритм? Вопрос был в том "как
инициализировать массив структур во флэшь". Будь там не связный
список, а обычный массив, вопрос будет тем же. - VladislavS.(29.04.2022 17:01)
- оно инициализируется циклом. то есть можно тупо вычислять значения.
но хитроделанный алгоритм вывода в шим не даёт этого сделать. тут
вообще DMA напрашивается. а все эти плюсовые заморочки сродни
лечению поноса пробкой. и выбор между списком и массивом это как
либо брать пробку большего размера, либо на старой резьбу накатать. - Mahagam(29.04.2022 17:11)
- Каким это образом алгоритм вывода не даёт инициализировать данные? Это вообще разные задачи. Можно инициализировать и вообще не использовать ни в каком алгоритме, если захочется. Плюсы тут помогают тем, что имеют механизм вычислений на этапе крмпиляции. Да и код меньше, понятнее и ошибкоустойчивей получается. - VladislavS.(29.04.2022 17:44)
- Микроконтроллер - это всего лишь кусок кремния. Если он справится с задачей то совершенно не важно, какими средствами эта задача решена. - =AlexD=(29.04.2022 17:15)
- оно инициализируется циклом. то есть можно тупо вычислять значения.
но хитроделанный алгоритм вывода в шим не даёт этого сделать. тут
вообще DMA напрашивается. а все эти плюсовые заморочки сродни
лечению поноса пробкой. и выбор между списком и массивом это как
либо брать пробку большего размера, либо на старой резьбу накатать. - Mahagam(29.04.2022 17:11)
- Да какая разница, какой там алгоритм? Вопрос был в том "как
инициализировать массив структур во флэшь". Будь там не связный
список, а обычный массив, вопрос будет тем же. - VladislavS.(29.04.2022 17:01)
- +1. Я вообще думаю, что там на самом деле всё не так, как в
действительности. ТС набросил и убежал :-) - SciFi(29.04.2022 16:24)
- Ну почему.. он придумал пиздатенькую вещь (как ему кажется) и
отказываться от не не хочет, хотя нахрен бы она нужна. - POV(29.04.2022 16:37)
- И ты прав. © ) - Moлoдoй кoллeгa(29.04.2022 16:58)
- Всё ТС правильно делает. Скорость перебора в связном списке выше,
чем по индексу в массиве. Желание константные данные разместить во
флэшь тоже нормально. Возможно, можно было что-то с DMA намутить,
но я тип контроллера в хрустальном шаре не вижу. - VladislavS.(29.04.2022 16:46)
- нормальный компилятор побегает по массиву также эффективно как и по списку. тем более, что в массиве не придётся хранить лишний элемент. - Mahagam(29.04.2022 16:52)
- Ну почему.. он придумал пиздатенькую вещь (как ему кажется) и
отказываться от не не хочет, хотя нахрен бы она нужна. - POV(29.04.2022 16:37)
- Странный вопрос. Есть контроллер, который справляется, пусть даже и
на пределе, с поставленной задачей. Предлагается заменить его на
более производительный чтобы был запас в эту одну ассемблерную
команду? - VladislavS.(29.04.2022 16:51)
- вообще вопрос в алгоритме, который критичен к лишней ассемблерной
команде. - Mahagam(29.04.2022 16:14)
- Причём тут ассемблер? Операция p=p->next это одна ассемблерная
команда (для ARM) и любой компилятор cделает её на изи. Вопрос в
размещении данных во flash. - VladislavS.(29.04.2022 15:05)
- небось, данные скармливаются в таймер или цап. и требования к
постоянству таймингов выдачи данных? - Mahagam(29.04.2022 12:22)
- Ага, хитрый "шим", нужно как можно быстрее и одинаково по времени
(колличетву команд) каждый цикл. - Moлoдoй кoллeгa(29.04.2022 17:02)
- а точно нужен этот "хитрый шим"? а то может задачи как у Ксении -
поиски торсионных полей. - Mahagam(29.04.2022 17:40)
- Не, у меня более приземлённые задачи, лампочкой там помигать :) - Moлoдoй кoллeгa(29.04.2022 17:59)
- а конкретнее? - Mahagam(29.04.2022 18:03)
- Не, у меня более приземлённые задачи, лампочкой там помигать :) - Moлoдoй кoллeгa(29.04.2022 17:59)
- Хех, я не так давно делал для такого формирование по настройкам последовательности инструкций в ОЗУ. Кузяво получилось... - SciFi(29.04.2022 17:29)
- Контроллер то какой хоть? - VladislavS.(29.04.2022 17:04)
- Cortex M0+ - Moлoдoй кoллeгa(29.04.2022 17:18)
- а точно нужен этот "хитрый шим"? а то может задачи как у Ксении -
поиски торсионных полей. - Mahagam(29.04.2022 17:40)
- Ага, хитрый "шим", нужно как можно быстрее и одинаково по времени
(колличетву команд) каждый цикл. - Moлoдoй кoллeгa(29.04.2022 17:02)
- Хм. А если расположить массив в обратном порядке и сравнивать индекс с нулём? От процессора зависит конечно, но часто есть подходящие инструкции/паттерны. LightElf(283 знак., 29.04.2022 01:53)
- А так: p += sizeof(*p) ? - Cкpипaч(28.04.2022 20:01)
- Как это поможет избавиться от условия с проверкой выхода за граници
перед переходом на следующий элемент? - Moлoдoй кoллeгa(28.04.2022 20:09 - 20:13)
- если массив по количеству элементов равен степени 2, 3-4-8-16, то можно закруглить наложив маску на индекс. Nikolay801_(432 знак., 04.05.2022 10:14)
- Принято. Я такие конструкции собирал на ассемблере и отдавал линкеру напрямую, мимо компилятора Си. Но это на 86-м, под Дос. Cкpипaч(227 знак., 29.04.2022 19:52)
- Обычно каждый узел списка хранит значение (value) и указатель на
следующий элемент (next). Последний элемент списка указывает на
начало списка. Указатель - это обычно 32-битное число. Для случая,
когда элементы списка размещены в массиве, т.е. последовательно, то
каждый next отличается от предыдущего на константу
sizeof(ListItem). В общем, меняем указатели next на индексы
массива. Последний индекс/указатель направит нас в начало списка. Costic(424 знак., 29.04.2022 14:30)
- Это хуже, так как потребует хранить где-то индекс (дополнительный
РОН) и вычислять смещение из индекса в каждом цикле. В случае
p=p->nexet доступ к полям через p просто адресацией со
смещением происходит. - VladislavS.(29.04.2022 15:12)
- Предположение, что обращение к флешу занимает константное время
вижу я. - LightElf(29.04.2022 18:25)
- При наличии предвыборки флэшь, работе в прерываниии и наличии DMA
на борту контроллера, не стоит на это рассчитывать, юный падаван. - VladislavS.(29.04.2022 18:42)
- Имана. При наличии всей этой тряхомудии утверждение: "список с
указателями быстрее массива с индексом" кажется мне несколько
голословным, о мудрейший. Думаю ещё через сотню сообщений мы узнаем
модель процессора, примененного ТС и сможем оценить всю глубину
глубин. - LightElf(29.04.2022 20:54)
- Архитектуру мы таки знаем. Это Cortex-MO+. А у него доступ по
указателю будет всяко быстрее вычисления смещения из индекса,
проверки и инкремента индекса. - VladislavS.(29.04.2022 21:38)
- Какое-то верование запрещает сразу инкрементировать указатель?
Инкремент на 8-битную константу занимает, емнип, одну инструкцию.
Загрузка же указателя из флеша требует двух обращений к флешу.
Имеется ли у обсуждаемого проца кэш чтения или там просто буфер
предвыборки - неизвестно. Так чта не все так однозначно, как
говорила дочь офицера. - LightElf(30.04.2022 16:49)
- Верование или нет, но я не видел, чтобы компиляторы так делали. Но
даже если допустить, с учётом развитости косвенной адресации, это
не много что меняет. Наверное, поэтому компиляторы и не делают
подобные оптимизации. Лишнии команды в случае с индексом тоже не из
воздуха, а из флэшь читаются, тут баш на баш. В кортексах шина к
флэшь обычно 64 бит и через буфер предвыборки. Контроллеру всё
равно за данными массива в флэшь обращаться, за одно и новый
указатель прочитается. VladislavS.(267 знак., 01.05.2022 00:33)
- Суть моего спича кагбэ в том, что даже на мелких кортексах выигрыш
в количестве команд не всегда приводит к выигрышу в реальной
производительности. И раз уж мы не знаем точную модель, то не знаем
и как там флеш устроен. Потому, считаю, утверждать "так быстрее чем
эдак" несколько преждевременно. - LightElf(01.05.2022 02:05)
- Ну это же всё легко проверяется. Берём Cortex-M0+, пишем в
прерывании как у ТС код и смотрим листинги: VladislavS.(4175 знак., 01.05.2022 08:05)
- Справедливости ради, код от начала прерывания до отправки данных по
назначению одинаков в случае связного списка и инкремента
указателя. Если общая загрузка процессора не зашкалит, то результат
будет одинаков. Но зачем делать плохо, если можно сделать хорошо. - VladislavS.(01.05.2022 08:37)
- блеать. если первое требование - равномерность подачи данных, то в
текущем прерывании готовим данные для отправки в следующем.
сохраняем их в заготовленную переменную и в самом начале следующего
прерывания отправляем куда там требуется. в этом случае можно
вообще нихрена не хранить, а считать на лету. - Mahagam(01.05.2022 10:25)
- Для полноты картины посмотрим листинг и этого варианта. За сдвиг
записи полезных данных на одну команду к началу прерывания платим
дополнительной переменной в SRAM и более длинным прерыванием: VladislavS.(811 знак., 02.05.2022 10:06)
- Для полноты картины надо мой вариант было рассмотреть, причём
желательно использовать для массива индекс типа uint16_t. Тогда в
моём варианте читать из флеша в 2 раза меньше, но использовать 1
РОН. И на частотах выше 25 МГц (предел флеша), думаю, будет профит. - Costic(02.05.2022 16:54)
- Во-первых, даже для чтения переменной из RAM надо сначала загрузить
её адрес из флэшь. Во-вторых, РОН экономить смысла нет, они при
входе в прерывание сохраняются в достаточгом количестве. В-третьих,
чтение 8/16/32 бит из флэшь занимает одинаково времени, ничего тут
не сэкономишь. Ну и самое главное, зачем в рантайме вычислять из
индекса адрес элемента массива, если его можно вычислить на этапе
компиляции? Так что, приводите листинг вашего варианта - будем
посмотреть. - VladislavS.(02.05.2022 17:31)
- По-вашему, наверное как-то так: Costic(209 знак., 02.05.2022 20:59, ссылка)
- Даже проверять не буду. Кода будет стопудово больше. Надо загрузить
адрес начала массива, загрузить адрес текущего индекса, загрузить
сам индекс и сложить их. Вместо того чтобы загрузить сразу
указатель. Желание на 32-битной системе сэкономить на разрядности
переменной улыбает - обычно эффект обратный получается. Кстати,
Cortex-M0 не умеет невыровненный доступ к памяти. Если вы сделаете
упакованную структуру с малоразрядным индексом, то получите вместо
экономии VladislavS.(146 знак., 02.05.2022 21:56)
- Чушь. Вы грузите свой 32-битный указатель, у которого старшие 16+
битов всегда одни и те же. Т.е. впустую гоняете данные из медленной
флеш. В моем варианте загружается только смещение (младшие 16 бит).
О выравнивании структуры пусть компилятор заботится. короче,
демагогия. - Costic(02.05.2022 23:18)
- Компилятор как раз таки позаботится о выравнивании и будет ваши 16 бит гонять в 32-битных словах. А если вы ему выкрутите руки и упакуете структуры, то будет побайтово их читать, ибо не умеет контроллер невыровненный доступ. Збсь такая "экономия". Адресация 32-битная, а значит к вашим 16 младшим битам нужно подгрузить и прибавить старшие вместо того чтобы одним чтением загрузить сразу указатель. И нет никакой проблемы с пропускной способностью флэша в современных VladislavS.(187 знак., 02.05.2022 23:57)
- Чушь. Вы грузите свой 32-битный указатель, у которого старшие 16+
битов всегда одни и те же. Т.е. впустую гоняете данные из медленной
флеш. В моем варианте загружается только смещение (младшие 16 бит).
О выравнивании структуры пусть компилятор заботится. короче,
демагогия. - Costic(02.05.2022 23:18)
- Даже проверять не буду. Кода будет стопудово больше. Надо загрузить
адрес начала массива, загрузить адрес текущего индекса, загрузить
сам индекс и сложить их. Вместо того чтобы загрузить сразу
указатель. Желание на 32-битной системе сэкономить на разрядности
переменной улыбает - обычно эффект обратный получается. Кстати,
Cortex-M0 не умеет невыровненный доступ к памяти. Если вы сделаете
упакованную структуру с малоразрядным индексом, то получите вместо
экономии VladislavS.(146 знак., 02.05.2022 21:56)
- По-вашему, наверное как-то так: Costic(209 знак., 02.05.2022 20:59, ссылка)
- Во-первых, даже для чтения переменной из RAM надо сначала загрузить
её адрес из флэшь. Во-вторых, РОН экономить смысла нет, они при
входе в прерывание сохраняются в достаточгом количестве. В-третьих,
чтение 8/16/32 бит из флэшь занимает одинаково времени, ничего тут
не сэкономишь. Ну и самое главное, зачем в рантайме вычислять из
индекса адрес элемента массива, если его можно вычислить на этапе
компиляции? Так что, приводите листинг вашего варианта - будем
посмотреть. - VladislavS.(02.05.2022 17:31)
- Для полноты картины надо мой вариант было рассмотреть, причём
желательно использовать для массива индекс типа uint16_t. Тогда в
моём варианте читать из флеша в 2 раза меньше, но использовать 1
РОН. И на частотах выше 25 МГц (предел флеша), думаю, будет профит. - Costic(02.05.2022 16:54)
- Ирония судьбы в том, что загрузить заготовленную заранее переменную в прерывании это то же самое что выбрать по заранее заготовленному указателю из массива. В смысле равномерности. Смотрим листинги, не ленимся. Шах и мат. - VladislavS.(01.05.2022 11:45)
- Для полноты картины посмотрим листинг и этого варианта. За сдвиг
записи полезных данных на одну команду к началу прерывания платим
дополнительной переменной в SRAM и более длинным прерыванием: VladislavS.(811 знак., 02.05.2022 10:06)
- блеать. если первое требование - равномерность подачи данных, то в
текущем прерывании готовим данные для отправки в следующем.
сохраняем их в заготовленную переменную и в самом начале следующего
прерывания отправляем куда там требуется. в этом случае можно
вообще нихрена не хранить, а считать на лету. - Mahagam(01.05.2022 10:25)
- Справедливости ради, код от начала прерывания до отправки данных по
назначению одинаков в случае связного списка и инкремента
указателя. Если общая загрузка процессора не зашкалит, то результат
будет одинаков. Но зачем делать плохо, если можно сделать хорошо. - VladislavS.(01.05.2022 08:37)
- Ну это же всё легко проверяется. Берём Cortex-M0+, пишем в
прерывании как у ТС код и смотрим листинги: VladislavS.(4175 знак., 01.05.2022 08:05)
- Суть моего спича кагбэ в том, что даже на мелких кортексах выигрыш
в количестве команд не всегда приводит к выигрышу в реальной
производительности. И раз уж мы не знаем точную модель, то не знаем
и как там флеш устроен. Потому, считаю, утверждать "так быстрее чем
эдак" несколько преждевременно. - LightElf(01.05.2022 02:05)
- Верование или нет, но я не видел, чтобы компиляторы так делали. Но
даже если допустить, с учётом развитости косвенной адресации, это
не много что меняет. Наверное, поэтому компиляторы и не делают
подобные оптимизации. Лишнии команды в случае с индексом тоже не из
воздуха, а из флэшь читаются, тут баш на баш. В кортексах шина к
флэшь обычно 64 бит и через буфер предвыборки. Контроллеру всё
равно за данными массива в флэшь обращаться, за одно и новый
указатель прочитается. VladislavS.(267 знак., 01.05.2022 00:33)
- Какое-то верование запрещает сразу инкрементировать указатель?
Инкремент на 8-битную константу занимает, емнип, одну инструкцию.
Загрузка же указателя из флеша требует двух обращений к флешу.
Имеется ли у обсуждаемого проца кэш чтения или там просто буфер
предвыборки - неизвестно. Так чта не все так однозначно, как
говорила дочь офицера. - LightElf(30.04.2022 16:49)
- Архитектуру мы таки знаем. Это Cortex-MO+. А у него доступ по
указателю будет всяко быстрее вычисления смещения из индекса,
проверки и инкремента индекса. - VladislavS.(29.04.2022 21:38)
- Имана. При наличии всей этой тряхомудии утверждение: "список с
указателями быстрее массива с индексом" кажется мне несколько
голословным, о мудрейший. Думаю ещё через сотню сообщений мы узнаем
модель процессора, примененного ТС и сможем оценить всю глубину
глубин. - LightElf(29.04.2022 20:54)
- При наличии предвыборки флэшь, работе в прерываниии и наличии DMA
на борту контроллера, не стоит на это рассчитывать, юный падаван. - VladislavS.(29.04.2022 18:42)
- Это не хуже, т.к. всё равно надо хранить или индекс, или указатель.
Вопрос в том, как автору удобнее заполнять этот список/массив.
Можно использовать макросы с __LINE__, но мне кажется, что это
будет не красиво. Дополнительный РОН... это от компилятора зависит.
Смещение (+1) к индексу известно на этапе компиляции, РОН не нужен.
Главное же - удобство пользования и размещение во флэш. - Costic(29.04.2022 15:49)
- В случае с указателем, доступ к полям структуры по фиксированному смещению. Компилятор все смещения знает и жёстко закодирует. В случае с индексом надо в одном регистре хранить адрес массива, во второй индекс загружать и для доступа к полям структуры их складывать и только потом смещение использовать. Посмотрите листинги, я чуть выше все ссылки на разные реализации собрал. - VladislavS.(29.04.2022 16:38)
- Предположение, что обращение к флешу занимает константное время
вижу я. - LightElf(29.04.2022 18:25)
- Это хуже, так как потребует хранить где-то индекс (дополнительный
РОН) и вычислять смещение из индекса в каждом цикле. В случае
p=p->nexet доступ к полям через p просто адресацией со
смещением происходит. - VladislavS.(29.04.2022 15:12)
- Как это поможет избавиться от условия с проверкой выхода за граници
перед переходом на следующий элемент? - Moлoдoй кoллeгa(28.04.2022 20:09 - 20:13)
- Если время критично, пишите на ассемблере, или возьмите другой чип.
) - AПM(29.04.2022 14:22)
- Есть небольшая, критичная в моём случае, разница времени выполнения Moлoдoй кoллeгa(70 знак., 28.04.2022 19:57)