Apfelmännchen mit Parallel Pattern Library
Das OpenMP-Programm muss leicht modifiziert werden.
//: pplmandelbrot.cpp : Fraktalbild - R.Richter 2011-01-27 ////////////////////////////////////////////////////////// // mit Parallel Pattern Lib (VC10) #include <ppl.h> #include <ctime> #include <iostream> #include <complex> #include "image.h" typedef std::complex<double> complex; int compute(complex c, int maxIterations) { int count = 0; complex z; while (abs(z) <= 2.0 && count < maxIterations) { z = z * z + c; ++ count; } return count; } inline Color color(int height, int max) { // color scheme from: // http://shreyassiravara.wordpress.com/2010/08/14/the-mandelbrot-set/ if (height >= max) return Color::BLACK; double h = 255 * log(double(height)) / log(double(max)); return Color(0.9 * h, 0.8 * h, 0.6 * h); } inline double scale(int pos, int length, double low, double high) { return low + pos * (high-low) / (length-1); } Image mandelbrot(int width, int height, int maxIterations, complex left_bottom, complex right_top) { Image image(width, height); Concurrency::parallel_for (0, height, [&](int y) { for (int x = 0; x < width; ++x) { complex c(scale(x, width, real(left_bottom), real(right_top)), scale(y, height, imag(left_bottom), imag(right_top))); int iterations = compute(c, maxIterations); image.pixel(x, y) = color(iterations, maxIterations); } }); return image; } int main() { int width = 1000; int height = 1000; int maxIterations = 10000; complex left_bottom(-2.0, -2.0); complex right_top ( 2.0, 2.0); saveBMP("mandel.bmp", mandelbrot(width, height, maxIterations, left_bottom, right_top)); std::cout << clock() / double(CLOCKS_PER_SEC) << " seconds CPU time\n"; return 0; }
Der Abschnitt
Concurrency::parallel_for (0, height, [&](int y) { // ... });
nutzt zur Parallelisierung eine Template-Funktion der zunächst nur bei Visual Studio verfügbaren Bibliothek <ppl.h>. Als deren dritter Parameter fungiert ein Lambda-Ausdruck (eine Adhoc-Funktion)
[&][int y){ /*... */ }
die den eigentlichen Schleifenrumpf darstellt. Diese Version (Release-Konfiguration) benötigt 116 Sekunden Laufzeit, die ebenfalls mit Visual C++ erstellte OpenMP-Version (Kommandozeilen-Option /openmp) 130 Sekunden. die nichtparallelisierte Version 223 Sekunden.
Rechenzeit und Prozessorauslastung sind hier nicht von der Berechnungsfolge (waagerecht oder senkrecht) abhängig. Dies deutet darauf hin, dass für jeden Wert des Durchlaufzählers eine eigene Task an den intern genutzten Threadpool übergeben wird.