Forum: PC-Programmierung Kostet ein Typecast/Typenumwandlung Ressourcen?


von Carapa (Gast)


Lesenswert?

In vielen Programmiersprachen werden primitive als auch komplexe 
Datentypen nach Bedarf in einen anderen Datentyp überführt.

Kleines Beispiel in der Programmiersprache C:
1
int a_i = 3;
2
float b_f = a_i; //float b_f = (float)a_i;

Ich würde gerne wissen, ob so eine Typenumwandlung in der 
Programmiersprache C Ressourcen kostet?

Damit meine ich Laufzeit, Assembly Instruktionen oder sonstiges.

Hintergrund ist der, dass ich mit fremden Code anschaue und 
Verbesserungsvorschläge suche. In den Sourcen wird häufig von
1
int
 nach
1
float
 und wieder zurück nach
1
int
 konvertiert ohne das eine direkte Operation auf den float Attribut 
statt findet. Abgesehen davon, dass dies nicht unbedingt sinnvoll und 
sauber ist, brauche ich argumente dafür nur Typenkonvertierung zu 
betreiben, wenn diese auch wirklich nötig ist.

Vielen Dank schonmal in vorraus

von Klaus W. (mfgkw)


Lesenswert?

Carapa schrieb:
> Ich würde gerne wissen, ob so eine Typenumwandlung in der
> Programmiersprache C Ressourcen kostet?
>
> Damit meine ich Laufzeit, Assembly Instruktionen oder sonstiges.

Das kann so sein, muß aber nicht.

Es gibt casts, die letztlich nur etwas bewirken in der Art 
"interpreteiere den Ausdruck nur anders", z.B. ein char* nach int* 
casten.
Das kostet dann auch nichts.

Andere casts haben eine Bedeutung in der Art "wandle den Ausdruck in ein 
anderes Format um", z.B. double d=(double)2/5
Dann kann es sein, daß der Compiler schon zur Übersetzungszeit weiß, was 
rauskommt und gleich das Ergebnis einsetzt, es kann aber auch sein, daß 
zur Laufzeit dann mehr oder weniger aufwendige Aktionen passieren.

Also kein Ja der Nein, so pauschal geht das nicht.

von Karl H. (kbuchegg)


Lesenswert?

> In den Sourcen wird häufig von
> int
>  nach
> float
>  und wieder zurück nach
> int
> konvertiert ohne das eine direkte Operation auf den float Attribut
> statt findet. Abgesehen davon, dass dies nicht unbedingt sinnvoll
> und sauber ist, brauche ich argumente dafür nur Typenkonvertierung
> zu betreiben, wenn diese auch wirklich nötig ist.

Wie wärs mit der obersten 'Direktive' aller Programmierer:

Schreibe sauberen, übersichtlichen Code!

Denselben Wert in 20 unterschiedlichen Variablen zu haben, die sich nur 
durch den Datentyp unterscheiden, ist nicht wirklich dazu angetan, die 
Übersicht und damit die Wartbarkeit zu erhöhen.

Nicht umsonst ist eine der Grundregeln zb im Datenbankdesign: Speichere 
niemals denselben Wert in einer Datenbank an 2 verschiedenen Stellen ab. 
Im besten Fall gewinnst du dadurch nichts, im schlimmsten Fall laufen 
dir die Werte auseinander.


Und float ist sowieso so eine Sache für sich. Wenns nicht gerade 
Millionen floats sind und somit das Speicherplatzargument greift, ist 
double einem float bei numerischen Berechnungen praktisch immer 
vorzuziehen.

von Karl H. (kbuchegg)


Lesenswert?

> brauche ich argumente dafür nur Typenkonvertierung zu
> betreiben, wenn diese auch wirklich nötig ist.

Letzten Endes musst du damit Casten.
Casts aber sind Waffen!
Man setzt sie niemals leichtfertig und unnötigerweise ein, oder gar nach 
dem Muster: Oooch, da caste ich mal ein wenig.

