Idee gesucht....

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Antworten
Benutzeravatar
heinz
Beiträge: 535
Registriert: 20.12.2007 01:43:49

Idee gesucht....

Beitrag von heinz » 10.09.2015 16:54:58

Hallo Zusammen,

hatte letztens die Idee, mittels eines scripts das Zippen von grossen Dateien
auf mehrere Prozessoren zu verteilen.
Nur so aus Spass...

Seitdem versuche ich das Script noch weiter zu beschleunigen.
Im Moment ist es so:
Die Datei wird mittels split aufgeteilt, fuer jeden Prozessor ein Stueck.
Dann wird fuer jeden Prozessor ein Hintergrund-Prozess gestartet, der einen
diser Dateistuecke zippt.
Wenn alle fertig sind, werden die Zip-Stuecke zusammen gebracht.
Funktioniert fuer Dateien bis ~1GB eigentlich ganz gut.
Werden die Dateien aber groesser, dauert es irgendwann uebermaessig lange
bis alleine mal split durchgelaufen ist.

Dann kam ich auf die Idee in jedem Hintergrund-Prozess mittels dd direkt aus
der Quelldatei zu lesen.
Aber das war viel langsamer, da gzip sich die Rechenpower mit dd teilen musste.

Hat einer von Euch eine Idee wie man das noch loesen koennte?

Wie schon geschrieben, nur so zum Spass am scripten. Ich suche keine
Fertigloesung ala: Das Programm xy-z kann das doch schon...

Viele Gruesse,
heinz

rendegast
Beiträge: 15041
Registriert: 27.02.2006 16:50:33
Lizenz eigener Beiträge: MIT Lizenz

Re: Idee gesucht....

Beitrag von rendegast » 10.09.2015 20:09:36

Es dürfte eher am Einlesen liegen.
Liest Du mehrere Stücke einer Datei gleichzeitig, so muß der Lesekopf hin- und herspringen,
das dürfte den Prozeß eher verlangsamen.

Meine hdd ~ 100MB/s,
einen /dev/zero-Stream wird mit ~ 100MB/s komprimiert.
Solange die Festplatte nicht sehr viel schneller liefert, als die CPU komprimiert,
verlangsamt ein Splitten/Parallelisieren den Vorgang nur.

Code: Alles auswählen

$ dd if=/dev/zero bs=1M count=1000 | gzip -c > /dev/null
1000+0 Datensätze ein
1000+0 Datensätze aus
1048576000 Bytes (1,0 GB) kopiert, 10,6017 s, 98,9 MB/s

$ dd if=/dev/zero bs=1M count=1000 | gzip -1 -c > /dev/null
1000+0 Datensätze ein
1000+0 Datensätze aus
1048576000 Bytes (1,0 GB) kopiert, 7,24732 s, 145 MB/s

# hdparm -tT /dev/sdb
/dev/sdb:
 Timing cached reads:   3506 MB in  2.00 seconds = 1754.76 MB/sec
 Timing buffered disk reads: 394 MB in  3.00 seconds = 131.23 MB/sec



--------------------------------------------------------------------
Okay, wenn es wirklich was zu tun gibt

Code: Alles auswählen

# dd bs=1M if=/dev/shm/urandom | gzip -c > /dev/null
512+0 records in
512+0 records out
536870912 bytes (537 MB) copied, 21.8989 s, 24.5 MB/s

# dd bs=1M if=/dev/shm/urandom | gzip -1 -c > /dev/null
512+0 records in
512+0 records out
536870912 bytes (537 MB) copied, 20.1811 s, 26.6 MB/s
wird das zippen doch erheblich langsamer.
Aber dennoch, das muß ja auch geschrieben werden ~ verringert die Leserate,
und Random-Daten werden auch nicht komprimiert, zippen also irgendwo ~ Lesen/Schreiben.
Mir würde ein Parallelisieren also nichts oder wenig bringen.
Zuletzt geändert von rendegast am 10.09.2015 20:24:41, insgesamt 1-mal geändert.
mfg rendegast
-----------------------
Viel Eifer, viel Irrtum; weniger Eifer, weniger Irrtum; kein Eifer, kein Irrtum.
(Lin Yutang "Moment in Peking")

Colttt
Beiträge: 2986
Registriert: 16.10.2008 23:25:34
Wohnort: Brandenburg
Kontaktdaten:

