Prozessor Taktzyklen von Funktionen

OP Persönliche Seite #4282025
Lesenswert?

Hallo,
zunächst ich habe mir das Programmieren vor ca 3 Jahren selber 
beigebracht.
Nach dem ich immer mehr dazu lerne und meine Projekte immer größer und 
komplexer werden versuche ich von globalen variablen weg zu kommen.
Jedoch hatte ich bis her die Befürchtung,das Prozessor Laufzeit verloren 
geht, wenn ich eine Funktion mit Übergabe-Parameter erstelle.

Nun meine Frage, wir später auf dem Prozessor dann für die Funktion eine 
zusätzliche variable erzeugt oder wird der Funktion nur die Adresse der 
Variablen übergeben, sodass die Funktion weiß mit welchen Variablen sie 
Arbeiten soll

Über eine Antwort würde ich mich freuen.

Grüße
Basti
Gast #4282033
Lesenswert?

Guten Morgen,

deine Frage ist leider noch zu allg. gefasst, da es hunderte 
Programmiersprachen und Kompilerbauer und Komputer gibt.

Bitte spezifiziere deine Frage und stelle auch noch Beispielcode ein,
dann kann man darauf eingehen.
Moderator (Firma: Titel) Persönliche Seite #4282044
Lesenswert?

Sebastian B. schrieb:
> Jedoch hatte ich bis her die Befürchtung,das Prozessor Laufzeit verloren
> geht, wenn ich eine Funktion mit Übergabe-Parameter erstelle.
Das stimmt auch. Die Stackverwaltung braucht Rechenzeit.

Die letztendlich alleinig interessanten Fragen sind andere: 1. passt das 
Programm wenn es fertig ist noch in den uC? Und: 2. ist es schnell 
genug?

Wenn diese beiden Fragen mit JA beantwortet werden können, dann ist jede 
Sorge um die Programmeffizienz uninteressant.

> Nun meine Frage, wir später auf dem Prozessor dann für die Funktion eine
> zusätzliche variable erzeugt oder wird der Funktion nur die Adresse der
> Variablen übergeben, sodass die Funktion weiß mit welchen Variablen sie
> Arbeiten soll
Zeig mal ein Beispiel, das dazu passt.
#4282054
Lesenswert?

Sebastian B. schrieb:
> Jedoch hatte ich bis her die Befürchtung,das Prozessor Laufzeit verloren
> geht, wenn ich eine Funktion mit Übergabe-Parameter erstelle.

RISC-artige Architekturen wie AVR, ARM oder PIC32 tun sich mit 
Parameterübergabe leichter als mit globalen Variablen.

> Nun meine Frage, wir später auf dem Prozessor dann für die Funktion eine
> zusätzliche variable erzeugt oder wird der Funktion nur die Adresse der
> Variablen übergeben, sodass die Funktion weiß mit welchen Variablen sie
> Arbeiten soll

In FORTRAN wird die Adresse übergeben, in C der Wert wenn es kein Array 
ist.
OP Persönliche Seite #4282060
Lesenswert?

Ich programmiere in C
Bsp.
in beiden Funktionen soll die Variable bearbeitet werden.
ich habe eine Globale Variable (var_glob)
und eine lokale (var_loc)
1
void funktion1(void) 
2
{ 
3
var_glob ++; 
4
} 
5

6
int funktion2 (int XY)
7
{
8
XY ++; 
9
return XY; 
10
}
11

12
Main 
13
{
14
funktion1();
15
var_loc = Funktion2(var_loc);
16
}
meine Frage ist ob beim Funktionsaufruf von Funktion 2 im Prozessor eine 
2. Variable erzeugt wird, die zunächst mit der lokalen Variablen 
gleichgesetzt und so eine bestimmt anzahl von Taktzyklen und zusätzlich 
RAM braucht oder dies nur dazu ist, dass es übersichtlicher wird.

Ich hoffe das meine Frage etwas anschaulicher geworden ist
#4282075
Lesenswert?

Sebastian B. schrieb:
> Wie kommt es das Globale Variablen schlechter verarbeitet werden können
> als lokale?

Parameter und lokale Variablen liegen oft in Registern. Zugriffszeit 0.

Selbst wenn sie auf dem Stack liegen können sie relativ zum Stack- oder 
Framepointer meist direkt adressiert werden, da die Distanz dazu gering 
ist und direkt im Lade/Speicherbefehl codiert werden kann.

