Почему большее количество и более быстрых ядер замедляет работу многопоточного программного обеспечения?

Я испытываю странное поведение при масштабировании многопроцессорного / многопоточного приложения C ++. Приложение содержит 10 отдельных процессов, обменивающихся данными через сокеты домена Unix , и каждый из них имеет ~ 100 потоков, выполняющих ввод-вывод, и несколько процессов для этого ввода-вывода. Система является OLTP, и время обработки транзакции имеет решающее значение. IPC IO основан на ускоренной сериализации с использованием zmq по сокетам домена unix (это достаточно быстро во всех тестах на нашем локальном сервере, двух старых xeon с 24 ядрами). Сейчас, 1x Intel® Xeon® E5-4669 v4 - выделенный - 32 ядра - TPS ~ 700 (ожидается)
2x Intel® Xeon® E5-2699 v4 - выделенный - 88 ядер - TPS составляет ~ 90 (должно было быть ~ 2000)

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

htop показывает очень высокие значения времени на ядре (красная часть). Итак, наше первое предположение заключалось в том, что выполнение некоторых системных вызовов занимает слишком много времени или что мы сделали что-то не так в многопоточном коде. (См. Рисунок ниже) perf top сообщает об определенной подпрограмме системного вызова / ядра ( native_queued_spin_lock_slowpath ), которая занимает около 40% времени ядра (см. Изображение ниже). Мы понятия не имеем, что это такое. делает.

Однако еще одно очень странное наблюдение:

уменьшение количества ядер, назначенных процессам, заставляет систему лучше использовать ядра (больше зеленых частей, более высокая загрузка процессора) и заставляет все программное обеспечение (все 10 процессов) работать намного быстрее (TPS составляет ~ 400).

Итак, когда мы запускаем процессы с taskset -cp 0-8 service , мы получаем ~ 400 TPS.

Как вы можете объяснить, почему уменьшение количества назначенных процессоров с 88 до 8 заставляет систему работать в 5 раз быстрее, но при этом составляет 1/4 ожидаемой производительности на 88 ядрах?

Дополнительная информация:
ОС: Debian 9.0 amd64
Kernel: 4.9.0

htop results perf top results

2
задан 6 July 2018 в 18:37
3 ответа

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

Основные признаки:

  • ~ 100 потоков для ввода-вывода
  • Вы ничего не говорите о вводе-выводе. Это типичная область, которую неопытные люди упускают из виду и никогда не говорят. Типично для баз данных: «О, у меня так много оперативной памяти, но я не говорю вам, что бегаю с медленного диска большой емкости, почему я медленный».
2
ответ дан 3 December 2019 в 09:15

Конечно, похоже на эффект NUMA при нескольких сокеты резко ухудшают производительность.

perf очень полезен. Уже в отчете о производительности вы можете увидеть native_queued_spin_lock_slowpath , занимающий 35%, что кажется очень большим объемом накладных расходов для вашего кода параллелизма. Сложная часть - это визуализировать то, что вызывает что, если вы не очень хорошо знаете код параллелизма.

Я бы рекомендовал сделать графики пламени из общесистемной выборки CPU . Быстрый старт:

git clone https://github.com/brendangregg/FlameGraph  # or download it from github
cd FlameGraph
perf record -F 99 -a -g -- sleep 60
perf script | ./stackcollapse-perf.pl > out.perf-folded
./flamegraph.pl out.perf-folded > perf-kernel.svg

Найдите самые высокие «плато» на получившемся графике. Которые указывают функции с наиболее эксклюзивным временем.

Я с нетерпением жду, когда пакет bpfcc-tools будет в стабильной версии Debian, он позволит напрямую собирать эти «свернутые» стеки с меньшими накладными расходами.

Что вы будете делать с этим, зависит от того, что ты находишь. Знайте, какая критическая секция защищена замком. Сравните с существующими исследованиями масштабируемой синхронизации на современном оборудовании. Например, в презентации Concurrency Kit отмечается, что разные реализации спин-блокировки имеют разные свойства .

3
ответ дан 3 December 2019 в 09:15

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

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

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

1
ответ дан 3 December 2019 в 09:15

Теги

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