Тайна числа 1,5

«Пятничная угадайка», удивляющая своей иррациональностью и величиной цифр.

Если увеличить число процессорных ядер в 1,5 раза, не трогая ничего остального — как изменится время сборки проекта?

… оно тоже увеличится в 1,5 раза!
Не верите? И я не поверил. Предупреждаю сразу — ответа у меня всё ещё нет…

Дано:


Процессоры — OEM, их «официальные» аналоги 2680v3 и 2699v3. Единственное отличие — OEM умеют работать с DDR3. В остальном они близнецы-сёстры. Лок турбобуста отключен. Процессоры бустят все ядра, пока не упрутся в TDP (18 ядерник может единственное ядро аж до 3.8 добустить, но сейчас это не важно)

Сборка идёт в виртуалке. При этом не важно, на passthrough SSD SATA диске, или же cow2 образе, лежащем на SSD M2. Разница незаметна.

12 ядерники собирают примерно за час (real 66m, user 2705m, sys 126m)
18 ядерники собирают примерно за 1,5 часа (real 92m, user 5528m, sys 310m)
И это не поддаётся никакому объяснению, ведь 18 ядерники ничем не хуже!

Может быть билд-система не умеет использовать столько ядер? Но тогда время было бы примерно равно 12 ядерникам, только часть ресурсов бы простаивала. На всякий случай проверим. Будем уменьшать число потоков, доступных билд системе:


Может один из 18 ядерных процессоров дефектный? Вынимаем по очереди один, и второй. Получаем время сборки около 100m. Т.е. процессоры в порядке.

Изначально машина была одна. На которой и столкнулся с ситуацией, заменив только процессоры. Собрал вторую машину, на 18 ядерниках. Ситуация прекрасно воспроизвелась опять. У этой второй машины нет пользователей, и она более-менее свободна для тестов.

NUMA выглядит правдоподобным объяснением. Но изменение топологии в QEMU/KVM на аналог хостовой не приносит никакого результата.

В сухом остатке:

  1. добавление второго 12 ядерника ускоряет сборку почти линейно.
  2. добавление второго 18 ядерника ускоряет сборку на ~10%.

Любые идеи и гипотезы приветствуются. Особенно которые легко проверить. Например, я бы с радостью проверил сборку напрямую, без виртуалок, но свободного SSD хотя бы на 512Gb у меня просто нет. И систему с 2678 желательно не останавливать. (Т.е. вариант перетестировать с прямой загрузкой с HDD не подходит).

UPD: чтобы не вспоминали закон Амдалла приведу ещё такой пример. На 128/256 двухголовом EPYC (64 ядра каждый камень), 1Tb RAM, и NVMe RAID тот же AOSP собирается за 12 минут.
@screwer
29.01.2022 13:51 UTC
Первоисточник

Комментарии

@
29.01.2022 09:11 UTC
0
НЛО прилетело и опубликовало эту надпись здесь
@Number7
29.01.2022 09:17 UTC
+1

У вас чудо чудное только при сборке AOSP? Как я понял из поста, вы ничего другого не тестили. Попробуйте замерять время сборки, скажем linux kernel на 12ядрах и на 18ти.

@screwer
29.01.2022 09:31 UTC
0

AOSP хорош исключительной стабильностью получаемых результатов. Ну и одна из функций сервера - сборка AOSP.

@napa3um
29.01.2022 09:18 UTC
+15

Гипотезы:

  1. Ошибки в условиях тестирования или сбора результатов.

  2. Пределы масштабирования используемого ПО (издержки на согласование результатов работы всех ядер становятся выше полезного вклада отдельного ядра). Возможно, плохая масштабируемость многопоточности (для данного профиля нагрузки) затаилась прям в операционной системе или в ограничениях системы виртуализации.

  3. Троттлинг из-за перегрева более многоядерного процессора или его более жёсткое воздержание от турбобустов при загрузке всех ядер (во избежание перегрева).

  4. Злоумышленник, подделывающий результаты или намеренно замедляющий вашу гостевую систему на слишком жирных процессорах (может, продаёт ваши ядра на сторону или майнит на них что-нибудь).

  5. Случайное совпадение, радиоактивный фон, влияющий на вычисления, проклятие или наведённая порча.

@screwer
29.01.2022 09:25 UTC
0
  1. Исключено. Но можем провести другие тесты.

  2. масштабирование-согласование не обьясняет, почему 48 потоков на 18 ядрах работают намного хуже 48 потоков на 12 ядрах

  3. Серверный корпус, хороший обдув, холод в помещении. Температуры отличные.

  4. Хост система чистая, установленна с нуля сутки назад. Тестовую виртуалку могу выложить для ознакомления.

  5. Слишком хорошее воспроизведение ((

29.01.2022 09:49 UTC
+4

Второй и третий пункт вы не опровергли.

29.01.2022 10:25 UTC
0

Второй большой очень. Про виртуализации мне нечего ответить.

Третий опроверг. И за температурами наблюдал. Они в норме.

29.01.2022 10:27 UTC
0

Температура могла быть в норме именно из-за управления частотами ядер (сдерживания их турбобуста). Ну и устойчивость проклятия вы недооценили :).

29.01.2022 10:39 UTC
+2

Турбобуст как раз не сдерживается. Он разлочен в UEFI сторонний утилитой. 12 ядерники бустятся до стабильных 3300 по всем ядрам, 18 ядерники до 3200-3600. Упор мог быть только в TDP. Но он выше у 18 ядерников, поэтому не объясняет их отставание

29.01.2022 11:28 UTC
+3

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

29.01.2022 15:46 UTC
0

Так нарисуйте график частоты ядер от времени. Думаю, вас ждёт сюрприз.

Кроме того, процессор может тротлится и не снижая частоту, просто пропуская такты. Это тоже где-то можно обнаружить (в смысле, прочитать в /proc или /sys), но не помню где.

29.01.2022 09:52 UTC
+2

а почему именно 48 потоков и там и там ? логичнее сделать на Xeon E5-2678v3 24 потоков а на Xeon E5-2696v3 - 36 потоков. иначе у вас получается что лишние потоки отнимают время на переключения

29.01.2022 10:24 UTC
0

Чтобы попытаться получить на 18 ядерниках хотя бы производительность 12 ядерникоа

29.01.2022 10:03 UTC
+1
  1. А мне кажется как раз неплохо объясняет... 48/18 = 2.6, как они там по ядрам в таком случае распределяются - вопрос к специалистам, а при 48/12 всё ровненько и раз процессы одинаковые, почему б им не занимать место в памяти оптимальнее?

29.01.2022 10:26 UTC
0

Загрузка всех потоков 100% основную часть времени. Хоть на 12, хоть на 18 ядерниках. Простоя ядер не видно.

29.01.2022 14:33 UTC
0

Загрузка в мониторе мало о чем вообще говорит. Пока процесс по какой-то причине ждёт данных из памяти в мониторе будет отображается 100% загрузка.

29.01.2022 10:31 UTC
0

36/18 тоже ровненько. И 72/18. А результат странный.

30.01.2022 03:37 UTC
0

Более того, 48/18 = 2,6666666666(6).... Мне кажется, что совокупность програмно-аппаратных средств при такой конфигурации представима в виде вычислителя который пытается разделить 2 на 3, с бесконечной точностью, что в принципе недостижимо. Видимо в процессе где-то есть переход который при переключении потока выполняет "код деления" и записывает виртуальные 6-ки в виртуальный результат :). Кстати угадайка вполне себе рациональна. Каким способом не делить 3 на 2, в итоге получишь полтора! Попробуйте поиграйтесь с кратностью потоков.

29.01.2022 16:59 UTC
0
  1. 48 на 12 делится нацело, а на 18 нет, это может влиять.

@napa3um
29.01.2022 11:07 UTC
0

2.1 - предел масштабирования может быть и в IO, это и предельные ограничения многопоточного доступа к физическому устройству / файловой системе, и ограничения настроек на количество одновременно открываемых файлов.

29.01.2022 13:18 UTC
0

Версия с ограничением объяснила бы примерно равную производительность, но столь значительное падение.

29.01.2022 13:28 UTC
+1

Почему же, падение тоже может объяснить, может даже и полную остановку объяснить :).

@chersun
29.01.2022 09:22 UTC
+4

Похоже вы открыли тайну... добавление мощностей не приводит к линейному масштабированию. Это базовое правило, которое по-моему уже все давно учитывают при построении больших систем.

