Takte pro Befehl

Gast #2529071
Lesenswert?

Servus,
Ich programmiere gerade ein sehr "hochfrequentes" Programm.
Ich würde gerne wissen wieviel Takte bzw. Instruktionen für eine 
if-Abfrage und eine hochzählende for-Schleife benötigt werden.
Hier die Codeschnipsel:
1
if(abl2_A <= 0.005 && abl2_B <= 0.005){
abl2_A und abl2_B sind vom Typ double.
Und die for-Schleife:
1
for(i=0;i<=16;i++){
2
  data[i] = data[i+1];
3
}
i und data sind beide integer.
Gast #2529223
Lesenswert?

Diddi schrieb:
> Ich programmiere gerade ein sehr "hochfrequentes" Programm.
> Ich würde gerne wissen wieviel Takte bzw. Instruktionen für eine
> if-Abfrage und eine hochzählende for-Schleife benötigt werden.

Die Zahl der Taktzyklen der for-Schleife dürfte im Vergleich zu den 
floating-point-Berechnungen auch nicht mehr weiter auffallen.
Gast #2529298
Lesenswert?

Mich würde mal interessieren, was sinnvoller/effektiver ist:

[unter der Annahme das data ein 8Bit-Wert sit]

Das:
1
for(i=0;i<=16;i++)
2
{
3
  data[i] = data[i+1];
4
}

oder das:
1
i=0;
2
k=1;
3
while ( i != 16 )
4
{
5
  data[i++] = data[k++]
6
}

Also ich meine, eine Variable mit plus_eins, oder lieber zwei 
Hilfszähler..?
Gast #2529339
Lesenswert?

Matthias Lipinsky schrieb:
> Also ich meine, eine Variable mit plus_eins, oder lieber zwei
> Hilfszähler..?

Am besten der Vorschlag von Jörg. Dann kann der Compiler sich drum 
kümmern, das möglichst effizient zu machen. Deine Schleifen werden beide 
im Bestfall vom Compiler automatisch durch memmove ersetzt, im 
schlechtesten Fall behindern sie die Optimierung.
Gast #2529996
Lesenswert?

Nur aus Interesse:
Warum ist die memmove Methode schneller?

Die wird doch intern auch mit irgend einer Art Schleife arbeiten, 
zusätzlich kommt noch der Funktionsaufruf und die sizeoff-Berechnung.

Klärt mich auf :-)
Moderator Persönliche Seite #2530045
Lesenswert?

Masl schrieb:
> Warum ist die memmove Methode schneller?

Sie ist nicht per se schneller, hat aber die Chance, handoptimierten
Code zu benutzen, und sie ist halt standardisiert.  Solange du nicht
mit -ffreestanding arbeitest, darf dabei der Compiler auch statt der
Bibliotheksfunktion eine eigene Implementierung liefern, falls er der
Meinung ist, damit günstiger zu fahren.

Im vorliegenden Fall ist der Compiler mit dem expliziten C-Code
tatsächlich gar nicht so schlecht.
#2530089
Lesenswert?

Masl schrieb:
> Nur aus Interesse:
> Warum ist die memmove Methode schneller?

Ist sie nicht notwendigerweise

> Die wird doch intern auch mit irgend einer Art Schleife arbeiten,
> zusätzlich kommt noch der Funktionsaufruf und die sizeoff-Berechnung.
>
> Klärt mich auf :-)

Weil sie vom Compilerhersteller auf deine µC, dein Board, deinen 
speziellen Computer angepasst werden kann. Wenn dein Rechner über einen 
DMA Kanal verfügt, könnte der Compiler auch soweit gehen, den Transfer 
gar nicht über die CPU abzuarbeiten, sondern über DMA oder irgendwelche 
anderen Mechanismen, die du mit einer simplen Schleife nicht aktivieren 
kannst.
Persönliche Seite #2530251
Lesenswert?

Karl Heinz Buchegger schrieb:

> Wenn dein Rechner über einen DMA Kanal verfügt,
> könnte der Compiler auch soweit gehen, den Transfer
> gar nicht über die CPU abzuarbeiten, sondern über DMA oder irgendwelche
> anderen Mechanismen, die du mit einer simplen Schleife nicht aktivieren
> kannst.

Es gibt Compiler, die memmove auf DMA abbilden??? Schwer vorzustellen.
#2530288
Lesenswert?

Johann L. schrieb:

>> gar nicht über die CPU abzuarbeiten, sondern über DMA oder irgendwelche
>> anderen Mechanismen, die du mit einer simplen Schleife nicht aktivieren
>> kannst.
>
> Es gibt Compiler, die memmove auf DMA abbilden??? Schwer vorzustellen.

Warum soll das schwer vorstellbar sein?
memmove ist eine Bibliotheksfunktion mit definierter Funktionalität. 
Wenn der Hersteller einen Weg findet, das schneller als mit einer 
CPU-Schleife zu machen, dann kann er das tun.
Persönliche Seite #2530301
Lesenswert?

Jörg Wunsch schrieb:
> Johann L. schrieb:
>> Es gibt Compiler, die memmove auf DMA abbilden??? Schwer vorzustellen.
>
> Zumindest könnte eine Bibliotheksfunktion das problemlos tun.

Es geht weniger darum, ob sie es prinzipiell tun kann oder nicht, 
sondern ob es zum Standard passt, wenn die Implementierung damit 
beginnt, Hardware auf diese Weise zu verwenden und zu programmieren.
#2530326
Lesenswert?

Johann L. schrieb:

> Es geht weniger darum, ob sie es prinzipiell tun kann oder nicht,
> sondern ob es zum Standard passt, wenn die Implementierung damit
> beginnt, Hardware auf diese Weise zu verwenden und zu programmieren.

Johann, jetzt muss ich mich aber wundern.
Du weißt doch am allerbesten, dass der C-Standard so gut wie nichts über 
Hardware aussagt.

Aber: anderes Beispiel
Im Z80 gab es die Instruktionen LDIR, LDDR, etc. Ihre Funktion war 
prinzipiell die eines Block-Shifts. HL, DE, BC sind CPU-Register

ein LDIR machte (in relaxter Assembler / C Mischnotation)

1:  *(DE) = *(HL)
    HL++
    DE++
    BC--
    if BC == 0
      goto 1


wieviele Takte pro transferiertem Byte notwendig waren weiß ich nicht 
mehr. Es waren auf jeden Fall wesentlich weniger, als wie wenn man das 
selber ausprogrammiert.


Ob heutige Compiler eine Schleife

    for( i = 0; i < 100; i++ )
      dest[i] = src[i]

auf einem Z80 in

   LD  DE, #dest
   LD  HL, #src
   LD  BC, 100 * sizeof(*dest)
   LDIR

übersetzen würden, kann ich nicht sagen. Wohl auch deswegen, weil es 
kaum noch Z80 C-Compiler gibt. Aber in einem memmove ist das eine 
leichte Übung.
#2530546
Lesenswert?

Anderes Beispiel:

Die (alten) EZ-USB Chips hatten einen 8051er Befehlssatz, dort war das 
Speicher-Umkopieren über eine Schleife zu langsam für die erwünschte 
USB-Performance.

Deshalb gabs als Erweiterung die autopointer/autodata Register.
(siehe Datenblattschnippsel).

Der Compiler kannte die nicht und konnte die folglich auch nicht 
selbständing für die Optimierung einsetzen, aber innerhalb der lib 
konnte man die problemlos in memmove, memcpy, memset, strlen usw. 
verwursten.
Angehängte Dateien:
Persönliche Seite #2530728
Lesenswert?

Karl Heinz Buchegger schrieb:
> Johann L. schrieb:
>
>> Es geht weniger darum, ob sie es prinzipiell tun kann oder nicht,
>> sondern ob es zum Standard passt, wenn die Implementierung damit
>> beginnt, Hardware auf diese Weise zu verwenden und zu programmieren.
>
> Johann, jetzt muss ich mich aber wundern.
> Du weißt doch am allerbesten, dass der C-Standard so gut wie nichts über
> Hardware aussagt.

Der C-Standard ist eine Sache. Aber was bringt ein Compiler, der das, 
was nicht durch den Standard abgedeckt ist, zu 100% ausnutzt?

Ein Programmierer, der ein C Programm schreibt, braucht 3 Dinge:
1) Einen Sprachstandard, der Syntax und Semantik beschreibt.
2) Ein Compiler, der sich daran hält.
3) Ein Compiler, der "vernünftigen" Code erzeugt.

Je mehr Unwärbarkeiten des Standards ein Compiler ausschöpft, desto 
weniger wird 3) erfüllt sein. Der Compiler wäre dann zwar immer noch 
standardkonform, aber niemand würde ihn einsetzen, da witzlos.

Wem würde solch ein Compiler nutzen?

Beispiel: "volatile" wird durch die Implementierung definiert, mithin 
auch die Semantik von (mit der üblichen Definition von POTRC):

>> PORTC = 0;

Zunächst wird 0 nach PORTC geschrieben. Weil "PORTC = 0" ein Ausdruck 
ist, der auszuwerten ist und PORTC volatile ist, wird PORTC wieder 
zurückgelesen, analog zu

>> (void) PORTC;

oder

>> char a = PORTC = 0;

Das alles wäre durch den Standard abgedeckt. Aber würde irgendjemand das 
wollen? Ich behaupte: Nein.

