Чтобы исправить метафору EightBitTony:
"Почему это происходит?" вроде легко ответить. Представьте, что у вас есть два бассейна, один полный и один пустой. Вы хотите переместить всю воду от одного к другому, и у вас есть 4 ведра . Самое эффективное количество людей - 4.
Если у вас 1-3 человека, то вам не хватает нескольких ведер . Если у вас 5 или более человек, то хотя бы один из них застрял в ожидании ведра . Добавление все большего количества людей ... не ускоряет деятельность.
Таким образом, вы хотите, чтобы одновременно было столько людей, сколько они могли бы выполнять какую-то работу (использовать ведро) .
Человек здесь - это поток, а сегмент представляет собой узкое место, где находится ресурс выполнения. Добавление большего количества потоков не поможет, если они ничего не могут сделать. Кроме того, мы должны подчеркнуть, что передача ведра от одного человека другому обычно медленнее, чем один человек, несущий ведро на одинаковом расстоянии. То есть два потока по очереди на ядре обычно выполняют меньше работы, чем один поток, работающий вдвое дольше: это связано с дополнительной работой, выполняемой для переключения между двумя потоками.
То, является ли ограничивающий ресурс выполнения (сегмент) процессором, ядром или гиперпоточным конвейером команд для ваших целей, зависит от того, какая часть архитектуры является вашим ограничивающим фактором. Обратите внимание, что мы предполагаем, что потоки полностью независимы. Это только в том случае , если они не разделяют ни одного данных (и избежать каких - либо столкновений кэша).
Как предположили несколько человек, для ввода-вывода ограничивающим ресурсом может быть количество полезных операций ввода-вывода, которые можно поставить в очередь: это может зависеть от целого ряда аппаратных факторов и факторов ядра, но может легко оказаться намного больше, чем число сердечники. Здесь переключение контекста, которое так дорого по сравнению с кодом, связанным с выполнением, довольно дешево по сравнению с кодом, связанным с вводом / выводом. К сожалению, я думаю, что метафора полностью выйдет из-под контроля, если я попытаюсь оправдать это ведрами.
Обратите внимание, что оптимальное поведение кода, связанного с вводом / выводом, обычно по- прежнему должно содержать не более одного потока на конвейер / ядро / процессор. Однако вы должны написать асинхронный или синхронный / неблокирующий код ввода-вывода, и относительно небольшое повышение производительности не всегда оправдывает дополнительную сложность.
PS. Моя проблема с оригинальной метафорой коридора состоит в том, что я настоятельно рекомендую иметь 4 очереди людей, из которых 2 очереди несут мусор, а 2 возвращаются, чтобы собрать больше. После этого вы можете сделать каждую очередь почти до тех пор , как коридор, и добавляющие люди сделали скорость до алгоритма (вы в основном превратили весь коридор в конвейерной ленте).
На самом деле этот сценарий очень похож на стандартное описание взаимосвязи между задержкой и размером окна в сети TCP, поэтому он у меня появился.