OpenMP Jobs unter Linux auf eine bestimmte Anzahl von Prozessor-Cores/Threads begrenzen

Manchmal stößt man als Linux-Nutzer auf etwas exotische Themenstellungen. Über eine solche bin ich neulich bei der Vorbereitung eines beauftragten Pentest gestolpert. Für Vor-Ort-Tests schleppt man dann seine Laptops zum Kunden und möchte natürlich vorab wissen, wo die physikalischen Grenzen für die Durchführung des einen oder anderen Test liegen – und für welche Aufgaben man im Nachhinein auf Spezialsysteme zurückgreifen muss.

Viele Programme, die parallele Aufgaben- und Lastverteilung über mehrere Prozessorkerne hinweg unterstützen sollen, nutzen dafür die OpenMP API und lassen sich so gezielt für Multithreading kompilieren.

Siehe hierzu :
https://en.wikipedia.org/wiki/OpenMP
http://www.linux-mag.com/id/4609/

Ein klassisches Beispiel ist das Programm JtR zur Hashanalyse (um es mal freundlich auszudrücken). Dieses Tool ist auf eine hohe Performance des Systems angewiesen, auf der es läuft. Kann man plattformbedingt nicht die GPU für die kontinuierlich durchzuführenden Kryptierungsaufgaben einsetzen, so nutzt man zumindest die für OpenMP kompilierte Variante und mehrere CPU-Threads, um JtR schneller seine Arbeit erledigen zu lassen.

Das hat je nach Verschlüsselungstiefe der zu untersuchenden Hashes gilt natürlich seine Grenzen … Aus Sicht des Security-Beraters gilt aber: Erfolgreiche Hash-Dekodierungen vor Ort helfen enorm, zusammen mit dem Kundenbeauftragten für Sicherheit die Awareness der Angestellten für die Wahl hinreichend guter Passwörter zu schärfen – im Besonderen wenn das Haus-und Hof-Betriebsysteme zur Hasherzeugung nur begrenzte oder eben schnell ausführbare Kryptoalgorithmen verwenden.

Siehe für eine Diskussion der Hash-Algorithmen unter MS Windows etwa
http://security.stackexchange.com/questions/17672/windows-7-password-hash-security
und die dort vorhandenen Kommentare.

Wie bei multi-thread-basierten Programmen generell kann eine maximale Performance bei der Programmausführung ggf. auch Nachteile nach sich ziehen. Wer etwa mal größere PHP-Projekte unter Eclipse Juno bereinigen lassen musste, kann ein Lied davon singen – da gingen auch Workstations mit 16 CPU Threads für einige Zeit in die Knie – wenn hunderte Klassenbibliotheken parallel und auf allen CPU-Cores validiert und indiziert wurden. Ein paralleles Arbeiten etwa mit Libreoffice-Anwendungen wurde dann im fraglichen Zeitraum zur Qual. (Mit Eclipse Mars wurde die Politik der maximalen CPU-Nutzung Gott sei Dank geändert.)

Muss man nun – wie in meinem Fall im Rahmen eines Penetrationstests –

  • vor Ort beim Auftraggeber mit Systemen begrenzter Leistungsfähigkeit arbeiten,
  • eine von Haus aus ressourcenbelastende Virtualisierungsumgebung einsetzen
  • und kann man bestimmte Aufgaben nicht an Remote-Spezialsysteme deligieren,

so wird ein Übermaß an Ressourcenbereitstellung für die Performance eines Programmes wie JtR ggf. zum Verhängnis für andere parallel abzuwickelnde Aufgaben.

JtR in der OpenMP-Variante für Kali z.B. nutzt ohne weitere Parameter automatisch die maximale (!) Anzahl der zur Verfügung stehenden CPUs, die dann auch zu 100% ausgelastet werden. Das gleichzeitige Auslasten vieler Prozessor-Kerne kann schnell zum Engpass für weitere ressourcenintensive Aufgaben werden, die man gleichzeitig und u.U. auf weiteren Virtualisierung-Gastsystemen erledigen will oder muss.

Dies führte mich zur Frage: Wie steuert man eigentlich den Thread-Zugriff eines OpenMP-Programs unter Linux – genauer: Wie legt man die Anzahl der CPU-Threads fest, die das Programm nutzen soll?

Es gibt zwei sehr einfache Antworten:

Steuerung über die
Virtualisierungsumgebung:

Läuft das OpenMP-Programm auf einer virtuellen Maschine (KVM, VMware, Libcontainber, ..) so kann man natürlich die bereitgestellten CPU-Threads über die Grund-Einstellungen zum virtualisierten Gastsystem steuern.

Steuerung über die Shell (u.U. in der virtualisierten Umgebung):
Hier muss man einfach eine Umgebungsvariable für den zu startenden Prozess setzen und exportieren:

mytux:~# export OMP_NUM_THREADS=n

“n” steht für Anzahl der zu nutzenden Threads. Danach startet man den OpenMP-nutzenden Job.

Man muss es – wie so oft – halt nur wissen!

Will man gezielt alle verfügbaren Core für ein OpenMP-Programm einsetzen, so hilft:

export OMP_NUM_THREADS=`grep ‘processor’ /proc/cpuinfo | wc -l `

Viel Spaß bei der gezielten Ressourcenauslastung durch OpenMP-Programme – ob als beauftragter Pentester (natürlich immer [!] mit der expliziten schriftlichen Erlaubnis des Auftraggebers) oder aber auch bei der Entwicklung und dem Einsatz eigener Hochperformance-Programme unter C oder Fortran!