Що може спричинити зависання при складанні на декілька ядер?


17

Вчора я намагався скласти пакет ROOT з джерела. Оскільки я складав його на 6-ядерній монстр-машині, я вирішив іти вперед і будувати, використовуючи кілька ядер, використовуючи make -j 6. Спочатку компіляція пройшла гладко і дуже швидко, але в якийсь момент makeвисіла, використовуючи 100% ЦП лише на одному ядрі.

Я трохи погуглив і знайшов цю посаду на дошках повідомлень ROOT. Оскільки я сам створив цей комп’ютер, я переживав, що я неправильно застосував радіатор і процесор перегрівся чи щось. На жаль, у мене немає на роботі холодильника, який я можу вставити. ;-)

Я встановив lm-sensorsпакет і побіг make -j 6знову, цього разу контролюючи температуру процесора. Хоча вона отримала високу (близько 60 ° C), вона ніколи не проходила повз високу або критичну температуру.

Я спробував запустити, make -j 4але знову makeвисів десь під час компіляції, цього разу в іншому місці.

Врешті-решт, я склав просто біг, makeі це спрацювало чудово. Моє запитання: Чому воно повисло? Зважаючи на те, що він зупинився на двох різних місцях, я б здогадався, що це було пов’язано з якоюсь умовою гонки, але я б подумав, що makeповинен бути досить розумним, щоб все було в правильному порядку, оскільки він пропонує -jможливість.


4
Це звучить як стан перегонів. Одне, що ви можете зробити, - це приєднати до запущеного процесу виготовлення (той, який обертається) за допомогою, наприклад, strace -p <pid>і подивитися, чи зможете ви дізнатися, на що він дивиться / на що. strace показуватиме вам тільки системні дзвінки (не функціональні дзвінки), але він все одно може дати вам цінну інформацію, якщо він обертається під час перегляду чи для певного файлу.
jlp

Нитка, яку ви знайшли через google, приводить до висновку, що ніхто не зміг її скласти -j >1.
Нілс

Не пов’язане з паралельною компіляцією, але у мене був висячий makefile, який назавжди потребував налагодження. Виявляється, це було просто в ініціалізації змінної, в $(shell ...)кінцевому рахунку виконується команда, яка чекала на введення зstdin . Це було викликано, коли змінна була порожньою і жодні аргументи файлів не передавались команді.
jozxyqk

Відповіді:


13

У мене немає відповіді на це чітке питання, але я можу спробувати дати вам натяк на те, що може статися: Відсутні залежності в Makefiles.

Приклад:

target: a.bytecode b.bytecode
    link a.bytecode b.bytecode -o target

a.bytecode: a.source
    compile a.source -o a.bytecode

b.bytecode: b.source
    compile b.source a.bytecode -o a.bytecode

Якщо ви телефонуєте, make targetвсе складеться правильно. Компіляція a.sourceвиконується (довільно, але детерміновано) спочатку. Потім b.sourceвиконується компіляція .

Але якщо make -j2 targetобидві compileкоманди будуть виконуватись паралельно. І ви насправді помітите, що залежності вашого Makefile порушені. Друга компіляція припускає a.bytecode, що вже складена, але вона не відображається в залежності. Тож помилка, ймовірно, трапиться. Правильною лінією залежності b.bytecodeмає бути:

b.bytecode: b.source a.bytecode

Якщо повернутись до своєї проблеми, якщо вам не пощастить, можливо, команда зависає в 100% циклі процесора через відсутність залежності. Це, мабуть, те, що тут відбувається, відсутня залежність не може бути виявлена ​​послідовною збіркою, але вона виявилася вашою паралельною збіркою.


Цікаво. Чи знаєте ви, чи є в наявності інструменти, які можуть запускати файл makefile і перевіряти ці залежності?
користувач545424

Я не знаю жодної. У будь-якому випадку такий інструмент міг знайти лише очевидні помилки. Якщо він не розуміє синтаксис для кожної команди, що з'являється в Makefile, і не знає, які є (потенційно неявні) залежності.
Стефан Гіменез

2

Я не знаю, скільки часу у вас була машина, але моя перша рекомендація - спробувати тест пам’яті і переконатися, що пам'ять функціонує належним чином. Я знаю, що це часто не проблема пам'яті, але якщо вона є, найкраще її усунути як причину, перш ніж спробувати відшукати інші, ймовірно, проблеми.


1

Я усвідомлюю, що це дуже старе питання, але воно все ще з’являється у верхній частині результатів пошуку, тому ось моє рішення:

GNU make має механізм серверних завдань, який гарантує, що її рекурсивні діти не споживають більше зазначеної кількості ядер: http://make.mad-scientist.net/papers/jobserver-implementation/

Він спирається на трубу, яку поділяють усі процеси. Кожен процес, який хоче розщедрити додаткових дітей, спочатку повинен споживати жетони з труби, а потім відмовитись від них, коли буде зроблено. Якщо дочірній процес не повертає витрачені ним жетони, то вищий рівень зробіть, поки вічно чекаєте їх повернення.

https://bugzilla.redhat.com/show_bug.cgi?id=654822

Я зіткнувся з цією помилкою під час створення бінутів з GNU make на моєму полі Solaris, де "sed" - це не GNU sed. Погортання PATH, щоб зробити sed == gsed, взяти пріоритет над системою sed вирішило проблему. Я не знаю, чому сед споживав жетони з труби.


0

у вашій системі може бути нормально, але це може бути стан перегонів, makeколи відбувається збіг паралельно.

Якщо з вашою системою щось не так, воно зависає / виходить з ладу для інших сценаріїв, а не лише при паралельних побудовах.


0

Це може бути умовою перегонів, але також якщо вся необхідна компіляція проводиться паралельно і чекає інших, зв'язок займає ваш час на вашій машині. Я думаю, що якщо посилання паралельно чекає попередньої необхідної компіляції, то ви отримуєте високу частоту процесора на зв'язуючу нитку, що б ви не склали.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.