Schmidt: C - wie Speicher nicht verschwenden? 9-Bit Variable?

Hallo ihr Lieben,

ich programmiere auf einem 8bit Mikroprozessor (ATMega168PA) in der Sprache C. Kompiliere mit GCC für AVR. (WINAVR)

Ich möchte euch um Hilfe zur effizienten Speichernutzung bitten.

Ich muss viele zustände Speichern. Sagen wir für den Anfang ich muss 64 Zustände speichern.
Jeder Zustand enthält 9Bit an Information.
Ich muss in einer Schleife nacheinander auf die gespeicherten Zustände zugreifen können.
Es gibt meines wissens beim GCC für AVR keine 9Bit Variable.

Ich habe zwei Ideen im Kopf.
1. Ich speicher die 9Bit jeweils in einer 16Bit Variable. Diese Variablen wiederum sind bestandteil eines Arrays. So kann ich per Index bequem nacheinander in einer Schleife auf die Variablen zugreifen. -> myVar[i] <- Jedoch verschwende ich für jeden Zustand 7Bit.

2. Ich Speicher die Zustände in Bitfeldern die jeweils 9Bit breit sind. Hat das Speicher gespart? Das Problem ist jedoch, dass ich dann meines Wissens nach nicht in einer Schleife nacheinander auf die Zustände zugreifen kann. Behelfen könnte ich mir mit einem Aray aus Zeigern auf die einzelnen Bitfelder. Aber wenn ein Zeiger selbst mehr als 6Bit Speicherplatz einnimmt, dann komme ich am Ende in der Summe nicht auf weniger Speicherverbrauch.

Desweiteren weiß ich nicht ob bei einer der Methoden nicht ohnehin automatisch noch diverse Zeiger angelegt werden, welche den Speicherbedarf erhöhen.

Könnt ihr meine Ideen beurteilen, verbessern, oder habt ihr eine komplett andere Idee?

