Forum: Mikrocontroller und Digitale Elektronik Memset via schleife


von Michael (Gast)


Lesenswert?

Hallo,


ich möchte die variable cache mit 0x00 initialisieren.
Kann mir jemand kurz erläutern welche Variante die bessere oder 
schnellere ist?
1
char cache[1024];
2
3
//Variante 1
4
for (int i=0;i<1024;i++)  cache[i] =0x00;
5
6
//Variante 2
7
memset(cache,0x00,sizeof(cache));

HW: ATMEGA128

von Rolf Magnus (Gast)


Lesenswert?

Ich würde schätzen, daß auf einem AVR beide gleich schnell sind.
Es würde mich nicht wundern, wenn der Compiler erkennt, was die 
for-Schleife tut und diese automatisch durch einen memset-Aufruf 
ersetzt. Dieser wiederum wird (zumindest bei GCC) vom Compiler selbst 
intern dann in die optimale Variante für den jeweiligen Prozessor 
umgesetzt.

von Falk B. (falk)


Lesenswert?

@ Rolf Magnus (Gast)

>Ich würde schätzen, daß auf einem AVR beide gleich schnell sind.

ICh würde schätzen, dass memset() schneller ist, weil es handoptimiert 
ist (ASM?).

>Es würde mich nicht wundern, wenn der Compiler erkennt, was die
>for-Schleife tut und diese automatisch durch einen memset-Aufruf
>ersetzt.

Würde ich nicht drauf spekulieren.

> Dieser wiederum wird (zumindest bei GCC) vom Compiler selbst
>intern dann in die optimale Variante für den jeweiligen Prozessor
>umgesetzt.

Praktisch. Simulier einfach mal beide im AVR Studio und schau dir die 
benötigten Taktzyklen an.

MFG
Falk

von Rolf Magnus (Gast)


Lesenswert?

> ICh würde schätzen, dass memset() schneller ist, weil es handoptimiert
> ist (ASM?).

Naja, beim AVR gibt's nicht viele Möglichkeiten, einen Speicherblock zu 
kopieren, und der C-Code für die Schleife ist so einfach, daß ich schon 
mit einem optimalen Ergebnis gerechnet hätte.

> Simulier einfach mal beide im AVR Studio und schau dir die
> benötigten Taktzyklen an.

Ich habe kein AVR-Studio, aber ich kann mir den ASM-Code anschauen:

For-Schleife:
1
        ldi r30,lo8(cache)
2
        ldi r31,hi8(cache)
3
.L2:
4
        st Z+,__zero_reg__
5
        ldi r24,hi8(cache+1024)
6
        cpi r30,lo8(cache+1024)
7
        cpc r31,r24
8
        brne .L2

memcpy:
1
        ldi r24,lo8(1024)
2
        ldi r25,hi8(1024)
3
        ldi r30,lo8(cache)
4
        ldi r31,hi8(cache)
5
        st Z+,__zero_reg__
6
        sbiw r24,1
7
        brne .-6

Die memcpy-Variante ist tatsächlich pro Durchlauf einen Taktzyklus 
schneller, aber nur weil bei der for-Schleife das Register r24 in jedem 
Schleifendurchlauf unnötigerweise neu geladen wird. Sonst wären die 
beiden gleich schnell.

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.