Анализ причины снижения производительности с другой версией ядра
Я столкнулся со странным снижением производительности ядра Linux с 3.11 по 3.12 в системах x86_64. Выполнение теста Radiance для Mark Stock на Fedora 20, 3.12 заметно медленнее. Больше ничего не меняется - идентичный двоичный файл, идентичный glibc - я просто загружаю другую версию ядра, и производительность меняется. Программа на время, rpict, представляет собой код пользовательского уровня, связанный с процессором, на 100%.
Прежде чем сообщить об этом как об ошибке, я бы хотел найти причину такого поведения. Я не знаю много о ядре Linux, и журнал изменений с 3.11 на 3.12 не дает мне никакой подсказки.
Я наблюдал это на двух системах: Intel Haswell (i7-4771) и AMD Richland (A8-6600K). На системе Haswell время пользователя изменилось с 895 сек с 3.11 до 962 с 3.12. На Ричленде с 1764 по 1844 год. Это время повторяется с точностью до нескольких секунд.
Я провел некоторое профилирование с помощью perf и обнаружил, что IPC снизился в той же пропорции, что и замедление. В системе Haswell это, по-видимому, вызвано большим количеством пропущенных ветвей, но почему скорость прогнозирования должна снижаться? Radiance использует генератор случайных чисел - может ли "лучшая" случайность вызывать пропущенные ветви? Но кроме поддержки OMAP4, RNG не должен казаться измененным в 3.12.
В системе AMD производительность просто указывает на увеличение числа циклов простоя бэкэнда, но причина не ясна.
Система Haswell:
3.11.10 895s user, 3.74% branch-misses, 1.65 insns per cycle
3.12.6 962s user, 4.22% branch-misses, 1.52 insns per cycle
Система Ричленда:
3.11.10 1764s user, 8.23% branch-misses, 0.75 insns per cycle
3.12.6 1844s user, 8.26% branch-misses, 0.72 insns per cycle
Я также посмотрел на diff из вывода dmesg обоих ядер, но не увидел ничего, что могло бы вызвать такое замедление работы программы, связанной с процессором.
Я попытался переключить регулятор cpufreq со стандартного ondemand на peformance, но это не имело никакого эффекта.
Исполняемый файл был скомпилирован с использованием gcc 4.7.3, но без инструкций AVX. libm все еще использует AVX (например, __ieee754_pow_fma4
) но эти функции составляют всего 0,3% от общего времени выполнения.
Дополнительная информация:
- Разные конфиги ядра
- diff выводов dmesg в системе Haswell.
- diff of / proc / pid / maps - 3.11 отображает только одну область кучи; 3,12 лота.
- перф стат с выхода системы A8-6600K
- статистика perf с TLB пропускает статистику dTLB выглядит совсем по-другому!
- Вывод /usr/bin/time -v из системы A8-6600K
Любые идеи (кроме деления ядра на изменения)?
2 ответа
Давайте проверим ваш perf stat
выходы: http://www.chr-breitkopf.de/tmp/perf-stat.A8.txt
Ядро 3.11.10
1805057.522096 task-clock # 0.999 CPUs utilized
183,822 context-switches # 0.102 K/sec
109 cpu-migrations # 0.000 K/sec
40,451 page-faults # 0.022 K/sec
7,523,630,814,458 cycles # 4.168 GHz [83.31%]
628,027,409,355 stalled-cycles-frontend # 8.35% frontend cycles idle [83.34%]
2,688,621,128,444 stalled-cycles-backend # 35.74% backend cycles idle [33.35%]
5,607,337,995,118 instructions # 0.75 insns per cycle
# 0.48 stalled cycles per insn [50.01%]
825,679,208,404 branches # 457.425 M/sec [66.67%]
67,984,693,354 branch-misses # 8.23% of all branches [83.33%]
1806.804220050 seconds time elapsed
Ядро 3.12.6
1875709.455321 task-clock # 0.999 CPUs utilized
192,425 context-switches # 0.103 K/sec
133 cpu-migrations # 0.000 K/sec
40,356 page-faults # 0.022 K/sec
7,822,017,368,073 cycles # 4.170 GHz [83.31%]
634,535,174,769 stalled-cycles-frontend # 8.11% frontend cycles idle [83.34%]
2,949,638,742,734 stalled-cycles-backend # 37.71% backend cycles idle [33.35%]
5,607,926,276,713 instructions # 0.72 insns per cycle
# 0.53 stalled cycles per insn [50.01%]
825,760,510,232 branches # 440.239 M/sec [66.67%]
68,205,868,246 branch-misses # 8.26% of all branches [83.33%]
1877.263511002 seconds time elapsed
Для поля 3.12.6 в поле "циклы" добавлено почти 300 циклов; и только 6,5 Gcycles были киосками фронтэнда и 261 Gcycles были остановлены в бэкэнде. У вас есть только 0,2 G дополнительных пропусков веток (каждый стоит около 20 циклов - на страницу Optim.manual 597; так что 4Gcycles), поэтому я думаю, что ваши проблемы с производительностью связаны с проблемами подсистемы памяти (более реалистичное внутреннее событие, которое может быть под влиянием ядра). Различия между числами страниц и количеством миграций низки, и я думаю, что они не будут напрямую тормозить тестирование (но миграции могут переместить программу в худшее место).
Вы должны идти глубже в perf
счетчики, чтобы найти точный тип проблемы (это будет проще, если у вас есть более короткие прогоны теста). Руководство Intel http://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-optimization-manual.pdf поможет вам. Проверьте стр. 587 (B.3.2) для общей иерархии событий (здесь также есть киоски FE и BE), B.3.2.1-B.3.2.3 для информации о стойлах бэкэнда и как начать копать (проверяет события в кэше и т. Д.) и ниже.
Как ядро может влиять на подсистему памяти? Он может настроить различное виртуальное физическое отображение (вряд ли в вашем случае), или он может отодвинуть процесс от данных. У вас не-NUMA-машина, но Haswell не является точной UMA - есть кольцевая шина, и некоторые ядра расположены ближе к контроллеру памяти или к некоторым частям общего LLC (кэш последнего уровня). Вы можете проверить свою программу с taskset
утилита, привязывающая его к какому-либо ядру - ядро не будет перемещать его в другое ядро.
ОБНОВЛЕНИЕ: После проверки вашей новой перф статистики от A8 мы видим, что есть больше промахов DLTB для 3.12.6. С изменениями в /proc/pid/maps (много коротких [heap]
разделы вместо одного [heap]
, до сих пор нет точной информации, почему), я думаю, что могут быть различия в прозрачной огромной странице (THP; с 2M огромными страницами требуется меньше записей TLB для того же объема памяти и меньше пропусков tlb), например в 3.12 это не может применяться из-за коротких участков кучи.
Вы можете проверить свои /proc/PID/smaps
за AnonHugePages
а также /proc/vmstat
для значений thp*, чтобы увидеть результаты thp. Значения задокументированы здесь kernel.org/doc/Documentation/vm/transhuge.txt
@osgx Вы нашли причину! После того, как echo никогда не> /sys/kernel/mm/transparent_hugepage/enabled, 3.11.10 занимает 3.12.6!
Хорошие новости!
Хотелось бы получить дополнительную информацию о том, как отключить рандомизацию, и о том, где сообщить об этом как об ошибке (регрессия производительности 7% довольно серьезна).
Я был не прав, этот эффект раздела с несколькими кучами не является случайным рандомизацией (который изменяет только начало кучи). Это сбой слияния VMA в do_brk
; не знаю почему, но некоторые изменения для VM_SOFTDIRTY были замечены в mm
между 3.11.10 - 3.12.6.
ОБНОВЛЕНИЕ 2: Возможная причина не слияния VMA:
http://lxr.missinglinkelectronics.com/linux+v3.11/mm/mmap.c#L2580 do_brk в 3.11
http://lxr.missinglinkelectronics.com/linux+v3.11/mm/mmap.c#L2577 do_brk в 3.12
3.12 только что добавлено в конце do_brk
2663 vma->vm_flags |= VM_SOFTDIRTY;
2664 return addr;
И чуть выше у нас есть
2635 /* Can we just expand an old private anonymous mapping? */
2636 vma = vma_merge(mm, prev, addr, addr + len, flags,
2637 NULL, NULL, pgoff, NULL);
и внутри vma_merge
есть тест для vm_flags
http://lxr.missinglinkelectronics.com/linux+v3.11/mm/mmap.c#L994 3.11
http://lxr.missinglinkelectronics.com/linux+v3.12/mm/mmap.c#L994 3.12
1004 /*
1005 * We later require that vma->vm_flags == vm_flags,
1006 * so this tests vma->vm_flags & VM_SPECIAL, too.
1007 */
vma_merge -> can_vma_merge_before -> is_mergeable_vma ...
898 if (vma->vm_flags ^ vm_flags)
899 return 0;
Но во время проверки новый vma не помечается как VM_SOFTDIRTY, а старый уже отмечен.
Это изменение может быть вероятным кандидатом http://marc.info/?l=linux-kernel&m=138012715018064. Я говорю это свободно, поскольку у меня нет ресурсов для подтверждения. Стоит отметить, что это было единственное существенное изменение в планировщике между 3.11.10 и 3.12.6.
В любом случае мне очень интересно увидеть конечные результаты ваших выводов, так что держите нас в курсе.