Обусловливается как пределами масштабирования, так и накладными расходами на параллелизацию.

@screwer
29.01.2022 09:22 UTC
+1

Ладно бы добавление мощности не привело бы к ускорению. Деградация такая огромная - почему ?

И см. апдейт в конце статьи.

29.01.2022 09:55 UTC
+3

Увеличение числа ядер, увеличивает мощность как N, а накладные расходы, очень часто, растут как N^2 (и это если кэши не переполняются, а так намного хуже).

29.01.2022 10:29 UTC
+1

И это если программист справился с масштабированием в принципе :).

29.01.2022 12:09 UTC
0

ІО проверили?

29.01.2022 13:19 UTC
0

Диск виртуалки на NVMe. Как с помощью Io объяснить просадку ?

Кроме того, ожидание ИО вылилось бы в недогруз ядер. А они были загружены до упора практически все время.

29.01.2022 15:24 UTC
0

Прежде чем пытаться объяснять, обычно, проверяют.

@czz
29.01.2022 10:18 UTC
0
Например, я бы с радостью проверил сборку няпрямую, без виртуалок

Было бы неплохо все же проверить на bare metal, дабы исключить влияние виртуализации.

Я наблюдал такую ситуацию, что при распределении CPU/RAM-intensive нагрузки на большое количество ядер (один 64-ядерник EPYC) производительность на ядро падала вплоть до 2-х раз, но только в QEMU. На bare metal та же нагрузка масштабировалась нормально.
@screwer
29.01.2022 10:28 UTC
+1

Да, это самая вероятная причина. Плохая работа NUMA внутри виртуалки. Неистовая межсокетная пересылка все бы объяснила. Сделаю при первой же возможности.

@Sdima1357
29.01.2022 10:30 UTC
0

Попробуйте уменьшить число ядер для сборки. Например в 1.5 раза :)

@screwer
29.01.2022 10:42 UTC
0

Уменьшал число потоков, параметром билд системы. Ядра в UEFI не блокировал. Могу заблокировать. Например из 18 ядерников можно сделать 12 ядерники, тогда они выдадут стабильные 3600 по всем ядрам.

29.01.2022 11:27 UTC
0

И как результат? У Вас явно processing power не узкое место.

29.01.2022 13:20 UTC
0

Процессоры в обоих случаях загружены до упора. Версию с ограничением ядер в UEFI протестирую вечером.

@myz0ne
29.01.2022 10:39 UTC
+1

И это не поддаётся никакому обьяснению, ведь 18 ядерники ничем не хуже!

у 12-ядерника базовая частота выше. 2.3 Ghz vs 2.5 Ghz

Tcase у 12-ядерника выше 84.5 vs 76.4. Не до конца понимаю этот параметр, но допускаю что 12 может дольше работать в режиме Turbo Boost.

https://ark.intel.com/content/www/ru/ru/ark/compare.html?productIds=81908,81061

Т.е. причина может быть в том что 12 ядерник дольше работает в turbo boost, но даже когда буст выключается и проц работает на базовой частоте, он все равно быстрее в расчете на ядро.

---

upd

В общем и целом, нужны графики нагрузки на каждое ядро, суммарная нагрузка на процессор, графики температуры и частоты ядер.

@screwer
29.01.2022 10:43 UTC
0

Турбобуст разлочен в обоих случаях. Процессоры бустят все свои ядра до максимально возможной частоты (3300 и 3600 соотв.) пока не упрутся в ТДП. Турбобуст не сбрасывается - в стрессе молотят постоянно на буст частоте.

@ky0
29.01.2022 10:44 UTC
+1
Вы всю интригу выдали тэгами :) Я так и подумал, что станет кратно дольше.
@screwer
29.01.2022 10:46 UTC
0

