Поведение sched_yield

У меня мало вопросов о функции sched_yield, потому что я вижу, что он не работает в моем коде. Много раз я вижу, что тот же поток запускается снова и снова, даже при наличии других потоков, когда я пытаюсь уступить его, вызывая sched_yield.

Также, если у меня есть multicores, будет sched_yield выход для потоков, запущенных на всех ядрах, или только одно ядро. Например, у меня есть потоки 1, 2 и 3, работающие на ядре 1 и Threads 4, 5 и 6 на ядре 2, и если sched_yield вызывается из Thread 2, он будет заменен только Thread 1 и 3 или 1, 3, 4, 5 и 6 возможны? Я спрашиваю об этом, потому что в .Net Thread.Yield выводится только потоки, запущенные на одном и том же ядре/процессоре.

Ответ 1

http://www.kernel.org/doc/man-pages/online/pages/man2/sched_yield.2.html

sched_yield() заставляет вызывающий поток отказываться от CPU. Нить    переместился в конец очереди для своего статического приоритета, и новый поток попадает в    работать.

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

Функция sched_yield не является .Net-вызовом, а модель потока/процесса отличается. Планировщик Windows/.NET отличается от планировщика Linux. Linux даже имеет несколько возможных планировщиков.

Итак, ваши ожидания относительно sched_yield ошибочны.

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

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

Если вы хотите получить полный контроль, как выполняются потоки, вы можете использовать потоки RealTime. http://www.linuxjournal.com/magazine/real-time-linux-kernel-scheduler - политики SCHED_FIFO и SCHED_RR RT.

Ответ 2

Почему вы хотите отказаться от процессора? Ну...

Я исправляю ошибку в клиентском коде. В принципе, у них есть общая структура, которая содержит информацию:

  • сколько монет в escrow - вернуть их
  • сколько счетов в escrow - вернуть их

Вышеизложенное происходит в процессе A. Остальная часть кода находится в процессе B. Процесс B отправляет сообщения процессу A для вычисления и возврата денег в escrow (это торговый автомат). Не вдаваясь в историю, почему код написан таким образом, исходная кодовая последовательность:

(процесс B)   отправить сообщение RETURN_ESCROWED_BILLS для обработки A   отправить сообщение RETURN_ESCROWED COINS to Process A   Нулевая общая структура

Выполняется как:

(процесс B):   отправлять сообщения;   обнулить структуру;

(позже.. Процесс A):   получать сообщения;   все поля в общей структуре равны 0;   ничего не делать;

Упс... деньги все еще находятся в депонировании, но процесс Код потерял эти знания. Что действительно необходимо (кроме массивной реструктуризации кода):

(процесс B):   отправлять сообщения;   получить процессор;

(Процесс A):   определять денежные средства и возвращать;   получить процессор; (может просто перейти к концу тайм-лиза, не требуется специальный метод)

(процесс B):   обнулить общую структуру;

В любое время, когда у вас есть сообщения IPC, и процессы, которые отправляют/получают сообщения, тесно связаны. наилучшим способом является двухстороннее рукопожатие. Тем не менее, есть случаи (обычно в результате плохой или несуществующей конструкции), где вы должны тесно связать процессы, которые действительно должны быть слабо связаны. Обычно выход процессора - это взлом, потому что у вас нет выбора. Добавление многоядерных процессоров является источником боли, особенно при переносе от одного ядра к многоядерному.