Насколько дорогой контекстное переключение? Лучше реализовать ручное переключение задач, чем полагаться на потоки ОС?

Предположите, что я имею два (три, четыре, безотносительно) задачи, которые должны работать параллельно. Теперь, простой способ сделать это должно было бы создать отдельные потоки и забыть об этом. Но на простом одножильном ЦП, который означал бы большое контекстное переключение - и все мы знаем, что контекстное переключение является большим, плохо, медленный, и обычно просто Зло. Этого нужно избежать, правильно?

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

Второе решение действительно имеет преимущество адаптации к количеству доступных ядер процессора, но ручное переключение задач действительно будет быстрее, чем то в ядре ОС? Особенно, если я пытаюсь сделать все это универсальным с a TaskManager и ITask, и т.д.?

Разъяснение: я - разработчик Windows, таким образом, я, прежде всего, интересуюсь ответом для этой ОС, но было бы самым интересным узнать о других Ose также. Когда Вы пишете свой ответ, заявите, для которого ОС это.

Больше разъяснения: хорошо, таким образом, это не находится в контексте конкретного приложения. Это - действительно общий вопрос, результат на моих размышлениях о масштабируемости. Если я хочу, чтобы мое приложение масштабировало и эффективно использовало будущие центральные процессоры (и даже различные центральные процессоры сегодня), я должен сделать его многопоточным. Но сколько потоков? Если я сделаю постоянное количество потоков, то программа будет работать субоптимальным образом на всех центральных процессорах, которые не имеют того же количества ядер.

Идеально количество потоков было бы определено во времени выполнения, но немногие - задачи, которые могут действительно быть разделены на произвольное число частей во времени выполнения. Много задач однако могут быть разделены в довольно большом постоянном количестве потоков во время проектирования. Так, например, если бы моя программа могла бы породить 32 потока, она уже использовала бы все ядра до центральных процессоров с 32 ядрами, который довольно далек в будущем все же (я думаю). Но на простом одножильном или двухъядерном ЦП это означало бы БОЛЬШОЕ контекстное переключение, которое замедлит вещи.

Таким образом моя идея о ручном переключении задач. Таким образом, можно было сделать 32 "виртуальных" потока, которые будут отображены на стольких реальных потоках, сколько оптимально, и "контекстное переключение" было бы сделано вручную. Вопрос просто - был бы издержки моего ручного "контекстного переключения" быть меньше, чем то из контекстного переключения ОС?

Естественно, все это относится к процессам, которые являются зависящими от ЦП, как игры. Для Вашего заурядного Приложения типа CRUD это имеет мало значения. Такая заявка лучше всего подана с одним потоком (самое большее два).

9
задан tshepang 7 May 2014 в 10:21
поделиться

3 ответа

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

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

Если вы действительно ограничены процессором, определите количество процессоров и запустите столько потоков. Вы должны увидеть почти 100% использование процессора. Если нет, то вы не полностью привязаны к процессору и, возможно, стоит запустить N + X потоков. Для очень привязанных к IO процессов, вы должны запускать количество потоков, кратное количеству CPU (например, веб-серверы с высоким трафиком запускают 1000+ потоков).

Наконец, для справки, планировщики как Windows, так и Linux просыпаются каждую миллисекунду, чтобы проверить, не нужно ли запустить еще один процесс. Таким образом, даже на незагруженной системе вы увидите 1000+ переключений контекста в секунду. На сильно загруженных системах я наблюдал более 10 000 в секунду на один процессор без каких-либо существенных проблем.

5
ответ дан 4 December 2019 в 15:12
поделиться

Одноядерные машины под управлением Windows вымрут в ближайшие несколько лет, поэтому я обычно пишу новый код, предполагая, что многоядерные кейс. Я бы посоветовал перейти к управлению потоками ОС, которое автоматически позаботится о том, какой параллелизм обеспечивает оборудование, сейчас и в будущем.

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

3
ответ дан 4 December 2019 в 15:12
поделиться

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

Советую не тратить на это свои силы.

5
ответ дан 4 December 2019 в 15:12
поделиться
Другие вопросы по тегам:

Похожие вопросы: