Forum: Mikrocontroller und Digitale Elektronik memcpy vs for-loop bei AVR


von Obs (Gast)


Lesenswert?

Hallo Community,

ich nutze eine AVR-MCU und möchte einen Puffer umkopieren und wollte mal 
fragen, ob es einen großen Performance Unterschied gibt zwischen 
memcpy() und dem "manuellen" umkopieren in einer for-Schleife? Ich weiß, 
dass memcpy für das Umkopieren von Daten hochgradig optimiert sein soll 
und so weiter, aber wollte mal fragen, ob jemand konkret Erfahrung damit 
hat und ob es wirklich so den großen Unterschied macht. Danke schon mal.

von holger (Gast)


Lesenswert?

>in einer for-Schleife?

Ich nehm immer do{}while();
Das ist viel schneller als for() :)

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Obs schrieb:
> aber wollte mal fragen, ob jemand konkret Erfahrung damit
> hat und ob es wirklich so den großen Unterschied macht.

Das kannst Du selbst rausfinden. Schreib Dir Deine Kopierschleife so wie 
Du sie Dir denkst, übersetze das ganze (mit Optimierung) und sieh Dir 
den Assemblercode an, den der Compiler daraus gemacht hat.

Und den vergleichst Du mit dem Sourcecode von memcpy.

von Michael (Gast)


Lesenswert?

Rufus Τ. Firefly schrieb:
> Und den vergleichst Du mit dem Sourcecode von memcpy.

Noch einfacher ist es, wenn du dir im Simulator die Stopuhr anguckst. 
Dann siehst du u.a. direkt die Anzahl der Prozessortakte.

von c.m. (Gast)


Lesenswert?

Rufus Τ. Firefly schrieb:
> sieh Dir
> den Assemblercode an, den der Compiler daraus gemacht hat.

wie eigentlich? braucht man einen speziellen disassembler, oder wird das 
"irgendwie mitgeliefert"?
wäre schon nett den unterschied einer schleife und einem avr equivalent 
von "repz movsb" zu sehen.

von Tom M. (tomm) Benutzerseite


Lesenswert?

c.m. schrieb:
> wie eigentlich? braucht man einen speziellen disassembler, oder wird das
> "irgendwie mitgeliefert"?

Im einfachsten Fall kannst du das Zwischenformat "zurück-übersetzen", 
etwa mittels:

avr-objdump -d meine.elf

von Tom M. (tomm) Benutzerseite


Lesenswert?

holger schrieb:
>>in einer for-Schleife?
>
> Ich nehm immer do{}while();
> Das ist viel schneller als for() :)

Quark, das ist wohl eine urban legend. Zumindest erzeugt mein Compiler 
praktsich identischen Code für beide Konstrukte. Taktzyklen habe ich 
nicht gezählt, aber ich denke das gibt sich nix.

Hast du ein Beispiel, wo du einen signifikanten Unterschied festgestellt 
hast?

von Michael (Gast)


Lesenswert?

c.m. schrieb:
> wie eigentlich? braucht man einen speziellen disassembler, oder wird das
> "irgendwie mitgeliefert"?

Das kommt drauf an, was du geliefert bekommen hast. Bei ATMEL-Studio 6.0 
kannst du dir nach dem Build einfach den List-File (.LSS) ansehen.

von holger (Gast)


Lesenswert?

>Quark, das ist wohl eine urban legend.

Du hast den Smiley übersehen.

von Andreas B. (andreas_b77)


Lesenswert?

Rufus Τ. Firefly schrieb:
> Das kannst Du selbst rausfinden. Schreib Dir Deine Kopierschleife so wie
> Du sie Dir denkst, übersetze das ganze (mit Optimierung) und sieh Dir
> den Assemblercode an, den der Compiler daraus gemacht hat.
>
> Und den vergleichst Du mit dem Sourcecode von memcpy.

Das muss man genauer ausdrücken, den Sourcecode von memcpy gibt es 
unter Umständen so allgemein nicht. Der Compiler kann (und der gcc wird, 
bei eingeschalteter Optimierung) den memcpy Aufruf durch äquivalenten 
Code ersetzen und den Gegebenheiten entsprechend optimieren.

Also die eigene Implementierung vergleichen mit einer Implementierung, 
die memcpy verwendet.


Beispiel:
1
#include <string.h>
2
3
char x[40];
4
char y[40];
5
6
void func(void)
7
{
8
  memcpy(x, y, 40);
9
}

Aus func() macht avr-gcc mit -Os das:
1
  ldi r24,lo8(40)
2
  ldi r30,lo8(y)
3
  ldi r31,hi8(y)
4
  ldi r26,lo8(x)
5
  ldi r27,hi8(x)
6
  0:
7
  ld r0,Z+
8
  st X+,r0
9
  dec r24
10
  brne 0b
11
  ret

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Andreas B. schrieb:
> Das muss man genauer ausdrücken, den Sourcecode von memcpy gibt es
> unter Umständen so allgemein nicht. Der Compiler kann (und der gcc wird,
> bei eingeschalteter Optimierung) den memcpy Aufruf durch äquivalenten
> Code ersetzen und den Gegebenheiten entsprechend optimieren.

Aus
 
1
#include <string.h>
2
#include <stdint.h>
3
4
float next_float (float f)
5
{
6
    uint32_t i;
7
8
    memcpy (&i, &f, sizeof (i));
9
    i++;
10
    memcpy (&f, &i, sizeof (i));
11
    
12
    return f;
13
}

wird zum Beipiel:
 
1
next_float:
2
  subi r22,-1
3
  sbci r23,-1
4
  sbci r24,-1
5
  sbci r25,-1
6
  ret

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.