OSDev http://osdev.su/ |
|
Измерение времени в ОС http://osdev.su/viewtopic.php?f=6&t=797 |
Страница 2 из 4 |
Автор: | maisvendoo [ 11 сен 2013, 08:19 ] |
Заголовок сообщения: | Re: Измерение времени в ОС |
Nable писал(а): В общем, например, для переключения задач и тому подобного очень удобен local APIC timer. Почитаю документацию Nable писал(а): откуда такое увлечение асмом там где можно обойтись без него, да ещё и в вырвиглазном синтаксисе? Есть же inline asm (правда, тут тоже может понадобиться AT&T, но писанины хотя бы меньше) Тут мое имхо: 1. "Железные" особенности вынуждают использовать ассемблер. Что касается синтаксиса - дело вкуса и я например не считаю его вырвиглазным, а считаю удобным. К тому же GAS хорошо без допнастройки интегрирован со всеми средствами разработки в среде *nix. И если есть горячее желание использовать Intel-синтаксис - пожалуйста, есть директивы .intel_syntax noprefix, которые допускается применять в том числе и в ассемблерных вставках 2. По поводу ассемблерных вставок. Реализуйте приведенный в стартовом сообщении кусок кода с применением asm volatile(...), выполните сборку и посмотрите дизасcемблерный листинг. Сколько отсебятины добавит gcc в ваш ассемблерный код? И как эта отсебятина повлияет потом на работу реализуемой функции? У меня было такое. По-моему проще и быстрее написать объектный модуль на чистом асме (если он требуется реально), выкинув в заголовок прототип внешней функции и получить детерминированный результат, а инлайн ассемблер оставить для случаев когда необходимо выполнить одну-две команды. К тому же asm volatil-ы затрудняют чтение кода, ибо ужасны на вид эти заборы скобок и кавычек с равенствами и двоеточиями. Используя ассемблерные вставки мы уже используем ассемблер. Зачем притворятся что мы типо пишем на С, если код истыкан asm volatile в больших количествах? Получается не проще а сложнее - несколько *.s файлов не испортят картины, а только придадут коду ясность и структурированность. Add: Вот "безассемблерная" реализация той же функции что и в стартовом посте Код: /*------------------------------------------------------------------------------ // //----------------------------------------------------------------------------*/ void get_cpu_ticks2(u64int* ticks) { u32int lo = 0; u32int hi = 0; asm volatile ("rdtsc":"=a"(lo),"=d"(hi)); *ticks = hi; *ticks = *ticks << 32; *ticks |= lo; } Вот дизассеблерный листинг того что получается без оптимизации С оптимизацией ключем -O2 не отличается от ассемблерной реализации get_cpu_ticks(...), которая внизу скрина М-да, интересный результат... Но все же, не очевидный |
Автор: | Nable [ 11 сен 2013, 09:52 ] |
Заголовок сообщения: | Re: Измерение времени в ОС |
Здрасте. На код без оптимизации вообще смотреть не надо - он сгенерён чтобы можно было ровно по сишным строкам ходить и иметь возможность в отладчике видеть все промежуточные вещи. Чтобы не было тонны отсебятины - надо, как минимум, (про необходимость -O2 я уж и не говорю) использовать inline и ключи -ffomit-frame-pointer (забываем про отладку, ну да и фиг с ней: если нужно будет, можно и собрать с -O0 или глянуть в оптимизированный листинг, зачастую он очень компактен и понятен) и -flto. Правда нюанс: с одной стороны, LTO может сильно уменьшить объём (ну и ускорить, за счёт встраивания мелких функций) кода за счёт того что модули уже не будут в код валиться целиком, как есть, т.е. безо всякого учёта взаимоотношений между этими модулями; с другой стороны - для этого нужна весьма новая версия компилятора (у MS уже давно появилось LTCG, а GCC только догоняет, впрочем, кроме наличия фичи есть ещё качество реализации), а у gcc нередко попадается. Если код весь истыкан asm volatile - это может означать что автор пошёл куда-то не туда. С тех пор как железки управляются преимущественно через MMIO, в большей части драйверов asm вообще не упёрся. Асм остаётся для для сугубо специфичных для процессора вещей: регистров управления (CRx), MSR, сохранение/загрузки контекста, быть может, I/O портов, ну и для сложных примитивов синхронизации (если не используем интеловский компилятор, libatomic-ops или чего подобное). Конечно, я мог чего-то пропустить, но мысль в том что зачастую автор слишком рано начинает увлекаться натыкиванием асма, в т.ч. из-за того что некоторые вещи на нём пишутся проще (но потом продолжать их всё тяжелее), хотя как сказать: нужно постоянно думать о соблюдении ABI (какие регистры сохранять, через какие могут быть переданы параметры - на более других архитектурах, чем IA-32 это делать весьма сложно). |
Автор: | maisvendoo [ 11 сен 2013, 10:15 ] |
Заголовок сообщения: | Re: Измерение времени в ОС |
Думаю что для задачи чтения TSC применение ассемблера вполне оправдано. Другой вопрос в том надо ли его читать в связи с решаемой задачей - тут я согласен со всеми приведенными замечаниями - реализация получилась кривой. Что ж, переделаю, затем и постил, чтобы проконсультироваться Nable писал(а): код без оптимизации вообще смотреть не надо - он сгенерён чтобы можно было ровно по сишным строкам ходить и иметь возможность в отладчике видеть все промежуточные вещи Однако количество лишнего в приведенном листинге поражает воображение. Даже если это отладочный код, к чему там втыкать esi/edi и целую гору пересылок туда-сюда |
Автор: | Nable [ 11 сен 2013, 10:57 ] |
Заголовок сообщения: | Re: Измерение времени в ОС |
https://code.google.com/p/crcutil/source/browse/tests/rdtsc.h писал(а): // Reads CPU cycle counter on AMD64 and I386 (for performance measurements). Мде, похоже что до сих пор не сделали intrinsic. Хотя это и понятно: в отличии от MS и Intel список поддерживаемых платформ дюже велик, так что поддерживать специфичные для каждой костылики (пусть даже они часто используются) - нафиг гццшникам не сдалось.// Thanks to __rdtsc() intrinsic, it's easy with Microsoft and Intel // compilers, but real pain with GCC. Цитата: Однако количество лишнего в приведенном листинге поражает воображение. Даже если это отладочный код, к чему там втыкать esi/edi и целую гору пересылок туда-сюда А это уже что-то типа непонимания процесса. Как минимум, в двух моментах:> втыкать esi/edi и целую гору пересылок туда-сюда Их не "воткнули", а, скорее, "не убрали". Надеюсь что разница понятна. Я не смотрел как оно на самом деле, но предполагаю что для отладочного кода даже с register allocator особо не заморачиваются, тупо для каждого сишного оператора (пардон, для каждой AST-ноды) заново выделяются регистры с постоянными загрузками и сохранениями (примерно как на стековых машинах с одним регистром-аккумулятором и постоянными операциями по извлечению операндов из стека и запихиванием туда результата). > Даже если это отладочный код А нету (быть может, даже нигде, ибо нафиг не надо, разве что для встроенки, где совсем топорный подход может привести к тому что код не поместится в ППЗУ) отдельного кодогенератора, который бы специально порождал код для упрощения отладки. Кодогенератор один (хотя, помнится мне, например, в v8 их два: один быстрый с втыканием кучи затычек, второй работает долго, но уже порождает оптимизированный код), разница между отладочным кодом - то что к внутреннему представлению не применяются стадии оптимизации, которые как раз убирают лишнее и делают прочие полезные вещи. |
Автор: | maisvendoo [ 11 сен 2013, 11:02 ] |
Заголовок сообщения: | Re: Измерение времени в ОС |
Nable писал(а): Их не "воткнули", а, скорее, "не убрали". Это результат какого-то промежуточного прохода компилятора? |
Автор: | Himik [ 11 сен 2013, 13:11 ] |
Заголовок сообщения: | Re: Измерение времени в ОС |
maisvendoo писал(а): Используя ассемблерные вставки мы уже используем ассемблер. Зачем притворятся что мы типо пишем на С, если код истыкан asm volatile в больших количествах? Получается не проще а сложнее - несколько *.s файлов не испортят картины, а только придадут коду ясность и структурированность. Код не будет не истыкан ассемблерными вставками, их количество минимально. Все они находятся внутри Сишных функций, и их вызов всегда выглядит как обычная Сишная функция (типа самодельных intrinsics). На каждую ассемблерную инструкцию можно сделать встраиваемую Сишную функцию, получится всего десяток функций, которые легко умещаются в заголовочном файле. Для простых ассемблерных вставок можно использовать и дефайны. |
Автор: | maisvendoo [ 11 сен 2013, 13:24 ] |
Заголовок сообщения: | Re: Измерение времени в ОС |
Говоря о целесообразности применения вставок, я имел в виду, что, скажем, вместо вот такого ужаса Код: void switch_to_user_mode() { // Настраиваем структуру стека для переключения в пользовательский режим. asm volatile(" \ cli; \ mov $0x23, %ax; \ mov %ax, %ds; \ mov %ax, %es; \ mov %ax, %fs; \ mov %ax, %gs; \ \ mov %esp, %eax; \ pushl $0x23; \ pushl %eax; \ pushf; \ pushl $0x1B; \ push $1f; \ iret; \ 1: \ "); } лучше написать нормальную ассемблерную функцию (это код из мануала JM). Мне представляется приемлемым со всех сторон такой подход. Вместе с тем, признаю свою неправоту в вопросе полного их неприятия - следовало посмотреть во что генерируется мой исходный код. P.S.: Кстати, разобрался с thread_suspend() |
Автор: | phantom-84 [ 11 сен 2013, 15:10 ] |
Заголовок сообщения: | Re: Измерение времени в ОС |
Что касается засыпания, то здесь опять-таки не обойтись без ожидания. Спящие потоки помещаются в спец. очередь ожидания так, чтобы выйти из нее в соответствии с временем их возобновления. Я не использую каких-то сложных структур, ограничиваясь обычной очередью ожидания и запоминая временные отрезки между возобновлением смежных потоков в этой очереди, типа: 5-6-0-0-0-5. nanosleep'а у меня пока нет, но понятно, что это должно работать, как совокупность описанного только что подхода и циклического замера высокоточного счетчика в коде "спящего" потока, только тут надо действовать аккуратно, чтобы грубое округление не получилось в конечном счете более эффективным подходом, чем точная подгонка, на которую тратится время работы потока. Конечно для повышения точности нужно задействовать отдельный приоритетный класс, чтобы снизить влияние "обычных" потоков. У меня есть ядерные и прикладные realtime-потоки. Помимо безусловного вытеснения менее приоритетных потоков RT-потоки обладают еще и тем свойством, что их значения приоритета связаны с вполне определенными временными квантами, т.е. можно совместно рассчитывать время сна и время непрерывной работы. |
Автор: | maisvendoo [ 11 сен 2013, 15:51 ] |
Заголовок сообщения: | Re: Измерение времени в ОС |
phantom-84 писал(а): Спящие потоки помещаются в спец. очередь ожидания так, чтобы выйти из нее в соответствии с временем их возобновления thread_suspend() реализовал как изъятие потока из очереди выполнения и постановку его в очередь ожидания. Со слипом пока думаю... |
Автор: | phantom-84 [ 11 сен 2013, 18:18 ] |
Заголовок сообщения: | Re: Измерение времени в ОС |
maisvendoo писал(а): thread_suspend() реализовал как изъятие потока из очереди выполнения и постановку его в очередь ожидания. Вполне приемлемый вариант. Слишком придирчивые конечно могут спросить, ожидания чего? В том плане, что здесь не будет обычной очереди ожидания с извлечением из начала очереди по факту освобождения нек. ресурса. Это похоже на стек, но со штатным извлечением из "середины" списка.
|
Страница 2 из 4 | Часовой пояс: UTC + 3 часа |
Powered by phpBB® Forum Software © phpBB Group http://www.phpbb.com/ |