Re: Idee gesucht....

Beitrag von Colttt » 10.09.2015 20:20:14

Heinz warum nutzt du pbzip2 oder pxz nicht??
Debian-Nutzer :D

ZABBIX Certified Specialist

Benutzeravatar
MSfree
Beiträge: 10759
Registriert: 25.09.2007 19:59:30

Re: Idee gesucht....

Beitrag von MSfree » 10.09.2015 20:34:53

rendegast hat geschrieben:Es dürfte eher am Einlesen liegen.
Liest Du mehrere Stücke einer Datei gleichzeitig, so muß der Lesekopf hin- und herspringen,
das dürfte den Prozeß eher verlangsamen.[/code]
Das ist auf jeden Fall ein Teil der Erklärung.

Wenn man split vorweg laufen läßt, werden die Dateiteile zunächst in den Cache geschrieben (der Linuxkern verwendet praktisch den kompletten freien Hauptspeicher für Cacheoperationen). Je nach RAM-Größe können alle Dateiteile, die split produziert, komplett ins RAM (also Cache) passen. Die einzelnen zip-Prozesse können dann extrem schnell die Dateiteile lesen, Cache-Zugriffe sind rund 100 mal schneller als Plattenzugriffe.

Steigt die ursprüngliche Dateigröße über die RAM-Größe, reicht der Cache nicht mehr aus und es wird wohl oder über über die Festplatte gearbeitet, was die überproportionale Verlangsamung ab 1GB Dateigröße erklärt. Bei meinem Rechner mit 8GB RAM sind praktisch ständig 7GB frei, so daß bei mir erst am 3.5 GB Dateigröße eine überproportionale Verlangsamung festzustellen wäre. Warum 3.5 GB? Nun, in den freien 7GB RAM werden die 3.5GB der Ausgangsdatei und die 3.5GB des Spiltresultats zwischengespeichert.

Läßt man split weg und verwendet direkt dd, um die Dateiteile ohne Cache direkt zu lesen, verlangsamen nicht nur die Kopfbewegungen den Lesevorgang, sondern auch das Fehlen des Caches. Die CPU-Last, die dd erzeugt, ist allerdings völlig vernachlässigbar, das bremst praktisch nicht.

Man könnte, um den Vorgang zu beschleunigen, die Urspungsdatei einmal komplett durchlesen lassen, was den Cache vorbefüllen würde. Da keine Dateiteile benötigt werden, passen so auch doppelt so große Ausgangsdateien in den Cache, so daß sie die Datengrenze bei meine 8GB-System auf rund 7GB erhöhen ließe, bevor der Cache voll läuft. Beim System des OP sollte sich die Grenze auf mindestens 2GB erhöhen lassen.

Wie kann man nun den Cache vorbefüllen?
Nun, einfach einmal durchlesen, z.B. mit
dd if=Ausgangsdatei of=/dev/null bs=10485760

Danach kann man direkt mit dd, wie der OP vorgeschlagen hat, auf die Dateiteile zugreifen. Da hier dann über den Cache gearbeitet werden kann, fallen keine Kopfbewegungen an und der lineare Datendurchsatz aus dem RAM liegt bei 10GB/s statt 100MB/s von der Platte.

Milbret
Beiträge: 827
Registriert: 26.05.2008 12:04:54
Lizenz eigener Beiträge: GNU Free Documentation License
Wohnort: Nörten-Hardenberg
Kontaktdaten:

Re: Idee gesucht....

Beitrag von Milbret » 11.09.2015 11:26:23

Je nachdem wie groß deine Dateien und wieviele es sind, könntest du ggf. direkt in einer RAM Disk arbeiten.
Dort kannst du dann deine ZIP Datei erstellen lasse und schiebst die am Ende einfach mit einem mv in deinen Ordner auf der Platte.
Abhängig von der Menge der Archive und deren größe könntest du quasi alles in der RAM Disk erstellen, was die Platte dann auch beim lesen nicht behindern dürfte.
Erst wenn alles durch ist müsste er die Daten einmal schreiben.

So solltest du die Platte im Idealfall ohne gleichzeitge Lese- und Schreibzugriffe nutzen können.
Sollte im Idealfall auch etwas Performance bringen.

Martin
Es gibt keine if Schleife -> http://www.if-schleife.de/
Ansonsten GPL/GNU/Linux/Debian/Free Software 4 Ever :D