Effektiv hebelt man mit einem expliziten Cast die Kontrolle der 
Datentypen durch den Compiler aus und verlagert damit einen 
Kontrollmechanismus vom Compiler zum Programmierer. Und das letzteres 
des öfteren schon mal schief geht, weil eben der Programmierer Fehler 
macht, der Compiler an dieser Stelle aber nicht, ist auch bekannt. -> 
Lass den Compiler seinen Job tun, der macht den zuverlässiger.
Und wenn eine Typumwandlung ansteht, dann sollte der erste Lösungsansatz 
darin bestehen, sich zu überlegen, ob man diese Umwandlung durch 
Änderungen im Programmdesign nicht loswerden kann. Ekzessives Casten ist 
oft ein Zeichen dafür, dass im Programm etwas Grundsätzliches nicht 
stimmt. Es ist fast wie in der Physik: Wenn in einer Formel links und 
rechts vom Gleichheitszeichen nicht die gleichen Einheiten (=Datentyp in 
einem Programm) stehen, dann ist etwas faul. In diesem Sinne kann man 
auch Datentypen sehen: Im Regelfall stimmen sie überein.

In diesem Sinne sind derartige Typumwandlungen als implizite Casts zu 
sehen, die jeweils eigene Untersuchungen und Analysen benötigen, um 
deren Zulässigkeit und Korrektheit zeigen zu können.

von Andreas D. (rackandboneman)


Lesenswert?

Vor allem: Wenn man Annahmen über die Eigenschaften von Daten auf 
Maschinenebene macht (und genau das tut man bei bestimmten casts) sollte 
es nicht zuviel verlangt sein sich den generierten Assemblercode (an den 
man ja bei gcc usw. problemlos herankommt) mal zu überfliegen und ggf 
mit dem von Alternativen zu vergleichen.

von Carapa (Gast)


Lesenswert?

Danke für die Antworten. Mir fehlt aber leider "DAS Argument" dass den 
Kunden dazu beweget daran etwas zu tun.

Ich persöhnlich würde sofort eine Änderung durchführen, wenn ein 
Attribut gecastet wird aber dies nicht notwendig ist. Es gibt 
ausreichend viele Codierrichtlinien die das Beschreiben (MISRA-C, PEP, 
...). Aber auch ohne diese ist es einfach sauber wenn man typecasts nur 
dann verwendet wenn sie notwendig sind und diese dann auch im Quellcode 
beschreibt. Alles andere führt zu verwirrung und die Wartbarkeit, Pflege 
und das Testen benötigt schon mal etwas mehr Zeit und kostet Geld.

Hier geht es aber um Modellbasierte Softwareentwicklung in Simulink und 
Auto-Codegeneratoren. Modellentwickler interessiert ein Datentyp nicht. 
Hauptsache es läuft :-) Lange Geschichte und ich möchte nicht zu sehr 
darauf eingehen.

Um tatsächlich so einen Verbesserungsvorschlag machen zu können, ist 
meine einzige Möglichkeit Ressourcenersparnisse darzustellen. SW-Design, 
Strukturierung hat alles bisher nichts genützt.

Der Kunde wird nicht auf mich hören wenn ich ihm nur sage: "Wartbarkeit" 
und "Fehleranfälligkeit". Wenn ein Typecast auch nur eine zusätzliche 
ASM-Instruktion liefert habe ich gewonnen, da dieser Fall ca. 500 mal im 
Code vorkommt (Auto-Code-Generator).

von Mark B. (markbrandis)


Lesenswert?

Carapa schrieb:
> Hintergrund ist der, dass ich mit fremden Code anschaue und
> Verbesserungsvorschläge suche.

Warum willst Du fremden Code verbessern? Das wäre doch in erster Linie 
die Aufgabe desjenigen, der diesen Code schreibt.

Oder hast Du das Luxusproblem, dass Dein Anteil am Code zu 100% 
implementiert, getestet und dokumentiert ist, und Du nicht weißt was 
Du noch tun sollst? ;-)

von Kevin (Gast)


Lesenswert?

"Never change a running system" könnte mann da als anderes Extrem 
hinzufügen.

von Karl H. (kbuchegg)


Lesenswert?

Carapa schrieb:
> Danke für die Antworten. Mir fehlt aber leider "DAS Argument" dass den
> Kunden dazu beweget daran etwas zu tun.

Das ist leider ein großes Problem.
Es ist ein bischen so, wie das Aufräumen der Abstellkammer.