Globale und statische Variablen hingegen haben eine recht breite 
Adresse, die viel Platz benötigt und insbesondere bei 32-Bit RISCs nicht 
in einem Befehl direkt verarbeitet werden kann. Bei den Cortex M3 
(Thumb2) sind dann auf Zeit optimiert 3 Befehle nötig. 2 laden die 
Adresse in ein Register und einer spricht darüber den Speicher an. Auf 
Platz optimiert ist es zwar etwas kürzer, sorgt aber ggf. für etliche 
Waitstates aufgrund Datenzugriffs auf das Flash-ROM. In beiden Fällen 
fällt ein zusätzlich verwendetes Register an.

Anders sieht es beispielsweise bei den 8-Bit PICs aus. Die verfügen 
entweder überhaupt nicht über die Fähigkeit, einen Stack anzusprechen, 
oder Zugriff und Verwaltung davon sind relativ aufwändig. 
Optimierungsstrategien für solche nicht auf C optimierte Architekturen 
sind daher deutlich anders als für Standardarchitekturen.
Gast #4282080
Lesenswert?

Sebastian B. schrieb:
> Globale Variablen .... als lokale

Ob man etwas global, oder lokal macht, sollte man davon abhängig machen, 
welche Sichtbarkeit man der Variablen geben muss.
Immer wieder eine gute Strategie: Kapseln!

Um die Taktzyklen, oder den Speicherbedarf, kann man sich einen Kopf 
machen, wenn es eng wird.
#4282088
Lesenswert?

Grundsätzlich gilt: Auf Sprachebene sollte man sich keine Gedanken über 
Optimierung machen, sondern auf gute Strukturierung achten.

Aus zwei Gründen:
- Erstens ist der allermeiste Code in keiner Weise performance-kritisch. 
Ob er doppelt oder zehnmal so lange braucht wie die optimale Lösung, hat 
auf die gefühlte Effizienz des Programms keinerlei Einfluss. Setze also 
die Zeit zum Optimieren genau dort ein, wo du tatsächlich 
Performance-Probleme identifiziert hast.
- Der Compiler optimiert extrem stark und intelligent. Er weiss viel 
besser als du, wie man bestimmte Sprachkonstrukte in effizienten 
Maschinencode umwandelt. Erkläre dem Compiler auf möglichst 
"verständliche" Art, was du haben möchtest und er wird das richtige 
daraus machen.
#4282149
Lesenswert?

Sebastian B. schrieb:
1
> void funktion1(void)
2
> {
3
> var_glob ++;
4
> }
5
> 
6
> int funktion2 (int XY)
7
> {
8
> XY ++;
9
> return XY;
10
> }

> meine Frage ist ob beim Funktionsaufruf von Funktion 2 im Prozessor eine
> 2. Variable erzeugt wird, die zunächst mit der lokalen Variablen
> gleichgesetzt und so eine bestimmt anzahl von Taktzyklen und zusätzlich
> RAM braucht oder dies nur dazu ist, dass es übersichtlicher wird.

Du machst dir Gedanken um nichts. Ein vernünftiger Compiler (das sind 
heutzutage fast alle) wird dir für beide Funktionen praktisch 
identischen Code generieren. Die Variable wird sich vor dem 
Funktionsaufruf in einem Register befinden. Für den Aufruf von funktion2 
wird die Variable in einem Register übergeben und in einem Register 
(meist dem gleichen) zurückgegeben. Der Compiler wird, wenn er clever 
ist, jegliche Register-zu-Register Transfers einsparen, indem er die 
Variable von Anfang an in das richtige Register lädt. Und eine so kurze 
popelige Funktion wie oben wird der Compiler fast sicher sowieso 
inlinen, also gar keinen Funktionsaufruf machen sondern den Rumpf der 
Funktion dort wo sie aufgerufen wird, einfügen.

Du machst dir aber sowieso die falschen Gedanken. Ein Ziel bei der 
Entwicklung höherer Programmiersprachen ist immer auch eine bessere 
Lesbarkeit des Programmcodes. Und Lesbarkeit meint nicht nur lesbar, 
sondern auch: von vorn herein leichter schreibbar, leicher debugbar, 
leicher zu warten und zu pflegen. Und die Vermeidung globaler Variablen 
dient ebenfalls diesem Zweck.

Wenn du in einer Hochsprache programmierst, dann sollte die Effizienz 
des vom COmpiler erzeugten Codes so ziemlich das Letzte sein, an das du 
beim Schreiben des Programmes denkst. Achte lieber darauf daß es 1. 
korrekt und 2. lesbar ist.

Optimierung auf Geschwindigkeit findet meist auf höheren Ebenen statt, 
z.B. indem man einen anderen Algorithmus implementiert. Mikrooptimierung 
wie du sie hier betreiben willst, ist in 99% aller Fälle vollkommen 
unnötig. Anders ausgedrückt: Quicksort ist nicht deswegen schneller als 
Bubblesort, weil es globale statt lokaler Variablen verwendet, sondern 
weil es einen [für größere Datenmengen] besseren Algortihmus verwendet.
Moderator (Firma: Titel) Persönliche Seite #4282535
Lesenswert?

Moby A. schrieb:
> Lothar M. schrieb:
>> Die letztendlich alleinig interessanten Fragen sind andere: 1. passt das
>> Programm wenn es fertig ist noch in den uC? Und: 2. ist es schnell
>> genug?
> Beides stellst Du zuallererst mit (gutem) Assembler sicher.
Das ist hier in keinster Weise die Frage!

Ich werde in Zukunft jeden Versuch, einen Thread zu entführen einfach 
per Löschung unterbinden. Leute, tut mir leid für eure Zeit zum 
Schreiben der Beiträge, die auf diesen Trollaufruf folgten. Lasst es 
einfach bleiben und meldet solche Entführungsversuche per Knopfdruck.
#4282769
Lesenswert?

Axel S. schrieb:
> Optimierung auf Geschwindigkeit findet meist auf höheren Ebenen statt,
> z.B. indem man einen anderen Algorithmus implementiert. Mikrooptimierung
> wie du sie hier betreiben willst, ist in 99% aller Fälle vollkommen
> unnötig. Anders ausgedrückt: Quicksort ist nicht deswegen schneller als
> Bubblesort, weil es globale statt lokaler Variablen verwendet, sondern
> weil es einen [für größere Datenmengen] besseren Algortihmus verwendet.

Mikrooptimierung ist schon wichtig, aber man macht es nicht von Hand, 
sondern der Compiler macht es. Wenn man beispielsweise eine 
mathematische Formel in einer Schleife auswertet, so gewinnt man 
Zehnerpotenzen an Performance dadurch, dass die einzelnen Funktionen 
ge-inlined und nicht separat aufgerufen werden.
#4282810
Lesenswert?

P. M. schrieb:
> Axel S. schrieb:
>> Optimierung auf Geschwindigkeit findet meist auf höheren Ebenen statt,
>> z.B. indem man einen anderen Algorithmus implementiert. Mikrooptimierung
>> wie du sie hier betreiben willst, ist in 99% aller Fälle vollkommen
>> unnötig. Anders ausgedrückt: Quicksort ist nicht deswegen schneller als
>> Bubblesort, weil es globale statt lokaler Variablen verwendet, sondern
>> weil es einen [für größere Datenmengen] besseren Algortihmus verwendet.
>
> Mikrooptimierung ist schon wichtig, aber man macht es nicht von Hand,
> sondern der Compiler macht es.

Und man betreibt natürlich auch nicht sinnlos kompliziertes 
Programmieren, sondern benutzt normales, übliches Vorgehen. In diesem 
Sinne muss man ein generelles "mach dir keine Sorgen, der Compiler wirds 
schon richten" auch zurechtrücken.
Eng damit im Zusammenhang steht natürlich auch, dass man seine 
Programmiersprache einigermassen beherrscht. Wer von seiner Sprache 
gerade mal 10% des Sprachumfangs kennt, und das auch nur mehr schlecht 
als recht, wird nicht viel zu Stande bringen - mit oder ohne 
Mikrooptimierung.
#4282851
Lesenswert?

P. M. schrieb:
> Axel S. schrieb:
>> Optimierung auf Geschwindigkeit findet meist auf höheren Ebenen statt,
>> z.B. indem man einen anderen Algorithmus implementiert. Mikrooptimierung
>> wie du sie hier betreiben willst, ist in 99% aller Fälle vollkommen
>> unnötig

> Mikrooptimierung ist schon wichtig, aber man macht es nicht von Hand,
> sondern der Compiler macht es.

Ich dachte es wäre im Kontext klar gewesen, daß ich manuelle Mikro- 
optimierung gemeint habe. Und nicht das was der Compiler tut.
#4282871
Lesenswert?

Axel S. schrieb:
> Ich dachte es wäre im Kontext klar gewesen, daß ich manuelle Mikro-
> optimierung gemeint habe. Und nicht das was der Compiler tut.

Ich habe es vermutet, ja. Wollte aber sicher gehen und noch ein paar 
Worte anfügen, da der TO sich damit scheinbar noch wenig auskennt.

Karl H. schrieb:
> Eng damit im Zusammenhang steht natürlich auch, dass man seine
> Programmiersprache einigermassen beherrscht. Wer von seiner Sprache
> gerade mal 10% des Sprachumfangs kennt, und das auch nur mehr schlecht
> als recht

Richtig. Besonders sollte man auch wissen, was in einer Sprache 
teuer/problematisch ist. In C/C++ beispielsweise dynamische 
Speicherallokation oder versehentliches pass-by-reference von grossen 
Objekten. Genau aus diesem Grund halte ich es für sinnvoll, eine Sprache 
tiefer kennen zu lernen als bloss die Sprachkonstrukte und 
Bibliotheksaufrufe kennen zu lernen. Man muss wissen, was unter der 
Haube passiert.
Gast #4282925
Lesenswert?

A. K. schrieb:
> Parameter und lokale Variablen liegen oft in Registern. Zugriffszeit 0.

Hehe.. du hast heut wohl nen eher schlechten Tag. Von wegen Zugriffszeit 
0 - das Argument muß ja erstmal dort hinein kommen.

Ich halte das Herumgefummel mit Funktionsargumenten dort, wo es nicht 
sein muß, für einen ziemlich überflüssigen Kropf. Es bringt nix und 
kostet bloß bei jedem Aufruf der betreffenden Funktion das Laden des 
Argumentes.

Viel wichtiger als all das Grübeln über globale Variablen oder nicht ist 
es, eine Firmware sinnvoll zu modularisieren, so daß man nicht das ganze 
Gekröse an Variablen und anderem Krempel überall um die Ohren hat. Was 
dann an globalen Variablen wirklich noch übrig bleibt, ist fast immer 
nur ganz wenig - und das Wenige hat dann seine Berechtigung.

W.S.
Gast #4282993
Lesenswert?

A. K. schrieb:

> Parameter und lokale Variablen liegen oft in Registern. Zugriffszeit 0.

Nanana.

Ganz so einfach ist das natürlich nicht. Das hängt leider von sehr 
vielen Variablen ab. Klar: Sprache, Compiler, Optimierungslevel. Darüber 
hinaus aber auch noch massiv vom Zielsystem. Wenn das einfach mal nur 
wenige Register besitzt, ist nicht damit zu rechnen, daß viele für die 
Parameterübergabe genutzt werden (können). Und leider setzt bei den oft 
relativ starren Algorithmen der Codegeneratoren die Stacknutzung oft 
schon ein, lange bevor die Register "alle" sind.

Abgesehen davon: Natürlich ist auch ein Registerzugriff nicht zum 
Nulltarif zu bekommen. Nicht mal in Assembler...
#4283009
Lesenswert?

W.S. schrieb:
> Hehe.. du hast heut wohl nen eher schlechten Tag. Von wegen Zugriffszeit
> 0

Welche Zahl wär dir lieber, wenn man mal davon ausgeht, dass RAM bei µCs 
einen Takt Zugriffszeit hat? Ein Register hat mindestens bei den RICSs 
weniger Zugriffszeit als das RAM und negativ wirds nicht. Bei CISCs mit 
darauf optimierter Pipelining kann man zwar was einsparen, aber so arg 
viele µCs dieser Bauart fallen mir grad nicht ein.

> das Argument muß ja erstmal dort hinein kommen.

Korrekt. Das ist aber hauptsächlich dann von Vorteil, wenn die Funktion 
die Variable überhaupt nicht benötigt.

Ich hatte oben schon aufgeführt, dass ich mich in dieser Betrachtung 
eher auf registerorientierte Architekturen beziehe. Bei 8-Bit 
PIC/8051/68xx kann die Sache anders ausgehen.

> Ich halte das Herumgefummel mit Funktionsargumenten dort, wo es nicht
> sein muß, für einen ziemlich überflüssigen Kropf. Es bringt nix und
> kostet bloß bei jedem Aufruf der betreffenden Funktion das Laden des
> Argumentes.

Klar, 0 Parameter sind schneller als 1 Parameter. Aber das ist hier 
nicht die Alternative. Sondern Parameter gegenüber globaler Variable. 
Und da hat der (skalare) Parameter noch einen weiteren Vorteil, wenn 
davon nirgends die Adresse verlangt wird: Weder kann Aliasing auftreten, 
noch wird er in einem Unterprogramm verändert.

> Viel wichtiger als all das Grübeln über globale Variablen oder nicht ist
> es, eine Firmware sinnvoll zu modularisieren, so daß man nicht das ganze
> Gekröse an Variablen und anderem Krempel überall um die Ohren hat.

Modularisierung vermeidet keine Variablen, sondern platziert sie 
übersichtlicher im Quellcode und adressiert sie evtl anders. Das kann in 
Verbindung mit struct/class zu relativer Adressierung von Variablen 
führen, die sonst absolut adressiert würden. Was meist ein klarer 
Vorteil ist, es sei denn der Prozessor tut sich damit schwer. Nur hatte 
ich diese bei µC-Programmierung in C++ häufiger als in C verbreitete 
Technik hier erst einmal aussen vor gelassen.

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