Hi, ich habe eine Datei mit 180.000 Zeilen in denen je ein Index und ein 96 stelliger hex Wert steht. Sie so aus: (natuerlich in einer Zeile) 000001 dfa34efdfbf7efdfbf7efdfbf7efdfb93efdfbd7eedf9f7efdfbf7efdfbf7efdfbf7efdfbf7efdfbf7efdfbf7eff0000 Jetzt muss jede Zeile ausgelesen werden und der hex-Wert in einen bin-Wert ueberfuehrt werden. von diesem bin-Wert (384 stellig) muessen jetzt die ersten beiden Bit's sowie die Bit's 110000 subtrahiert werden. Das Ergebniss repraesentiert dann einen Zeitraum, sagen wir mal vom 1.1.2004-31.12.2004 Jeder Tag innnerhalb dieses Zeitraumes wird durch je eine Stelle in dem bin-Wert dargestellt. Eine 1 bedeutet, es passiert was an diesem Tag, eine 0 bedeutet, es passiert nichts. Die Tage sind jetzt mit Ereignissen verknüpft, wobei zu je einem Ereigniss alle Tage rausgesucht werden sollen, an denen es Stattfindet. Die Verknüpfung geschieht ueber den Index. Das ganze wird dann in eine (wuerg) access-DB geschrieben. Folgende Probleme ergeben sich: 1.) umwandeln des hex-Wertes in einen bin-Wert. Da habe ich folgende Schleife gebastelt: -- snipp -- open(FILE, $pref{"_bitFieldFile"}) or die "Konnte $pref{_bitFieldFile} nicht oeffnen!\n"; open(FILEW, "> val.txt") or die "Konnte val.txt nicht oeffnen!\n"; my ($id, $bitField, $dez, $bin, $n); while (<FILE>) { ($id, $bitField) = split / /, $_; my $m = 0; my $bit = ""; foreach ($bitField =~ /.{8}/g) { # alle anderen Faelle $dez = hex($_); # erster Teil, die ersten zwei Bits subtrahieren $dez = hex($_) - 3221225472 if ($m == 0); # letzter Teil, die letzten zwei Bits subtrahieren $dez = hex($_) - 196608 if ($m == 11); $bin = unpack("B32", pack("N", $dez)); $bit = $bit . $bin; $n++; $m++; } print FILEW $bit; } close FILE; close FILEW; Das Konstrukt benoetigt ca 30 sec. Geht das nicht schneller? Ich finde die folgenden zwei Zeilen umstaendlich. $dez = hex($_); $bin = unpack("B32", pack("N", $dez)); 2.) In den Access-DB existiert eine Tabelle mit saemtlichen Tagen im dem Zeitraum. Aus den oben ermittelten Werten soll jetzt eine Tabelle erzeugt werden, in der zu jedem Ereigniss fuer jeden Tag an dem es stattfindet, eine Zeile erzeugt werden soll. Ziel ist, alle Ereignisse aus der DB auszulesen, die an einem bestimmten Tag stattfinden. Damit haette die Tabelle im unguenstigsten Fall 365(Tage)*180.000 Zeilen, also ca 65.700.000 Zeilen. Meine Loesung funktioniert zwar, jedoch dauert das natuerlich ewig. Vorallendingen muss der ganze Krempel ja auch in die DB geschrieben werden. Faellt Euch dazu eine bessere Loesung ein? -Joerg
Hallo,
foreach ($bitField =~ /.{8}/g) {
# alle anderen Faelle $dez = hex($_);
# erster Teil, die ersten zwei Bits subtrahieren $dez = hex($_) - 3221225472 if ($m == 0);
# letzter Teil, die letzten zwei Bits subtrahieren $dez = hex($_) - 196608 if ($m == 11);
$bin = unpack("B32", pack("N", $dez)); $bit = $bit . $bin; $n++; $m++; }
Das Konstrukt benoetigt ca 30 sec. Geht das nicht schneller? Ich finde die folgenden zwei Zeilen umstaendlich. $dez = hex($_); $bin = unpack("B32", pack("N", $dez));
Ich bin kein Experte darin, wie man Perl dazu bekommt, möglichst schnell zu laufen. Aber ich würde mutmaßen, dass ein direktes (zifferweises) Umrechnen ('0' -> '0000', '1' -> '0001' usw) schneller gehen müsste. Das Subtrahieren müsste man dann wohl per Hand machen. Oder man behandelt die ersten und letzten acht Ziffern mit der alten Methode.
2.) In den Access-DB existiert eine Tabelle mit saemtlichen Tagen im dem Zeitraum. Aus den oben ermittelten Werten soll jetzt eine Tabelle erzeugt werden, in der zu jedem Ereigniss fuer jeden Tag an dem es stattfindet, eine Zeile erzeugt werden soll. Ziel ist, alle Ereignisse aus der DB auszulesen, die an einem bestimmten Tag stattfinden. Damit haette die Tabelle im unguenstigsten Fall 365(Tage)*180.000 Zeilen, also ca 65.700.000 Zeilen. Meine Loesung funktioniert zwar, jedoch dauert das natuerlich ewig. Vorallendingen muss der ganze Krempel ja auch in die DB geschrieben werden. Faellt Euch dazu eine bessere Loesung ein?
Mmh, wäre es vielleicht möglich, das ganze mit C (o.ä.) zu machen. Sollte nicht allzu aufwendig werden, weil die Strings ja immer gleich lang zu sein scheinen. Viele Grüße, Jürgen PS: Hilft "use integer;"?
Am 20.08.2003 19:23 schrieb Jürgen Wieferink:
Hallo,
foreach ($bitField =~ /.{8}/g) {
# alle anderen Faelle $dez = hex($_);
# erster Teil, die ersten zwei Bits subtrahieren $dez = hex($_) - 3221225472 if ($m == 0);
# letzter Teil, die letzten zwei Bits subtrahieren $dez = hex($_) - 196608 if ($m == 11);
$bin = unpack("B32", pack("N", $dez)); $bit = $bit . $bin; $n++; $m++; }
Das Konstrukt benoetigt ca 30 sec. Geht das nicht schneller? Ich finde die folgenden zwei Zeilen umstaendlich. $dez = hex($_); $bin = unpack("B32", pack("N", $dez));
Ich bin kein Experte darin, wie man Perl dazu bekommt, möglichst schnell zu laufen. Aber ich würde mutmaßen, dass ein direktes (zifferweises) Umrechnen ('0' -> '0000', '1' -> '0001' usw) schneller gehen müsste. Das Subtrahieren müsste man dann wohl per Hand machen. Oder man behandelt die ersten und letzten acht Ziffern mit der alten Methode.
Dazu muesste ich eine Schleife 96'zig mal durchlaufen, je hex-Wert ein mal. Auuserdem braeuchte ich einen Hash mit 16 Schluessel-Wert Paaren. Das wird wohl wesentlich laenger dauern.
2.) In den Access-DB existiert eine Tabelle mit saemtlichen Tagen im dem Zeitraum. Aus den oben ermittelten Werten soll jetzt eine Tabelle erzeugt werden, in der zu jedem Ereigniss fuer jeden Tag an dem es stattfindet, eine Zeile erzeugt werden soll. Ziel ist, alle Ereignisse aus der DB auszulesen, die an einem bestimmten Tag stattfinden. Damit haette die Tabelle im unguenstigsten Fall 365(Tage)*180.000 Zeilen, also ca 65.700.000 Zeilen. Meine Loesung funktioniert zwar, jedoch dauert das natuerlich ewig. Vorallendingen muss der ganze Krempel ja auch in die DB geschrieben werden. Faellt Euch dazu eine bessere Loesung ein?
Mmh, wäre es vielleicht möglich, das ganze mit C (o.ä.) zu machen. Sollte nicht allzu aufwendig werden, weil die Strings ja immer gleich lang zu sein scheinen.
Ich brauche es nicht nur fuer Linux, sondern auch fuer M$. Ausserdem sind da noch wesentlich mehr Funktionen drin und einzelne Funktionen auszugliedern sieht irgendwie doof aus.
PS: Hilft "use integer;"?
hilft haeufig, duerfte aber hier keine nennenswerten Effekte haben. -Joerg
Hallo,
Dazu muesste ich eine Schleife 96'zig mal durchlaufen, je hex-Wert ein mal. Auuserdem braeuchte ich einen Hash mit 16 Schluessel-Wert Paaren. Das wird wohl wesentlich laenger dauern.
Ich dachte eher an ein switch/case-Konstrukt mit 16 Fällen. Sonst muss Perl ja auch jeden Buchstaben einzeln parsen. "Sieht" Perl eigentlich, dass $bit ein so langer String wird? Sonst könnte es doch günstig sein, es vorher mit Nullen vollzuschreiben, und nachher in Teilarrays zu schreiben. Aber ich seh schon, ich kenne weniger von dem Problem als Du. Ciau, Jürgen
Hi, Am 20.08.2003 20:14 schrieb Jürgen Wieferink:
Hallo,
Dazu muesste ich eine Schleife 96'zig mal durchlaufen, je hex-Wert ein mal. Auuserdem braeuchte ich einen Hash mit 16 Schluessel-Wert Paaren. Das wird wohl wesentlich laenger dauern.
Ich dachte eher an ein switch/case-Konstrukt mit 16 Fällen. Sonst muss Perl ja auch jeden Buchstaben einzeln parsen.
eine 96 stellige Hex-Zahl entspricht einer 384 stelligen Bin-Zahl. Leider habe ich aber nur eine 32-Bit Maschine;)
"Sieht" Perl eigentlich, dass $bit ein so langer String wird? Sonst könnte es doch günstig sein, es vorher mit Nullen vollzuschreiben, und nachher in Teilarrays zu schreiben.
Aber ich seh schon, ich kenne weniger von dem Problem als Du.
meistens hilft schon eine andere Sicht. Danke. -Joerg
participants (3)
-
Joerg Zimmermann
-
Jörg Zimmermann
-
Jürgen Wieferink