VslavX 0 16 апреля, 2012 Опубликовано 16 апреля, 2012 · Жалоба ваш вариант TNKernel : 2.83uS для LPC1768, @100МГц, scmRTOS: 2.55uS STM32F103 @72MHz (приведённое к 100МГц - 1.83uS). Более чем в полтора раза однако :) Та не™ Сравнивать надо на одинаковых процах, одинаковый прикладной код, одинаковым методом (скопом импульс на одной и той же ножке наблюдаем, например), с одинаковыми опциями компилятора, и исполнением из одного и того же места (из флеша, да :), и с одинаковыми waitstates). В упомянутой теме апдейт давний написан - включаешь у компилятора оптимизацию по скорости - и уже имеем 2.50uS на 1768@100МГц для TNKernel. BTW, я там еще оптимизаций добавил, надо бы потестить - а то что-то давно я ерундой не страдал Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 15 16 апреля, 2012 Опубликовано 16 апреля, 2012 · Жалоба У меня нет ни IAR-а ни LCP17xx :) BTW, а не было ли среди ваших оптимизаций TNKernel-а отключения round-robin? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VslavX 0 16 апреля, 2012 Опубликовано 16 апреля, 2012 · Жалоба У меня нет ни IAR-а ни LCP17xx :) BTW, а не было ли среди ваших оптимизаций TNKernel-а отключения round-robin? Не-а, оно вообще-то условными флагами не отключается (не было надобности в таких флагах). Тестировался полнофункциональный релизный вариант. Я постараюсь при возможности попробовать scmRTOS 4.0 на той же платформе. Думаю что результаты будут очень близкими. Потому как при грамотной структуре данных реализация round-robin не так уж и страшна. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 15 16 апреля, 2012 Опубликовано 16 апреля, 2012 · Жалоба Думаю что результаты будут очень близкими. Потому как при грамотной структуре данных реализация round-robin не так уж и страшна. Предсказываю процентов 40 выигрыша scmRTOS. Потому что это всё равно что-то (реализация round-robin, пусть даже при грамотной структуре данных) против ничего (две инструкции для выбора младшей единицы в слове-карте процессов). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VslavX 0 16 апреля, 2012 Опубликовано 16 апреля, 2012 · Жалоба Предсказываю процентов 40 выигрыша scmRTOS. Потому что это всё равно что-то (реализация round-robin, пусть даже при грамотной структуре данных) против ничего (две инструкции для выбора младшей единицы в слове-карте процессов). Это все из серии "Пастернака не читал - но осуждаю" . TNKernel точно так же ищет младший бит в битовой маске приоритетов - для кортекса юзается та же банальная инструкция CLZ (а для ARM7TDMI остроумный алгоритм из 5-6 инструкций) //________________________________________________________________ // // Функция быстрого поиска номера младшего установленного бита // // Входные параметры: // value - исходное 32-битовое слово // Возвращает: // номер самого младшего единичного бита + 1; // (для бита 0 - возвращается 1, для бита 31 - 32) // если исходное значение было нулевое, то возвращается 0 // INLINE_FORCED DWORD ffs_asm(DWORD value) { value = value & (0 - value); value = 32 - __CLZ(value); return value; } А round-robin там списком реализован, поэтому TCB новой планируемой задачи при переключении максимум дополнительно извлечения указателя потребует (и то я не уверен в этом, TNKernel элемент списка встраивает прямо в объект, поэтому просто возможна банальная коррекция указателя инструкцией ADD/SUB #const вместо извлечения нового указателя). То есть - SCMRTOS ищет самый приоритетный бит и берет из массива указатель на TCB по индексу этого бита. А TNKernel по индексу бита извлекает из того же массива указатель на список round-robin, и потом из этого указателя делает указатель на TCB. Вот и вся разница, делов-то. Если где и будет некоторый расход ресурсов - так это в таймере, который будет тикать и листать список round-robin - переходить на следующий TCB. Но собственно к переключению контекста оно никак не относится. Так что какие там 40 процентов :laughing: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dxp 58 16 апреля, 2012 Опубликовано 16 апреля, 2012 · Жалоба Оперативы ровно столько же - ведь меняется только схема приоритетов, а количество процессов и их стеки остаются теми же самыми. Я про вариант, когда низкоприоритетные задачи просто выполняются по очереди - одна отработала, другой управление передаётся в рамках одного и того же процесса. На практике я просто делаю это через очередь заданий, которую обрабатывает низкоприоритетный процесс. А round-robin там списком реализован, поэтому TCB новой планируемой задачи при переключении максимум дополнительно извлечения указателя потребует (и то я не уверен в этом, TNKernel элемент списка встраивает прямо в объект, поэтому просто возможна банальная коррекция указателя инструкцией ADD/SUB #const вместо извлечения нового указателя). То есть - SCMRTOS ищет самый приоритетный бит и берет из массива указатель на TCB по индексу этого бита. А TNKernel по индексу бита извлекает из того же массива указатель на список round-robin, и потом из этого указателя делает указатель на TCB. Вот и вся разница, делов-то. Если где и будет некоторый расход ресурсов - так это в таймере, который будет тикать и листать список round-robin - переходить на следующий TCB. Но собственно к переключению контекста оно никак не относится. Так что какие там 40 процентов :laughing: А идентификация задачи как производится? В scmRTOS таким идентификатором является как раз значение приоритета. И каждый сервис при переводе процесса в спячку или пробуждении оперирует с этим значением, которое всегда доступно и однозначно определяет процесс. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 15 16 апреля, 2012 Опубликовано 16 апреля, 2012 · Жалоба Это все из серии "Пастернака не читал - но осуждаю" . Я не читал, но отнюдь не осуждаю:) Так что какие там 40 процентов :laughing: Посмотрим-посмотрим:) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VslavX 0 16 апреля, 2012 Опубликовано 16 апреля, 2012 · Жалоба Я про вариант, когда низкоприоритетные задачи просто выполняются по очереди - одна отработала, другой управление передаётся в рамках одного и того же процесса. На практике я просто делаю это через очередь заданий, которую обрабатывает низкоприоритетный процесс. Угу, именно это я называю "кооператив". Если система одновременно не поддерживает несколько процессов одинакового приоритета, то остается только такой выход. Хороший кооператив - это тоже достаточно непросто, вон мой HTTP-сервер в основном потоке кооперативный, и то потребовалось внутри три очереди создавать, а как дошло дело до скриптов CGI тут чистый кооператив сдох, пришлось выносить скриптовую часть в чистую вытесняйку. А идентификация задачи как производится? По значению указателя на TCB (task control block, аналог экземпляра TBaseProcess, если не ошибаюсь). И с объектом TCB сразу можно работать - не надо преобразовывать id (приоритет) в указатель. Понятно что это извлечение из массива, но - надо сделать ldr адреса массива (ага, из очен-но быстрой флеши), потом сам ldr из массива (ну тот уже в RAM). И каждый сервис при переводе процесса в спячку или пробуждении оперирует с этим значением, которое всегда доступно и однозначно определяет процесс. Ну так оперируем сразу с TCB. При глубокой отладке опционально возможно включение проверки, что указатель на TCB действителен, и содержится в списке действительных на данный момент в системе задач (сканирутся список, при отладке это допустимо). P.S. Ага, я посмотрел листиг - таки round-robin потребовал при переключении одной дополнительной инструкции subs для коррекции указателя списка в указатель на TCB. Одна инструкция - это как, подъемная цена за round-robin среди процессов одного приоритета? И количество процессов не будет ограничено. Update: я как-то упустил из вида что scmRTOS на 8/16-битных платформах тоже работает (мой порт TNKernel исключительно предусматривался для 32-х разпядных - как минимум предполагает что операции загрузки/сохранения указателей атомарны). На 8-битной платформе идентификация процесса по уровню приоритета вероятно даст выигрыш по размеру и быстродействия кода. Но для 16/32-битных платформ это уже становится явных архитектурным ограничением. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dxp 58 16 апреля, 2012 Опубликовано 16 апреля, 2012 · Жалоба По значению указателя на TCB (task control block, аналог экземпляра TBaseProcess, если не ошибаюсь). И с объектом TCB сразу можно работать - не надо преобразовывать id (приоритет) в указатель. Понятно что это извлечение из массива, но - надо сделать ldr адреса массива (ага, из очен-но быстрой флеши), потом сам ldr из массива (ну тот уже в RAM). Про какое ldr речь? Что-то нету у нас в AVR никакой ldr. :) Шутка. Но идея та же. Ну так оперируем сразу с TCB. При глубокой отладке опционально возможно включение проверки, что указатель на TCB действителен, и содержится в списке действительных на данный момент в системе задач (сканирутся список, при отладке это допустимо). Это хорошо на 32-битном проце, одна инструкция. На мелочи манипуляции с указателями вместо битов уже не так красиво выглядят. Кроме того, Битовая маска, являющаяся идентификатором процесса, одновременно является и средством для манипуляции картами процессов в каждом сервисе. С указателем на процесс так не получится. Там потребуются отдельные телодвижения, чтобы обслуживать все эти вещи. Поскольку битовая маска не может быть уникальной для процесса/задачи, то для фиксации ожидающего процесса, например, нужно будет завести для этого отдельную переменную в TCB. А как, скажем, достичь такой функциональности: Event Flag, когда его сигналят, переводит все процессы, которые встали на ожидание флага, в готовые к выполнению - своего рода широковещательный "подъём" спящих, но не broadcast, а multicast - т.е. не просто всех поднять, а выборочно, только тех, кто "записался" на ожидание? В случае битовых карт процессов с уникальными приоритетами это делается одной командой по маске. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VslavX 0 16 апреля, 2012 Опубликовано 16 апреля, 2012 · Жалоба Это хорошо на 32-битном проце, одна инструкция. На мелочи манипуляции с указателями вместо битов уже не так красиво выглядят. Да, это я уже сообразил - одновременно с Вами апдейт своего поста написал. в TCB. А как, скажем, достичь такой функциональности: Event Flag, когда его сигналят, переводит все процессы, которые встали на ожидание флага, в готовые к выполнению - своего рода широковещательный "подъём" спящих, но не broadcast, а multicast - т.е. не просто всех поднять, а выборочно, только тех, кто "записался" на ожидание? В случае битовых карт процессов с уникальными приоритетами это делается одной командой по маске. Наверное да - тут проще OR сделать на маску активных процессов. Но тут есть нюанс - у меня редко (я даже не могу вспомнить такой случай) бывает что какой-то объект с автосбросом ждет несколько процессов. Такое может быть с мьютексом - но там нужно выбрать и пробудить один самый приоритетный процесс (unicast, Вашими словами). Критическая секция на семафоре - то же самое - пробудить один процесс, первый в очереди. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VslavX 0 16 апреля, 2012 Опубликовано 16 апреля, 2012 · Жалоба Посмотрим-посмотрим:) Да нету там никаких 40 процентов :) Исходные условия: - STM32F103RG - тактовая частота ядра 72МГц - тактовая частота шины периферии 36МГц - исполнение из флеша с 2 тактами ожидания - печатная плата - стартеркит от Терраэлектроники - компилятор IAR 6.30 - максимальные оптимизации по скорости Тестовый алгоритм такой: - имеется две задачи - 1 и 2 - приоритет задачи 1 выше (более приоритетная) чем у задачи 2 - задача 1 в бесконечном цикле { ждет синхрообъект (семафор для TNKernel и ef для scmRTOS) после срабатывания синхрообъекта сбрасывает тестовый пин GPIO } - задача 2 в бесконечном цикле { спит 10 мс устанавливает тестовый пин GPIO сигналит синхрообъектом задаче 2 } В итоге осциллографом наблюдаем импульсы положительной полярности длительностью несколько микросекунд с частотой следования 100 Герц. Примечание: Для SCM выполнена дополнительная оптимизация кода (отличие от релизной версии) предложенная AHTOXA - внесена инструкция "bl os_context_switch_hook" в файле OS_Target_asm.s Для SCM за основу взял проект 1-EventFlag для порта на STM32F1xx. Tрадиционно помучался со средой (а почему это у вас там есть конфигурация Release которая нихрена не компилируется?), в итоге пришлось проходить все опции ручками - выбирать тагет, включать оптмизации, и прочее. Вкрутил свой код настройки тактовой частоты и флеша. Итоговый результат - длительность тестового импульса 2.72мкс. Потом взял свой проект на TNKernel, тот же самый код инициализации тактового генератора, тот же самый тестовый алгоритм. Отключил отладку и всякие плюшки типа профайлера времени исполнения задачи - оп-па, импульс 4.04 мкс. Не, такого не бывает, я же железобетонно уверен. Ага - забыли оптимизацию по скорости включить - 3.56 мкс. Ну не может быть. Полез ковыряться, в итоге нарыл у себя глюк в порту - запрос PendSV избыточно вызывался дважды (это я давно перестраховался при разработке порта и потом забыл убрать, так что уже сегодняшний вечер провел с пользой ). Откорректировал, тестим - 2.88мкс. Та не (ТМ), ага - 5.41 компилируется, а надо 6.30 (как было для SCM). Берем 6.30 - итого 2.76мкс . Кстати 6.30 глючный при высоких степенях оптимизации, я его не использую. Еще немного поигрался с оптимизациями - но начали видимо играть начальные выравнивания функций, уже тут эти такты выловить сложно - было от 2.64 до 3.10 мкс, поэтому за пруф результат все-таки принимаю 2.76. Итоговый результат длительностей наблюдаемых импульсов: scmRTOS - 2.72 мкс TNKernel - 2.76 мкс Ессно, никаких 40 процентов тут и близко нету, так что "Пастернака надо-таки читать", ага :tongue: Я не берусь утверждать что тут эта разница именно из-за более сложного диспетчера - уж очень разные ОС и много факторов влияет. Но то что двухуровневый диспетчер с round-robin-ом вещь совсем не аццки сложная и медленная - это экспериментально доказанный факт. Update: поигрался с конфигурацией scmRTOS, отключил отладку - добился еще снижения до 2.69 мкс. Почему оно так повлияло - явного места в коде ОС не нашел, видимо опять смещения начала функций и циклов отыграли. В-общем, общая картина понятна, на этом завязываю - дальше наносекунды ловить смысла большого нет. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_pv 71 16 апреля, 2012 Опубликовано 16 апреля, 2012 · Жалоба Поллингом - использовал чужой драйвер, а допиливать "под себя" было некогда. Хотя по идеи, если время переключения контекста мало, то и в поллинге можно вставить небольшие задержки и выкрутиться. Так или иначе с одинаковыми приоритетами решить подобные задачи проще всего, особенно для не очень искушенных людей в подобных вопросах. :) ну, наверное, можно запилить в scmTROS сущность, которой скармливается лишь битовая маска процессов которым надо карусель устроить и эта сущность каждые N системных тиков будет на время насильно усыплять очередной процесс из этой маски если он активен, таким образом давая поработать другим хоть и с меньшим приоритетом, таким образом чужие библиотеки которые внутри что-то поллят вполне могут работать по очереди? или так не получится? накладных расходов на такой псевдо round-robbin вроде никаких. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aprox 0 16 апреля, 2012 Опубликовано 16 апреля, 2012 · Жалоба Может, хватит вам уже позориться, а? Неужели трудно понять, что механизмы инкапсуляции C++ ну никак не защищают данные при конкурентном доступе к ним из разных потоков выполнения (в вашем случае - из прерываний)? Вы слишком спешите с выводами. Нет никаких "конкурентных" потоков у периферии. Если от UARTa идут строки запросов, то они идут в строго определенный интерпретатор этих запрсов. И никто другой туда не сунется. То же самое, инапример, с Ethernet MAC-ом, после выделения, HTTP запросы поступают в строго определенный интерпретатор, и тоже никто к этому WEB серверу не сунется с чем-то другим. О каких таких "конкурентных потоках" вы говорите? Я их не наблюдаю. Наверное вы не поняли, что задачей в моем случае является ISR, которая оформлена в виде защищенного метода в классе с защищенными данными. Никто туда, кроме методов самого класса добраться не может. Какие такие "конкурентные потоки"? Можете представить конкретный пример? тоже достаточно непросто, вон мой HTTP-сервер в основном потоке кооперативный, и то потребовалось внутри три очереди создавать, а как дошло дело до скриптов CGI тут чистый кооператив сдох, пришлось выносить скриптовую часть в чистую вытесняйку. Я видимо чего-то упустил, но по-моему CGI основано на использовании .dll в серверах на ПК? При чем тут scmRTOS для малых 8-ми разрядных чипов? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 15 17 апреля, 2012 Опубликовано 17 апреля, 2012 · Жалоба scmRTOS - 2.72 мкс TNKernel - 2.76 мкс Ессно, никаких 40 процентов тут и близко нету, так что "Пастернака надо-таки читать", ага :tongue: Давайте всё же уточним, что это не Пастернак, а сильно допиленное чудовище Франкенштейна, причём в данный момент никем, кроме самого Франкенштейна не проверяемое :) ЗЫ. У меня, кстати, получилось 2.55 мкс (scmRTOS 4.0/GCC). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VslavX 0 17 апреля, 2012 Опубликовано 17 апреля, 2012 · Жалоба Я видимо чего-то упустил, но по-моему CGI основано на использовании .dll в серверах на ПК? При чем тут scmRTOS для малых 8-ми разрядных чипов? CGI это несколько более широкая концепция. Имхо, под CGI следует понимать такое - поступает HTTP-запрос, сервер принимает заголовок запроса, определяет имя ресурса. Если это имя является именем скрипта (неважно на каком языке написанном - Ява, Перл, Питон, ПХП, или это вообще может быть приложение на С/С++), то сервер запускает этот скрипт и дальнейший поток данных входящего HTTP-запроса (тело, если оно есть) перенаправляется в stdin порожденного скрипта. А поток stdout, генерируемый скриптом, сервером также перехватывается и отправляется как ответ на HTTP-запрос удаленному хосту. Так вот, веберы (разработчики сайтов) поднакопили некоторый багаж алгоритмов и опыт разработки таких скриптов, принудить их поддерживать явный кооператив сложновато. К тому же обычно из этих скриптов (во встраиваемом сервере это просто процедуры на C/C++ выполняемые в отдельном порожденном потоке) требуется доступ к аппаратуре или внутренним базам данных устройства, например, оно как выдаст "SELECT к внутреннему SQL-серверу" - какой уж тут кооператив. Возвращаясь к scmRTOS, жесткое использование приоритета как идентификатора процесса имеет еще один недостаток - приоритет не может быть динамически изменен. Значит все протоколы управления приоритетами, предназначенные для борьбы с инверсией приоритетов, также не могут быть реализованы даже теоретически :(. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться