Sekundenweise in der Form: hh:mm:ss hochzählen
-
DirkB schrieb:
Abgesehen davon dass von Controllern bisher nicht die Rede war, brauchst du die Divisionen ja nur bei der Ausgabe.
Nö, lies' den Titel genau, das läßt keine Interpretation zu. Er will im Format hh
ss hochzählen.
rüdiger schrieb:
pointercrash() schrieb:
Das ist auf einer Maschine ohne HW- Divdierer zigfach schneller.
Und auf einer Maschine mit HW-Dividierer zigfach langsamer.
Was bringt Dich zu dieser kühnen Annahme? Hast Du 'nen Sack Hühnerknochen bei Neumond um Mitternacht geschüttelt und Petro beschworen, der Dir das erzählt hat?
Gehen wir mal davon aus, daß die ISR sekündlich drankommt, dann haben wir in DirkBs letzter Routine 3600 mal Hochzählen, 5*3600 = 18'000 Divisionen und 3*3600 = 10'800 Zuweisungen pro Stunde.
Bei mir sind's 3600 + 60 + 1, also 3661 Hochzählen mit Vergleich und 61 Zuweisungen, wenn ich mich nicht irre.Selbst bei HW-DIV- ALUs ist Deine Behauptung Behauptung "zigmal schneller" nichtmal über den Daumen gepeilt haltbar, bei SW-DIV beginnen die Schmerzen spätestens, wenn's mit 'nem Uhrenquarz laufen soll.
-
pointercrash() schrieb:
DirkB schrieb:
Abgesehen davon dass von Controllern bisher nicht die Rede war, brauchst du die Divisionen ja nur bei der Ausgabe.
Nö, lies' den Titel genau, das läßt keine Interpretation zu. Er will im Format hh
ss hochzählen.
Es wäre nicht das erste mal, daß ein Thread-Ersteller bei seinem Thema meilenweit am tatsächlichen Problem vorbei schießt
@arz: Ehe hier alle Anwesenden wild herumraten: Was hast du denn mit diesem "Zähler" überhaupt vor?
-
CStoll schrieb:
pointercrash() schrieb:
DirkB schrieb:
Abgesehen davon dass von Controllern bisher nicht die Rede war, brauchst du die Divisionen ja nur bei der Ausgabe.
Nö, lies' den Titel genau, das läßt keine Interpretation zu. Er will im Format hh
ss hochzählen.
Es wäre nicht das erste mal, daß ein Thread-Ersteller bei seinem Thema meilenweit am tatsächlichen Problem vorbei schießt
@arz: Ehe hier alle Anwesenden wild herumraten: Was hast du denn mit diesem "Zähler" überhaupt vor?
Ich habe Messwerte unterschiedlicher Stationen die in unterschiedlichen txt files liegen und unterschiedliche Start- und Endzeiten haben, die Zeitangaben in den txt files liegen in der Form hh
ss. Zum Auswerten möchte ich die Daten eines Tages aller Stationen in Arrays speichern. Da es uU Lücken in den Messreihen gibt, brauche ich quasi ein Referenzzeitfeld anhand dessen ich die vorhandenen Daten dann in eine zeitliche Abfolge einsortieren kann.
ich muss also nix in Echtzeit zählen oder einen Timer setzen, es geht nur um das Befüllen des Referenzarrays.
Hoffe das hat geholfen ...
Grüße!
arz
-
pointercrash: Du kannst davon ausgehen, dass moderne Compiler (mit entsprechenden Optimierungsschaltern) Divisionen mit festen Nennern in Multiplikationen umwandeln - dabei wird ausgenutzt, dass faktisch modulo 2^Registerbreite gerechnet wird. Ob eine Division in Hardware erledigt wird oder nicht, dürfte hier also eher selten eine Rolle spielen.
arz: Für mich klingt das so, als wolltest du eigentlich Zeiten der Form hh
ss in Sekundenzahlen umwandeln, also genau umgekehrt. Die Mathematik ist natürlich ziemlich ähnlich:
counter = sec + min * 60 + hour * 3600;
Das kannst du dann auch direkt als Index für ein Array benutzen.
-
seldon schrieb:
pointercrash: Du kannst davon ausgehen, dass moderne Compiler (mit entsprechenden Optimierungsschaltern) Divisionen mit festen Nennern in Multiplikationen umwandeln - dabei wird ausgenutzt, dass faktisch modulo 2^Registerbreite gerechnet wird. Ob eine Division in Hardware erledigt wird oder nicht, dürfte hier also eher selten eine Rolle spielen.
arz: Für mich klingt das so, als wolltest du eigentlich Zeiten der Form hh
ss in Sekundenzahlen umwandeln, also genau umgekehrt. Die Mathematik ist natürlich ziemlich ähnlich:
counter = sec + min * 60 + hour * 3600;
Das kannst du dann auch direkt als Index für ein Array benutzen.
Ich mein's nicht persönlich, aber für welchen Planeten codet ihr? Auch gute Compiler entbinden niemanden, sein Hirn zu gebrauchen! Ich hab' jetzt aufm PC beide Lösungen nacheinander und meine durch char- Counter sogar in Nachteil gesetzt. Wer will, darf auch Timer einsetzen. Kann jetzt sein, daß Rüdiger bezweifelt, daß PCs HW-DIV- Einheiten haben, aber für den Rest der denkenden Menschheit dürfte das Ergebnis eindeutig sein.
#define YEARSECONDS (364 * 24 * 3600) #define DAYSECONDS (24 * 3600) int main(int argc, char *argv[]) { int count = 0, tag = 0, std = 0, min = 0, sec = 0; unsigned char cstd = 0, cmin = 0, csec = 0; printf("DirkB calculates, rüdiger applauses\n"); for (count = 0; count <= YEARSECONDS; count++) { sec = count % 60; min = (count /60 ) % 60; std = (count /3600) % 24; if (!(sec | min | std)) tag++; } printf("Tag: %d\n", tag); printf("pointercrash() counts ...\n"); tag = 0; std = 0; min = 0; sec = 0; for (count = 0; count <= (YEARSECONDS+DAYSECONDS); count++) { if (++csec >= 60){ csec = 0; if (++cmin >= 60){ cmin = 0; if (++cstd >= 24) cstd = 0; } } if (!(csec | cmin | cstd)) tag++; } printf("Tag: %d ... oops ...\n", tag); return 0; }
@edit: wer mir ans Bein pissen mag, daß die Lösungen nicht völlig adäquat sind, das war mir klar, ich setz' mich um einen Tag in Nachteil, hab's nur schnell hingeschottert, um zu zeigen, wie unsinnig rüdis Behauptung ist ...
-
Benchmarking mit printf ist eine ganz schlechte Idee; du hast keine Ahnung, wann der Buffer geflusht wird und verlässt dich auf dein Gefühl. Benutz clock().
Um das zu machen, was du da tust, ist die Zählvariante natürlich schneller (sofern Branching nicht sehr, sehr teuer ist). Damit, ob die eine Division in Hardware stattfindet, hat es aber wenig zu tun, weil nicht davon auszugehen ist, dass eine Division ausgeführt wird. Der Compiler entbindet einen nicht davon, sein Hirn zu gebrauchen, aber man sollte ihn in seine Überlegungen doch einbeziehen, bevor man völlig irrelevanten Stuss über HW-Dividierer in die Diskussion wirft.
Und da sich die Problemstellung inzwischen als eine völlig andere entpuppt hat, ist die Zählidee eh hinfällig.
-
seldon schrieb:
Benchmarking mit printf ist eine ganz schlechte Idee; du hast keine Ahnung, wann der Buffer geflusht wird und verlässt dich auf dein Gefühl. Benutz clock().
Das betrübt mich nun zutiefst.
Ich habe ja geschrieben, wer will, soll sich da was mit clock oder anderen Timerfunktionen was reinbasteln, aber das ist so offensichtlich, wie der Film "Bambi vs. Godzilla" kurz sein wird. Da ich meine Compiler alle in virtuellen Maschinen betreibe, wird auch clock() keine echten Benchmarkdaten liefern, man müßte das Ding profilen und das war's mir nicht wert.seldon schrieb:
Um das zu machen, was du da tust, ist die Zählvariante natürlich schneller (sofern Branching nicht sehr, sehr teuer ist). Damit, ob die eine Division in Hardware stattfindet, hat es aber wenig zu tun, weil nicht davon auszugehen ist, dass eine Division ausgeführt wird. Der Compiler entbindet einen nicht davon, sein Hirn zu gebrauchen, aber man sollte ihn in seine Überlegungen doch einbeziehen, bevor man völlig irrelevanten Stuss über HW-Dividierer in die Diskussion wirft.
Häh? Wenn man aus einem Counter std, min, sec extrahiert, geht das nur durch Division, arz braucht den Tag sekundenweise hochgezählt, um eine Zeitskala zu erhalten. Dabei wird sehr wohl relevant, ob man einen HW- Dividierer hat, war ja Rüdigers These, daß damit die Divisionslösung schneller wird als Hochzählen. In Software hat die Divisionslösung aus ersichtlichen Gründen Null komma gar keine Chance und auch mit HW-DIV bleibt die Divisionslösung dimensional langsamer, ist mitnichten "zigmal schneller", wie rüdiger in einem Anfall geistiger Verwirrung geschrieben hat - nichts anderes belegt mein Codeschnipsel. Eher ist Dein Einwand mit den Branching irrelevant, das kann niemals teurer sein, als fünf Int/Mod- Divs.
seldon schrieb:
Und da sich die Problemstellung inzwischen als eine völlig andere entpuppt hat, ist die Zählidee eh hinfällig.
Eben nicht, arz braucht ja alle Tagessekunden als String. Ich habe das sprintf (oder fprintf, whatsoever) weggelassen, um deutlich zu machen, daß Zählen schneller ist als Dividieren, q.e.d.
Die Ausgabefunktionen sind abartig lahm, demgegenüber würde es weniger ins Gewicht fallen, daß Dividieren langsamer ist. Auch, wenn es nur um das Füllen eines array von Strings geht, ist Hochzählen schneller, viel schneller sogar.
-
Lies das hier. Diese Optimierung wird von allen gängigen Compilern benutzt. Du wirst im Maschinencode keine Divisionen bekommen, weil die Divisoren allesamt konstant sind und die Divisionen zu Multiplikationen und Bitshifts optimiert werden.
Greif dir mal nen gcc, nudel den Kram durch und schau in den Maschinencode. Eine Division durch 3600 wird zu
movl $-1851608123, %edx movl %ecx, %eax imull %edx leal (%rdx,%rcx), %eax movl %eax, %edx sarl $11, %edx movl %ecx, %eax sarl $31, %eax
...und da ist noch nicht mal ein -O-Schalter drin.
Was die Aufgabenstellung angeht -- so wie ich das lese, hat arz eine Datei voll mit derart formatierten Zeitstempeln und muss diese in ein Kontinuum einordnen. Dazu wäre dann genau die umgekehrte Umwandlung sinnvoll.
-
seldon schrieb:
Lies das hier.
Jo, die Sache mit Shift und mul ist uralt, der LCC macht's genauso, wobei noch nicht endgültig geklärt ist, ob diese Optimierung für den X86 noch Sinn macht. Zumindest wird kein HW- DIV bemüht.
Wobei die Inkrementiersequenz immer noch wesentlich schneller läuft.seldon schrieb:
Was die Aufgabenstellung angeht -- so wie ich das lese, hat arz eine Datei voll mit derart formatierten Zeitstempeln und muss diese in ein Kontinuum einordnen. Dazu wäre dann genau die umgekehrte Umwandlung sinnvoll.
Ja, wahrscheinlich wäre das sinnvoller gewesen. Aber ob er's so macht, da hätte er ja fragen müssen, ob man drei Multiplikationen und zwei Additionen durch was praktischeres ersetzen kann - da hätte ich eher Trollerei vermutet. Gefragt hat er nach Zeitstrings im Format std:min:sec und die produzier' ich schneller mit Hochzählen.
-
noch einen nachtrag hierzu:
ich habe mich jetzt entschieden die Zeit als string auszulesen und habe also einen string der Form:
hhmmss
Daraus möchte ich direkt einen Index für ein array erzeugen.
also :
index = hh*3600+mm*60+ss
wie kann ich den string in 3 int-Werte zerlegen?
-
unsigned a,b,c; if( 3==sscanf(hhmmssstring,"%02u%02u%02u",&a,&b,&c) ) { } else puts("Fehler");
-
sowas habe ich mir gedacht,, leider funktioniert es nicht,, :
//so lese ich den Zeitstring in der Form hhmmss ein: sscanf(puffer, "%s%f", &Datum[zaehl], &MWA[zaehl]); //so geht es leider nicht .... int sec,min,std; sscanf(Datum,"%02d%02d%02d",&std,&min,&sec);
auch mit unsigned hab ich es nicht hinbekommen ....
-
Was steht denn in Datum drin?
Für die Vorgabe hhmmss arbeitet dieser Code fehlerfrei, es liegt also an dir bzw. deiner Umgebungssituation.
-
... ja, hab den Fehler gefunden,, es lag an dem Datum - Array,,
Danke!