Auslesen von unsigned long long



  • Hallo Leute

    ich habe eine binäre Datei, die 8 Bytes enthält und laut Spezifikation als ganzzahliger Wert interpretiert werden muss. Da diese Werte immer positiv sind ( Zeitangaben in Nanosekunden seit 01.01.1970 ) dachte ich daran es als unsigned long long zu interpretieren.

    Ich hab mir die 8 Bytes zunächst im Hexeditor angeschaut.
    Der liefert mir:
    12 E5 0D 68 B1 CB 17 80

    Der Windowstaschenrechner rechnet das erfolgreich um ( dezimaler Zeitwert macht Sinn ).

    Nun will ich das in meiner Applikation ebenso tun.

    Ich hab zunächst die Daten binär in einen char-Buffer eingelesen.
    Den habe ich nach unsigned long long* gecastet und dann einfach den ersten Wert dort entnommen. Die Ausgabe entspricht aber nicht dem Wert des Windowstaschenrechners.

    C++:
    unsigned char *ZeitBuffer = Buffer + 9;
    unsigned long long *tbuf = (unsigned long long*)( ZeitBuffer );
    std::cout << tbuf[ 0 ] << std::endl;

    Ich vermute, dass hier in meinem System eine andere Representation des Datentyps im Speicher vorliegt, oder aber die Streamausgabe hat ein Problem mit unsigned long long.

    Liege ich da richtig?



  • 1.) Byteorder beruecksichtigt?
    2.) Alignment beruecksichtigt? (wohl kaum)

    Bitte nicht casten, nutze memcpy oder aehnliches ...



  • Danke, die Byteorder wars...



  • Und bitte beachte den Tipp mit dem memcpy, das macht es auch auf nicht x86-Platformen sicher, und wird eh weg optimiert (bzw. wird zu einer mov instruction).



  • Ich werde drüber nachdenken, ob ich mir das leisten kann... Ich schreibe gerade einen Parser für einen UDP-Datentrom im 100MBit-Bereich. Da ist im Prinzip schon jede Instruktion eine zuviel 😉



  • Das kommt auf den Prozessor an. Ansonstenten kannst du ja den Speicher fuer read auch gleich so anlagen, dass die Elemente gleich richtig aligned sind. Nichtausgerichteten Speicher zu laden/schreibe, kostet wahrscheinlich auch.



  • 100 mbit ist doch total lächerlich, nicht mal bei 1000 mbit wird mehrmaliges Hin- und Herkopieren der gesamten Daten relevant. (Falls du von einem Desktop-PC/Server und nicht einem Handy aus den 90ern redest.) Bei 10 Gbit merkt man vielleicht was, aber dann solltest du dir am besten mal RIO oder so anschauen.



  • hast du zu dem "RIO" mal einen Link oder einen vollen Namen. Tät mich mal interessieren, hab ich nämlich noch nich gehört.

    Cooky, klingt als hättest du schon mal 1GB-Anbindung programmiert. Vielleicht solltest du mir noch ein paar mehr Tipps geben 😉





  • Das klingt irgendwie alles stark nach Windows...



  • It0101 schrieb:

    Cooky, klingt als hättest du schon mal 1GB-Anbindung programmiert. Vielleicht solltest du mir noch ein paar mehr Tipps geben 😉

    Nur simple Dinge, aber das ist hier auch gar nicht relevant. Man muss das nur mit der Geschwindigkeit vergleichen, mit der man Daten kopieren kann.

    It0101 schrieb:

    Das klingt irgendwie alles stark nach Windows...

    Ja, das ist ein Windows 8 Feature. Wobei Linux theoretisch etwas Äquivalentes haben könnte. Mit einem eigenen Netzwerkkartentreiber geht da sicher so einiges. Aber wie gesagt, 100 Mbit auf einem modernen Desktop-Prozessor: memcpy wird nicht dein Problem sein. (Und ein mov schon gar nicht.) (Und das mov haste btw auch bei dem Cast.)

    Edit: Aber asynchrones I/O nutzt du schon, oder?



  • cooky451 schrieb:

    100 mbit ist doch total lächerlich, nicht mal bei 1000 mbit wird mehrmaliges Hin- und Herkopieren der gesamten Daten relevant. (Falls du von einem Desktop-PC/Server und nicht einem Handy aus den 90ern redest.) Bei 10 Gbit merkt man vielleicht was, aber dann solltest du dir am besten mal RIO oder so anschauen.

    Da überschätzt du deinen Prozessor aber maßlos. Wenn du tatsächlich dauerhaft mit 100 MBit Daten reingeclockt kriegst, bleibt dir nicht mehr viel Zeit, die zu verarbeiten. Bei mehrmaligem Hin- und Herkopieren bekämst du allein durch die CAS-Latenz deines Arbeitsspeichers ernste Probleme. Bei dauerhaft Gbit schon mit der Taktrate deiner CPU.

    Moderne Computer sind keine Wundermaschinen, die alles in null Zeit bewältigen können. 10 Gbit an einem PC? Vorläufig eine witzige Idee.



  • cooky451 schrieb:

    Edit: Aber asynchrones I/O nutzt du schon, oder?

    Jop. Logo.



  • seldon schrieb:

    Da überschätzt du deinen Prozessor aber maßlos. Wenn du tatsächlich dauerhaft mit 100 MBit Daten reingeclockt kriegst, bleibt dir nicht mehr viel Zeit, die zu verarbeiten. Bei mehrmaligem Hin- und Herkopieren bekämst du allein durch die CAS-Latenz deines Arbeitsspeichers ernste Probleme. Bei dauerhaft Gbit schon mit der Taktrate deiner CPU.

    Hm.., so? Ich neige dazu, dir immer Recht zu geben, aber.. 100 Mbit/s wären 12.5MB/s. Also ich kann auf meinem PC kaum messen wie schnell ich 3200 4KB große Speicherblöcke kopieren kann. 32000 Stück dauern auch nicht viel länger. Bei Weitem keine Sekunde jedenfalls.



  • It0101 schrieb:

    Das klingt irgendwie alles stark nach Windows...

    Im Embedded- und Echtzeitbereich ist das seit Jahren Stand der Technik.
    Windoof ist da mal wieder weit hinterher.



  • cooky451 schrieb:

    seldon schrieb:

    Da überschätzt du deinen Prozessor aber maßlos. Wenn du tatsächlich dauerhaft mit 100 MBit Daten reingeclockt kriegst, bleibt dir nicht mehr viel Zeit, die zu verarbeiten. Bei mehrmaligem Hin- und Herkopieren bekämst du allein durch die CAS-Latenz deines Arbeitsspeichers ernste Probleme. Bei dauerhaft Gbit schon mit der Taktrate deiner CPU.

    Hm.., so? Ich neige dazu, dir immer Recht zu geben, aber.. 100 Mbit/s wären 12.5MB/s. Also ich kann auf meinem PC kaum messen wie schnell ich 3200 4KB große Speicherblöcke kopieren kann. 32000 Stück dauern auch nicht viel länger. Bei Weitem keine Sekunde jedenfalls.

    Naja, 100 Mbit/s bedeuten 10 Nanosekunden pro Bit. Wenn du ne ziemlich dicke CPU hast (core-i7 geht bis 3,6 GHz), sind das so 30 Clocks. Legen wir eine 64-Bit-CPU zugrunde und beschränken uns auf einen Kern (weil wir den Kram synchron abarbeiten), bedeutet das so um die 2000 Zyklen pro Maschinenwort Daten (beachte: 2000 Zyklen bedeutet weniger als 2000 Instructions). Bei niedriger getakteten Maschinen ist es entsprechend weniger (auf einem handelsüblichen kleinen Atom der bei 600 MHz idlet beispielsweise knapp 400). Bei Gigabit entsprechend 40-200, und 10Gbit wäre mit 4-20 jenseits dessen, was sich ohne spezialisierte Hardware handhaben lässt. Deswegen findet man das auch nicht in PCs, sondern eher in Rechenzentren bei kaskadierenden Netzwerkswitches und dergleichen.

    Das nur, um die theoretische Obergrenze abzustecken. In der Realität hat man eine ganze Reihe von Zeitverschwendern an einer CPU hängen. Zum Beispiel braucht DDR3-RAM, um eine memory column rauszusuchen, so Pi * Daumen knappe 10 Nanosekunden. Wobei, wo ich nochmal drüber nachdenke, das ein geringeres Problem ist, weil es bei sequentieller Datenverarbeitung nur einmal alle (üblicherweise) 64 Byte passiert. Das wird bei Gigabit langsam ein Faktor, dürfte aber für 100 Mbit noch unproblematisch sein; da hab ich mich vorhin verdacht. Aber es gibt genug andere -- das Betriebssystem rückt Netzwerkdaten üblicherweise per Syscall raus, was (gerade auf x86) erstaunlich teuer kommt, und ohnehin kann ein Betriebssystem einen immer mit context switches überraschen und in die Performance hauen.

    Wie dem auch sei, wir bewegen uns hier schon in einer Größenordnung, in der man sich etwas sputen muss, selbst wenn man der einzige Prozess im Betriebssystem ist, und es ist ja auch davon auszugehen, dass It0101 mit den Daten noch etwas mehr vorhat, als sie nur zu parsen. Wenn du, wie das bei Netzwerkcode üblicherweise der Fall ist, eine begrenzte Menge Daten in hoher Geschwindigkeit erwartest, kann der Kernel die Daten erstmal buffern (von 10Gbit mal abgesehen), bis du sie gemütlich abarbeitest, aber wenn dauerhaft 100 Mbit reinströmen und du sie nicht schnell genug abholst, ist der Buffer halt irgendwann voll und Pakete gehen verloren. Was bei einem UDP-basierten Protokoll sinnvollerweise nicht so schlimm sein sollte, aber das ist ein anderes Thema.

    Bei all diesen Überlegungen reden wir übrigens von vergleichsweise dicken Maschinen. Es ist kein Zufall, dass der Raspberry Pi und vergleichbare ARM-Boards ohne Gigabit-Ethernet kommen -- auch dickere ARMs wären mit einer solchen Datenrate heillos überfordert.



  • Die Anbindung der Maschinen innerhalb des Rechenzentrums ist 10GBit und von dort kommt auch der Datenstrom von ca. ( schwankend ) 100 MBit. Die Hardware dürfte sicherlich zu den besten kommerziellen Kisten gehören, die in Deutschland so rumstehen. Dort nehmen auch noch andere Nutzer den Datenstrom ab, daher gehe ich davon aus, dass die Hardware ausreicht.

    Jedenfalls weiß ich jetzt schon, dass ich mir jeden Befehl und jede Funktion genauestens überlegen muss, damit die Applikation dann nachher auch funktioniert bzw. stabil durchhält und auch mal größere Peaks im Durchsatz verkraftet.

    Es handelt sich in dem Fall um eine Art Protokollwandler, der einen Datenstrom, bzw. zwei parallele identische Datenströme entgegennimmt ( Stichwort UPD-Paketverluste ), den resultierenden, bestenfalls dann vollständigen, Datenstrom umwandelt und weiterleitet.



  • seldon schrieb:

    Naja, 100 Mbit/s bedeuten 10 Nanosekunden pro Bit.

    Aber man kopiert doch nicht einzelne bits, ich verstehe nicht was das mit meiner Aussage zu tun hat. Abgesehen davon passiert das doch alles im OS, vermutlich über DMA, da holt die CPU doch nicht jedes einzelne bit ab? 😕 Und wenn man dann 64 oder 256 bit auf einmal kopieren kann, sehen die Zahlen schon wieder ganz anders aus.



  • Ich hab zunächst die Daten binär in einen char-Buffer eingelesen.

    Warum nicht direkt in das ull? Dann wäre die ganze memcpy-Diskussion hinfällig.
    Ansonsten: Kannst du garantieren dass das Aligment passt? Dann caste einfach. Ansonsten memcpy. So einfach ist das.



  • Ethon schrieb:

    Ich hab zunächst die Daten binär in einen char-Buffer eingelesen.

    Warum nicht direkt in das ull? Dann wäre die ganze memcpy-Diskussion hinfällig.
    Ansonsten: Kannst du garantieren dass das Aligment passt? Dann caste einfach. Ansonsten memcpy. So einfach ist das.

    Die Daten kommen in Zukunft ja von einem Socket. D.h. die liegen auf jeden Fall schon in einem Buffer. Zusammen mit noch anderen Daten, die nicht als ull interpretiert werden. Insofern wird es beim memcpy wohl bleiben müssen.


Log in to reply