MiniBachelor
|
#include <vector>
#include <sstream>
#include <iostream>
#include <fstream>
#include <string>
#include <mutex>
#include <chrono>
#include <thrift/protocol/TBinaryProtocol.h>
#include <thrift/transport/TSocket.h>
#include <thrift/transport/TTransportUtils.h>
#include "gen-cpp/Solver.h"
#include "include/Buffer.hpp"
#include "include/Connection.hpp"
Makrodefinitionen | |
#define | CONFIGFILE "farmer.conf" |
#define | INITIALOPT 0 |
Funktionen | |
void | fillInitialFix (void) |
bool | isValid (vector< bool > fix) |
void | branch (vector< bool > fix) |
void | workerFunction (SolverClient *remote) |
void | farmerFunction (void) |
void | distributor (string fileName) |
int | main (int argc, char *argv[]) |
Variablen | |
Instance | in |
diese Daten werden später an die Worker gesendet Mehr ... | |
int | workerCnt |
int | vorbelegung |
mutex | muSol |
SolveResult | sol |
mutex | muJobs |
long long int | jobs |
long long int | jobAdd |
Buffer< vector< bool > > | jobBuffer |
bool | killWorker |
chrono::steady_clock::time_point | go |
Im C++2011 Standard gibt es nicht nur mutex, sondern auch bessere Zeitmessungs-Funktionen. Mehr ... | |
chrono::steady_clock::time_point | fin |
vector< vector< bool > > | initalFix |
In dieser Variablen werden alle Vorbelegungen inital abgespeichert. Mehr ... | |
#define CONFIGFILE "farmer.conf" |
#define INITIALOPT 0 |
void branch | ( | vector< bool > | fix | ) |
Diese Funktion fügt an eine Vorbelgung eine weitere Vorbelegung hinzu. Wenn diese neue Vorbelegung gültig ist, wird sie dem JobBuffer begefügt. Diese Funktion ist ein Produzent, da sie in den Buffer Jobs ablegt. Es kann etwas verwirrend sein, weil ein Worker-Thread in diesem Beispiel im Grunde sowohl Konsument als auch Produzent ist, weil in einem Worker die branch() Funktion aufgerufen wird. Diese Vermischung ist unüblich.
fix | ist ein Bool-Vektor mit einer Projekt-Vorbelegung |
void distributor | ( | string | fileName | ) |
Diese Funktion stellt die Verbindung zu allen Workern her und startet zur asynchronen Verarbeitung der Verbindungen Worker-Threads (= Proxies). Ein Farmer-Thread, der primär eine überwachende Funktion über die Worker-Threads und den jobBuffer hat, wird ebenfalls gestartet.
fileName | Der Name der Konfigurations-Datei, in der alle Infos zur Verteilung (engl.: Distribution) stehen |
void farmerFunction | ( | void | ) |
Diese Funktion läuft auch als Thread. Sie ist ein Produzent weil sie mit push() in den Buffer Jobs ablegt. Eine kleine Endlos-while-Schleife prüft alle 500000 Microsekunden, ob bereits alle Jobs aus den Buffer erledigt wurden. Ohne das usleep würde dieser Farmer-Thread viel CPU-Zeit kosten.
void fillInitialFix | ( | void | ) |
Um in der Funktion branch() nicht jedes mal einen binären Vektor hoch zu zählen, wird dies einmal zu Anfang mit dieser Funktion gemacht und die Werte dem bestehenden fix-Vector nur noch beigefügt. Statt Parameter arbeitet die funktion mit der globalen Variable vorbelegung.
bool isValid | ( | vector< bool > | fix | ) |
Die Funktion isValid() testet einen binären Vektor, ob dieser eine gültige Projekt-Vorbelegung enthält.
fix | ist ein Bool-Vektor mit einer Projekt-Vorbelegung |
int main | ( | int | argc, |
char * | argv[] | ||
) |
Der "Farmer" ist die Client Anwendung, die die in kleine Teilprobleme aufgeteilten Aufgaben für glpk auf die Worker (Server) verteilt.
void workerFunction | ( | SolverClient * | remote | ) |
Diese Funktion wird als Thread benutzt und ist ein Proxy. Zu jeder Verbindung zu einem Service eines Workers existiert auf dem Farmer so ein Thread. Solange wie dieser aus jobBuffer
Jobs holen kann und die Variable killWorker
keinen Abbruch erzeugt, werden Jobs an den Service der Worker zum lösen - also solve() - gesendet. Dieser Thread ist ein Konsoment und durch eine Semaphore in Buffer
geschieht beim pop() aufruf nichts, solange im Buffer nichts ist.
remote | Repräsentiert den Service des Workers |
chrono::steady_clock::time_point fin |
chrono::steady_clock::time_point go |
Im C++2011 Standard gibt es nicht nur mutex, sondern auch bessere Zeitmessungs-Funktionen.
Instance in |
diese Daten werden später an die Worker gesendet
vector<vector<bool> > initalFix |
In dieser Variablen werden alle Vorbelegungen inital abgespeichert.
long long int jobAdd |
Buffer<vector<bool> > jobBuffer |
Dieser Buffer nimmt alle Jobs auf - also alle Projekt-Vorbelegungen, bei denen die Worker mit glpk eine optimale Lösung finden sollen.
long long int jobs |
bool killWorker |
mutex muJobs |
Die Variable jobs
wird ebenfalls von allen Threads ausgelesen und verändert. Dieser kritische Bereich muss ebenfalls geschützt werden.
mutex muSol |
Da alle Threads (= unsere Worker-Proxies) auf die sol
Variable zugreifen können, muss dieser Zugriff mit einer Mutex-Semaphore geschützt werden.
SolveResult sol |
int vorbelegung |
int workerCnt |