[Bitte um Rat] Benchmark: C# vs C++

Alexander Krieger

Grünschnabel
hi,
ich bin gerade dabei ein Programm zu entwickeln das möglichst effizient und schnell sein soll.
die erste Programmiersprache die ich gelernt habe war c#.
weil ihr hörte das c/c++ schnell arbeitet habe ich einen Teil meines Programmes in c++ umgeschrieben ohne dabei das .net Framework zu benutzen.
als Compiler benutze ich den mingw.

Nun habe ich so eine art Benchmark veranstaltet, um zu erfahren welche Sprache effizienter ist.
Dabei habe ich einen Teil meines Programmes in c++ portiert.
c++ und c# nutzen die gleiche klasse mit dem gleichem Algorithmus und die gleichen Datentypen. Die Zeit wird vor dem starten und nach dem beenden des Algorithmus gespeichert und anschließend subtrahiert.
das irritierende ist, dass c++ für das zählen und vergleichen deutlich länger braucht.

Code:
--------------------------------------
Eigener Benchmark 19.01.2011
--------------------------------------
AMD Phenom 2 X4 955 3.2GHz
Windows 7 64bit
--------------------------------------
C# .NET:
CPU belastung ca. 25%
--------------------------------------
Die größe der Kombination: 40 Aus: 49
Seit dem Start sind 00:01:41 vergangen.
Kombinationen:  2.054.455.634

Die größe der Kombination: 39 Aus: 49
Seit dem Start sind 00:06:13 vergangen.
Kombinationen:  8.217.822.536

Die größe der Kombination: 38 Aus: 49
Seit dem Start sind 0:20:32 vergangen.
Kombinationen: 29.135.916.264

Die größe der Kombination: 36 Aus: 49
Seit dem Start sind 02:41:16 vergangen.
Kombinationen: 262.596.783.764
--------------------------------------
C++:
CPU belastung ca. 25%
--------------------------------------
Die größe der Kombination: 40 Aus: 49
Seit dem Start sind 00:03:19 vergangen.
Kombinationen:  2.054.455.634

Die größe der Kombination: 39 Aus: 49
Seit dem Start sind 00:12:03 vergangen.
Kombinationen:  8.217.822.536

Die größe der Kombination: 38 Aus: 49
Seit dem Start sind 0:39:53 vergangen.
Kombinationen: 29.135.916.264
--------------------------------------

fällt euch spontan ein wie es sein kann das c++ langsamer ist?

mfg. bitcode
 
Zuletzt bearbeitet:
Willkommen bei tutorials.de :)

Das Doppelte!?

Kann ich nicht so recht glauben.

Gründe könnten zB sein:
dass du das C++-Programm nur mit einem von mehreren Kernen ausführst oder
eventuell C# mit 64bit, C++ mit 32 kompilierst
...

Würdest du vllt. den Code der Benchmarkprogramme posten? Vielleicht finde ich da was (oder ich kann es zumindest selber probieren, ob die Situation bei mir anders ist).
 
Willkommen bei tutorials.de :)

Gründe könnten zB sein:
dass du das C++-Programm nur mit einem von mehreren Kernen ausführst oder
eventuell C# mit 64bit, C++ mit 32 kompilierst
ich bin mir sicher das ich sie beide mit 32bit kompiliere und und sie mit allen kernen laufen
übrigens bin ich ein c++ anfänger der sich damit erst seit wenigen tagen beschäftigt

etwas anderes könnte hilfreich sein
ohne zwei gewisse dll's will es auf meinem anderen pc nicht starten und nach dem abschluss bekomme ich von windows ein meldung das mein programm abgestürzt ist

das soll ein algorithmus sein der mir variable zahlenkombinationen geben soll ohne das eine zahl doppelt vorkommt
(vll kommentier ich es noch gleich für euch)
Code:
#include <iostream>
#include <sys/time.h>
#include "Combination.h"

using namespace std;

int main() {
	int feld, kombi;
	long i = 0;
	cout << "Die groesze des Feldes: ";
	cin >> feld;
	cout << "Die groesze der Kombination: ";
	cin >> kombi;

	timeval start, end;
	gettimeofday(&start, 0);
	Combination c(kombi, feld);
	do { i++; } while(!c.Next(kombi-1));
	i++;
	gettimeofday(&end, 0);
	int min = (end.tv_sec-start.tv_sec)/60;
	int h = min/60;
	int sec = (end.tv_sec-start.tv_sec)%60;
	cout << "Seit dem Start sind " << h << ":" << min << ":" << sec << " vergangen." << endl;
	cout << "Kombinationen: " << i << endl;
	return 0;
}

