Кто любит RISC в жизни, заходим, не стесняемся.
Ответить

Re: Лучше не использовать типы char в stm32?

Сб окт 23, 2021 09:12:25

Логика очень простая - новые технологии экономят флеш, и значительно повышают быстродействие.

А какие из технологий здесь вы считаете новыми? Если оптимизатор компилятора, то он одинаковый в обоих случаях. А использованные алгоритмы преобразования в строку не менялись с каких-то допотопных времен.

Re: Лучше не использовать типы char в stm32?

Сб окт 23, 2021 09:18:09

Не понял - а при чём тут AVR если тема про ARM?
При том, что именно эта ветка дискуссии была про AVR, естественно.
Если на клетке слона прочтёшь надпись «буйвол», не верь глазам своим. Козьма Прутков
Изображение
тема.png
(9.46 KiB) Скачиваний: 458


Пока что единственное, что нам известно - что мой код в занимает в 1.6 раз меньше места в ПЗУ. Поскольку никаких кэширований и других оптимизаций на скорость не использовалось, логично предположить, что он будет быстрее выполняться.
Дарю самый быстрый в мире код. Одна ассемблерная команда будет всего.
Код:
for(;;);

Re: Лучше не использовать типы char в stm32?

Сб окт 23, 2021 09:33:18

Все-таки проверил скорость работы. Правда, под рукой оказался только древний AVRStudio, у которого далеко не лучшая оптимизация. Ну да для грубой оценки сойдет.
Вариант jcxz выполняется за 10180 тактов.
Вариант мой - за 11116
Результат: вариант jcxz чуть быстрее.
Для моих задач (обычно это отладочный вывод на UART или дисплей с человеко-читаемой скоростью) эта разница не критична, и я скорее всего продолжу пользоваться своим вариантом, как более читаемым.
Еще, наверное, проверю на ARM-M3, поскольку такие камни у меня есть, и поскольку аппаратной математики у них побольше, чем у AVR, с которых мы начинали.

Re: Лучше не использовать типы char в stm32?

Сб окт 23, 2021 10:12:55

COKPOWEHEU, а как насчет на F0 проверить?
Что-то меня гложут сомнения, что операции над uint64_t будут выполняться быстрей, чем деление (пусть и софтовое) на 10 uint32_t.

Re: Лучше не использовать типы char в stm32?

Сб окт 23, 2021 10:19:40

COKPOWEHEU, а как насчет на F0 проверить?

Мне неначем: ни симулятора, ни железки нет.
---
А вот на stm32L151 не удержался и проверил. Попутно оказалось, что обе наши реализации работают неправильно. Заодно ради эксперимента привел код jcxz к своему чтобы не пришлось в конце переворачивать строку.
Исправленный вариант jcxz:

На конвертацию числа 4294967295 уходит примерно 200 тактов.
Исправленный мой вариант:

Выполняется примерно за 176 тактов
Гибридный вариант:

Выполняется за 137 тактов.
Результат: исходный вариант jcxz выполняется уже чуть дольше моего, скорее всего из-за того, что приходится в конце переворачивать строку. Если заполнять массив справа налево, выполняется уже быстрее.

Re: Лучше не использовать типы char в stm32?

Сб окт 23, 2021 10:33:27

А вот на stm32L151 не удержался и проверил.

На M3 и выше, как я уже говорил, компилятор сам заменяет деление умножением, при том что там есть и аппаратное деление с которым результат будет не особо хуже, а вот на М0 будет использоваться софтовое деление потому твой вариант с делением и взятием остатка - это один из самых медленных подходов.

Re: Лучше не использовать типы char в stm32?

Сб окт 23, 2021 11:15:47

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

Re: Лучше не использовать типы char в stm32?

Сб окт 23, 2021 11:27:18

Напомню что язык Си совершенно бесплатно даёт возможность отстрелить себе все конечности. У нас именно такой случай.
В идеале нужно обвесить функцию проверками размера стека, так чтобы не отсвечивали. Меня хватило на передачу хвоста буфера - защита на минималках.
Кроме того меня нервирует пропавшее второе умножение, вместо которого используется три строчки сдвигов и сложений.

Re: Лучше не использовать типы char в stm32?

Сб окт 23, 2021 12:03:43

Пруфы где?

Берем STM32G0(M0+) и тестим(-O2) с твоей оригинальной функцией, затем убираем получение остатка от деления и наконец заменяем само деление:

Последний вариант быстрее в 2.7 раза, хотя разница падает по мере уменьшения передаваемого значения, т.к. софтовое деление тогда завершается быстрее. Если числа порядка 1000, то первый и последний вариант выдают сравнимые значения, в среднем наверное второй вариант самый оптимальный, тем более так можно не только десятичные числа выводить.

