2013-08-21 2 views
2

Я огляделся по всему миру и не могу найти то, что искал, но позвольте мне сначала подчеркнуть, что я не ищет высокого разрешения, прецизионная функция сна.Отказаться от процессорного времени в C++ (Windows)

Вот фон для этой проблемы я пытаюсь решить:

Я сделал библиотеку отображения памяти, которая работает много как именованный канал. Вы можете поместить в него байты, вывести из него байты и запросить, сколько байтов доступно для чтения/записи, все это хорошее.

Это быстрые (в основном) процессы, сообщающие с использованием этого, будут в среднем на 4 ГБ/с, если они передают куски байтов 8 КБ или больше. Производительность снижается примерно до 300 Мбайт/с, когда вы приближаетесь к размеру блока 512B.

Проблема:

Очень редко, на сильно загруженных серверах, очень большие времена запаздывания будет происходить (Ввысь из 5с). Моя запущенная теория для причины этой проблемы заключается в том, что при больших переносах (больше, чем размер сопоставленной памяти) процесс, который записывает данные, будет затруднять опрос, ожидая, что в циклическом буфере будет доступно больше места поверх карты памяти. Нет никаких вызовов для сна, поэтому процесс опроса может привести к потере процессора без уважительной причины! Проблема в том, что даже самый маленький вызов спать (1 мс) будет абсолютно разрушать производительность. Размер memmap составляет 16 КБ, поэтому, если он спал за 1 мс каждые 16 КБ, производительность снизилась до наилучшего варианта 16 МБ/с.

Решение:

Я хочу функцию, которую я могу назвать, что уступит процессор, но не делает никаких ограничений, когда он получает перенесен операционной системы (Windows 7 в данном случае).

У кого-нибудь есть какие-либо яркие альтернативы?/Кто-нибудь знает, существует ли такая функция?

Спасибо.

ответ

0

Если вы работаете в .Net, вы можете изучить метод Thread::Yield().

Это может быть или не помочь вашему конкретному сценарию, но это правильный способ сообщить планировщику, что вы хотите отказаться от оставшейся части вашего таймлиса.

Если вы работаете в среде pre -.Net (кажется маловероятной, если вы работаете в Windows 7), вы можете посмотреть в функции Win32 SwitchToThread().

+0

Конечно, если он работал под .NET, то это был бы C++/CLI, а не C++. :) –

3

В соответствии с документацией MSDN на XP или новее, когда вы вызываете Sleep с таймаутом 0, вы получите другие процессы с равным приоритетом.

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

http://msdn.microsoft.com/en-us/library/windows/desktop/ms686298(v=vs.85).aspx

Другого варианта, который потребует больше работы, но это будет работать более надежно будет делить дескриптор события между производителем и процессом потребителя.Вы можете использовать CreateEvent, чтобы создать свое событие и DuplicateHandle, чтобы получить его в другой процесс. Когда производитель заполняет буфер, он вызовет ResetEvent на дескрипторе события и вызовет с ним WaitForSingleObject. Когда потребитель удалит некоторые данные из общего общего буфера, он вызовет SetEvent, что вызовет продюсера, который ожидал в WaitForSingleObject.

+0

Спасибо, чувак, это именно то, что я ищу. На самом деле у меня есть версия библиотеки, которая использует CreateEvent, OpenEvent, ResetEvent и др. В регрессионном тестировании на данный момент, но я просто хотел изучить этот сон (0) в качестве крайней меры в случае, если проблема не исчезнет. – jknielse

+1

@jknielse: На самом деле 'Sleep (0)' отказывается от своего временного фрагмента безоговорочно, но это, вероятно, * не * то, что вы ищете. Смотри ниже. – Mehrdad

+1

События - это путь. Пусть планировщик разбудит ваш процесс, когда есть что-то делать, а не записывать время процессора. –

1

std::this_thread::yield(), вероятно, делает то, что вы хотите. Я считаю, что он просто вызывает Sleep с 0 в большинстве реализаций.

1

Вам нужна SwitchToThread() функцию (которая будет только отказаться от своего квант времени, если что-то еще может работать), неSleep(0) (который бы отказаться от своего квант времени, даже если ничего другого не может работать).

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

+0

Два процесса передачи * - это разные процессы, а не потоки. Если я не пойму, я считаю, что мне нужно * отказаться от моего таймлиса, чтобы другие процессы работали. – jknielse

+0

@jknielse: Мое понимание (я мог ошибаться), что 'SwitchToThread' заботится только о потоках, а не о тех процессах, к которым они принадлежат. Если вы видите доказательства обратного, дайте мне знать, но, насколько я знаю, Windows рассматривает «процесс» как просто * контекст *, в котором работает поток, - он не «расписывает процессы»; он планирует потоки, а 'SwitchToThread', похоже, ничего не говорит об обратном. – Mehrdad

+0

Эта документация явно противоречит вашему первому утверждению: 'SwitchToThread' * будет * выдавать выполнение на оставшуюся часть временного фрагмента, если что-то еще может работать. (Вы действительно имели в виду _even_ if? Это противоположность _if и только if_) – MSalters

1

Вы ошибочно принимаете двоичный выбор. Теперь вы всегда заняты, потому что сон всегда будет плохой идеей.

Лучшее решение - попробовать несколько раз, не спать. Если это все еще не удается (поскольку карта заполнена, а другой поток не запущен), вы можете выдать настоящий сон. Это будет достаточно редко, если в среднем вы будете спать микросекунды. Вы даже можете проверить часы реального времени (RDTSC), чтобы определить, как долго вы провели ожидание, прежде чем сдавать свой таймлис.

Смежные вопросы