Es wird solange rausgeschoben, bis es gar nicht mehr anders geht. Erst 
wenn man ein teures Gerät ein 2-tes mal unnötig kauft, weil man es in 
der Kammer nicht findet, wird dann irgendwann aufgeräumt. Solange man 
nur die M8 Schrauben für Pfennigbeträge nachkaufen muss, ist die 
Grundhaltung halt oft: Ist jetzt auch kein Beinbruch, wenn ich die 
Schraubenschachtel nicht finde.

> Der Kunde wird nicht auf mich hören wenn ich ihm nur sage: "Wartbarkeit"
> und "Fehleranfälligkeit".

Das nächste Problem.
"Wieso, läuft doch?"
Wir alle (also die Profis hier), haben diesen Satz schon hundertemale 
gehört. Erst wenn ein blöder Fehler teuer wird, ist dann plötzlich ein 
Einlenken zu bemerken.

> Wenn ein Typecast auch nur eine zusätzliche
> ASM-Instruktion liefert habe ich gewonnen, da dieser Fall ca. 500 mal im
> Code vorkommt (Auto-Code-Generator).

Wie es Klaus oben schon gesagt hat: Man muss sich jeden Fall einzeln 
ansehen.

Vielleicht kriegst du so einen Fuss in die Tür:
Die saubere Art einen Floating Point Typ an einen int zuzuweisen, geht 
immer noch über runden

   int = (int)( float + 0.5 );

(bzw. mit einer Fallunterscheidung für negative Zahlen). Es hat schon 
Fälle gegeben, bei denen nach einer Berechnung rein mathematisch 2.0 
rauskommen müsste, tatsächlich kommt aber 1.9999999 raus, was mit einer 
naiven Zuweisung zu 1 wird.

OK, IEEE 754 (also das am häufigsten verwendete Floating Point Format), 
macht die Zusicherung, dass bis zu einer gewissen Größe Ganzzahlen exakt 
dargestellt werden können, so gesehen sollt bei

   int = float = int

nix passieren, solange der int sich im Rahmen hält, Schwachsinn ist es 
aber dennoch, zumal bei einem Cast von int nach float bzw. umgekehrt ja 
auch Taktzyklen verbraucht werden, solange der Optimizer die komplette 
Berechnung nicht überhaupt entfernt. Gerade bei Floating Point Dingen 
wäre ich da aber vorsichtig. Zumindest früher haben Optimizer da ganz 
gerne die Finger davon gelassen.

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

Vorallem ist ein Cast int->float und float->int nicht zwangsweise 
verlustlos. also könnte es sein, das der vermeintlich nutzlose Code 
doch etwas macht was auf den ersten Blick nicht ersichtlich ist. Ohne 
Unittest sollte man an sowas garnichts ändern!

von Carapa (Gast)


Lesenswert?

Nun meine Aufgabe möchte ich hier aus Geheimhaltungsgründen nicht näher 
beschreiben. Mir ist auf jeden Fall nicht langweilig und leider bin ich 
in meiner Rolle kein Entwickler, da ich sonst selbst solche Dinge 
"gerade ziehen" würde.

Als C-Programmierer im Embedded Bereich lernt man im laufe der Zeit viel 
darüber, was eine saubere Code-Strukturierung, sprich Design bedeutet 
und wie wichtig es auch heute noch ist mir Ressourcen Strukturiert und 
Dokumentiert vorzugehen. Spätestens nachdem man Module abgibt oder neue 
übernimmt wird klar, wie wichtig das Thema ist.

Modellbasiertes Entwickeln, hier mittels Simulink, ist nicht für 
Programmierer entwickelt sondern für Physiker, Kybernetiker, sonstige.. 
sprich für Entwickler die sich nicht mit einer Programmiersprache 
Rumschlagen wollen. Da alles Bilder sind und keine Syntax soll es 
angeblich einfacher sein. Diese Bilder werden von sogenannten 
Auto-Code-Generatoren in die Sprache C überführt, und das Modell kann in 
einem Mikrocontroller ausgeführt werden.

