Typumwandlung mit Union fehlerhaft?



  • c_newbie schrieb:

    Evtl. würds dann auch Sinn machen den String in größeren Chunks einzulesen und
    dann aufzuteilen(bearbeiten) statt jedes Char einzeln abzuholen.Den Loop könnte
    man aus Preformance gründen auch unrollen allerdings müßte man das eh etwas
    anders angehen wenn man größere chunks holt.

    Bin mir nicht ganz sicher, ob ich verstanden habe was du meinst. Ich lese bisher in Chars ein, weil ich z.T. auf einzelne Bits zugreifen will. Meine ausgelesenen Werte haben Größen zwischen 1 Bit und 32 Byte und verschiedene Datentypen.
    Bin mir nicht sicher ob es da sinnvoll ist, größere Chunks (= Blöcke? 😕 ) einzulesen.



  • /*
                for(m=0;m<2;m++){
                    union_rechnen.c[m]=fgetc(FDatei);
                } 
    */
    
    fread(union_rechnen.c,sizeof(union_rechnen.c[0]),2,FDatei);
    


  • Achso. Du meinst so spar ich mir die for-Schleife?



  • Denk die Schleife ist dann in der Funktion. Wenn nun fgetc fread aufruft z.b.
    fread(p_s,sizeof(char),1,fp); würds schon sinn machen. Abgesehen davon stubst nur
    einmal das Os an und nicht in ner schleife.



  • Bin mir nicht sicher ob das wirklich einen Vorteil bringt.
    Da wäre es doch eher sinnvoll sowas zu machen:

    union_rechnen.c[0] = fgetc(FDatei);
    union_rechnen.c[1] = fgetc(FDatei);
    

    Bin mir nicht sicher, aber das sollte es ein wenig schneller machen...



  • Spreche jetzt mal nur für Linux. Die meißten wenn nicht sogar alle Funktionen aus der stdio.h
    die mit dem Dateisystem arbeiten rufen intern syscall 3 oder 4 auf ne schöne tabelle gibts
    hier http://bluemaster.iu.hio.no/edu/dark/lin-asm/syscalls.html
    beide syscalls benötigen die Größe und Anzahl so wie bei fread.



  • Bin leider was Linux angeht noch relativ unbedarft. Mein Firmen-PC ist ein reiner XP-Rechner.



  • Ach normal macht windows intern doch das gleiche wie unix



  • [quote="Blue]
    Ich lese ja nur aus, wenn ich auch was hineingeschrieben habe.
    Mein Betreuer (das ganze hier ist ne Diplomarbeit) hat mich extra den Code umstellen lassen um die Unions zur Typkonvertierung zu nutzen. Er begründet das mit Rechenzeitvorteilen.
    [/quote]
    naja, aber auch wenns bei dir funktioniert, ist es unportabel und nur ein hack. ausserdem glaub ich kaum, dass es zu lahm wird, wenn du's richtig machst. compiler sind ganz oft schön schlau, erkennen bekannte codemuster (z.b. zusammenbau zweier byte zu 'nem 16-bit wert) und optimieren sowas ziemlich gut.
    🙂



  • Was ist daran unportabel? Und wieso hack?



  • Blue][ce schrieb:

    Bin mir nicht sicher ob das wirklich einen Vorteil bringt.
    Da wäre es doch eher sinnvoll sowas zu machen:

    union_rechnen.c[0] = fgetc(FDatei);
    union_rechnen.c[1] = fgetc(FDatei);
    

    Bin mir nicht sicher, aber das sollte es ein wenig schneller machen...

    Im Gegenteil, es führt zu schlechter Performance, Daten aus dem OS- Filesystem charweise zu holen.
    Ist mir drastisch vor Augen geführt worden, als ich 'ne ASM- Routine ausm Controller unter XP nach C portiert und den Stream zur Simulation aus 'ner Datei geholt habe. Einzelne chars abzuholen und zusammenzubasteln kostet irre Rechenzeit. Bei kleinen Testdatensätzen war's wurscht, weil einem nicht auffällt, ob das Ding 0,1 oder 0,3 Sekunden läuft, bei großen Datenmengen spielt es dann schon eine Rolle, ob das Ding eine halbe oder anderthalb Minuten vor sich hinrattelt.
    Nach Umpacken in eine Struct hat das Ding um Faktor 3 an Tempo zugelegt, ist zwar nur exemplarisch, dürfte sich aber allgemein in der Größenordnung bewegen. Also byteweise vom Filesystem zu lesen, ist ein echter Performancekiller ⚠

    Und die Typkonvertierung über 'ne Union zu machen hat sowieso die von fricky dargelegten Nachteile, so ^^^^^^ würdest Du alle Nachteile vereinen. 🙄



  • Blue][ce schrieb:

    Was ist daran unportabel? Und wieso hack?

    Unportabel deshalb, weil nicht eindeutig festgelegt ist, wie der Compiler seine unions und structs zu organisieren hat. Mit pack- pragmas kannst Du z.B. verschiedene Alignments erzwingen. Heißt, Du kannst nicht davon ausgehen, daß die gleiche Source auf verschiedenen Systemen die gleichen Daten erzeugt, die physikalisch auf Platte landen.
    Noch eine Möglichkeit des Schiefgehens bietet die Little/BigEndian- Problematik.

    So ziemlich alles, was die Source an eine ganz bestimmte Compiler/HW-Plattform- Kombination bindet, bezeichnet man als Hack. In C löst man solche Sachen besser über defines auf, die explizit die Unterschiede klarmacht und schafft sich keine Probleme durch zunächst augenscheinlich unauffällige Codestückchen mitten in der Source.



  • Okay. Man lernt doch jeden Tag was dazu. Ich werd mir das mal durch den Kopf gehen lassen.

    Bezüglich des Einlesens mittels Struct. Da kann ich mir leider garnichts drunter vorstellen. Könntest du ein Beispiel bringen?
    Vielleicht gerade diese kurzen Zeilen ersetzen?

    for(m = 0; m < 2; m++){
        union_rechnen.c[m] = fgetc(FDatei);
    }
    

    Wäre sehr hilfreich, denn solche Stellen habe ich deutlich über 100x in meinem Quelltext und wenn das ein Performancekiller ist wie ihr sagt, wäre das von den ganzen Dingen für mich erstmal das wichtigste.

    Danke.

    Greez,
    Blue][ce



  • Also wenn das was du aus der Datei einliest mehr als zwei Zeichen sind,
    ist eine Optimierung dieser 3 Zeilen ein Tropfen auf den heißen Stein.



  • Diese Zeilen sollen mir ja nur helfen zu verstehen, wie ich das grundsätzlich besser machen kann. Ich will ja was lernen und nicht alles andere machen lassen. Aber mit Beispielen lernt es sich am einfachsten finde ich.



  • also mal im pseudo stil...

    1. wir holen 4096 Zeichen bzw. weniger falls Dateiende aus der Datei und
    speichern sie in nem char*
    2. diesen String bearbeiten wir nun und schieben nach jedem schleifen Durchlauf
    den Zeiger 2 Zeichen vor.
    3. ab zu 1. oder fertig 😉



  • Klingt zwar ganz nett, ist für meinen Fall aber nicht sonderlich praktikabel.Ich muß Dateien mit mehreren 100 MByte verwenden. Von diesen Daten benutze ich aber garnicht alle (nur fast) und leider auch nicht in der Reihenfolge wie sie in der Datei stehen.



  • Ohne die Datensätze zu kennen ists natürlich immer schwierig, dieser Meinung
    bin ich allerdings immer noch, evtl. kann da jemand anders noch was dazu sagen.

    c_newbie schrieb:

    /*
                for(m=0;m<2;m++){
                    union_rechnen.c[m]=fgetc(FDatei);
                } 
    */
    
    fread(union_rechnen.c,sizeof(union_rechnen.c[0]),2,FDatei);
    


  • Blue][ce schrieb:

    Klingt zwar ganz nett, ist für meinen Fall aber nicht sonderlich praktikabel.Ich muß Dateien mit mehreren 100 MByte verwenden. Von diesen Daten benutze ich aber garnicht alle (nur fast) und leider auch nicht in der Reihenfolge wie sie in der Datei stehen.

    Okay, fangen wir mal andersrum an:
    Was genau steht in Deiner Datei überhaupt drin?
    Und worin genau besteht die Nicht- Sequenzialität?

    Du hast zwei eigentlich voneinander unabhängige Probleme, einerseits die Typ- Konvertierung und andererseits den Dateizugriff.

    Beim Dateizugriff ist es performanter, möglichst viele Daten über nur einen fread/fwrite an einen Betriebssystemaufruf zu binden; char- Zugriffe unbedingt meiden, wenn anders möglich.
    Ich habe auch noch nicht ganz kapiert, warum Du nicht gleich union_rechnen.i[0] einlesen kannst, dann steht's ja eh schon als int drin.



  • @pointercrash
    könnt schon sein dass das so besser wär, hast sowas schon mal getestet?
    sonst werd ich das abends mal auf nen benchmark los lassen. könnt aber
    auch identisch sein was ich fast tippen würd.

    fread(union_rechnen.c,sizeof(union_rechnen.c[0])<<1,1,FDatei);
    
    VS
    
    fread(union_rechnen.c,sizeof(union_rechnen.c[0]),2,FDatei);
    

Anmelden zum Antworten