Seite 1 von 2

C++0X Thread Class

Verfasst: Fr Dez 14, 2012 2:36 pm
von Fisherman
Hallo zusammen,

ich lese mich gerade ein bisschen in C++0X ein und bin einfach nur begeistert von der Möglichkeit nun auf unkomplizierte Art und Weise Klassen als Threads laufen zu lassen.
Früher mußte man Zeiger verbiegen, bis einem "schlecht" wurde um dies zu erreichen ...

Hier ein kleines Hello World - Beispiel :
g++ -pthread -o helloclass helloclass.cpp -std=c++0x

Code: Alles auswählen

#include <iostream>
#include <thread>

class bgthread
{
private:
        void printtext()
        {
                std::cout << "Thread Class says HelloWorld\n";
        }
public:
        void printit()
        {
                int loop = 10;
                while (loop > 0)
                {
                        this->printtext();
                        --loop;
                }
        }
};

int main()
{
        bgthread x;
        std::thread th(&bgthread::printit,&x);
        th.join();
        return 0;
}
Vielleicht hilft dies dem ein oder anderen ....

Gruß Fisherman

Re: C++0X Thread Class

Verfasst: Fr Dez 14, 2012 6:40 pm
von Xin
Schreib es etwas ausführlicher und mache einen Artikel daraus. Solche Informationen sollten möglichst im Wiki landen.

Re: C++0X Thread Class

Verfasst: Fr Dez 14, 2012 8:17 pm
von Fisherman
OK, bin dabei ;)

Werde mir das "Wortzähl-Projekt" vornehmen und versuchen mit der Hilfe von Threads deinem Sieger-Algorithmus noch ein bissle Kerosin zu verpassen ;)

Gruß Fisherman

Re: C++0X Thread Class

Verfasst: Sa Dez 15, 2012 5:30 pm
von Fisherman
Salute,

also direkt ein dokuWiki wird es wohl doch nicht - mir fehlt die Zeit dazu.
Wer aber etwas über c++0x erfahren möchte sei auf das engl. Tutorial verwiesen.

Generell läßt sich aber festhalten, dass Threads einen enormen Performance-Schub auslösen und man dieses Thema nicht ignorieren sollte. Auch sind neue Zeitmessroutinen (std::chrono) hinzugekommen, die wirklich erstklassig sind!

Hier mal eine Testausgabe meines heutigen Ergebnisses [Debug]
Sequentiell: Xin_Speed Algorithmus - Thread: 4 x Xin Speed Algorithmus parallel

Code: Alles auswählen

Lasse nun alle 4 Buffer sequentiell durchrechnen...
Anzahl Wörter :200640001
Anzahl Wörter :200640001
Anzahl Wörter :200640001
Anzahl Wörter :200640001
Gesamtzeit : 5530 ms
Lasse nun 4 Threads jeweils 1 Buffer berechnen ...
Anzahl Wörter :200640001
Anzahl Wörter :200640001
Anzahl Wörter :200640001
Anzahl Wörter :200640001
Gesamtzeit : 2570 ms
Threads waren 215.175 % schneller
Gruß Fisherman

Re: C++0X Thread Class

Verfasst: Sa Dez 15, 2012 10:19 pm
von Fisherman
Ein wenig kommt doch noch zum Thema <random> und C++0x

Es wurden ein paar Neuerungen bzgl. des Zufallsgenerators eingebaut. Man kann nun unter verschiedenen Generatoren wählen. eine Liste der Zufallsgeneratoren ist hier aufgelistet.

Die ebend angesprochene Chrono Bibliothek soll im folgenden verwendet werden um den mt19937_64 (64bit) zu initialisieren. Im Prinzip genauso wie früher mittels time(NULL) nur halt "moderner" ...

Ich habe jeweils ein kleines Beispielprogramm zu den folgenden Themen geschrieben um das ganze besser zu verdeutlichen:

ChronoSeed.cpp

Code: Alles auswählen

#include <chrono>
#include <iostream>

/*
   RandomSeed by Chrono
   Liefert einen Ersatz für die Initialisierung des Zufallsgenerators

   g++ -std=gnu++0x ChronoSeed.cpp -o ChronoSeed
*/


