PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Compileroptimierung temporärer Variablen in C


Gast
2009-03-14, 10:21:36
Hallo,

Eine kleine Frage zur Compileroptimierung für die Programmiersprache C:
In meinem Algorithmus (komplexe Gaphtraversierung eines "großen" Graphen) benötige ich viele temporäre Variablen.
Vom Datentyp sind das einfache Ganzzahlen (Int) bishin zu Warteschlangen von Stapeln (oder queues von stacks :-) ).
Um die Lesbarkeit des Codes zu erhöhen, habe ich in den verschiedenen Algorithmusabschnitten die Variablen über #defines "wiederverwendet".




int eineTempwarmitnichtpassendemNamenA;
complexDataType eineTempVarMitNichtPassendemNamen;

/* .. */

//ein neuer Algorithmus(teil)abschnitt fängt an
#define eineNeueTempVarMitPassendemNamen eineTempVarMitNichtPassendemNamen


/* ... */

#undef eineNeueTempVarMitPassendemNamen
//ein neuer Algorithmus(teil)abschnitt hört auf

/* ... */



Mehrfach wurde mir erzählt, ich kan mir beliebig viele temporäre Variablen deklarieren - der Compiler verwendet nur soviel Heap/Stack/Register wie nötig.
Nun bin ich nicht vom Fach und habe vom Übersetzerbau bis auf ein paar Grundlagen nicht so den Plan.
Kann ich davon ausgehen, das ein "Standard" C-Compiler immer und überall temporäre Variablen "wegoptimiert" (Das scheint mir nämlich auf den ersten Blick nicht trivial) oder soll ich es lieber so lassen?
Wenn jemand dazu noch eine Literaturempfehlung dazu hätte, wäre ich dankbar!

RMC
2009-03-14, 11:19:33
Um die Lesbarkeit des Codes zu erhöhen, habe ich in den verschiedenen Algorithmusabschnitten die Variablen über #defines "wiederverwendet".


Ich bezweifle stark, dass damit die Lesbarkeit erhöht wird.

Vorallem die Wartbarkeit wird damit ein Graus, wenn du quer durch dein Programm die Bezeichner deiner Variablen re-deklarierst.

Wenn du nicht passende Namen hast, solltest du dir zunächst mal überlegen, warum das überhaupt soweit kommt und lieber dort den Rotstift ansetzen ;)

Ansonsten kannst du immernoch Funktionen machen, wo du innerhalb dann andere Bezeichner hast. Aber bitte lass die Finger von Präprozessoranweisungen für die Umbenennung von Variablen, das ist ein Unding.

Gast
2009-03-14, 11:45:29
Ich bezweifle stark, dass damit die Lesbarkeit erhöht wird.
Vorallem die Wartbarkeit wird damit ein Graus, wenn du quer durch dein Programm die Bezeichner deiner Variablen re-deklarierst.


Naja ist ja nicht quer durchs Programm sondern nur in einer (ziemlich großen und laufzeitkritischen) Funktion die einen Algorithmus implementiert und in begrenzten Algorithmus"abschnitten" (zwischen #define und #undef liegen wenige Zeilen Code) (siehe auch unten)



Wenn du nicht passende Namen hast, solltest du dir zunächst mal überlegen, warum das überhaupt soweit kommt und lieber dort den Rotstift ansetzen ;)

das war ja meine Frage. Ich hab schon passende Namen. Nur nicht an den richtigen Stellen :-)
Ein Beispiel: wenn ich einen Subgraph traversiere benötige ich einen Stapel.
Diesen Stapel verwende ich in einem anderen Abschnitt um beispielsweise Knoten zu markieren.
Im ersten Fall heißt dieser vielleicht "travStck" im anderen "markStck".


Ansonsten kannst du immernoch Funktionen machen, wo du innerhalb dann andere Bezeichner hast. Aber bitte lass die Finger von Präprozessoranweisungen für die Umbenennung von Variablen, das ist ein Unding.
Klar so macht man das ja auch, aber "inline"-Funktionen gibt es ja in C nicht und der Overhead eines Funktionsaufrufs ist mir einfach zu groß.
Deshalb ja die Frage bzgl. der Compileroptimierung.

RMC
2009-03-14, 12:44:27
das war ja meine Frage. Ich hab schon passende Namen. Nur nicht an den richtigen Stellen :-)
Ein Beispiel: wenn ich einen Subgraph traversiere benötige ich einen Stapel.
Diesen Stapel verwende ich in einem anderen Abschnitt um beispielsweise Knoten zu markieren.
Im ersten Fall heißt dieser vielleicht "travStck" im anderen "markStck".

Ich verstehe dein Problem :)

Trotzdem würde ich, wenn es geht, diese Anweisungen eher nicht machen, auch wenn es nur an einer Stelle ist. Das wird schnell zur unsauberen Bequemlichkeit.

Ich würde Versuchen, den Namen allgemein zu halten. Da du ja mehrere Operationen darauf anwendest wär es ein Overkill, den Stack dafür jedesmal umzubenennen auf "sortStack", "traverseStack", "markStack", .. ;)

Ein einfaches "subgraphStack" reicht dazu aus. Ich kenne jetzt dein Anwendung nicht genau, aber da könnte man noch genauer definieren, welchen Abschnitt dieser Subgraph beinhaltet.



Klar so macht man das ja auch, aber "inline"-Funktionen gibt es ja in C nicht und der Overhead eines Funktionsaufrufs ist mir einfach zu groß.
Deshalb ja die Frage bzgl. der Compileroptimierung.

Ich halte einen zusätzlichen Funktionsaufruf weniger für einen Overkill als für eine strukturelle und übersichtliche Notwendigkeit.

Du kannst ja den Graphen auch per Referenz übergeben und musst ihn ja nicht kopieren, wenn das dein Bedenken ist.

maximAL
2009-03-14, 13:26:22
Klar so macht man das ja auch, aber "inline"-Funktionen gibt es ja in C nicht
das schlüsselwort vielleicht nicht, aber inlinen kann der compiler natürlich trotzdem.

noid
2009-03-15, 10:03:46
das schlüsselwort vielleicht nicht, aber inlinen kann der compiler natürlich trotzdem.

inline ist sehr wohl auch ein C-Schlüsselwort (zB GNU C, C99). Muss ja nicht immer Ansi-sein.

@eigentliches Topic:
Eigentlich optimiert so gut wie jeder guter Compiler dir die Zwischenvariablen weg, wenn du entsprechende Optimierungen an hast und
nicht gerade eine Debugversion erstellst.
Bei den Compilern die ich verwende hat man idR sich den Kram aus den Registern des Prozessors dann herauszufischen ;(

Nasenbaer
2009-03-15, 23:06:13
Ich kann den anderen nur zustimmen. Am wichtigsten ist Wartbarkeit und darum sollte man den Code vorallem gut lesen können. Wenn es dann Performanceprobleme gibt kann man immer noch einen Profiler nutzen.
Und wegoptimieren der temporären Variablem sollte auch nicht das Problem sein, wobei ich den Algorithmus aber auch eher in Funktionen aufteilen würde. So ein Function-Call ist sicher längst nicht so aufwändig wie die Arbeit, die dein Aglo ausführt.

ScottManDeath
2009-03-15, 23:44:34
Ausserdem, mit C99 (wie in C++) kann man Variablen ueberall im Scope deklarieren, nicht nur am Beginn.

Notfalls macht man halt extra Scopes auf mit {}

Btw, gibts einen spezifischen Grund C anstellen von C++ zu nutzen?

Aber solche Sachen sind Mikroptimierungen, das macht bei heutigen Architekturen nix aus, da sind Sachen wie z.b Speicher/Cache-koheraenz wichtiger.

Btw, gibts einen spezifischen Grund C anstellen von C++ zu nutzen?

Gast
2009-03-16, 08:16:55
Und wegoptimieren der temporären Variablem sollte auch nicht das Problem sein, wobei ich den Algorithmus aber auch eher in Funktionen aufteilen würde. So ein Function-Call ist sicher längst nicht so aufwändig wie die Arbeit, die dein Aglo ausführt.
Ich glaub da hilft nur das ganze mal durch zu "profilieren" - muss ich mir mal anschauen. Größenordungsmäßig sind das einige 10000 (kleine) Subgraphen.

Ausserdem, mit C99 (wie in C++) kann man Variablen ueberall im Scope deklarieren, nicht nur am Beginn.

Notfalls macht man halt extra Scopes auf mit {}


Btw, gibts einen spezifischen Grund C anstellen von C++ zu nutzen?

Ja, das Vorhandensein von Compilern für die Zielarchitektur :-)

Gast234
2009-03-18, 00:09:37
Bin kein Experte, aber ich glaube jeder vernünftige Compiler transformiert den Code als Zwischenschritt sowieso nach SSA, siehe http://en.wikipedia.org/wiki/Static_single_assignment_form
D.h. wenn du ne Variable mehrmals zuweist, wird das vom Compiler eh in mehrere Variablen zerlegt; daher ist das, was du machst, redundant.

Coda
2009-03-18, 00:13:43
Ja, das Vorhandensein von Compilern für die Zielarchitektur :-)
Welche Zielarchitektur wird denn nicht von GCC unterstützt? ;)

Bin kein Experte, aber ich glaube jeder vernünftige Compiler transformiert den Code als Zwischenschritt sowieso nach SSA, siehe http://en.wikipedia.org/wiki/Static_single_assignment_form
Dann sind GCC 3.x und der Microsoft-Compiler nicht vernünftig? ;)