Приложение My Python, работающее на 64-ядерном Linux-сервере, обычно работает без проблем. Затем, после некоторого случайного промежутка времени (обычно от 0,5 до 1,5 дней), я внезапно начинаю частые паузы/блокировки более 10 секунд! Во время этих блокировок системное время процессора (т.е. Время в ядре) может быть более 90% (да: 90% всех 64 ядер, а не только одного процессора).
Мое приложение перезапускается часто в течение дня. Перезапуск приложения не устраняет проблему. Однако перезагрузка машины.
Вопрос 1. Что может привести к 90% времени системного процессора в течение 10 секунд? Все системное время процессора находится в моем родительском процессе Python, а не в дочерних процессах, созданных с помощью многопроцессорности Python или других процессов. Таким образом, это означает что-то порядка 60+ потоков, затрачивающих 10+ секунд в ядре. Я даже не уверен, что это проблема Python или проблема ядра Linux.
Вопрос 2: проблема с перезагрузкой проблемы должна быть большой подсказкой в отношении причины. Какие ресурсы Linux могут быть исчерпаны в системе между перезагрузкой приложения, но не между перезагрузками, которые могут заставить эту проблему застревать?
То, что я пробовал до сих пор, чтобы решить эту проблему/выяснить ее
Ниже я расскажу о многопроцессорной обработке. Это потому, что приложение работает в цикле, и многопроцессорность используется только в одной части цикла. Высокий ЦП почти всегда происходит сразу же после завершения всех вызовов многопроцессорности. Я не уверен, что это намек на причину или красную селедку.
- Мое приложение запускает поток, который использует
psutil
для вывода статистики процесса и системного процессора каждые 0,5 секунды. Я самостоятельно подтвердил, что он сообщает с помощьюtop
. - Я конвертировал мое приложение из Python 2.7 в Python 3.4, потому что Python 3.2 получил новую реализацию GIL, а 3.4 перезаписал многопроцессорную обработку. Хотя это улучшило ситуацию, оно не решило проблему (см. мой предыдущий вопрос SO, который я ухожу, потому что это еще полезный ответ, если не общий ответ).
- Я заменил ОС. Первоначально это был Ubuntu 12 LTS, теперь это CentOS 7. Никакой разницы.
- Получается многопоточное и многопроцессорное столкновение в Python/Linux и не рекомендуется вместе, у Python 3.4 теперь есть
forkserver
иspawn
контексты многопроцессорности. Я пробовал их, никакой разницы. - Я проверил /dev/shm, чтобы убедиться, что у меня закончилась общая память (которую использует Python 3.4 для управления многопроцессорной обработкой), ничего
-
lsof
вывод списка всех ресурсов здесь - Трудно проверить на других машинах, потому что я запускаю многопроцессорный пул из 59 детей, и у меня нет других 64-х основных машин, которые просто лежат
- Я не могу запускать его с помощью потоков, а не процессов, потому что он просто не может работать достаточно быстро из-за GIL (следовательно, почему я переключился на многопроцессорность в первую очередь).
- Я попытался использовать
strace
только в одном потоке, который работает медленно (он не может работать во всех потоках, потому что он слишком сильно замедляет приложение). Ниже я получил то, что не говорит мне много. -
ltrace
не работает, потому что вы не можете использовать-p
для идентификатора потока. Даже просто запустить его в основном потоке (нет-f
) делает приложение настолько медленным, что проблема не появляется. - Проблема не связана с загрузкой. Иногда он будет работать нормально при полной нагрузке, а затем при половинной нагрузке он вдруг столкнется с этой проблемой.
- Даже если я перезагружаю компьютер каждую ночь, проблема возвращается каждые пару дней.
Среда/примечания:
- Python 3.4.3, скомпилированный из источника
- CentOS 7 полностью обновлен.
uname -a
: Linux 3.10.0-229.4.2.el7.x86_64 # 1 SMP Wed 13 мая 10:06:09 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux (хотя это обновление ядра было применено только сегодня) - Машина имеет 128 ГБ памяти и имеет множество бесплатных
- Я использую numpy, связанный с ATLAS. Я знаю, что OpenBLAS сталкивается с многопроцессорностью Python, но ATLAS этого не делает, и это столкновение решается с помощью Python 3.4
forkserver
иspawn
, которые я пробовал. - Я использую OpenCV, который также выполняет много параллельной работы.
- Я использую
ctypes
для доступа к библиотеке C.so, предоставленной производителем камеры. - Приложение работает под управлением root (требование библиотеки C, на которую я ссылаюсь)
- Многопроцессорность Python
Pool
создается в коде, защищенномif __name__ == "__main__":
и в основном потоке
Обновлены результаты strace
Несколько раз мне удалось привязать поток, который работал на 100% "системном" процессоре. Но только однажды я получил от него что-то значимое. См. Ниже вызов в 10: 24: 12.446614, который занимает 1,4 секунды. Учитывая тот же идентификатор (0x7f05e4d1072c), который вы видите в большинстве других вызовов, я предполагаю, что это синхронизация PILON GIL. Означает ли это предположение? Если это так, то возникает вопрос, почему ожидание занимает 1,4 секунды? Кто-то не выпускает GIL?
10:24:12.375456 futex(0x7f05e4d1072c, FUTEX_WAIT, 2, NULL) = 0 <0.000823>
10:24:12.377076 futex(0x7f05e4d1072c, FUTEX_WAIT, 2, NULL) = 0 <0.002419>
10:24:12.379588 futex(0x7f05e4d1072c, FUTEX_WAIT, 2, NULL) = 0 <0.001898>
10:24:12.382324 sched_yield() = 0 <0.000186>
10:24:12.382596 futex(0x7f05e4d1072c, FUTEX_WAIT, 2, NULL) = 0 <0.004023>
10:24:12.387029 sched_yield() = 0 <0.000175>
10:24:12.387279 futex(0x7f05e4d1072c, FUTEX_WAIT, 2, NULL) = 0 <0.054431>
10:24:12.442018 sched_yield() = 0 <0.000050>
10:24:12.442157 futex(0x7f05e4d1072c, FUTEX_WAIT, 2, NULL) = 0 <0.003902>
10:24:12.446168 futex(0x7f05e4d1022c, FUTEX_WAKE, 1) = 1 <0.000052>
10:24:12.446316 futex(0x7f05e4d11cac, FUTEX_WAKE, 1) = 1 <0.000056>
10:24:12.446614 futex(0x7f05e4d1072c, FUTEX_WAIT, 2, NULL) = 0 <1.439739>
10:24:13.886513 futex(0x7f05e4d1072c, FUTEX_WAIT, 2, NULL) = 0 <0.002381>
10:24:13.889079 sched_yield() = 0 <0.000016>
10:24:13.889135 sched_yield() = 0 <0.000049>
10:24:13.889244 futex(0x7f05e4d1072c, FUTEX_WAIT, 2, NULL) = 0 <0.032761>
10:24:13.922147 sched_yield() = 0 <0.000020>
10:24:13.922285 sched_yield() = 0 <0.000104>
10:24:13.923628 futex(0x7f05e4d1072c, FUTEX_WAIT, 2, NULL) = 0 <0.002320>
10:24:13.926090 sched_yield() = 0 <0.000018>
10:24:13.926244 futex(0x7f05e4d1072c, FUTEX_WAIT, 2, NULL) = 0 <0.000265>
10:24:13.926667 sched_yield() = 0 <0.000027>
10:24:13.926775 sched_yield() = 0 <0.000042>
10:24:13.926964 futex(0x7f05e4d1072c, FUTEX_WAIT, 2, NULL) = -1 EAGAIN (Resource temporarily unavailable) <0.000117>
10:24:13.927241 futex(0x7f05e4d110ac, FUTEX_WAKE, 1) = 1 <0.000099>
10:24:13.927455 futex(0x7f05e4d11d2c, FUTEX_WAKE, 1) = 1 <0.000186>
10:24:13.931318 futex(0x7f05e4d1072c, FUTEX_WAIT, 2, NULL) = 0 <0.000678>