Multithreading …

Kann ich vielleicht die neu in den C++-Standard integrierten Threads für mein Projekt verwenden? Ich tippe mal folgendes Beispiel aus der iX ab und messe die Zeit der Ausführung, für einen Thread und für beide Threads, mit std::lock_guard und Zugriff auf gemeinsame Variable und ohne:

#include <iostream>
#include <thread>
#include <time.h>

int counter;
const int NCOUNTS = 10000000000;
std::mutex incrementMutex;

void increment(){
    for (int i=0; i<NCOUNTS; i++){
        std::lock_guard<std::mutex> lock(incrementMutex);
        counter++;
        std::cout << counter << std::endl;
    }
}

void decrement(){
    for (int i=0; i<NCOUNTS; i++){
        std::lock_guard<std::mutex> lock(incrementMutex);
        counter--;
        std::cout << counter << std::endl;
    }
}


main(){

    time_t seconds = time (NULL);

    std::thread a(increment);
    std::thread b(decrement);
    a.join();
    b.join();

    time_t seconds2 = time(NULL);
    std::cout << std::endl << seconds2-seconds << std::endl;
}

Mein aktueller g++ kommt ja schon zum großen Teil mit den neuen C++11-Features zurecht, so dass ich mit g++ -std=c++0x -pthread thread.cpp -o thread das Programm kompilieren kann. Der ich noch nicht so viel mit dem gefürchteten Thema des gemeinsamen Zugriffs von Threads auf Ressourcen zu tun hatte, bin überrascht. Benutze ich std::lock_guard und lasse beide Threads gleichzeitig die Variable count manipulieren, hört die Ausführung mit diesem NCOUNTS nicht mehr in vertretbarer Zeit auf. Ohne gemeinsamen Variablenzugriff hingegen, dauert die Ausführung 4 Sekunden. Eine Zeitersparnis hat man also nur ohne Zugriff auf gemeinsame Ressourcen. Wenn ohne diesen Zugriff beide Threads so ideal wie hier das selbe tun, kann man dies wunderbar parallelisieren. Man sieht schön in der Systemüberwachung und anhand der Ausgabe der benötigten Zeitdauer, dass hier in gleicher Zeit das Doppelte getan wird. Aber wo kann man in der Realität eine Aufgabe in genau gleiche Teile teilen? Mal schauen, ob ich diese Verwendung noch in meiner Programmiererei unterbringen kann … Threads sind aber auch da sinnvoll, wo Multitasking ermöglicht werden soll. Android schreibt z.B. vor, dass länger dauernde Prozesse nicht im GUI-Thread laufen, sondern parallelisiert werden sollen. Wird die Ausführung der Oberfläche auch für einige Sekunden unterbrochen, sieht der Benutzer den gefürchteten ANR (Application not responding)-Dialog. Natürlich läuft eine Oberfläche flüssiger, wenn Hintergrundprozesse auch in einem eigenen Thread laufen.

Posted in C++

Gutes altes C++, Qt und QtCreator

