ubuntuusers.de

Unterschied Linux / Windowsprogrammierung in C++?

Status: Ungelöst | Ubuntu-Version: Ubuntu
Antworten |

TheImaginator

Avatar von TheImaginator

Anmeldungsdatum:
5. Februar 2007

Beiträge: 20

Wohnort: Schwäbisch Hall

@Marc 'BlackJack' Rintsch:
Du willst mir jetzt doch wohl nicht einreden, dass OOP-Code schneller ist als prozedualer Code.
Zu deinen Optimierungen am Code:
1.) t lokal –> OK.
2.) GetVar() inline –> Das hat wenig mit OOP zu tun, da "normale" Funktionen ebenfalls inline unterstützen. Um den Test objektiv bewerten zu können müssen also 2 gleichstark optimierte Codestücke her:

// c-test
#include <cstdio>
#include <ctime>

using namespace std;

inline unsigned int GetVar();

unsigned int i = 0;

int main()
{

	while(GetVar() < 400000000)
	{}

	printf("%d\n", clock());
	return 0;
}

unsigned int GetVar()
{
	i++;
	return i;
} 
// c++-test
#include <cstdio>
#include <ctime>

using namespace std;

class Test
{
	public:
	Test(unsigned int x);
	unsigned int GetVar() {i++; return i;}

	private:
	unsigned int i;
};

int main()
{
	Test t(0);

	while(t.GetVar() < 400000000)
	{}

	printf("%d\n", clock());
	return 0;
}


Test::Test(unsigned int x):
i(x)
{} 

Ergebnis:

marcel@marcel-desktop:~/test$ ./c-test
2103
marcel@marcel-desktop:~/test$ ./c++-test
2743

--> 30 % Unterschied! Das war n Schuss in Ofen


Zu deinem Argument mit dem "absichtlich" langsamer machen:
In der Praxis werden eben Polymorphie und überladene Operatoren benutzt, was den Code verlangsamt.
Aber selbst bei einem Vergleich wie diesen schneidet "normaler" Code besser ab.

Zu eurem Problem mit clock():
Es ist völlig scheißegal, ob die Ticks/OP auf allen Plattformen gleich sind, solange ich ein Verhältnis daraus ableite!

Und um es jetzt endgültig klar zu machen:
JA! Ihr habt mich überzeugt, dass der Geschwindigkeitsvorteil den ich versuche zu erreichen bei GUI's verschwindent gering ist.
Zeitkritische Operationen würde ich aber trotzdem noch mit C schreiben, anstatt mit C++.

Gruß TheImaginator

Marc_BlackJack_Rintsch Team-Icon

Ehemalige
Avatar von Marc_BlackJack_Rintsch

Anmeldungsdatum:
16. Juni 2006

Beiträge: 4687

Wohnort: Berlin

TheImaginator hat geschrieben:

Du willst mir jetzt doch wohl nicht einreden, dass OOP-Code schneller ist als prozedualer Code.

OOP und prozedural sind Programmierparadigma, die werden nicht ausgeführt, sondern beschreiben einen bestimmten Stil Programme zu schreiben.

Zu deinen Optimierungen am Code:
1.) t lokal –> OK.
2.) GetVar() inline –> Das hat wenig mit OOP zu tun, da "normale" Funktionen ebenfalls inline unterstützen. Um den Test objektiv bewerten zu können müssen also 2 gleichstark optimierte Codestücke her:

[Codebeispiele]

Ergebnis:

marcel@marcel-desktop:~/test$ ./c-test
2103
marcel@marcel-desktop:~/test$ ./c++-test
2743

--> 30 % Unterschied! Das war n Schuss in Ofen

Mein Ergebnis sieht da anders aus:

marc@s8n:~/tmp/kapseln$ ./c-test
1380000
marc@s8n:~/tmp/kapseln$ ./c++-test
920000

Das liegt aber nicht an OOP vs. prozedural, sondern an dem völlig ungeeigneten Beispielcode.

Zu deinem Argument mit dem "absichtlich" langsamer machen:
In der Praxis werden eben Polymorphie und überladene Operatoren benutzt, was den Code verlangsamt.

Verlangsamt gegenüber was? Äquivalentem prozeduralem Code? Warum? Schreiben wir doch mal wirklich vergleichbaren C-Code zur C++-Variante, also wo das i in einer Datenstruktur stecht und die lokal in der main()-Funktion deklariert wird:

// c-test2 
#include <cstdio> 
#include <ctime> 

using namespace std; 

typedef struct {
   unsigned int i;
} Test;

inline void Test_init(Test *t, unsigned int i);
inline unsigned int GetVar(Test *t); 

int main() 
{ 
   Test t;
   Test_init(&t, 0);

   while(GetVar(&t) < 400000000) 
   {} 

   printf("%d\n", (int) clock()); 
   return 0; 
} 

void Test_init(Test *t, unsigned int i)
{
   t->i = i;
}

unsigned int GetVar(Test *t)
{
   t->i++;
   return t->i;
} 

Und nochmal alle drei Zeiten:

marc@s8n:~/tmp/kapseln$ ./c-test
1380000
marc@s8n:~/tmp/kapseln$ ./c++-test
920000
marc@s8n:~/tmp/kapseln$ ./c-test2
1350000

Zu eurem Problem mit clock():
Es ist völlig scheißegal, ob die Ticks/OP auf allen Plattformen gleich sind, solange ich ein Verhältnis daraus ableite!

Der C-Standard garantiert nicht, dass clock() bei jedem Programmlauf bei 0 startet, oder überhaupt immer mit dem gleichen Wert. Bei Linux scheint's aber netterweise der Fall zu sein.

Apollon

Avatar von Apollon

Anmeldungsdatum:
27. Oktober 2004

Beiträge: 724

Wohnort: Darmstadt

TheImaginator hat geschrieben:

[...]Es ist völlig scheißegal, ob die Ticks/OP auf allen Plattformen gleich sind, solange ich ein Verhältnis daraus ableite!

Eben nicht. Du kannst daraus kein Verhaeltnis ableiten.

TheImaginator

Avatar von TheImaginator

Anmeldungsdatum:
5. Februar 2007

Beiträge: 20

Wohnort: Schwäbisch Hall

Der C-Standard garantiert nicht, dass clock() bei jedem Programmlauf bei 0 startet, oder überhaupt immer mit dem gleichen Wert. Bei Linux scheint's aber netterweise der Fall zu sein.

Bei mir ist das tatsächlich anders.
Die Werte unter Linux varieren um etwa +/- 100 % (mal liegt c vorn und mal c++), wohingegen die Werte auf Windows relativ konstant scheinen.
Wir müssen uns also eine andere Testmethode einfallen lassen (clock() am Anfang und Ende feststellen und die Differenz ausgeben?).
Wenn du in "c-test2" Datenstrukturen verwendest und diese Mithilfe einer Referenzierung (t->i = 0) initialisierst, dann musst du dies in "c++-test" genauso mit einer Referenzierung tun (this->i = 0). Ich weiß, ich bin pingelich, aber wir wollen doch fair bleiben 😉

Das liegt aber nicht an OOP vs. prozedural, sondern an dem völlig ungeeigneten Beispielcode.

Dann sollten wir festlegen, was wir mit dem Beispielcode testen wollen.
Vorschlag:
- Vergleich der Aufrufzeiten von Funktionen bzw. Methoden.
- Vergleich der Speicherreservierungszeit von verschiedenen Instanzen (Datenstruktur vs. Klasse).

Alles andere wird unter C++ als auch unter C gleichschnell ausgeführt (Äquivalente zu überladenen Operatoren usw. fallen mir im Moment nicht ein, sodass wir sie auf Unterschiede testen könnten).

Und da wir diesen Thread jetzt schon ziemlich zweckentfremdet haben (sry an den Threadersteller), sollten wir vielleicht einen neuen aufmachen?

Gruß TheImaginator

EDIT:

OOP und prozedural sind Programmierparadigma, die werden nicht ausgeführt, sondern beschreiben einen bestimmten Stil Programme zu schreiben.