Benutzeravatar
TRex
Moderator
Beiträge: 8071
Registriert: 23.11.2006 12:23:54
Lizenz eigener Beiträge: MIT Lizenz
Wohnort: KA

Re: Idee gesucht....

Beitrag von TRex » 11.09.2015 16:00:28

Colttt hat geschrieben:Heinz warum nutzt du pbzip2 oder pxz nicht??
heinz hat geschrieben:Wie schon geschrieben, nur so zum Spass am scripten. Ich suche keine
Fertigloesung ala: Das Programm xy-z kann das doch schon...
OK? :)
Jesus saves. Buddha does incremental backups.
Windows ist doof, Linux funktioniert nichtDon't break debian!Wie man widerspricht

Benutzeravatar
heinz
Beiträge: 535
Registriert: 20.12.2007 01:43:49

Re: Idee gesucht....

Beitrag von heinz » 12.09.2015 15:36:17

Erstmal Danke fuer Eure Antworten.

So wie ich das alles hier lese, sind wohl die Plattenzugriffe einer der Haupttaeter.

Das mit dem Cache oder der Ramdisk ist ne gute Idee aber ich meine wirklich grosse Dateien.
Gepackt werden einzelne Dateien mit bis zu 30 GB.

Um die Quelldatei nur einmal zu lesen koennte man doch mit:

Code: Alles auswählen

cat $quelldatei | tee ./fifo_1 | tee ./fifo_2 >./fifo_3
die Quelldatei z.B. in 3 "Datenstroeme" aufteilen
und in den Hintergrundprozessen dann mit:

Code: Alles auswählen

dd skip=... count=... if=./fifo...
lesen.

Koennte das gehen?
Wie verhaelt sich denn cat, wenn an den fifos unterschiedlich schnell gelesen wird? Sollte man buffern?
Fragen ueber Fragen... Ich werds wohl ausprobieren.
Melde mich wieder.

Weitere Anregungen sehr willkommen...

Gruss,
heinz

tomi89
Beiträge: 269
Registriert: 21.08.2014 00:21:52

Re: Idee gesucht....

Beitrag von tomi89 » 12.09.2015 18:13:55

Man könnte noch für möglichst viel freien Cache sorgen.

D.h. folgendes zu Erst im Hintergrund starten:

Code: Alles auswählen

(sync ; echo "3" | sudo tee /proc/sys/vm/drop_caches >/dev/null) &
Wobei das sync im Fall der Fälle auch ewig dauern kann und wieder für Bewegung des Festplattenkopfes sorgt.

Benutzeravatar
heinz
Beiträge: 535
Registriert: 20.12.2007 01:43:49

Re: Idee gesucht....

Beitrag von heinz » 13.09.2015 14:00:35

Habs ausprobiert.

Ein:
cat ./quelldatei |tee ./fifo1 |tee ./fifo2 >./fifo3
und dann 3 mal:

Code: Alles auswählen

cat ./fifo[1-3] |gzip >./[1-3].gz
Erzeugt 3 gezippte Kopien der Quelldatei. Soweit so gut...

Sobald ich aber versuche den dd ins Spiel zu bringen klappt es nicht mehr.

Dateigroesse = 563MB = 196782764
Screiben wieder wie oben mit cat.
Lesen mit:

Code: Alles auswählen

dd if=./fifo1 of=./1.bin skip=        0 bs=1 count=196782764
dd if=./fifo2 of=./2.bin skip=196782764 bs=1 count=196782764
dd if=./fifo3 of=./3.bin skip=393565528 bs=1 count=196782764
Was passiert:

Egal in welcher Reihenfolge die "dds" und cat gestartet werden.
Alle drei "dds" und der schreibende cat sind der Meinung die Arbeit sei erledigt, wenn der erste dd seinen count= erreicht hat.
Ergebnis:
  • 188M 1.bin
    70K 2.bin
    0 3.bin
Aber das scheint sowieso eine Sackgasse zu sein...
Selbst ohne Abbruch wuerde der zweite dd erst anfangen,
wenn der erste "durch" ist.

Schade, da laesst sich wohl mit "Bordmitteln" nicht viel Optimieren.

Wenn noch einer eine zuendende Idee hat, bitte, gerne...

Ansonsten, vielen Dank fuer Eure Vorschlaege.

Viele Gruesse,
heinz

Antworten