So ein Auto-Code-Generator ist einstellbar. D.h. der Anwender kann einem 
bestimmen wie das Ausgangssignal seines Blockschaltbildes im generiertem 
Quellcode erzeugt wird. Default ist allerdings bei Simulink der Typ 
<c>float</c> und ein Modellentwickler interessiert sich in der Regel 
nicht dafür. So nun haben wir ein Modell, dass mittlerweile richtig groß 
ist und viele Entwickler wirken mit. Man muss sich vorstellen, dass so 
eine Typänderung nicht von einem durchgeführt werden muss sondern von 
vielen. D.h. man muss ein Druckmittel haben. Nur weil es schöner wäre 
oder strukturierter, dass zählt nicht. Jemand der kein Verständnis für 
Hand-Code Programmierung hat, wird sich davon nicht überzeugen lassen. 
Man braucht Fakten wie: Ressourcenverbrauch. Ressourcen kosten Geld und 
das ist nicht gut.

Ich werde mir mal im laufe der Woche das Disassembly zu der Typecast 
geschichte anschauen. Dann habe ich es schwarz auf weiß oder muss das 
Thema unterordnen.

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

Carapa schrieb:
> Ich werde mir mal im laufe der Woche das Disassembly zu der Typecast
> geschichte anschauen. Dann habe ich es schwarz auf weiß oder muss das
> Thema unterordnen.
Wenn tatsächlich "nichts" gemacht wird, sollte jeder bessere Compiler 
sowas auch komplett wegoptimieren.

von Mark B. (markbrandis)


Lesenswert?

Läubi .. schrieb:
> Wenn tatsächlich "nichts" gemacht wird, sollte jeder bessere Compiler
> sowas auch komplett wegoptimieren.

Womit sich auch die "Notwendigkeit" zu handeln erübrigen würde.

von Andreas D. (rackandboneman)


Lesenswert?

"Ressourcenersparnisse"

Ist der existierende Code denn nun tatsächlich zu langsam bzw wird der 
vorhandene Speicher knapp?

von (prx) A. K. (prx)


Lesenswert?

Konvertierungen zwischen ganzzahligen Datentypen und Fliesskommatypen 
können u.A. bei PC-Prozessoren deutlich teuerer sein als einfache 
Rechenoperationen wie add/sub/mul innerhalb einer Rechenart.

Grund: Die beiden Rechenarten finden u.U. in völlig verschiedenen 
Bereichen des Cores und zwischen getrennten Registersets statt und der 
Transport dazwischen kann ziemlich umständlich sein.

So existiert beim in 32-Bit Programmierung üblichen x87-Befehlsatz kein 
Befehl für Register zu Register Konvertierung, das läuft aufwendig über 
Store-Load.

Aber auch bei 64-Bit Programmierung mit dem SSE Befehlssatz wird man bei 
AMD Prozessoren feststellen, dass je nach Modell eine oder auch beide 
Richtungen mangels Datenpfad ebenfalls recht teuer sind und AMD zur 
Optimierung an Stelle des direkten Einzelbefehls das aufgeteilte 
Store-Load Verfahren empfiehlt.

Wenn es also keinen zwingenden Grund gibt, dann sollte man für abhängige 
Operationsketten innerhalb einer Rechenart bleiben.

von (prx) A. K. (prx)


Lesenswert?

Carapa schrieb:

> Ich werde mir mal im laufe der Woche das Disassembly zu der Typecast
> geschichte anschauen. Dann habe ich es schwarz auf weiß oder muss das
> Thema unterordnen.

Das Disassembly-Listing nützt aber nur begrenzt, wenn man die Kosten der 
Operationen nicht im Blick hat. Einen guten Einblick darin gibt
http://www.agner.org/optimize/

von Karl (Gast)


Lesenswert?

Ohne das Projekt im Detail zu kennen, ist es imho garnicht so einfach 
abzuschätzen, ob ein Weglassen der Floats wirklich was bringt. Wir 
rechnen im Moment auch noch alles in fixed-point (> 1000 Seiten Doku), 
aber manchmal wäre die Verwendung von float wesentlich eleganter und 
Resourcenschonender, weil dann viele Umrechnungen wegfallen würden. Bei 
einer Zielplattform mit einer einigermaßen performanten FPU wäre das in 
Zukunft mein Ziel, weil wir damit viel Arbeit und gleichzeitig Resourcen 
sparen könnten.

