Performance von inline Funktionen
-
ohne cli
-
c++neuling2 schrieb:
Das verwirrt mich jetzt endgültig, was versteht ihr genau unter c++ programmieren, wenn nicht das?
Na C++, nicht WinForms/CLI/VS Spracherweiterungen. Diese ^ Handles sind z.B. kein C++ Sprachmittel.
-
inwiefern läuft dieses c++ programmieren ohne cli ab?
beschränkt sich das dann auf konsolen oder wie?
inwiefern läuft ohne anzeigefenster die kommunikation mit dem Programm ab?nochmal sry ich hab mich wohl verrant

-
Naja, du nimmst halt eine Bibliothek, die direkt mit dem System kommuniziert ohne .NET dazwischen.
Zb Qt statt Winforms.
-
Ahh ok also es GIBT noch sowas wie controls nur eben anders, damit kann ich ja noch leben

Ich hab das ganz kurz versucht umzuschreiben. Gibt mir trotzdem keine äquivalente Ausführzeit.
cpp der Anwendung(Konsolen)
// vektortest.cpp: Hauptprojektdatei. #include "stdafx.h" #include <Windows.h> #include <stdio.h> #include "vektortest.h"; using namespace System; Vektor::Vektor(double x1,double y1,double z1) { Vektor::x = x1; Vektor::y = y1; Vektor::z = z1; } inline void Vektor::operator +=(Vektor vekt) { Vektor::x += vekt.x; Vektor::y += vekt.y; Vektor::z += vekt.z; } int main(array<System::String ^> ^args) { Console::WriteLine(L"Hello World"); Vektor test = *new Vektor(10,10,10); SYSTEMTIME st; GetSystemTime(&st); Vektor tester = *new Vektor(1,1,1); for(int i = 0; i < 10000000;i++) { test += tester; } SYSTEMTIME st2; GetSystemTime(&st2); double verstrichen = (st2.wMilliseconds - st.wMilliseconds); for(int i = 0; i < 10000000;i++) { test.x += tester.x; test.y += tester.y; test.z += tester.z; } GetSystemTime(&st); double verstrichen2 = (st.wMilliseconds - st2.wMilliseconds); return 0; }umgeschriebene vereinfachte Vektor Klassen definition(.h):
#ifndef header #define header public class Vektor { public: double x; double y; double z; Vektor(double x1,double y1,double z1); void operator+=(Vektor vekt); private: }; #endif
-
Ich glaube, die Diskussion über Performance macht an der Stelle keinen Sinn mehr. Du verstehst noch nicht, was du tust, verbeißt dich aber in völlig unwichtige Details.
-
Es ist mir egal ob ich mit 15 Jahren schon soviel Berufserfahrung habe wie du und das einzige was ich erreichen will ist das ich mir diese drei Zeilen Code durch einen überladenen Operator sparen kann und das zum gleichen Zeitaufwand.
Und damit ist denke ich bei verwendung des inline präfixes in diesem fall zu rechnen insofern inline vor der compilation lediglich Codeersetzung betreibt.
Also abschließend, was nicht ist kann ja noch werden und ich fände es nett wenn du dich lieber auf meine performance probleme konzentrieren würdest als auf meine unausgebildeten Programmierkentnisse.
Nichts für ungut.
-
c++neuling2 schrieb:
Wenn c++ gänzlich ungeeignet für winforms ist warum sind winforms anwendungen in c++ erstellbar?
Da liegt wohl ein Missverständnis vor. Du kannst mit C++ keine Windows Forms Anwendungen machen. Das geht nur mit C++/CLI und das ist eine völlig andere Sprache.
Und auch wenn C++/CLI Windows Forms Anwendungen erstellen kann, so ist es trotzdem nicht für die Erstellung von Windows Forms Anwendungen gedacht...c++neuling2 schrieb:
mir gehts auch eigentlich erstmal ums prinzip das ganze in c++ nutzbar zu machen, also versuche ich auf "richtiges c++" umzusteigen.
Wenn du richtiges C++ verwenden willst, dann tu das. C++/CLI ist wie gesagt was anderes.
-
c++neuling2 schrieb:
Also abschließend, was nicht ist kann ja noch werden und ich fände es nett wenn du dich lieber auf meine performance probleme konzentrieren würdest als auf meine unausgebildeten Programmierkentnisse.
Du hast doch schon mehrere Antworten auf die Performancefrage bekommen. Eindeutig kann ich das zumindest nicht beantworten. Die Vermutung mit der Cache Lokalität von Ethon ist plausibel. Eine andere Vermutung wäre der instruction cache. Oder der L1 Cache. Vielleicht kann auch der Prozessor den einen Block besser optimieren als den anderen. Vielleicht kann auch der Compiler den Code besser optimieren, wenn er nicht inline ist. Überlass sowas dem Compiler. Er analysiert selber, ob es sich lohnt, die Funktion zu inlinen und meist wird er das besser schätzen, als der Programmierer.
-
c++neuling2 schrieb:
[...] insofern inline vor der compilation lediglich Codeersetzung betreibt.
Wo auch immer du das her hast: Das ist völliger Schwachsinn.
inline tut viele Dinge (in richtigem C++). Die Tatsache dass es ein leiser Hinweis an den Compiler ist, dass er vielleicht mal drüber nachdenken könnte, die entsprechende Funktion zu inlinen ist nur eins davon...
Abgesehen davon ist das kein C++ und du bist hier nicht native sondern in der CLI Welt unterwegs in der sowieso völlig andere Spielregeln gelten.
Anyway: Ich vermute mal du hast dem Compiler in irgendeiner Weise einen sehr guten Grund gegeben, hier nicht zu inlinen. Ist das überhaupt ein Release Build? Sind die entsprechenden Optimierungen überhaupt aktiviert?
c++neuling2 schrieb:
Also abschließend, was nicht ist kann ja noch werden und ich fände es nett wenn du dich lieber auf meine performance probleme konzentrieren würdest als auf meine unausgebildeten Programmierkentnisse.
Deine unausgebildeten Programmierkenntnisse sind aber genau das eigentliche Problem. Das mangelnde Verständnis der Kräfte mit denen du hier spielst, führt nämlich zu unrealistischen Erwartungen deinerseits, die zwangsweise von der Wirklichkeit enttäuscht werden...
Wenn du C++ lernen willst, dann tu das. Aber dann tu es ordentlich. Und das bedeutet für den Anfang nunmal Konsolenanwendungen.
Wenn du Windows Forms Anwendungen schreiben willst dann vergiss C++/CLI und nimm C#.
-
dot, das hast du schön gesagt