Zurück zum guten alten C++. Was soll dieser ganze neumodische Schnickschnack eigentlich? Was Grafischs soll es diesmal sein. Ich visualisiere ein Buch. Ich gehe jedes einzelne Wort des Buches durch. Wenn es sich in einer Stopwortliste befindet, wird es ignoriert. Stopworte sind bedeutungslose Wörter wie sein, ist, wird, war, ein, auf, … Die auf diese Weise gefunden natürlichen Wörter werden gezählt und gemerkt. In dieser Liste gehören aber immer noch viele Worte zum selben Wortstamm. Z.B. gehören laufen, gelaufen, lief, lauf(!) zum selben Stamm. Es gibt einen Algorithmus, den Porter Stemmer, der Worte anhand irgendwelcher Regeln auf ihren Wortstamm zurück führt. Dieser Algorithmus wird in der Computerlinguistik und im Information Retrievel angewendet. Perfekt geht das natürlich nicht. Auch Suchmaschinen ignorieren Stopwörter und betrachten die Stämme von Wörtern, um die Vielfalt von Worten zu reduzieren. Die nun gewonnenen gestemmten Wörter will ich nun der Häufigkeit nach sortieren und visualisieren. Die Wörter breiten sich spiralförmig von der Mitte bis zum Rand aus. In der Mitte befinden sich die Wörter, die am häufigsten im zu betrachtenden Text vorkommen und am Rand die seltensten Wörter des Textes. Nun kann man in diese Wortebene hinein und herauszoomen. Klickt man auf ein Wort, soll man grafisch sehen, welche anderen Worte mit diesem Wort am häufigsten im selben Satz/Kapitel vorkommen. Bis dahin erstmal. Wofür das Ganze? Weil ich Lust habe, etwas zu programmieren. Weil die geforderte Geschwindigkeit der vielen Berechnungen und die Geschmeidigkeit der grafischen Ansicht C++ erfordern. Und es gibt bestimmt Bücher, die man so meditativ betrachten kann. Zum Einsatz kommen Qt und QtCreator, da ich unter Linux entwickeln will. Bisher habe ich den Porter Stemmer, welcher in C geschrieben ist, plattgeklopft, in ein Verzeichnis portiert und in mein QtCreator-Project integriert. Der Algorithmus ist pfeilschnell und hier lobe ich mir C. Ich brauche ja hier nicht viel Hand an die Pointerarithmetik und an Arrayoperatonen anlegen zu müssen. Aber eine Liste von 35.000 Wörtern ist in Null, Nichts gestemmt. Ich habe mir eine Stopwortliste aus heruntergeladenen Stopwortlisten generiert und meine Datenstrukturen in Headerdateien festgehalten. Bisher habe schon einige STL-Container verwendet: set, vector, map. Das kleine Projekt scheint also einiges zum Spielen zu bieten. QtCreator finde ich gar nicht schlecht. Kleinere Sachen stoßen mir übel auf. Warum kann man z.B. in der Projektansicht nicht mehrere Dateien auswählen und löschen? Nein, es geht nur einzeln. Beim Debuggen von Konsolenanwendungen bekomme ich eine Fehlermeldung. Nachforschungen zufolge, könnte ich diese oder jene Einstellung in einer Datei ändern. Na gut, dann eben keine Konsolenanwendung. Entgegen der Menübeschreibung kann ich einen markierten Text mit Strg+/ nicht auskommentieren, sondern die Hilfe ploppt auf. Nun ja, von solchen kleinen Dingen abgesehen, klappt die Entwicklung aber ganz gut. Ich kann mit QtCreator schön zwischen der Definition und der Deklaration von Methoden und Variablen hin- und herspringen, eine Funktion, die Visual Studio nur in Verbindung mit Visual Assist bietet. Grafisch sieht die IDE ganz gut aus, unter Linux ist man anderes gewohnt. Qt scheint also auch nicht schlecht zu sein. Der Editor mit seiner Syntaxvervollständigung ist geschmeidig. Funktionen, wie Funktionsrümpfe anhand des Headers zu erstellen, vermisse ich. Es ist also etwas Handarbeit nötig. Warum kann ich die kleinen Fensterchen Haltepunkte, Aufrufliste, Lokale Variablen und Ausdrücke … nicht wie bei Eclipse oder Visual Studio zu einem Fenster mit verschiedenen Tabs vereinigen und auf einen anderen Bildschirm schieben? Es gibt viele Kleinigkeiten, die nicht so ganz laufen, und die Kleinigkeiten machen den Komfort aus. Aber das ist unter Linux der Preis der Freiheit. Schließlich bin ich ja bei Qt und wenn es mich nervt, kann ich nach Windows und zu anderen IDE wechseln.
Da ich früher bei der Arbeit immer mit CString gearbeitet habe, frage ich mich jetzt, wie ich mit std::string umgehen soll. Etwa gemäß RAII (Resource Acqusition is Initialization) vorgehen und in shared_ptr verpacken? In Effective STL von Scott Meyers habe ich dann aber noch mal nachgelesen, dass die STL ihre Objekte selbst verwaltet. Genauso, wie ich vector-Objekte selbst nicht lösche, muss ich mich auch nicht um das dynamische Erzeugen und das Löschen von string-Objekten kümmern.

Posted in C++