Ich habe das ganze mal mittels PThreads und C realisiert. Kompiliert habe ich es unter Debian 8 mit gcc, da Windows aber ebenfalls POSIX-Threads unterstützt, sollte sich das auch mit VC++ oder so für Windows kompilieren lassen.
Es ist zu beachten, dass durch meine Realisierung des Threadings nur gerade Threadanzahlen möglich sind. So spare ich mir das alternierende Vorzeichen in der Hauptschleife. Mein Lösungsweg kurz dargestellt am Beispiel von 4 Threads:
Leibniz-Reihe: 1 - 1/3 + 1/5 - 1/7 + 1/9 - 1/11 + 1/13 - 1/15...
Thread 1: 1 + 1/9 +...
Thread 2: 1/3 + 1/11 + ...
Thread 3: 1/5 + 1/13 + ...
Thread 4: 1/7 + 1/15 + ...
Ergebnis: (Thread 1 + Thread 3) - (Thread 2 + Thread 4)
In Worten: Ich erzeuge Teilsummen bei gleicher Schrittgröße durch unterschiedliche Startwerte. Um das wechselnde Vorzeichen zu beachten, wird am Ende die Summe aller geraden Threads von der Summe der ungeraden Threads subtrahiert. (Mein Programm arbeitet direkt mit Brüchen, die im Zähler 4 stehen haben, um die Multiplikation am Ende zu sparen.)
Ansonsten... Der C-Code an sich ist total unoptimiert. Es ging hier wirklich nur ums Threading. Außerdem ist die ein oder andere Programmiersünde im Quellcode enthalten.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#define DEBUG 0
#define THREADS 5
#define LOOPSEACH 100000000 / THREADS
//Threadfunktion
static void *loop(void* result) {
//void* result: Doppelt benutzte Variable
// 1. Übergabe des Startwertes
// 2. Rückgabe der Teilsumme
int i = (int) (*((double*)result));
const int add = 2*THREADS;
*((double*)result) = 0.0;
#if DEBUG
printf("Enter Thread.\n");
#endif
int count = LOOPSEACH;
while(count--) {
*((double*)result) += (double)4.0/i;
i += add;
}
#if DEBUG
printf("Exit Thread.\n");
#endif
pthread_exit(0);
}
int main (void) {
pthread_t threads[THREADS];
double parts[THREADS];
double pi = 0.0;
int error;
for(int i = 0; i < THREADS; i++) {
parts[i] = (double)((i * 2) + 1);
error = pthread_create(&threads[i], NULL, &loop, &parts[i]);
if(error) {
#if DEBUG
printf("Cannot start Thread %d.\n", i+1);
#endif
return EXIT_FAILURE;
}
}
for(int i = 0; i < THREADS; i++) {
pthread_join(threads[i], NULL);
pi += parts[i] * (((i+1)%2) ? +1 : -1); //Vorzeichenwechsel
}
printf("Pi: %f\n", pi);
return EXIT_SUCCESS;
}
Alles anzeigen