Paralleles Auslesen von diversen Sensoren und Zusammenbauen der Daten
Soweit ich verstanden habe, besteht die Aufgabe darin, den AD-Wandler mit einer Frequenz im Bereich 1 kHz und die Koordinaten mit einer Frequenz im Bereich 10 Hz auszulesen. Evtl. kommen auch mal noch weitere Sensoren hinzu. Die Weiterverarbeitung soll in Form von n-Tupeln (Zeitstempel; AD-Wert; Koordinaten) erfolgen. Das Ganze soll auch unter Belastung des Rechners noch zuverlässig erfolgen. Die Speicherung der Rohdaten erfolgt dabei sinnvollerweise nicht als n-Tupel, sondern in einem Raster der Art:
mit
Die Koordinaten werden also z.B. nur immer aller 100 Werte auch wirklich ausgelesen und aufgeschrieben. Aus solch einem File kann für die Weiterverarbeitung sofort eine Liste mit kompletten n-Tupen erstellt werden.
Verschiedene Prozesse
Die Kommunikation könnte man über Pipes, Fifos, Shared-Memory, Message-Queues, TCP (Sockets) machen, im Prinzip auch mit MPI.
- MPI ist Mist, weil man dann immer ein MPI-System braucht
- Message Queues sind im Prinzip cool, praktisch aber viel zu kurz und für zu kleine Datenmengen gedacht (10 Messages a 8kB ist Standard unter Linux). Dafür soll das halt sehr schnell sein (im L1-Cache bleiben etc).
- Pipes, Fifos ist halt ein bisschen fummelig. TCP keine Ahnung
- SHMem ist eigentlich ziemlich ok. Man muss natürlich von Hand synchronisieren. Das ist eigentlich auch kein Ding weiter. Wenn man einmal Zugriff auf den gemeinsamen Speicherbereich hat, sollte das nicht schwieriger sein als mit OpenMP (s.u.).
Verschiedene Threads
Nachteil ist, dass die einzelnen Ausleseprozesse nicht gegeneinander geschützt sind.
OpenMP
Dafür gibt es die nahezu triviale Variante mit OpenMP. Der geringe Aufwand könnte die eher theoretischen Nachteile durchaus wieder wettmachen, finde ich. Ich stelle mit das ungefähr so vor:
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <omp.h>
#include <unistd.h>
using namespace std;
int showAction;
/* Das ist eine etwas missbräuchliche aber immer noch sehr einfache Verwendung
von OpenMP zur Arbeit mit Threads. Auf alle Fälle ist es schön
einfach. Evtl. müssen die Jobs das Lesen nicht in einer critical Section
machen aber es wird hier nichts schaden.
*/
int job1(void)
{
for(;;)
{
#pragma critical
int sAct=showAction;
if (sAct&1) cout << "1";
cout.flush();
usleep(5000); // nominell 5 ms
}
}
int job2(void)
{
for(;;)
{
#pragma critical
int sAct=showAction;
if (sAct&2) cout << "2";
cout.flush();
usleep(5000); // 5 ms
}
}
int job3(void)
{
for(;;)
{
#pragma critical
int sAct=showAction;
if (sAct&4) cout << "3";
cout.flush();
usleep(5000); // 5 ms
}
}
int main()
{
int nthreads, tid;
omp_set_nested(1);
/* Fork a team of threads with each thread having a private tid variable */
#pragma omp parallel private(tid) num_threads (4)
{
/* Obtain and print thread id */
tid = omp_get_thread_num();
printf("Hello World from thread = %d\n", tid);
switch (tid)
{
case 1: job1(); break;
case 2: job2(); break;
case 3: job3(); break;
}
/* Only master thread does this */
if (tid == 0)
{
nthreads = omp_get_num_threads();
printf("Number of threads = %d\n", nthreads);
}
for(;;) // master thread verteilt die aufgaben
{
#pragma critical
showAction=rand();
usleep(100000); // nominell 100 ms
}
} /* All threads join master thread and terminate */
}
Synchronisation
Mit den Pragmas von OpenMP kann man eine Synchronisation erreichen. Ein Thread wartet auf andere Threads, ich würde denken aktiv. Für Zwecke des Datensampelns sind die meisten Threads fast immer in Wartestellung. OpenMP bietet die Möglichkeit, Locks zu setzen. Darauf aufbauend könnte man eine sinnvolle Datenübergabe bauen und dazwischen die Threads Schlafen legen. Das stelle ich mir so vor: