Main /

Verteiltes Builden mit distcc

Verteiltes Builden mit distcc

/ HomePage / Computer / Software / Linux-Konfiguration / distcc

Verteiltes Builden mit distcc

Gentoo auf alter Hardware zu installieren, ist ein langwieriges Unterfangen, da alle Pakete erst kompiliert werden müssen. Aber es gibt Abhilfe! Falls ein oder mehrere aktuelle Rechenknechte im Netz verfügbar sind, kann man deren Rechenpower zum kompilieren nutzen wobei sie noch nicht mal zwingend unter Gentoo-Linux laufen müssen - es funktioniert mit anderen Distridutionen genau so.

Das Zauberwort heißt distcc

Hier steht geschrieben was alles eingestellt werden sollte, um distcc unter Gentoo zum Laufen zu bringen. Danach sollte ein emerge die wahre Freude sein, zumindest um Welten schneller als vorher. Doch Vorsicht: Der Präprozess wird immer nur auf der aktuellen Maschine gestartet! Falls diese also die Bremse ist, hilft auch distcc nicht viel. Desweiteren sind die Compilerprozesse nicht gerade klein, benötigen also eine Menge Speicher.

1. Installation

emerge distcc

2. Initialisierung

in der /etc/make.conf FEATURES hinzufügen:

FEATURES="distcc"
MAKEOPTS="-j2"

MAKEOPTS gibt an wieviele Compile-Prozesse gleichzeitig im ganzen distcc-Verbund gestartet werden sollen. Die Gentoo-Doku nennt als Richtiline "Anzahl der Prozessoren +1" pro Maschine. Bei vielen Hosts entsprechend hoch, da hier alle Prozesse aller Maschinen zusammengezählt werden. Wo dabei die Speichergrenze pro Maschine liegt - d.h. wieviele Parallelprozesse zur geringsten Compilezeit führen (also ob die Gentoo-dokumentation recht hat), ist noch nicht klar. Siehe Tests.

in /etc/profile path zu distcc hinzufügen:

PATH="/usr/bin/distcc/bin:..."

distcc deamon starten:

/etc/init.d/distccd start

so wird der distcc deamon immer beim boot gestartet:

rc-update add distccd default

Rechner (hosts) setzen:

distcc-config --set-hosts DISTCC_HOSTS
distcc-config --set-hosts localhost/1 lemur/2,lzo

Das bedeutet dass localhost nur einen Prozess zur Zeit starten soll (/1), lemur soll 2 Prozesse bekommen (/2) und die Kommunikation übers Netz läuft komprimiert (lzo) was schneller sein soll. Ob es wirklich schneller ist muss getestet werden. Wenn der Rechner langsam, das Netz aber schnell ist, könnte die komprimierte Kommunikation sogar langsamer als die unkomprimierte sein, weil die Komprimierung zu viel Zeit benötigt.

MAKEOPTS sollte in unserem Fall also mindestens ein -j3 enthalten, so dass drei Build-Prozesse gestartet werden. localhost sollte immer gesetzt sein, da sonst auf dem lokalen Rechner nicht mehr compiliert werden kann, falls die anderen nicht mehr im Netz verfügbar sind.

Ein

top -u distcc

auf den entsprechenden Maschinen zeigt, ob wirklich etwas passiert.

3. Troubleshooting

3.1 Makeopts in /etc/make.config

MAKEOPTS="-j2" darf nicht CC=distcc enthalten, das geht's schief und endet in seltsamen Fehlermeldungen. Weterhin darf distcc nicht in den cflags stehen, wirklich nur in FEATURES. distcc sollte nur über $PATH zu finden sein.

3.2 Verschiedene GCC-Versionen und Prozessoren

Manchmal es zu Problemen kommen wenn verschiedene GCC-Versionen oder Prozessoren auf den Rechnern im distcc-Verbund verwendet werden. In solchen Fällen hilft es in der make.conf folgende Zeilen hinzuzufügen:

CC="gcc"
CXX="g++"

dann klappt es auch wieder. Quelle: Gentoo-Forum

4. Tests

Lars hat z.Z. vier Rechner - mal sehen was die so wegrechnen. P133, P200, K6-III-450, PIII-500 dann wollen wir mal sehen, wo bei distcc schluß ist. winking smiley

Lars:
Ich habe mein aktuelles Projekt genommen, es enthält ca. 470kb C++ source code über mehrere Dateien verteilt. Voraussetzung zum Builden ist libsdl, sdl-gfx, sdl-sound, sdl-mixer und was davon abhängt.

Verwendet habe ich 4 Rechner

Proz. TypNameMHzRAM
Pentiummoon13380MB
Pentiumphobos20080MB
AMD K6-IIIlemur450128MB
Pentium IIIsputnik500192MB

Gebaut wird immer mit time make, evtl. ein -jX angehängt. Ausgegeben wird dann immer
real 1m5.0
user 0m59.0
sys 0m3.0

Was folgendes besagt: der gesamte Build-Prozess lief 1:05 Minuten, im Usermode wurden 59 Sek. verbraten, sys soll hier nicht weiter interessieren.

Lets start.

Die Tabellen sind vielleicht etwas komisch zu lesen, aber ich habe auf dem Rechner immer die /etc/distcc/hosts manipuliert. Ist der Host also moon/1 steht in /etc/distcc/hosts nur ein moon/1. Darunter sind die Zeiten angegeben, wie lange der Kompiliervorgang gedauert hat.

4.1 Test auf lemur alleine

hostmoon/1phobos/1sputnik/1localhost/1
real6:104:571:060:57
user0:080:080:080:52

Zu den Zeiten: localhost heisst, das Programm wurde nur auf lemur kompiliert, es hat 57sek gedauert. Bei den anderen Rechnern entsprechend. Es wurde also immer nur ein Rechner zum Compilieren verwendet, wobei lemur der Rechner war von dem das Ganze initiiert wurde.
Interessant ist, dass 'user' (wird nur auf entfernten Rechnern gebaut) immer 8sek. beträgt. Das ist der Overhead, also die Zeit die Präprozessor und Linker brauchen, um die Sourcen zusammenzustellen und die fertigen Objekte zu erstellen.

4.2 mehrere Rechner gleichzeitig

time make -j2

hostmoon/1 phobos/1sputnik/1 localhost/1
real2:510:34
user0:080:31

Hier ist zu sehen, dass auch zwei langsame Rechner durchaus nütylich sein können können. Zusammen brauchen phobos und moon ca. 3min zum Builden, fast doppelt so schnell als einer der beiden allein.
Ok, die beiden schnelleren Rechner brauchen zusammen nur 34sek.

4.3 Test auf sputnik

spare ich mir hier, Ergebnisse sind nicht viel anders.

4.4 Test auf phobos

hostmoon/1localhost/1sputnik/1lemur/1
real 5:201:331:28
user 5:110:330:33

Hier sieht man, dass der Overhead 33sek beträgt, die ältere Hardware fordert ihren Tribut. (SCSI 4GB IBM DCAS, aber 100MBit Netz)

time make -j2

hostsputnik/2lemur/2
real1:131:10
user0:330:33

Hier kann man schön sehen, das die Latenz durch gleichzeitiges Builden etwas gemildert werden kann. Normal wird ja ein Source durch den Präprozessor getrieben, an den anderen Rechner übertragen, dort gebuildet, assembliert und zurück geschickt.

Setzt man jetzt ein /2 ein (der Rechner nimmt 2 Prozesse gleichzeitig entgegen) ist der entfernte Rechner besser ausgelastet, da er nicht auf den langsameren warten muß. Also ist /2 (mindestens) fuer entfernte Rechner eigentlich Pflicht.

time make -j2

hostsputnik/1 lemur/1
real0:56
user0:33

Ist etwas besser, es sind halt 2 Rechner. Aber trotzdem wird jeder etwas warten müssen, also /2 setzen und entsprechend mehr Prozesse starten.

time make -j4

hostsputnik/2 lemur/2
real0:50
user0:33

