Ответ 1
Там больше для компиляции, чем скорость процессора и количество доступных ядер: пропускная способность диска и полоса памяти также очень важны.
В вашем случае я полагаю, что каждый процессор HT sibling получает примерно 4 процесса для выполнения. По мере запуска он блокирует на диске IO и переходит к следующему процессу. Второй пытается открыть второй файл, блокирует на диске IO, и брат переходит к следующему процессу. Запуск четырех компиляторов до того, как первый диск IO будет готов, меня не удивит.
Итак, когда первый, наконец, прочитанный в исходном коде программы, компилятор должен начать поиск по каталогам, чтобы найти #included файлы. Для каждого из них требуются некоторые вызовы open(), за которыми следуют вызовы read(), все из которых могут блокироваться, и все они откажутся от родного брата для запуска других процессов.
Теперь умножьте это на восемь братьев и сестер - каждый ядро HT будет работать до тех пор, пока он не блокирует доступ к памяти, после чего он перейдет к другому родному брату и запустится некоторое время. После того, как память первого брата была выбрана в кеш, вероятно, время, когда второй брат будет стоять в ожидании памяти.
Существует верхний предел того, насколько быстрее вы сможете запускать свои компиляции с помощью make -j
, но для меня в прошлом была хорошей отправной точкой для двухзначного числа.