Auch die Code-Generatoren von Simulink sind so schlecht nicht, besonders 
der Embedded Coder erzeugt erstaunlich gut lesbaren Code. Der RTW-Coder, 
ähem, funktioniert schon, ist aber nicht für embedded gemacht. Wenn ihr 
den einsetzt, ist die Suche nach Typecasts evtl. der falsche Ansatz.

Gerade die Tatsache, dass sich die Physiker und Konsorten eben nicht 
um jedes Bit kümmern müssen, kann man mit modellbasierter SW-Entwicklung 
durchaus nennenswert Zeit und Geld sparen. Zum Teil bezahlt man das zwar 
mit höheren Anforderungen an die Plattform, aber wer legt sein Design 
schon auf 99% Ausnutzung aus, wenn modellbasiert entwickelt werden soll.

von (prx) A. K. (prx)


Lesenswert?

Bei PC-Prozessoren mit den heute sehr leistungsfähigen FPUs ergibt der 
Ersatz von skalaren Fliesskommaoperationen durch Festkommaoperationen in 
meinen Augen keinen Sinn, jedenfalls was die Performance angeht. Man 
verliert dabei wohl eher an Performance als dass man gewinnt.

von (prx) A. K. (prx)


Lesenswert?

Karl Heinz Buchegger schrieb:

> Und float ist sowieso so eine Sache für sich. Wenns nicht gerade
> Millionen floats sind und somit das Speicherplatzargument greift, ist
> double einem float bei numerischen Berechnungen praktisch immer
> vorzuziehen.

Wenn es nicht grad um Prozessoren der PC-Klasse geht kann der 
Performanceunterschied zwischen float und double deutlich spürbar sein. 
Mittlerweile ist ja zulässig, dass ein C Compiler nicht mehr implizit 
alles in double rechnet und nicht jede FPU ist bei double ähnlich 
schnell. Manche Controller haben eine auf float Operationen optimierte 
FPU. Und wenn sie überhaupt keine haben, dann sowieso.

Wenn man andererseits an die Kante der Leistungsfähigkeit heutiger 
Prozessoren geht und beim PC mit SSE SIMD-Operationen arbeitet, dann 
kann float ebenfalls kräftig an Performance gewinnen. Auch ganz ohne 
Speicherplatzeffekte.

von Roland H. (batchman)


Lesenswert?

Carapa schrieb:
> Hier geht es aber um Modellbasierte Softwareentwicklung in Simulink und
> Auto-Codegeneratoren.

Wenn sich nun herausstellt, dass ein paar "casts" überflüssig sind, wie 
groß sind die Chancen, die Generatoren wegzulassen bzw. zu verändern?

Ich verstehe die Motivation nicht. Wenn es modellgetrieben ist, 
interessiert in erster Linie die Güte des Modells.

Carapa schrieb:
> man muss ein Druckmittel haben. Nur weil es schöner wäre
> oder strukturierter, dass zählt nicht. Jemand der kein Verständnis für
> Hand-Code Programmierung hat, wird sich davon nicht überzeugen lassen.
> Man braucht Fakten wie: Ressourcenverbrauch. Ressourcen kosten Geld und
> das ist nicht gut.

Das sehe ich differenzierter. Beide Ansätze haben ihre Berechtigung. Was 
ist Dein Ziel? Generatoren verändern oder ganz weglassen? Wie viel 
Kosten denn die Ressourcen und welche sind das konkret? Was kostet dazu 
im Vergleich die Umstellung des Entwicklungsprozesses eines "richtig 
großen Projektes mit vielen Entwicklern"? Sind das 
"Schönheitsoperationen" oder wird der Flash/RAM/was-auch-immer knapp? 
Von welchen Stückzahlen reden wir hier?

Kurz: Wie sieht denn der "business case" bzw. dessen Berechnung aus?

von Mark B. (markbrandis)


Lesenswert?

Vielleicht wäre es wirksamer, für zukünftige Projekte Regeln vorzugeben, 
wie die Datentypen vom Entwickler ausgesucht werden sollen? Wenn die 
offizielle Regelung bisher "jeder wie er will" oder "lass halt die 
Standardvoreinstellung, passt schon" ist, dann liegt das Problem doch 
eher in den Programmierrichtlinien der Firma, möchte ich mal vermuten.

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.