Минимальная задержка, разгружающая процессор (SpinLock'и)

Тема в разделе "WASM.ASSEMBLER", создана пользователем Jin X, 23 фев 2018.

  1. Jin X

    Jin X Active Member

    Публикаций:
    0
    Регистрация:
    15 янв 2009
    Сообщения:
    369
    Адрес:
    Кольца Сатурна
    Тема Плавный гуишный процесс (без загруза CPU) привела к идее создать новую (т.к. интересовался этим вопросом раньше, но в итоге так и не нашёл толком ответа)...

    Всё же интересно, можно ли сделать задержку (уже без привязки к графике и окнам), более короткую, чем NtDelayExecution, но вместе с тем разгружающую процессор?

    Скажем, её можно было бы вставить в SpinLoop-цикл при длительных ожиданиях (альтернатива использования Event'ов в стандартном EnterCriticalSection). Почему не EnterCriticalSection? Потому что там нет поддержки RWLock'ов (а без них использование критических секций в некоторых случаях – это расточительство ресурсов). Там нет поддержки очередей. Там нет поддержки приоритетов потоков. Нет защиты от dead-lock'ов, в которые мы можем попасть в том числе и при завершении потока, не освободившего критическую секцию. Ну и т.д. Да, можно использовать Event'ы, но я хочу найти ещё какой-то альтернативный вариант...
     
  2. Indy_

    Indy_ Well-Known Member

    Публикаций:
    4
    Регистрация:
    29 апр 2011
    Сообщения:
    4.775
    Jin X,

    Есть спец сервис NtYieldExecution. Это быстрая функция, которая отдаёт поточное время в планировщик.
     
  3. Jin X

    Jin X Active Member

    Публикаций:
    0
    Регистрация:
    15 янв 2009
    Сообщения:
    369
    Адрес:
    Кольца Сатурна
    Ну это же SwitchToThread. Он же просто переключает потоки, но процессор не разгружает.
     
  4. Indy_

    Indy_ Well-Known Member

    Публикаций:
    4
    Регистрация:
    29 апр 2011
    Сообщения:
    4.775
    Jin X,

    Это передача времени на следующую задачу, таким образом текущая останавливается. Это и есть разгрузка проца. Только фича данного сервиса - он выбирает готовый к исполнению поток, если такого нет, то возвращает управление.

    Что бы прервать задачу нужно как то переключиться на другую, прямых сервисов для управления планировщиком нет. Можно например понизить приоритет задачи. Косвенным образом можно сделать через функции ожидания, например NtDelayExecution, ожидание на синхрообьектах или например послать APC - это всё вытесняет задачу.
     
  5. Jin X

    Jin X Active Member

    Публикаций:
    0
    Регистрация:
    15 янв 2009
    Сообщения:
    369
    Адрес:
    Кольца Сатурна
    Я к тому, что нужно поместить что-то в длинный цикл, и открыв диспетчер задач увидеть минимальную загрузку процессора этим потоком...
    NtYieldExecution тут не поможет однозначно. Пока альтернативы Event'ам и KeyedEvent'ам, как это сделано в EnterCriticalSection, я не вижу.
    Ну да, NtDelayExecution, но 0,5 мс – это же реально дофига (в тактах это будет миллион+, а через Event'ы можно сделать точность в несколько тысяч тактов). Но вот не нравится мне вариант с Event'ами и всё тут! :)
     
  6. Indy_

    Indy_ Well-Known Member

    Публикаций:
    4
    Регистрация:
    29 апр 2011
    Сообщения:
    4.775
    Jin X,

    Вариантов не видно. Само ядро использует Yield в NtDelay. Обычно циклы разгружены pause, но это никакого эффекта не окажет на профайлер. Нэйтив RWL использует сервисы NtAlertThreadByThreadId/NtWaitForAlertByThreadId. Это видимо самый эффективный способ.
     
  7. Jin X

    Jin X Active Member

    Публикаций:
    0
    Регистрация:
    15 янв 2009
    Сообщения:
    369
    Адрес:
    Кольца Сатурна
    Indy_, если вопрос про формулировку (из соседней темы) касается этой темы, то суть такова, что я хочу сделать SpinLock без использования Event'ов, но разгружающий процессор после N-го числа неудачных витков (256 или 1024, скажем – можно задавать). Т.е. после N витков выполнять нечто (разгружающее процессор) либо каждый раз после попытки захвата мьютекса, либо после N (или N/M) неудачных попыток.
    Предполагаю, что во время выполнения этих N витков не помешает ещё делать NtYieldExecution (например, каждые 256 виктов, но не менее 4-х раз, но и не чаще 1 раза в 64 виктов), дабы передавать управление другим потокам на том же процессоре (на случай, если мьютекс захвачен именно таким потоком).
    Ну вот как-то так...
     
  8. Indy_

    Indy_ Well-Known Member

    Публикаций:
    4
    Регистрация:
    29 апр 2011
    Сообщения:
    4.775
    Jin X,

    Старшая версия системы использует быстрые синхронизации(RWL), для этого это и было создано. Вы сами можите посмотреть как это реализовано. Очевидно ничего лучше вы не найдёте, так как вашу задачу реализовали архитекторы нт. Да и кванты как то считать нет смысла. Поточный профайл в целом зависит от фазы луны.

    > Предполагаю, что во время выполнения этих N витков не помешает ещё делать NtYieldExecution

    Этот сервис отдаёт управление, только если есть куда его отдать.

    Да и вообще система экспортит слим блокировки, это годный и шустрый механизм, зачем вы пытаетесь свои костыли реализовать ?

    В км эти механизмы не нужны, так что суть вопроса не понятна. Вы не посмотрели как нэйтив реализует синхронизации в RWL, но хотите какую то железячную инструкцию - такой нет, увы :preved:
     
  9. Indy_

    Indy_ Well-Known Member

    Публикаций:
    4
    Регистрация:
    29 апр 2011
    Сообщения:
    4.775
    Jin X,

    Прошлая за несколько лет часть ресурса утеряна, но основная инфа хранится. Вот публикация по вашим сверх быстрым синхронизациям(слим-блокировки) https://yadi.sk/d/Wj55IWd3nuLAk

    В общем из за этой темы ресурс и поломали, точнее она вызвала цепочку обсуждений и событий, что привело к обиде Аквилы.
     
    Jin X нравится это.