Re: Лучше не использовать типы char в stm32?

Сб окт 23, 2021 12:27:25

Reflector, а зачем там кусок от вывода шестнадцатеричных остался? `else *buf -= 0x0A + 'A';` не будет выполняться.
А выводить шеснадцатеричные числа значительно проще, там никаких делений не нужно:
Код:
void printuhex(uint32_t val){
    addtobuf("0x");
    uint8_t *ptr = (uint8_t*)&val + 3;
    int i, j, z = 1;
    for(i = 0; i < 4; ++i, --ptr){
        if(*ptr == 0){ // omit leading zeros
            if(i == 3) z = 0;
            if(z) continue;
        }
        else z = 0;
        for(j = 1; j > -1; --j){
            uint8_t half = (*ptr >> (4*j)) & 0x0f;
            if(half < 10) bufputchar(half + '0');
            else bufputchar(half - 10 + 'a');
        }
    }
}

Re: Лучше не использовать типы char в stm32?

Сб окт 23, 2021 12:34:30

а зачем там кусок от вывода шестнадцатеричных остался?

Я для теста взял функцию COKPOWEHEU, главное что там деление и взятие остатка есть.

Re: Лучше не использовать типы char в stm32?

Сб окт 23, 2021 12:42:15

Напомню что язык Си совершенно бесплатно даёт возможность отстрелить себе все конечности. У нас именно такой случай.
В идеале нужно обвесить функцию проверками размера стека,

Разверните свою мысль чтобы понятна была. Какой случай? При чем здесь стек? Через стек передаются только uint32_t в качестве аргумента и char* (обычно uint16_t либо uint32_t) в качестве буфера. Уж 6-8 свободных байт в стеке скорее всего найдется.
Берем STM32G0(M0+) и тестим(-O2)
Да, именно это мне и нужно, что ж вы изворачиваетесь-то постоянно от прямого вопроса! Где тесты? Опять от вас одни "логические соображения".
В общем, пока пруфов нет, остается пользоваться моими данными: деление через B35 чуть-чуть быстрее, но менее читаемое. И, естественно, буфер надо заполнять с конца.

Re: Лучше не использовать типы char в stm32?

Сб окт 23, 2021 13:10:07

Да, именно это мне и нужно, что ж вы изворачиваетесь-то постоянно от прямого вопроса! Где тесты? Опять от вас одни "логические соображения".

Смотри, есть такой код:
Код:
buf[0] = val % 10;
val /= 10;

Если посмотреть что генерит gcc для M0, то там будут вызовы функций __aeabi_uidivmod() и __udivsi3(), при это первая дополнительно вызывает вторую, т.е. деление выполняется дважды о чем тебе уже говорил jcxz и я об этом также знал еще когда писал свои функции конвертации, так что это никакие не чисто "логические соображения". Более того я написал три разных функции, протестил их и результаты спрятал под спойлер, но видимо спрятал слишком хорошо, раз не все смогли с ними ознакомиться :)

Re: Лучше не использовать типы char в stm32?

Сб окт 23, 2021 13:55:40

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

Re: Лучше не использовать типы char в stm32?

Сб окт 23, 2021 14:26:40

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

Под спойлером есть все, что нужно, разве что класс замеряющий время выполнения придется чем-то заменить, если хочется мерять самому. Я даже на всякий случай проверил насколько точно измеряет и для nop<500>(), т.е. 500 подставленных NOP получил ровно 500 тиков.

COKPOWEHEU писал(а):Деление выполняется единажды, о чем я уже писал. Получение частного и остатка это одна функция.

Ну давай считать:
Код:
      buf[0] = val % 10;
0x20001ec4  movs r1, #10
0x20001ec6  movs r0, r5
0x20001ec8  bl 0x20001824 <__aeabi_uidivmod>
      val /= 10;
0x20001ecc  movs r0, r5
0x20001ece  uxtb r4, r1
0x20001ed0  movs r1, #10
0x20001ed2  bl 0x20001718 <__udivsi3>   ; раз udiv

__aeabi_uidivmod:
0x20001824  cmp r1, #0
0x20001826  beq.n 0x20001818 <__udivsi3+256>
0x20001828  b.n 0x20001718 <__udivsi3>   ; два udiv
0x2000182a  bx lr

Re: Лучше не использовать типы char в stm32?

Сб окт 23, 2021 15:33:13

Под спойлером есть все, что нужно
Да? И где там исходный вариант jcxz - который с переворотом строки?
Ну давай считать:
Даже не знаю что еще считать, если я уже даже название этой функции выложил. Ну ладно. Вот для AVR, с которого мы начали обсуждение:

Единственный вызов <__udivmodsi4> лично я нашел по адресу 0xEA.
Вот для arm-m3:

Инструкции udiv и mls вижу, подпрограмм деления с ходу не увидел.
---
Такое ощущение, что вы упорно пытаетесь съехать с исходной темы на ARM-M0. Но чем именно эта архитектура примечательна? Вроде как никто на ней изначально акцента не делал.

Re: Лучше не использовать типы char в stm32?

Сб окт 23, 2021 16:06:48

COKPOWEHEU, я писал, что для M3 и выше будет замена на умножение, хотя там и деление относительно быстрое, а для M0 будет софтовое деление и потому твой подход будет одним из самых медленных. И после этого ты попросил пруфы, которые с первого раза вообще не заметил, со второго видимо заметил только половину, а на третий раз в ход пошли тесты для AVR, а я оказался виновным в съезжании с AVR на M0 :) Какое отношение к медленной работе функции на M0, а я утверждал именно это, имеют реализации для M3 или AVR? И переворот строки тут не при чем, потому что речь о двойном и медленном делении, переворачивая строку можно дополнительно затормозить что угодно и вообще ни у меня, ни у тебя переворота строки нет, чего мне обсуждать недостатки реализации третьего лица? Читать нужно внимательнее, а то под спойлеры не заглядываем и независимо от того, что пишут другие считаем, что речь идет об AVR :)

Re: Лучше не использовать типы char в stm32?

Сб окт 23, 2021 17:31:11

Читать нужно внимательнее, а то под спойлеры не заглядываем и независимо от того, что пишут другие считаем, что речь идет об AVR :)

При чем здесь спойлеры? Вот прямая цитата:
Кстати, мне после AVR не нравится сдвиг на (4*j), лучше бы исходное число двигать, как в выводе десятичного:

А вот про М0 как раз речь не шла.
Какое отношение к медленной работе функции на M0
При чем здесь M0? На AVR, где нет не только аппаратного умножения и деления, но хоть какой-то работы с числами больше 8 бит, разница незначительная.
И после этого ты попросил пруфы, которые с первого раза вообще не заметил
Посмотрите вот на это сообщение, вот на это. И потом на свое. И сравните где результаты измерений, а где куски кода.
---
Впрочем, теперь это уже чисто академический вопрос. Измерения я провел, результаты выложил. Вариант с делением ненамного медленнее сдвигов, зато читабельнее.

Re: Лучше не использовать типы char в stm32?

Сб окт 23, 2021 18:49:11

При чем здесь M0? На AVR, где нет не только аппаратного умножения и деления, но хоть какой-то работы с числами больше 8 бит, разница незначительная.

M0 при том, что про AVR я даже не заикался, первый мой пост касался M3(и выше) и M0, а в качестве проблемной серии я обозначил только последнюю. То что ты до того обсуждал AVR с другими людьми, хотя они тоже задавались вопросом при чем тут AVR, меня совершенно не каcается. Если говоря про M0, при этом цитируя пост про L151, т.е. тоже про STM32, от меня требуют тестов, то это тесты для M0, думать что они для AVR нет никаких оснований.


COKPOWEHEU писал(а):Посмотрите вот на это сообщение, вот на это. И потом на свое. И сравните где результаты измерений, а где куски кода.

Ладно, по первому линку можно прочитать что две вариации тестируемого кода выполняются за 10180 и 11116 тактов, т.е. первый вариант немного быстрее, но разве что-то принципиально поменяется если этих тактов будет 15000 и 16000? Нет, по-прежнему первый вариант будет немного быстрее, потому у меня было написано, что последняя функция, у которой убрано вычисление остатка от деления и заменено само деление выполняется в 2.7 раза быстрее оригинальной функции у которой это все есть. Какие функции, как тестировалось и сколько тактов получилось - это все под спойлером, для особо любознательных.

Re: Лучше не использовать типы char в stm32?

Сб окт 23, 2021 21:46:44

Если говоря про M0, при этом цитируя пост про L151

Разве L151 это М0? Да нет, сейчас перепроверил: все stm'ки, на которых я могу протестировать - F100, F103, L151 - относятся к М3.
было написано, что последняя функция, у которой убрано вычисление остатка от деления и заменено само деление выполняется в 2.7 раза быстрее
А в 2.7 раза это сколько в тактах? Может, там как и в AVR десять тысяч тактов и оба варианта годятся только отладочную информацию раз в вечность передавать. То есть не "данные для любознательных" закопаны под спойлер, а просто какие-то сырые данные без пояснений.
Ответить