Die letztendliche Ausführung unterscheidet sich dennoch.

user_unknown

Avatar von user_unknown

Anmeldungsdatum:
10. August 2005

Beiträge: 17621

Wohnort: Berlin

a) Ich würde zum Zeitmessen time nehmen. Das rechnet meines Wissens parallel laufende updatedb-Läufe, Videos und VoIP raus.

time program_to_measure


Eine sehr praktische Erfindung.

b) Muß man wieder die alten Performance-Mantras runterbeten?
Z.B. diese: W. A. Wulf hat geschrieben:

More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single reason - including blind stupidity.

Oder dies:
M. A. Jackson hat geschrieben:

Rules of optimization:
Rule 1: Don't do it.
Rule 2 (for experts only): Don't do it now.

Oder his Guruness - Knuth:
Donald Knuth hat geschrieben:

We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil.

Performance beginnt beim Design, über Algorithmen und Datenstrukturen zieht sie sich hin bis zu verwendeten Werkzeugen und Hardware.
Und ich möchte Marc 'BlackJack' Rintschs Hinweis unterstreichen, daß Paradigmen und auch Sprachen nicht schnell oder langsam sind.
Der Compiler hat hier ein Mitspracherecht, und kann schnelleren oder langsameren Code produzieren.

Wenn zwei Lösungen in unterschiedlichen Sprachen genau das gleiche machen, dann müßte es möglich sein 2 Compiler zu bauen, die auch das gleiche binäre Resultat liefern, oder nicht?

Wenn man durch eine leicht zu nutzende Sprache Zeit einspart, dann kann man die gewonnene Zeit vielleicht darauf verwenden, die wenigen wahren Engpässe des Programms zu suchen, und dort ein geeignetes Tuning vorzunehmen - als Faustregel gilt, daß 80% der Zeit eines Programms in nur 20% des Codes verbracht wird.

Der objektorientierte Ansatz soll u.a. erreichen, daß ein Sortieralgorithmus vom Typ dessen, was da sortiert werden soll, absehen kann.
Ein solcher Algorithmus kann dann immer wieder verwendet werden.
Wenn er das wird, dann lohnt es sich auch eher, diesen zu optimieren, da viele kleine Gewinne einen großen machen können.

Und ein gut verständlicher Entwurf erlaubt es auch eher, einzelne Teile zur Optimierung zu isolieren - sei es für einen Experten, sei es für den Compiler.
Damit habe ich nicht gesagt, daß objektorientierte Entwürfe per se verständlich sind, oder rein prozedurale unverständlicher.

Was ich gesagt haben will ist: Programmiere verständlich.
Meine Erfahrung ist, daß objektorientiertes Programmieren ein verständliches Programmieren besser unterstützt, als nicht objektorientiertes.
Deswegen würde ich es empfehlen.

hackepeter

Avatar von hackepeter

Anmeldungsdatum:
8. Januar 2006

Beiträge: 185

Wohnort: München

user unknown hat geschrieben:

....
Was ich gesagt haben will ist: Programmiere verständlich.
Meine Erfahrung ist, daß objektorientiertes Programmieren ein verständliches Programmieren besser unterstützt, als nicht objektorientiertes.
Deswegen würde ich es empfehlen.

Da muss ich dir absolut recht geben. Gut gebrüllt!
Guter Quelltext ist für den Entwickler. Gut strukturiert und übersichtlich und schön gekapselt heisst
auch dass du viel besser algorithmisch optimieren kannst - und das bringt wesentlich mehr als "inline" ☺

Tipp auch noch: http://www.linuxfocus.org/Deutsch/March2005/article371.shtml

In meinen derzeitigen Hobby, einer Simulationslibrary in C++, beispielsweise ist Speicherallozierung und das Einfügen/Suchen in einem set
das Problem, da brauche ich gar net großartig über andere Dinge nachdenken. Und die STL alleine ist schon ein Riesenvorteil gegenüber plain
C.

Gruß HP

Antworten |