На многоядерной машине ОС Linux, когда планировщик процессов будет мигрировать один процесс на другой процессор
В моей программе, чья RSS составляет 65G, при вызове fork
, sys_clone->dup_mm->copy_page_range
будет потреблять более 2 секунд. В этом случае один процессор будет на 100% sys при выполнении fork, в то же время один поток не сможет получить время процессора до завершения форка. Машина имеет 16 процессоров, остальные процессоры простаивают.
Итак, мой вопрос: один процессор был занят на форке, почему планировщик не переносит процесс, ожидающий на этом процессоре, на другой простаивающий процессор? В общем, когда и как планировщик переносит процесс между процессорами?
Я ищу этот сайт, и существующие темы не могут ответить на мой вопрос.
1 ответ
rss - 65G, когда вызов fork, sys_clone->dup_mm->copy_page_range будет занимать более 2 секунд
Делая fork
(или же clone
) vmas существующего процесса следует скопировать в vmas нового процесса. dup_mm
функция (kernel/fork.c) создает новый mm
и сделать актуальную копию. Прямых звонков на copy_page_range
, но я думаю, статическая функцияdup_mmap
может быть встроен в dup_mm
и есть звонки copy_page_range
,
в dup_mmap
заблокировано несколько замков, оба в новом mm
и старый oldmm
:
356 down_write(&oldmm->mmap_sem);
После принятия mmap_sem
семафор читателя / писателя, существует цикл над всеми mmaps для копирования их метаинформации:
381 for (mpnt = oldmm->mmap; mpnt; mpnt = mpnt->vm_next)
Только после цикла (это долго в вашем случае), mmap_sem
разблокирован:
465 out:
468 up_write(&oldmm->mmap_sem);
В то время как рул mmap_sep
писатель не работает, никакой другой читатель или писатель не может ничего сделать с mmaps в oldmm
,
один поток не может получить время процессора до завершения форка Итак, мой вопрос: один процессор был занят на форке, почему планировщик не переносит процесс, ожидающий на этом процессоре, на другой процессор простоя?
Вы уверены, что другой поток готов к запуску и не хочет ничего делать с mmaps, например:
- mmaping что-то новое или unmapping что-то не нужно,
- растёт или сокращает свою кучу (
brk
), - наращивая свой стек,
- pagefaulting
- или много других занятий...?
На самом деле, поток wait-cpu - это мой поток ввода-вывода, который отправляет / получает пакет от клиента, по моим наблюдениям, пакет всегда существует, но поток ввода-вывода не может его получить.
Вы должны проверить стек своего потока ожидания-процессора (даже для этого есть SysRq) и тип ввода / вывода. mmap
ing of file - вариант ввода / вывода, который будет заблокирован на mmap_sem
вилкой
Также вы можете проверить "последний использовавшийся процессор" в потоке wait-cpu, например, в top
утилита для мониторинга, включив просмотр потока (H
ключ) и добавление столбца "Последний использованный ЦП" к выводу (fj
в пожилом возрасте; f
выделите P
, введите в новее). Я думаю, что возможно, что ваш поток wait-cpu уже был на другом процессоре, просто не разрешен (не готов) к запуску.
Если вы используете форк только для exec
, это может быть полезно для:
- либо переключиться на
vfork
+exec
(или просто чтобыposix_spawn
).vfork
приостановит ваш процесс (но может не приостановить другие ваши потоки, это опасно), пока новый процесс не сделаетexec
или жеexit
, но выполнение может быть быстрее, чем ожидание копирования 65 ГБ mmaps. - или не делать форк из многопоточного процесса с несколькими активными потоками и виртуальной памятью объемом несколько ГБ. Вы можете создать небольшой (без использования мульти-ГБ mmaped) вспомогательный процесс, обмениваться данными с ним с помощью ipc, сокетов или каналов и просить его разветвляться и делать все, что вы хотите.