Vielen Dank
Schmidt

    1. Ich Speicher die Zustände in Bitfeldern die jeweils 9Bit breit sind. Hat das Speicher gespart?

    Nur wenn du die restlichen 7 Bit auch verwendest.

    Das Problem ist jedoch, dass ich dann meines Wissens nach nicht in einer Schleife nacheinander auf die Zustände zugreifen kann.

    Wenn ich dich richtig verstehe nicht.

    Behelfen könnte ich mir mit einem Aray aus Zeigern auf die einzelnen Bitfelder.

    Nein, die Elemente sind nicht adressierbar (&-Operator verboten)

    Aber wenn ein Zeiger selbst mehr als 6Bit Speicherplatz einnimmt, dann komme ich am Ende in der Summe nicht auf weniger Speicherverbrauch.

    Was sonst.

    Desweiteren weiß ich nicht ob bei einer der Methoden nicht ohnehin automatisch noch diverse Zeiger angelegt werden, welche den Speicherbedarf erhöhen.

    Nein

    Könnt ihr meine Ideen beurteilen, verbessern, oder habt ihr eine komplett andere Idee?

    Macht es Sinn für 64-Byte Daten einen Algorithmus zu entwickeln der sicher viel mehr Code-Speicher kostet?

      1. Ich Speicher die Zustände in Bitfeldern die jeweils 9Bit breit sind. Hat das Speicher gespart?
        Nur wenn du die restlichen 7 Bit auch verwendest.

      Ich dachte an soetwas:

      struct s_matrix {  
      				unsigned z1:9;  
      				unsigned z2:9;  
      				unsigned z3:9;  
      				unsigned z4:9;  
      				unsigned z5:9;  
      				unsigned z6:9;  
      				unsigned z7:9;  
      				unsigned z8:9;  
      				[...]  
      			} invMatrix;  
      			  
      			invMatrix.z1 = 0b101001110;  
      			invMatrix.z2 = 0b111111000;  
      			invMatrix.z3 = 0b101100011;  
      			invMatrix.z4 = 0b110110110;  
      			invMatrix.z5 = 0b101010101;  
      			invMatrix.z6 = 0b011011011;  
      			invMatrix.z7 = 0b110001101;  
      			invMatrix.z8 = 0b011100101;  
      			[...]
      

      Das Problem ist jedoch, dass ich dann meines Wissens nach nicht in einer Schleife nacheinander auf die Zustände zugreifen kann.
      Wenn ich dich richtig verstehe nicht.

      Behelfen könnte ich mir mit einem Aray aus Zeigern auf die einzelnen Bitfelder.
      Nein, die Elemente sind nicht adressierbar (&-Operator verboten)

      Wie funktioniert denn der Zugriff mittels invMatrix.z7 = ...;? Ist das nicht eine Art Zeiger?

      Aber wenn ein Zeiger selbst mehr als 6Bit Speicherplatz einnimmt, dann komme ich am Ende in der Summe nicht auf weniger Speicherverbrauch.
      Was sonst.
      Desweiteren weiß ich nicht ob bei einer der Methoden nicht ohnehin automatisch noch diverse Zeiger angelegt werden, welche den Speicherbedarf erhöhen.
      Nein

      Belegt die Möglichkeit über invMatrix.z7 = ...; auf das 9Bit Feld zuzugreifen also nicht extra Speicher? Beispielsweise den Speicherplatz eines Zeigers.

      Könnt ihr meine Ideen beurteilen, verbessern, oder habt ihr eine komplett andere Idee?
      Macht es Sinn für 64-Byte Daten einen Algorithmus zu entwickeln der sicher viel mehr Code-Speicher kostet?

      STOP MISSVERSTÄNDNIS. Nicht 64Byte Daten sondern 64*9Byte Daten.

      Vielleicht war ich zu allgemein.
      Ich habe eine 3x3Felder (oder nenn es Pixel) große Anzeige mit den Zuständen AN und AUS. Wenn ich nun ein Bild anzeigen möchte, beinhaltet dieses Bild 9Bit Information. 1Bit für jedes Feld.
      Nun möchte ich einen "Film" Speichern und anzeigen. Dieser Film hat 64Bilder (später wohl noch mehr). Ich muss jedes Bild speichern und es dann mittels einer Schleife nacheinander anzeigen.
      Ich habe auf dem Mikroprozessor nur wenig Speicher. Deswegen suche ich nach einer Methode möglichst wenig Speicherplatz zu verschwenden.

      1. Wie funktioniert denn der Zugriff mittels invMatrix.z7 = ...;? Ist das nicht eine Art Zeiger?

        Nein, der Compiler wird dir die 7-ten 9 Bit extrahieren.

        Belegt die Möglichkeit über invMatrix.z7 = ...; auf das 9Bit Feld zuzugreifen also nicht extra Speicher? Beispielsweise den Speicherplatz eines Zeigers.

        Nein, keinen Datenspeicher, dein Code wird allerdings größer.

        STOP MISSVERSTÄNDNIS. Nicht 64Byte Daten sondern 64*9Byte Daten.

        64 mal 9Bit, wird genutzt und 64 mal 16 Bit angelegt? Bleiben knapp 64 Byte verschwendeter Speicher (56 genau). Wenn du also mehr als 56 ASM-Befehle (wenn ich von 1-Byte Befehlsgröße ausgehe, es werden also eher weniger werden) zusätzlich benötigst, um an die Daten zu gelangen, kannst du diese eher in den Flash legen (wobei das sicher auch zusätzlichen code bedeutet).

  1. hi,

    Ich muss viele zustände Speichern. Sagen wir für den Anfang ich muss 64 Zustände speichern.

    Jeder Zustand enthält 9Bit an Information.

    63 Bit brauchst Du da für 7 Zustände...

    Ich muss in einer Schleife nacheinander auf die gespeicherten Zustände zugreifen können.

    Es gibt Bit-Operatoren. Wenn Du einen 64-Bit-Block hast und brauchst die 9 Bit von ganz links, musst Du halt 7*9 Bit nach rechts shiften, legst ne 9 Bit Maske drüber und schon hast Du die Informationen.

    Hotti

  2. Hallo,

    Ich möchte Dir folgendes zu bedenken geben: Prozessoren sind besonders schnell, wenn sie auf Bytegrenzen ausgerichtete Speicherzugriffe machen können. Das heißt: Wenn Du die Werte in 16bit-Variablen abspeicherst, dann ist der Zugriff extrem schnell. Wenn Du dagegen die Werte in 9bit-Bitfeldern abspeicherst (wie hier im Thread vorgeschlagen), dann generiert der Compiler eine ganze Menge zusätzlichen Code, damit er die Daten richtig in die verschiedenen Bits reinquetschen kann. Dieser Code kann die Ausführung *dramatisch* verlangsamen.

    Außer wenn der Speicher wirklich extrem knapp ist und man wirklich keine andere Wahl hat, würde ich *nie* dazu raten, sich nicht an Bytegrenzen zu orientieren. Der Performanceverlust ist einfach zu groß. In der Regel lohnt es sich, die 6 bit einfach wegzuschmeißen.

    Ferner: Wenn Du 64 Zustände speichern musst (lese ich hier irgendwo heraus), wären das bei 16 bit ganze 128 Byte. Bei 9 bit a 64 Zustände wären es ganze 72 Byte. Differenz: 56 Bytes. Wenn Du an vielen Stellen im Code auf Deine Zustände zugreifen musst *und* Du auch noch alle Schleifen manuell ausrollen musst, weil Du ja nicht mehr einfach das über eine Schleife über den Index ansprechen kannst, dann wird der zusätzlich benötigte Programmcode vermutlich *locker* größer als die Differenz von 56 Bytes sein - d.h. den Vorteil in der Datenstruktur schmeißt Du durch einen riesigen Nachteil im Code (Performance + Größe) einfach weg.

    Wenn Du tausende Zustände speichern musst, dann kann es sein, dass es vom Verhältnis Codegröße vs. Datenstrukturgröße sich wieder umkehrt - aber selbst dann bricht Dir die Performance ein.

    Insofern: Außer, Dir geht der Speicher wirklich komplett aus, würde ich das an Deiner Stelle nicht machen.

    Viele Grüße,
    Christian

    1. Vielen Dank!

      Das finde ich sehr interessant und hilfreich.