Forum: Mikrocontroller und Digitale Elektronik uint64_t im ATmega8


von atmega (Gast)


Lesenswert?

Hallo,

kurze Frage zum ATmega8.

Hab in einem Programm ein uint64_t verwendet und dann eine Funktion der 
Art geschrieben, dass überprüft wird, ob ein Bit in einer langen Zahl 
gesetzt ist, oder nicht:

uint64_t Datensatz = (irgendeine_Zahl);

for(j=0; j<64; j++)
{
uint64_t Var = 1;
Var = (Var<<j);

if(Var = Datensatz)
{mache etwas}

else
{mach was anderes}
}

...nur irgendwie ist die Funktion tierisch langsam, so dass ich 
eigentlich den uint64_t im Verdacht habe das Problem zu begünstigen.
Ist das realistisch?

von Klaus W. (mfgkw)


Lesenswert?

"Tierisch" ist ein dehnbarer Begriff, aber ja: uint64_t ist 
vergleichsweise sehr langsam auf AVR.
Aber immer noch schneller, als von Hand, also eher "unmenschlich" 
langsam. "Tierisch" trifft es dann ganz gut.

P.S.: Shiften ist auf AVR ohnehin nicht der Bringer, was Geschwindigkeit 
angeht.

von atmega (Gast)


Lesenswert?

sorry,

ich meinte natürlich in der if-Abfrage das einfache &:

if(Var & Datensatz)
...

von Klaus W. (mfgkw)


Lesenswert?

Am besten ist entweder, auf lange Zahlen zu verzichten (was vielleicht 
kein guter Rat ist; schließlich wirst du einen Grund dafür haben), oder 
du machst dir ein Feld mit 64 Bitmasken: im ersten Element ist das 
unterste Bit gesetzt, im zweiten das nächste usw., und statt bei jedem 
Test die 1 entsprechend weit zu schieben, nimmst du nur das [i]-te 
Element aus dem Feld.
Dann hast du in 64 Bit immerhin nur einen Vergleich, was schon schneller 
gehen wird.

von Falk B. (falk)


Lesenswert?

@atmega (Gast)

>ich meinte natürlich in der if-Abfrage das einfache &:

>if(Var & Datensatz)

Was ist für dich "tierisch langsam" ? Man muss 8 Bytes jeweils 
miteinander vergleichen, das dauer halt mal wenigsten 8 Takte für die 
Vergleiche und je einen Takt pro bedingtem Sprung, macht wenisgten 16 
Takte. Dazu ggf. noch das Lade in die richtgen Register, macht in Summe 
vielleicht 30-50 Takte.

Solche 64 Bit Operationen sind nicht die Kernkompetenz von 8 Bit 
Controllern. Hier ist es oft sinnvoller und leistungsfähiger, die Daten 
als Array von Bytes zu betrachten und zu verarbeiten.

von Stephan B. (matrixstorm)


Lesenswert?

Hallo.

Mir ist vor einer ganze Weile mal aufgefallen,
das mein AVR-gcc fuer ein einfaches 64Bit Increment einen abartig langen 
und komplizierten Maschienencode generiert.

Seh dir mal den fertigen Code deiner Firmware an (objdump).
Vermutlich kannst du ein wenig Performance/Codegroesse durch "manuelles 
compilieren" via "naked" functions und inline assembler herauskitzeln - 
wenn du es dir zutraust...

MfG

von atmega (Gast)


Lesenswert?

...also ich wollte damit ein Signal generieren.

Der Code innerhalb der if/else Anweisung sollte eigentlich nicht länger 
als 15us dauern. Die gesamte for-Schleife zeigt mir aber eine 
Durchlaufzeit von mehr als 200ms, so dass der zusätzliche Zeitbedarf 
wohl aus dem Schieben und dem eigentlichen Vergleich herrührt, 
jedenfalls ist dies meine Vermutung.

Schön, dass andere ähnliche Erfahrungen mit dem uint64_t gesammelt 
haben...

von Markus W. (Firma: guloshop.de) (m-w)


Lesenswert?

Hallo!

atmega schrieb:
> Var = (Var<<j);

Das dauert – wie schon geschrieben wurde – recht lange. Ich würde Var 
lieber global definieren und in der Schleife immer nur um 1 Bit 
verschieben:

  Var<<= 1;


> if(Var = Datensatz)

Gemeint hast du bestimmt das hier:

  if(Var == Datensatz)

von atmega (Gast)


Lesenswert?

>> if(Var = Datensatz)

>Gemeint hast du bestimmt das hier:

>  if(Var == Datensatz)


ne, gemeint war

if(Var & Datensatz)

von Frank (Gast)


Lesenswert?

atmega schrieb:
> ne, gemeint war
>
> if(Var & Datensatz)

Sicher? Nicht eher
1
if (Var && Datensatz)

Frank

von Frank (Gast)


Lesenswert?

Frank schrieb:
> Sicher? Nicht eher
> if (Var && Datensatz)
>
> Frank

Vergiss es .... (Var & Datensatz) past schon ...

von C-Noob (Gast)


Lesenswert?

2 Ideen, die vielleicht helfen könnten:

1: Union benutzen und auf die einzelnen Bytes zugreifen
2: Auf Variable Var verzichten
1
union {
2
  uint64_t Datensatz;
3
  unit8_t Bytes[8];
4
}
5
6
for(j=0; j<8; j++) {
7
  for(k=0; k<8; k++) {
8
    if (Bytes[j] & (1<<k)) {
9
      machewas;
10
      }
11
    else {
12
      machewasanderes
13
      }
14
    }
15
  }

von Falk B. (falk)


Lesenswert?

@ atmega (Gast)

>...also ich wollte damit ein Signal generieren.

Also ein Array von Daten bitweise rausschieben. Das macht man deutlich 
besser mit einem Bytearray, wie bereits gesagt.

>Der Code innerhalb der if/else Anweisung sollte eigentlich nicht länger
>als 15us dauern. Die gesamte for-Schleife zeigt mir aber eine
>Durchlaufzeit von mehr als 200ms, so dass der zusätzliche Zeitbedarf
>wohl aus dem Schieben und dem eigentlichen Vergleich herrührt,
>jedenfalls ist dies meine Vermutung.

Das ist kein echter Code, nur ein hingeschriebenes Fragment. Poste den 
Originalcode OHNE Abschreiben als Anhang.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.