在理想狀況下,編譯器使用自動並行化可以管理一切事務,使用OpenMP指令的一個優勢是將並行性和算法分離,閱讀代碼時候無需考慮並行化是如何實現的。固然for循環是能夠並行化處理的自然材料,知足一些約束的for循環能夠方便的使用OpenMP進行傻瓜化的並行。html
爲了使用自動並行化對Mandelbrot集合進行計算,必須對代碼進行內聯:書中首次使用自動並行化時候,經過性能分析發現工做在線程中並未平均分配。算法
#include <stdio.h> #include <malloc.h> #define SIZE 4000 int inSet(double ix,double iy) { int iterations = 0; double x = ix,y = iy; double x2 = x*x, y2 = y*y; while ((x2 + y2 < 4) && (iterations < 1000)) { y = 2*x*y + iy; x = x2 -y2 +ix; x2 = x*x; y2 = y*y; iterations++; } return iterations; } int main() { int *matrix[SIZE]; for (int i = 0; i < SIZE; i++) { matrix[i] = (int* )malloc( SIZE*sizeof(int) ); } #pragma omp parallel for for (int x = 0 ;x <SIZE; x++) { for (int y =0;y <SIZE;y++) { double xv = ((double)x -(SIZE/2)) / (SIZE/4); double yv = ((double)y -(SIZE/2)) / (SIZE/4); matrix[x][y] = inSet(xv,yv); } } for (int x =0; x<SIZE;x++) { for (int y =0;y<SIZE;y++) { if (matrix[x][y] == -7) { printf(" "); } } } return 0; }
當咱們看到 分形圖的時候應該能夠很快的理解負荷不均衡從那裏產生,分形圖中大部分點不在集合中,這部分點只須要少許的迭代就能夠肯定,但有些在集合中的點則須要大量的迭代。編程
固然我再一次見識到了OpenMP傻瓜化的並行操做機制,糾正工做負荷不均衡只要更改並行代碼調度子句就能夠了,使用動態指導調度,下面代碼是增長了OpenCV的顯示部分:ide
#include "Fractal.h" #include <Windows.h> #include <omp.h> int Fractal::Iteration(Complex a, Complex c) { double maxModulus = 4.0; int maxIter = 256; int iter = 0; Complex temp(0,0) ; while ( iter < maxIter && a.modulus() < maxModulus) { a = a * a ; a += c; iter++; } return iter; } cv::Mat Fractal::generateFractalImage(Border border, CvScalar colortab[256] ) { cv::Size size(500,500); double xScale = (border.xMax - border.xMin) / size.width; double yScale = (border.yMax - border.yMin) / size.height; cv::Mat img(size, CV_8UC3); #pragma omp parallel for schedule(dynamic) for (int y=0; y<size.height; y++) { for (int x=0; x<size.width; x++) { double cx = border.xMin + x * xScale; double cy = border.yMin + y * yScale; Complex a(0.0, 0.0); Complex c(cx, cy); int nIter ; if (type == MANDELBROT) { nIter = Iteration(a, c); } else if (type == JUALIA) { nIter = Iteration(c, offset); } int colorIndex = (nIter) % 255; cv::Vec3b color; color.val[0] = colortab[colorIndex].val[0]; color.val[1] = colortab[colorIndex].val[1]; color.val[2] = colortab[colorIndex].val[2]; img.at<cv::Vec3b>(y,x) = color; } } return img; }
#pragma omp parallel for schedule(dynamic) 子句性能
schedule子句:ui
schedule(type[, size]),spa
參數type是指調度的類型,能夠取值爲static,dynamic,guided,runtime四種值。其中runtime容許在運行時肯定調度類型,所以實際調度策略只有前面三種。.net
參數size表示每次調度的迭代數量,必須是整數。該參數是可選的。當type的值是runtime時,不可以使用該參數。線程
動態調度dynamiccode
動態調度依賴於運行時的狀態動態肯定線程所執行的迭代,也就是線程執行完已經分配的任務後,會去領取還有的任務。因爲線程啓動和執行完的時間不肯定,因此迭代被分配到哪一個線程是沒法事先知道的。
當不使用size 時,是將迭代逐個地分配到各個線程。當使用size 時,逐個分配size個迭代給各個線程。
動態調度迭代的分配是依賴於運行狀態進行動態肯定的,因此哪一個線程上將會運行哪些迭代是沒法像靜態同樣事先預料的。
加速結果:
1.放大加速結果
2.未加速時候的放到功能,基本是3-5倍這個水平,也就是至關於臺式機cpu 的個數?本人的猜想
3.圖像計算結果(未加速)
4. 動態加速結果
代碼:http://download.csdn.net/detail/wangyaninglm/9516035
參考文獻:
http://www.cnblogs.com/easymind223/archive/2013/01/19/2867620.html
戈夫. 多核應用編程實戰[M]. 人民郵電出版社, 2013.