Code:
/* Combination.h
 *  Created on: 18.01.2011
 *      Author: bitcode
 */

#ifndef COMBINATION_H_
#define COMBINATION_H_

#include <iostream>
#include <sstream>
#include <string>
using namespace std;

class Combination {
private:
	int max;
	int length;

	int *value;
    int *constValue;
    int *maxValue;
public:
	Combination(int combination, int size);
	virtual ~Combination(void);

	bool Next(int i);
	bool NextValue(int i);
	void NewConstValue(int i, int newValue);
	bool IsMax(int i);
	int* getValue(void);
	string ToString(void);
};
#endif /* COMBINATION_H_ */
Code:
/* Combination.cpp
 *  Created on: 18.01.2011
 *      Author: bitcode
 */

#include "Combination.h"

Combination::Combination(int combination, int size) {
	max = size;
    length = combination - 1;

    Combination::value = new int[combination];
    Combination::maxValue = new int[combination];
    Combination::constValue = new int[combination];

    int i;
    for (i = length; i >= 0; i--){
        value[i] = i + 1;
        constValue[i] = i + 1;
        maxValue[i] = size--;
    }
}

Combination::~Combination() {
	delete[] value;
	delete[] constValue;
	delete[] maxValue;
}

bool Combination::Next(int i) {
	bool finish = false;
    if (i == 0)
    {
    	if (!IsMax(i))
            NextValue(i);
        if(IsMax(i))
        	return true;
        return false;
    }
	if (IsMax(i)){
		finish = Next(i - 1);
		NewConstValue(i ,value[i - 1] + 1);
	}
	else
		NextValue(i);
    return finish;
}

bool Combination::NextValue(int i) {
    if (value[i] < maxValue[i])
        value[i]++;
    else if (value[i] == maxValue[i])
        return true;
    return false;
}

void Combination::NewConstValue(int i, int newValue){
    if (newValue <= maxValue[i]){
        constValue[i] = newValue;
        value[i] = newValue;
    }
}

bool Combination::IsMax(int i){
    if (value[i] == maxValue[i])
        return true;
    return false;
}

int* Combination::getValue(void) {
	return value;
}

string Combination::ToString(){
	int i;
	ostringstream outStream;
	for (i = 0; i <= length; i++)
		outStream << value[i] << " ";
	return outStream.str();
}
 
Zuletzt bearbeitet:
Welche DLLs? Hast du das Ganze auch als Release kompiliert (nicht Debug)?
Bei Debug wäre die Langsamkeit normal.

Zum Absturz: Ich habs zurzeit ziemlich eilig, kanns also selber nicht ausprobieren.
Aber wahrscheinlich ist die vorletzte Zeile im main das Problem:
c.~Combination();
Am Ende von main wird das automatisch nocheinmal gemacht.
Und du kannst die gleichen drei Arrays eben nicht doppelt deleten.

Zum Mehrkernproblem: Wieso bist du dir da so sicher, dass es alle Kerne nimmt?
Ich kann jedenfalls keinen Threadstart im Programm entdecken.
 
Zuletzt bearbeitet:
Hi und herzlich willkommen
weil ihr hörte das c/c++ schnell arbeitet habe ich einen Teil meines Programmes in c++ umgeschrieben ohne dabei das .net Framework zu benutzen.

Mal ein kleiner Exkurs:
Es liegt in der Natur der Sache, dass unmanaged Code schneller ausgeführt werden kann, als managed Code. Das gilt für alle managed Sprache, sei es VB, die .NET Sprache, Java, usw.
Grund ist, dass managed Code innerhalb einer Runtime läuft, die die Dinge abnimmt, die es in einer unmanaged Umgebung nicht gibt. Dazu gehören im Fall .NET die Garbage Collection aber auch die Prüfung von Security-relevanten Dingen. Dies verlangsamt die Ausführung natürlich. Jedoch nicht so, dass der Anwender davon etwas mitbekommt.

Die Aussage "möglichst effizient und schnell" ist natürlich relativ! Mit mangelnden Kenntnissen in C++ ist es ein leichtes, Code zu schreiben, der weder das eine noch das andere ist.
 
@sheel
alle deine punkte waren richtig
es war nur ein debug und nicht release build
ich wusste nicht das "c.~Combination();" von selbst am ende aufgerufen wird
es nutzt doch nicht mehrere kerne
und ich habe heute versucht einen 64bit compiler zu benutzen und ich bin daran gescheitert
jedenfals probier ich es gleich nochmal als release build

ich möchte bald mit threads arbeiten, hast du vielleicht eine buchempfehlung an mich ?
 
