Brute Force
Mit nur minimalen Änderungen von Listing 1 wird die Verarbeitung massiv-parallel. Listing 2 startet für jedes Argument einen eigenen Prozess. In Zeile 6 wartet dann das Skript auf das Ende seiner Kindprozesse. Dieses Vorgehen kann aber nach hinten losgehen: Ist das System mit zu vielen Prozessen überlastet, dann steigt der Overhead durch die vielen Kontextwechsel. Kommt noch Speicherknappheit hinzu, beschäftigt sich das System bald nur noch mit dem Swapping einzelner Prozesse. Es gibt aber durchaus Anwendungsfälle, in denen dieser einfache Ansatz der Parallelisierung sinnvoll sein kann.
01 doMassiveParallel() {
02 local item
03 for item in "$@"; do
04 doSomething "$item" &
05 done
06 wait
07 }
|
Das Listing 2a, eine Variante von Listing 2, verdeutlicht dies. Hier sind die Argumente nicht vorher bekannt, stattdessen erzeugt sie ein eigener Prozess (»createWorkItems«) sequenziell - etwa ein »find« auf einem sehr großen Dateisystem. Wenn die Erzeugungs- und Verarbeitungsrate abhängig von der Anzahl der verfügbaren Prozessoren in etwa gleich ist, dann kommt es nicht zu einer Systemüberlastung.
01 doMassiveParallel2() {
02 local item
03 while read item; do
04 doSomething "$item" &
05 done
06 wait
07 }
08
09 createWorkItems | doMassiveParallel
|
Teile und herrsche
Ist dieser Fall jedoch nicht gegeben, dann muss man etwas mehr Aufwand treiben. Das Skript in Listing 3 teilt die Argumente abhängig von der Anzahl Prozessoren auf und arbeitet die einzelnen Teilmengen sequenziell ab. Dazu bestimmt das Skript in Zeile 1 die Anzahl der Prozessoren (»PMAX«) auf dem System. Ist die Verarbeitung I/O-lastig, kann es durchaus Sinn ergeben, die Anzahl der Prozesse größer als »PMAX« zu wählen, damit ein Prozess arbeiten kann, während ein anderer auf I/O wartet.
01 ${PMAX:=`ls -1d /sys/devices/system/cpu/cpu* | wc -l`}
02
03 doParallel() {
04 local items item currentProcess=0
05 for item in "$@"; do
06 items[$currentProcess]="${items[$currentProcess]} "$item""
07 shift
08 let currentProcess=$(( (currentProcess+1)%PMAX ))
09 done
10
11 for (( currentProcess=0; currentProcess<PMAX; currentProcess++ )); do
12 [ -n "${items[$currentProcess]}" ] &&
eval doSequentiell ${items[$currentProcess]} &
13 done
14 wait
15 }
|
Leider kennt die Bash nur eindimensionale Arrays, deshalb ist das Konstrukt in den Zeilen 6 und 13 etwas kompliziert. Für jeden Prozess erzeugt das Skript einen langen String innerhalb eines Array-Elements mit den Argumenten für den Prozess (Zeilen 5 bis 9). Anschließend startet das Skript »PMAX« parallele Prozesse (Zeilen 11 bis 14). Die Zeile 12 verhindert leere Verarbeitungen (etwa bei nur zwei Argumenten auf einem Quadcore-Rechner). Und das »eval« in Zeile 12 sorgt dafür, dass die Shell das Quoting aus Zeile 6 richtig interpretiert.
| Whitepaper |
|
The Role of Open Source in Data Integration
Obwohl in den letzten Jahren viele technische Fortschritte erzielt werden konnten, verfügen die meisten Datenintegrationsprozesse nach wie vor nur über eine sehr begrenzte Automatisierung. Das vorliegende White Paper von dem Industry Analyst Mark Madson wird zunächst ein grundlegendes Verständnis von Daten Integration vermitteln, die Vorzüge von Open Source Lösungen für Daten Integration erläutern und Ihnen professionelle Empfehlungen geben, damit Sie Ihre Integrationsjobs noch einfacher und produktiver gestalten können.
Download PDF (Registrierung erforderlich)
|
|
Open Source Datenintegration in der Praxis: Fallstudien und Anwendungsbeispiele (Folge 2)
Der zweite Teil des Open Source Datenintegration in der Praxis: Fallstudien und Anwendungsbeispiele White Papers beleuchtet anhand weiterer ausgewählter Case Studies die Implementierung von Open Source Datenintegration in der Praxis und benennt die daraus resultierenden Vorteile.
Download PDF (Registrierung erforderlich)
|
Dieser Online-Artikel kann Links enthalten, die auf nicht mehr vorhandene Seiten verweisen. Wir ändern solche "broken links"
nur in wenigen Ausnahmefällen. Der Online-Artikel soll möglichst unverändert der gedrucken Fassung entsprechen.
|