-
@c++neuling2
An deinem "Beispiel" ist so viel falsch/im Argen, das passt auf keine Kuhhaut mehr.-
Du gibst die berechneten Zeiten nirgends aus. D.h. du hast das Ding vermutlich im Debugger laufen lassen. Das tut man beim Benchmarken nicht. Weiters hast du vermutlich einen Debug-Build laufen lassen. Das tut man schon gar nicht.
-
Du verwendest GetSystemTime() zum messen einer Dauer. Das ist Quatsch. GetSystemTime() ist keine "steady clock" und (u.A.) daher nicht als Stoppuhr zu gebrauchen. Verwende timeGetTime() oder QueryPerformanceCounter().
-
Du berechnest das Ergebnis falsch. wMilliseconds ist schon überhaupt gar nicht steady, das springt jede Sekunde auf 0 zurück. Also völliger Quark.
-
Wenn man diese Dinge "bereinigt" optimiert MSVC die Schleife komplett weg, die Laufzeit für beide Schleifen ist dann genau gleich, nämlich genau Null.
-
-
dachte mir auch direkt, dass das garantiert im debug modus war. C++ Compiler sind schon ein wenig besser. Über C++/CLI trifft das natürlich keine Aussage.
-
Wo auch immer du das her hast: Das ist völliger Schwachsinn.
@dot
Aus mehreren Quellen liefert sich mir folgender Wortlaut:
Hier wird der Compiler die Anweisungen nicht als Funktion aufrufen, sondern an die Stelle des Funktionsaufrufs jeweils den Funktionsinhalt kopieren.Ich will ja überhaupt keine Winforms schreiben. Das ganze hier ist wie eine Exkursion für mich insofern habe ich mich von euch belehren lassen und fang jetzt erstmal mit konsolenanwendungen an.
forceinline sollte den aufruf inlineet erzwingen? Wenn ja dann funktionierts nicht.
@hustbear
Die direkte Programmausführung gibt mir die selben werte aus.Ich habe doch anfangs bereits angemerkt das ich getsystemtime lediglich aus einfachheitsgründen verwende.
wMillisecond ist eine short Variable die werte von 0 bis 999 ausgibt. Solange sich die Funktionsdauer auf 120 ms beschränkt nutze ich den Wertebereich von wMillisecond. In einigen Fällen, beim anbruch der nächsten sekunde bekomme ich negative Differenzen, diese ich einfach ignorieren kann.
warum sollte der Schleifeninhalt durch msvc bereinigt werden? In der Schleife werden doch relevante Operationen durchgeführt.
-
int main(array<System::String ^> ^args)
Es ist immer noch kein C++ Programm. Wie waere es mit dem Installieren von Visual C++ 2010 Express?
Die direkte Programmausführung gibt mir die selben werte aus.
Das kann viele Gruende haben.
-
c++neuling2 schrieb:
@dot
Aus mehreren Quellen liefert sich mir folgender Wortlaut:
Hier wird der Compiler die Anweisungen nicht als Funktion aufrufen, sondern an die Stelle des Funktionsaufrufs jeweils den Funktionsinhalt kopieren.Dann liegen deine Quellen falsch, oder du hast sie falsch verstanden.
Ach weißt du was, ich habe gerade nichts zu tun. VS öffnen, ein neues Leeres Projekt erstellen, Code einfügen, oben wo "Debug" steht auf "Release" stellen, Projekteigenschaften -> Linker -> Subsystem auf Console stellen, strg+f5 drücken, sehen dass beides gleich lange braucht.
#include <ctime> #include <iostream> class vector3 { float data_[3]; public: vector3() {} vector3(float x, float y = 0.f, float z = 0.f) { data_[0] = x; data_[1] = y; data_[2] = z; } float& x() { return data_[0]; } const float& x() const { return data_[0]; } float& y() { return data_[1]; } const float& y() const { return data_[1]; } float& z() { return data_[2]; } const float& z() const { return data_[2]; } }; vector3 operator + (const vector3& lhs, const vector3& rhs) { return vector3(lhs.x() + rhs.x(), lhs.y() + rhs.y(), lhs.z() + rhs.z()); } vector3& operator += (vector3& lhs, const vector3& rhs) { lhs.x() += rhs.x(); lhs.y() += rhs.y(); lhs.z() += rhs.z(); return lhs; } std::ostream& operator << (std::ostream& stream, const vector3& rhs) { return stream << '(' << rhs.x() << ", " << rhs.y() << ", " << rhs.z() << ')'; } int main() { vector3 v(10.f, 10.f, 10.f); auto t = std::clock(); vector3 v1(1.f, 1.f, 1.f); for (unsigned i = 500000000; i-- != 0; ) { v1 += v; } double elapsed = (std::clock() - t) / static_cast<double>(CLOCKS_PER_SEC); std::cout << v1 << '\n'; std::cout << "Elapsed: " << elapsed << "\n\n"; t = std::clock(); vector3 v2(1.f, 1.f, 1.f); for (unsigned i = 500000000; i-- != 0; ) { v2.x() += v.x(); v2.y() += v.y(); v2.z() += v.z(); } elapsed = (std::clock() - t) / static_cast<double>(CLOCKS_PER_SEC); std::cout << v2 << '\n'; std::cout << "Elapsed: " << elapsed << "\n\n"; return 0; }ASM Code für Additionen:
v1 += v; 000812F3 addss xmm1,xmm0 000812F7 addss xmm2,xmm0 000812FB addss xmm3,xmm0v2.x() += v.x(); 00081400 addss xmm1,xmm0 v2.y() += v.y(); 00081404 addss xmm2,xmm0 v2.z() += v.z(); 00081408 addss xmm3,xmm0
-
ja danke es funktioniert und ich seh grade er hats automatisch geinlinet