Stell dir einfach vor, PORTC ist ein Latch.

Ergo: Den Standard zu erfüllen ist nicht alles. Wenn ein Compiler dabei 
rauskommt, der praktisch unbenutzbar ist, ist der Compiler zu 100% 
unbrauchbar und keinem gedient.

Nehmen wir also mal an, die Verwendung einer DMA sei transparent, d.h. 
deren Verwendung ist ausserhalb der abstrakten Maschine nicht 
wahrnehmbar. Dies bedeutet insbesondere, daß eine memmove Operation 
atomar ablaufen muss.

Ich stelle meine Frage also etwas anders: Ist eine DMA in memmove 
vorstellbar, so daß deren Verwendung nicht aus der abstrakten Maschine 
"entkommt" und zusätzlich 3) erfüllt bleibt?
#2530791
Lesenswert?

Johann L. schrieb:

> Ich stelle meine Frage also etwas anders: Ist eine DMA in memmove
> vorstellbar, so daß deren Verwendung nicht aus der abstrakten Maschine
> "entkommt" und zusätzlich 3) erfüllt bleibt?

Atomare Ausführung aus Sicht der virtuellen Maschine ist nicht in jedem 
Fall zwingend. Die Nebenläufigkeit von DMA ist so lange kein Problem, 
wie der Compiler an passender Stelle auf dessen Beendigung wartet. Er 
könnte also den Transfer starten und mit anderem Code weiter machen, bis 
irgendwann einer der beiden Speicherbereiche benötigt wird oder er dies 
zumindest in Betracht ziehen muss.

Solange währenddessen nur lokale Daten ohne erforderliche Adresse 
verarbeitet werden ist das kein Problem, da es keine Überschneidung 
geben kann. Nur bei globalen Daten, und solchen deren Adresse irgendwo 
vorkommt, wird es komplizierter. Da besteht eine gewisse Verwandschaft 
zur Handhabung von potentiellem Aliasing bei Pointern.

Das ist im Grunde nicht viel anders als anno 8086, als der 8087 
Koprozessor seine Speicheroperationen nebenläufig durchführte und erst 
der WAIT-Befehl wieder für Ordnung sorgte (vgl. Warten auf Ende vom DMA, 
plus Barrier-Befehl).

Allerdings ist das natürlich eine sehr akademische Diskussion. Denn wer 
einigermassen bei Verstand ist, der programmiert so etwas explizit, 
statt es in einem Compiler einzubauen. Heutige und denen ähnliche 
Architekturen vorausgesetzt.

Und bei jenen Zwergen wie dem erwähten 51er, bei dem es sich ggf. lohnen 
kann weil die programmierte Version viel langsamer ist, ist eine rein 
atomare Version, also mit sofortigem Warten auf Beendigung, auch schon 
sinnvoll. Nebenläufigkeit erwartet man in solchem Kontext wohl nicht 
wirklich.
Persönliche Seite #2531258
Lesenswert?

Diddi schrieb:
> Servus,
> Ich programmiere gerade ein sehr "hochfrequentes" Programm.
> Ich würde gerne wissen wieviel Takte bzw. Instruktionen für eine
> if-Abfrage und eine hochzählende for-Schleife benötigt werden.
> Hier die Codeschnipsel:
>
> [...] double [...]

Diddi schrieb:
> ATmega8 mit 16Mhz

*hüstel* 

Du verwendest also double auf einem ATmega8 und machst dir nen Kopf um 
eine if-Abfrage?

Bevor du anfängst an der if-Abfrage zu knaupen solltest du dir 
überlegen, *wo* die Zeit für dein "hochfrequentes" Programm denn 
verloren geht.

Erst profilen. Dann optimiern. Und zwar das, was dir die Ressource 
frisst.

Wenn etwas im Code zB 90% der Resource braucht und das 10% besser wird, 
bringt das 9× mehr, als etwas das nur 1% braucht um 99% zu verbessern!
Gast #2532845
Lesenswert?

Danke für die vielen Antworten.
Ich habe mein Programm mal analysiert mit der Stop Watch stelle aber 
keinerlei Unterschied zwischen double und float fesst. Float(4 Byte) 
müsste doch deutlich schneller sein wie double(8 Byte). Dies ist 
allerdings nicht der Fall. Leider kann ich nicht auf die Fließkomma 
Berechnungen verzichten.
Gast #2533184
Lesenswert?

Floh schrieb:
> Schau dir das Assemblerlisting an und zähle laut Datenblatt die
> benötigten Takte zusammen.

Wenn man nicht ganz so masochistisch veranlagt ist, kann man auch die 
Stop-Watch in AVR-Studio benutzen und dort im Simulator die Anzahl der 
benötigten Taktzyklen ablesen.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren