• И это будет выполняться не только для потоков, диспетчеризуемых с дисциплиной RR (вытесняемых по истечении бюджета времени выделенного им кванта), но и для потоков с любойдисциплиной диспетчеризации, в том числе и FIFO, когда выполняющийся поток (а значит, поток наивысшего приоритета в системе) вообще «не собирается» никому передавать управление.
• Для программиста-разработчика результаты этого теста позволяют сформулировать правило, возможно абсурдное с позиций элементарной (но поверхностной) логики: Распараллеливание задачи (если это возможно) на N ветвей (будь то использование потоков или процессов) практически не изменяет итоговое время ее выполнения.
Еще одним побочным результатом рассмотрения можно назвать следующее: эффективность диспетчеризации потоков (сохранения и переключения контекстов), принадлежащих одному процессу, ни в чем не превосходит эффективность диспетчеризации группы потоков, принадлежащих различным процессам. И в этом своем качестве — эффективности периода выполнения — потоки в своей «легковесности» ничем не превосходят автономные параллельные процессы. [25]
В завершение воспользуемся все теми же тестовыми приложениями для ответа на часто задаваемый вопрос: «Насколько эффективно ОС QNX поддерживает приложения, содержащие большое («слишком большое») количество потоков? Посмотрим, как это выглядит. Все выполнения мы делаем при минимально возможном значении системного тика, когда ОС существенно более «озабочена» своими внутренними процессами, нежели процессом вычислений:
# nice -n-19 p4-2 2 10
Rescheduling interval = 0.036876 msec.
Threads scheduling time: 1555.43 msec [831574415 cycles]
# nice -n-19 p4-2 20 10
Rescheduling interval = 0.036876 msec.
Threads scheduling time: 15642 msec. [8362674590 cycles]
# nice -n-19 p4-2 200 10
Rescheduling interval = 0.036876 msec
Threads scheduling time: 161112 msec. [86134950020 cycles]
Наблюдается очень хорошая линейная зависимость итогового времени от числа потоков (от 2 до 200). Таким образом, время выполнения работы в каждом из потоков практически не зависит от общего числа параллельно выполняющихся с ним потоков.
Повторим то же самое, но уже для случая параллельных процессов:
# nice -n-19 p4-1 2 10
Rescheduling interval = 0.036876 msec.
Forks scheduling time: 1622.87 msec [867633362 cycles]
# nice -n-19 p4-1 20 10
Rescheduling interval = 0.036876 msec.
Forks scheduling time: 16682.1 msec [8918698991 cycles]
# nice -n-19 p4-1 200 10
Rescheduling interval = 0.036876 msec
Forks scheduling time: 173398 msec. [92703484992 cycles]
Здесь наблюдается лишь незначительное увеличение крутизны линейной зависимости, что можно отнести к некоторым накладным расходам на поддержание достаточно большого числа записей о процессах в таблицах менеджера процессов, но величина этого эффекта также весьма малосущественна.
В итоге, в отношении «легковесности» потоков можно сказать следующее:
• При необходимости динамическогосоздания параллельных ветвей в ходе выполнения программы (а это достаточно классический случай, например в разнообразных сетевых серверах, создающих ветвь обслуживания для каждого нового клиента) производительность приложения, функционирующего на основе потоков, может быть значительно выше (до нескольких порядков), а время реакции соответственно ниже.
• При статическомвыполнении (фиксированном количестве параллельных ветвей в приложении) эффективность приложений, построенных на параллельных потоках или параллельных процессах, практически не отличается. Более того, эффективности таких приложений не отличаются и от классической последовательной организации приложения, работающего в одном потоке.