Но я правда не знаю причину (((

@amarao
29.01.2022 11:00 UTC
+3

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

Попробуйте собрать LVM в режиме interleave из нескольких виртуальных устройств. raid0 тоже можно, но у него есть некоторые проблемы своего рода в районе высокой производительности.

@AelDeyr
29.01.2022 11:06 UTC
+4

По спецификации у процессоров, кажется, есть отличие: поддержка Transactional Synchronization Extensions 12-ти ядерным процессором, которой на первый взгляд нет у 18-ти ядерного. Для сборки это потенциально как раз порядка 30% за счёт ускорения межпоточной синхронизации
Можно попробовать отключить флагами компилятора (пересобрать сам компилятор без поддержки TSE), или лучше аппаратно флагами ядра и проверить

upd: https://www.cpu-world.com/Compare_CPUs/Intel_CM8064401610101,Intel_CM8064401967500/

@Nacreous1991
29.01.2022 11:18 UTC
+3

Может ли быть ограничение в чтение данных с диска. Есть такой прикол, что файл в 1 ГБ копируется за минуту, а если 2 файла паралельно копировать то это займет 10 минут

@szt_1980
29.01.2022 13:14 UTC
+3

>QEMU

Ключевое слово здесь. Во-первых, является ли эта задача CPU-bound или IO-bound? Более вероятно второе - смотрите количество потоков, порождаемых этой поделкой, и потребление памяти. Если потоков слишком много, то это оно (там IO так сделан), и надо подбирать бэкэнд среди нескольких полурабочих

@permeakra
29.01.2022 15:10 UTC
+1

1) скачать интеловскую утилиту мониторинга, посмотреть, что конкретно в процессоре загружено https://github.com/opcm/pcm .

2) Посмотреть статистику локов в ядре (возможно, придется пересобирать ядро)

3) Попробовать пересобрать с build_tree на tmpfs

4) попробовать запустить в параллель две сборки на одной и разной файловых системах.

5) сравнить kernel time/ user time.

Гипотеза 1): где-то, например в драйвере файловой системы или устройства, есть мьютекс, в спин-локе которого и просирается время.

Гипотеза 2): избыток ядер порождает избыток какого-то служебного трафика по процессорным шинам, например сообщений протокола когерентности кэша, который засирает какую-то критическую шину, например относительно узкий межпроцессорный линк QPI

@permeakra
29.01.2022 15:27 UTC
0

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

@DikSoft
29.01.2022 21:10 UTC
0

Поставить тот же опыт, использовав Hyper-V Core. Было бы интересно...

@vvviperrr
29.01.2022 22:46 UTC
0

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

во-вторых, аосп аоспу рознь, но

12 ядерники собирают примерно за час (real 66m, user 2705m, sys 126m)
18 ядерники собирают примерно за 1,5 часа (real 92m, user 5528m, sys 310m)

мой домашне-рабочий пк на 5950x, 64gb ram собирает наш аосп за 25 минут. процентов 10-15 этого времени - генерация жирных образов прошивок (которые не часть аоспа).

@szt_1980
30.01.2022 01:50 UTC
0

>если какая-то несовместимость с системными либами - можно ведь докер взять

Вообще не нужно. chroot, и все.

@screwer
30.01.2022 08:42 UTC
0

Виртуалка - потому что сборка АОСП не единственная функция. Изоляция между VM намного надёжнее докера.

Возьмите последний АОСП с сайта и соберите. Уверен, никаких 25 минут вы не получите.

30.01.2022 08:54 UTC
0

какой таргет?

30.01.2022 14:54 UTC
0

собрал дефолтный arm-eng.

build completed successfully (36:20 (mm:ss))

real 36m20.478s
user 1043m34.827s
sys 42m27.580s

root@4720ed223c15:/work/aosp# du -sh out/
65G out/

не учел, что у нас выпилена куча стандартных пакетов + все же 9-й aops.

@onyxmaster
30.01.2022 05:52 UTC
0

А попробуйте отключить SMT в BIOS ради эксперимента, если ещё нет.

@moroz69off
30.01.2022 19:53 UTC
-1

Я в компьютерах совсем не понимаю, но интуиция подсказывает - собака зарыта в кратности. Поскольку (постольку) я в компьютерах ничего не понимаю, то и пояснять не возьмусь. Но истина - где-то рядом (смотри комментарии, где упоминается кратность чисел и копай в сторону оптимизации (экономии вычислений), высосанной кожаным мешком из собственного пальца: 2*2 вседа равно 4, так и кладём большой прибор на 2*2, и просто пишем 4. Это не точно, это интуиция...

@alex319
01.02.2022 01:13 UTC
0

Я бы проверил для начала производительность процессоров в бенчмарках на других задачах. Может быть это вообще китайская подделка )). Я каноны брал с АлиЭкспресс только последнее время