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


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.