Nicht mehr so viel schneller. Die alte Hardware ist einfach zu langsam. Nichtsdestotrotz ist es nicht schlecht, mit zwei schnellen Rechnern im Netz das Builden um den Faktor 6 zu beschleunigen. Doch Vorsicht, das kann nach hinten losgehen, denn wenn noch ein langsamer Rechner dazukommt kann der Ergebnis schnell zusammenbrechen, da zu lange auf die Krücke gewartet werden muss.

time make -j5

hostlocalhost/1 sputnik/2 lemur/2
real1:08
user1:02

Beim nächsten Ergebnis ist nur die Reihenfolge in /etc/distcc/hosts vertauscht. Das sagt uns, dass die langsamen Rechner immer nach hinten sollten, Damit sie immer zum Schluss mit Aufgaben beliefert werden. Doch auch das kann nach hinten losgehen, also besser extrem langsame Rechner ganz weglassen.

time make -j5

hostsputnik/2 lemur/2 localhost/1
real0:56
user0:44

Es ist also durchaus Potenzial in distcc.

Doch auch distcc kann nicht zaubern, so ist der Gewinn beim Kompilieren zwar sehr hoch, aber der Overhead z.B. bei emerge doch um einiges höher, denn da wird zuerst entpackt (was auf langsamen Maschinen sehr lange dauern kann) dann wird mittels configure die Umgebung geprüft (was auch sehr lange dauert) dann wird kompiliert (was jetzt allerdings viel schneller geht) erst dann wird installiert und aufgeräumt. Besonders bei großen Paketen wie X, KDE oder Firefox wird distcc auch eine menge bringen wenn der "kleine" Rechner die Zielplattform sein soll, und dazu wird man distcc meistens verwenden.

Wenn ich mal Zeit bzw. Lust habe werde ich in phobos mal eine schnellere Platte einbauen und dann mal gucken ob der Overhead sinkt, was ich mal nicht annehme, da bei der Größe der Sourcen und dem compiler etc. alles brav in die Buffer passt und somit fast keine Plattenzugriffe mehr nötig waren.

BTW: Selbst auf phobos mit seinen nur 80MB RAM wurde der Swap nicht gebraucht, um mittels -j5 die Sourcen zu bilden, somit ist die Speicherverwaltung von Linux richtig gut.

Ist einer der eingetragenen Rechner in der /usr/distcc/hosts nicht erreichbar ist das Ergebnis unterschiedlich, mal geht die Erkennung sehr fix, mal dauert es ewig. Einen richtigen Weg habe ich noch nicht gefunden. Werde aber hier noch ein wenig analysieren winking smiley

 [Update zu Nikolausi]

4.5 Protzrechner (naja, heute taugt er nicht mehr dazu winking smiley )

Nur mal um zu zeigen, das es auch noch schneller geht, wenn mein neues Monster im Hintergrund steht. Habe mal /usr/distcc/hosts nur auf ihn gelenkt, somit wird nur dort kompiliert. Der Hauptrechner ist dabei sputnik

time make -j2

hostmonster/2
real0:16
user0:08

Update 2.12.2005

Mittlerweile ist Lars' Rechnerpark geupdated worden.

Verwendung finden jetzt 5 Rechner

Proz. TypNameMHzRAMKommentar
Pentium MMXmoon20096MBnur 64MB gecached, VX Board
Pentium IIIsputnik500192MBLaptop
Athlon64 3k+monster18001536MBMein Numbercruncher, sauschnell
Athlon 2200+ 1800256MBWird mein neuer Server
AMD K6-IIIlemurbootp450128MBkeine HD, Netboot only

Gerade mit dem K6-III könnte es interessant werden, da der Rechner keine eigene Festplatte mehr hat (Netboot) und alles über das Netz ziehen muß. Mal sehen ob sowas noch eine Compile-unterstützung sein kann oder nur noch eine Bremse, die man besser weglässt.

Desweiteren bringt ccache eine ganze Menge Speedup, gerade wenn alle Sourcen erneut compiliert werden werden müssen. Aber dazu später mehr...

5. Siehe auch

6. Links:

Frische Änderungen | Menü editieren
zuletzt geändert am 14.02.2010 12:19 Uhr von Lars
Edit Page | Page History