Also lag der Fehler bei meinem Funktionsprototypen? Bei mir wurde lediglich ein argument unzwar der 2. Summand übergeben und ich dachte die Funktion müsse keinen Rückgabetyp beinhalten, da der Operator direkt auf den ersten Summanden angewendet wird.
Ansonsten seh ich das Richtig, also keine Winforms in c++, sondern graphiktechnisches arbeiten mit externen Apis und verwendung nicht verwalteter typen? Noch was zu beachten?

sry übrigens das ich anscheinend wegen soner einfachen Frage das ganze Forum auf den Kopf gestellt habe

-
c++neuling2 schrieb:
Also lag der Fehler bei meinem Funktionsprototypen?
Ich denke mal es lag daran, dass du diese komischen ^ CLI Handles genutzt hast. (Warum auch immer, die sind eigentlich für was komplett anderes...)
c++neuling2 schrieb:
Ansonsten seh ich das Richtig, also keine Winforms in c++, sondern graphiktechnisches arbeiten mit externen Apis und verwendung nicht verwalteter typen? Noch was zu beachten?

Zu beachten? Kommt darauf an, was genau du eigentlich machen willst, das hast du uns ja immer noch nicht verraten.

Du willst C++ programmieren? Dann nutze auch nur C++. Oder kannst du die Sprachmittel nicht unterscheiden? Da hilft wohl nur ein Buch.. oder viel Geduld..
-
cooky451 schrieb:
Da hilft wohl nur ein Buch.. oder viel Geduld..
Eher beides

-
c++neuling2 schrieb:
Ansonsten seh ich das Richtig, also keine Winforms in c++, sondern graphiktechnisches arbeiten mit externen Apis und verwendung nicht verwalteter typen? Noch was zu beachten?
Was noch zu beachten ist sind sämtliche Konsequenzen, die sich aus dem Unterschied native<->managed ergeben. Der komplett unterschiedliche Programmierstil und die komplett unterschiedlichen Bibliotheken sind da nur die Spitze des Eisbergs. Immerhin bist du als C#er vielleicht einen halben Millimeter näher dran als Javaisten.
Erster Tip: nicht alles mit new anfordern und ein gutes Augenmerk auf die Speicherverwaltung haben. Zweiter Tip: Templates nicht mit Generics verwechseln.