Zuletzt bearbeitet:
Zum 64bit-Compiler: Warum gescheitert? Was geht denn nicht?
Compiler nicht startbar, Fehlermeldungen beim kompilieren von diesem Code... etc?

Zum ~Combination: Nur damit keine Missverständnisse entstehen, in C und C++ wird nicht in jedem Fall automatisch aufgeräumt wie in C#.

Zum Vergleich:
Dieser C#-Code
[cs]
Combination x;
x=new Combination();
...
[/cs]
würde in C/C++ so ausschauen:
C++:
Combination *x;
x=new Combination();
...
delete x;

In beiden Fällen gibt es das Objekt vor dem new noch nicht.
new ruft auch in beiden Fällen automatisch den Konstruktor auf.

In C# wird das Objekt, wenn es nicht mehr gebraucht wird, automatisch entfernt (und vor dem entfernen noch der Destruktor augeführt).
In C/C++ gibts für Destruktor/entfernen delete, keinen automatischen Garbage Collector.

Du hast jetzt aber statt
C++:
Combination *x;
x=new Combination();
...
delete x;
das geschrieben
C++:
Combination x;
...
Ohne *, new oder delete.

Der Unterschied: Beim oberen kannst du zur Laufzeit entscheiden, ob du ein Objekt anlegst oder nicht (if...).
Beim unteren gibt es die Combination x immer, auch wenn du x im ganzen Programm nicht benötigst.
Das wird schon fest ins Programm mitkompilert; dafür spart man sich dann new und delete.

Etwas Vergleichbares zur unteren Variante gibts in C# nicht, dort wird immer new verwendet.

@Debug/Release: Hat sich dann ja aufgeklärt.
Debug ist nur zur Fehlersuche (erleichtert diese sehr), ist um einiges langsamer als das Releaseprogramm und braucht von bestimmten DLLs eine extra zugeschnittene Debug-Version.
Diese DLLs werden in der Regel mit Visual Studio mitinstalliert, funktioniert daher aber auch nur auf Computern mit VS.
(Man könnte die DLLs natürlich auch mitkopieren, zur Fehlersuche braucht man VS aber trotzdem wieder).

@Threads: Habe leider keine Buchidee.
Aber schau dir mal _beginthread und alles rund um EnterCriticalSection an.
Google bringt genug.

Gruß
 
Zuletzt bearbeitet:
Zum 64bit-Compiler: Warum gescheitert? Was geht denn nicht?
Compiler nicht startbar, Fehlermeldungen beim kompilieren von diesem Code... etc?
Es hat lange gedauert bis meine IDE den Compiler gefunden hat und anschliessend hat es nicht geklappt.
bei einem manuelen versich bekam ich die meldung keine zuöässuge win32 anwendung oder soetwas in der art

Fals es jemanden interessiert, hier sind die aktuellen ergäbnisse meines release build
mit meinem code ca. 1/4 bis 1/3 schneller als in c#
ich habe mir noch etwas mehr erhofft
Code:
--------------------------------------
C++:
CPU belastung ca. 25%
--------------------------------------
Die größe der Kombination: 40 Aus: 49
Seit dem Start sind 00:01:16 vergangen.
Kombinationen:  2.054.455.634

Die größe der Kombination: 39 Aus: 49
Seit dem Start sind 00:04:41 vergangen.
Kombinationen:  8.217.822.536

Die größe der Kombination: 38 Aus: 49
Seit dem Start sind 0:15:10 vergangen.
Kombinationen: 29.135.916.264

Die größe der Kombination: 36 Aus: 49
Seit dem Start sind 01:54:07 vergangen.
Kombinationen: 262.596.783.764
--------------------------------------

jetzt habe ich nur noch eine kleine frage
ist das in ordnung oder muss ich zwichen den new auch deleten ?
laut meiner logic sollte man es dazwichen auch deleten
ein simples ja oder nein reicht
wenn diese frage beantwortet wurde darf man von mir aus das thema schließen
C++:
Combination *x;
x=new Combination();
...
x=new Combination();
...
delete x;

danke nochmals für deine hilfe sheel
mfg bitcode
 
Bin zwar nicht der C++ Experte, aber wenn ich mich recht entsinn solltest du das tun, da du sonst beim zweiten new die alte Referenz im Speicher lässt, dies aber nicht mehr nutzen kannst. Die Folge: Memory Leak
 
Also ja, zu jedem new gehört ein delete.

Und das Thema als erledigt markieren kann der Ersteller selber, mit dem Haken neben "Auf Thema Antworten"

Gruß
 
Zurück