int main()
{
  std::cout << "Zeiten:" << std::endl;
  for (int i=0; i < 10; ++i)
    std::cout << (std::chrono::high_resolution_clock::now().time_since_epoch().count()) << std::endl;
  return 0;
}
Wer ganzzahlige Zufallszahlen aus einer bestimmten Menge von a bis b benötigt dem sei die Uniform INT Distribution ans Herz gelegt. Mit diesem Code kann man leicht die gewünschten Zufallszahlen generieren. Auch ist es möglich von negativen Ganzzahlen bis hin zu positiven Ganzzahlen eine Menge zu erhalten.

UniformINTDistribution.cpp

Code: Alles auswählen

#include <random>
#include <chrono>
#include <iostream>

/*
   Uniform INT distribution
   Liefert ganzzahlige Zufahlszahlen aus der Menge [int]min. bis [int]max.

   g++ -std=gnu++0x UniformINTDistribution.cpp -o UniformINTDistribution
*/


int main()
{
	// Zufallsgenerator initalisieren (64bit Variante)
	std::mt19937_64 eng(std::chrono::high_resolution_clock::now().time_since_epoch().count());

	int min = 2, max = 8;
	std::cout << "Uniform INT Distribution :[" << min << "," << max << "]" << std::endl;
        // Bereich festlegen aus der die Zahlen generiert werden sollen
        std::uniform_int_distribution<int> uniform_int(min,max);
	for (int i=0; i < 10; ++i)
          {
	    for(int j=0; j < 10; ++j)
	    {
	       // Zufallszahl aus Bereich ausgeben
	       std::cout << uniform_int(eng) << " ";
	    }
          std::cout << std::endl; 
          }
	return 0;
}
Das gleiche gibt es auch für Fließkommazahlen und nennt sich UniformREALDistribution.

UniformREALDistribution.cpp

Code: Alles auswählen

#include <random>
#include <chrono>
#include <iostream>

/*
   Uniform REAL distribution
   Liefert Fliesskomma Zufahlszahlen aus der Menge [double]min. bis [double]max.

   g++ -std=gnu++0x UniformREALDistribution.cpp -o UniformREALDistribution
*/


int main()
{
	// Zufallsgenerator initalisieren (64bit Variante)
	std::mt19937_64 eng(std::chrono::high_resolution_clock::now().time_since_epoch().count());

	double min = 0.1, max = 0.9;
	std::cout << "Uniform REAL Distribution :[" << min << "," << max << "]" << std::endl;
        // Bereich festlegen aus der die Zahlen generiert werden sollen
        std::uniform_real_distribution<double> uniform_real(min,max);
	for (int i=0; i < 10; ++i)
          {
	    for(int j=0; j < 10; ++j)
	    {
               std::cout.fill(' ');
               std::cout.width(10);
	       // Zufallszahl aus Bereich ausgeben
	       std::cout << std::left << uniform_real(eng) << " ";
	    }
          std::cout << std::endl; 
          }
	return 0;
}
Dann haben wir noch die Möglichkeit uns einen zufälligen dualen Wert ausgeben zu lassen. Hierbei kann die Gewichtung wie die "Münze" fallen soll beeinflusst werden je nach Wunsch. Dabei ist allerdings von größeren Mengen auszugehen, die dann in der Summe die gewünschte Gewichtung haben. Man kann allerdings schon bei kleineren Mengen den Unterschied erkennen.

BernoulliDistribution.cpp

Code: Alles auswählen

#include <random>
#include <chrono>
#include <iostream>

/*
   Bernoulli Distribution
   Liefert ein dualen Wert ähnlich einem Münzwurf.

   g++ -std=gnu++0x BernoulliDistribution.cpp -o BernoulliDistribution
*/


int main()
{
	// Zufallsgenerator initalisieren (64bit Variante)
	std::mt19937_64 eng(std::chrono::high_resolution_clock::now().time_since_epoch().count());

	double p = 0.5;
	std::cout << "Bernoulli Distribution :[" << p << "]" << std::endl;
        // Gewichtung der mengenmäßigen Verteilung festlegen
        // 0.25 = 25[0] / 75[1]
        // 0.5  = 50[0] / 50[1]
        // 0.75 = 25[0] / 75[1]
        std::bernoulli_distribution bernoulli(p);
	for (int i=0; i < 10; ++i)
          {
	    for(int j=0; j < 10; ++j)
	    {
	       // Münze werfen ...
	       std::cout << bernoulli(eng) << " ";
	    }
          std::cout << std::endl; 
          }
	return 0;
}
Alle Beispiele sind unter Linux Debian getestet und mit g++ -std=gnu++0x zu kompilieren.
[gcc version 4.7.2 (Debian 4.7.2-4)]

Gruß Fisherman

Re: C++0X Thread Class

Verfasst: So Dez 16, 2012 12:50 am
von Fisherman
Und weil ich im Moment nicht genug von C++0x bekommen kann, da ich immer wieder etwas neues entdecke - hier noch ein nettes Feature. Die Auto Datentyp Erkennung. Vorbei die Zeiten in den man sich Sorgen um den richtigen Datentyp machen mußte. Mit auto wird die Entscheidung direkt dem Compiler überlassen. Einzig muß bei der Deklaration der Variable auch eine Initialisierung erfolgen.

Auto kann auch in Schleifen benutzt werden und so richtig dreht der neue "Befehl" bei Iteratoren von STL Containern auf. Aber genug der Rede - schaut euch den Beispielcode an, den ich ebend zum Thema zusammengestellt habe, nachdem ich das nette Video von Herb Sutter gesehen habe.

Das Beste an der ganzen Sache hier ist, das man keine extra Bibliotheken installieren muss - nur falls es noch nicht aufgefallen sein sollte !!! ;)

AutoType.cpp

Code: Alles auswählen

#include <iostream>
#include <vector>

/*
   AutoType.cpp
   Die Einführung von 'auto' ist eine der größten Änderungen
   in C++0x. Mit auto kann die Entscheidung um welchen Datentyp
   es sich handelt, dem Compiler überlassen werden.

   g++ -std=gnu++0x AutoType.cpp -o AutoType
*/

int main()
{
  auto i = 10, j = 20;
  auto d = 0.753, e = 0.107;
 
  std::cout << "Addiere " << i << " + " << j << " = " << (i+j) << std::endl;
  std::cout << "Addiere " << d << " + " << e << " = " << (d+e) << std::endl;
  std::cout << "Addiere " << (i+j) << " + " << (d+e) << " = " << (i+j+d+e) << std::endl;

  i = 30;
  d = 0.5;

  std::cout << "Dividiere " << i << " durch " << d << " = " << (i/d) << std::endl;
  std::cout << "Multipliziere " << i << " mit " << d << " = " << (i*d) << std::endl;

  std::cout << "Auto funktioniert auch in Schleifen" << std::endl;
  for (auto x = 10; x > 0; --x)
    std::cout << x << " ";

  std::cout << "\n";

  std::cout << "Auch die STL Container können mit auto arbeiten" << std::endl;
  std::vector<int> myVec {1,2,3,4,5};

  auto total = 0;
  for ( auto it : myVec)
  {
    std::cout << it << " ";
    total += it;
  }
  std::cout << " Summe = " << total << std::endl;

  return 0;
}
Gruß Fisherman

Re: C++0X Thread Class

Verfasst: Mo Dez 17, 2012 9:35 pm
von sebix
Den Auto-"Datentypen" kenn ich ja schon, besonders bei den Iteratoren liebe ich ihn, but wait: What's that?

Code: Alles auswählen

for ( auto it : myVec)
Was ist denn das für eine geniale Schleifendefinition?!

Re: C++0X Thread Class

Verfasst: Di Dez 18, 2012 3:35 am
von Fisherman
Genau - intuitives programmieren ....

Vielleicht interessiert Dich auch noch der folgende Artikel. Hier geht es um die Lambda Funktion, oder einfacher ausgedrückt um namenlose inline Funktionen.

Re: C++0X Thread Class

Verfasst: Di Dez 18, 2012 11:49 am
von Kerli
Lambda Funktionen gibt es auch bei uns im Wiki ;)

Übrigens mit 'auto' würde ich sparsam umgehen. Wenn der Typ bekannt ist und vor allem wenn dieser auch nicht übermäßig kompliziert ist (zb. kein Typ irgendwie in ein Template eingepackt) würde ich auf jeden Fall den Typ ausschreiben. Das ist meistens gleich schnell (bei 'int' statt 'auto' sogar schneller ;)) und macht den Code leichter lesbar bzw. auch weniger anfällig gegen Fehler, da nicht durch eine unscheinbar Änderung der Typ geändert werden kann:

Code: Alles auswählen

auto total = 0.5; // total ist vom Typ double
auto total = 1;    // Jetzt wird total vermutlich int oder etwas ähnliches sein
float total = 1;    // So ist man sicher dass total float bleibt, egal welchen Wert man verwendet

Re: C++0X Thread Class

Verfasst: Di Dez 18, 2012 7:11 pm
von sebix
Vielen Dank für die beiden Links, so wird C++-Code doch noch lesbarer!