OpenMP并行化实例----Mandelbrot集合并行化计算

在理想情况下,编译器使用自动并行化能够管理一切事务,使用OpenMP指令的一个优点是将并行性和算法分离,阅读代码时候无需考虑并行化是如何实现的。当然for循环是可以并行化处理的天然材料,满足一些约束的for循环可以方便的使用OpenMP进行傻瓜化的并行。

为了使用自动并行化对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的显示部分:

#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子句:

  schedule(type[, size]),

  参数type是指调度的类型,可以取值为static,dynamic,guided,runtime四种值。其中runtime允许在运行时确定调度类型,因此实际调度策略只有前面三种。

  参数size表示每次调度的迭代数量,必须是整数。该参数是可选的。当type的值是runtime时,不能够使用该参数。

动态调度dynamic

  动态调度依赖于运行时的状态动态确定线程所执行的迭代,也就是线程执行完已经分配的任务后,会去领取还有的任务。由于线程启动和执行完的时间不确定,所以迭代被分配到哪个线程是无法事先知道的。

  当不使用size 时,是将迭代逐个地分配到各个线程。当使用size 时,逐个分配size个迭代给各个线程。

动态调度迭代的分配是依赖于运行状态进行动态确定的,所以哪个线程上将会运行哪些迭代是无法像静态一样事先预料的。

加速结果:

1.放大加速结果

2.未加速时候的放到功能,基本是3-5倍这个水平,也就是相当于台式机cpu 的个数?本人的猜测

3.图像计算结果(未加速)

4. 动态加速结果

代码:http://download.csdn.net/detail/wangyaninglm/9516035

参考文献:

http://baike.baidu.com/view/1777568.htm?fromtitle=Mandelbrot%E9%9B%86%E5%90%88&fromid=1778748&type=syn

http://www.cnblogs.com/easymind223/archive/2013/01/19/2867620.html
戈夫. 多核应用编程实战[M]. 人民邮电出版社, 2013.

http://openmp.org/mp-documents/OpenMP3.1-CCard.pdf

http://blog.csdn.net/gengshenghong/article/details/7000979

时间: 2024-09-15 21:27:43

OpenMP并行化实例----Mandelbrot集合并行化计算的相关文章

TensorFlow教程之完整教程 2.9 曼德布洛特(Mandelbrot)集合

本文档为TensorFlow参考文档,本转载已得到TensorFlow中文社区授权. 曼德布洛特(Mandelbrot)集合 虽然可视化曼德布洛特(Mandelbrot)集合与机器学习没有任何关系,但这对于将TensorFlow应用在数学更广泛的领域是一个有趣的例子.实际上,这是tensorflow一个非常直截了当的可视化运用.(我们最终也许会提供一种更加精心设计的运用方式来生成真正更加美丽的图像.) 说明:本教程使用了IPython的notebook. 基本步骤 首先,我们需要导入一些库. #

OpenMP #pragma omp parallel for并行化小探究

今天用了一下openmp,本人表示非常喜欢openmp的傻瓜化模式,导入一个头文件 直接parallel for #include <iostream> #include <omp.h> using namespace std; int main() { //cout<<"Thread num == "<<omp_get_thread_num()<<endl; #pragma omp parallel for num_thre

问个从集合中计算指定数字并分组的方法

问题描述 有一个集合如idmoney133333244444355555466666输入了一个88888的数字要计算出所有小于等于这个数字的记录.并分组归类...一组有多条记录..但这几条记录的money的合要小于等于我输入的数字..需要把所有的分组都列出来... 解决方案 解决方案二:自己顶一下....解决方案三:比较好的办法是linq拉...类似sql的语法来查询集合...但是这个linq要你自己写,要求有的高.还有个方法是,放入内存数据库,使用sql查询,easy..推荐这个解决方案四:给

在线一元二次方程计算器实例(方程计算器在线计算)_javascript技巧

复制代码 代码如下: <html><head><meta http-equiv="Content-Type" content="text/html" charset="utf-8"><title>在线一元二次方程式计算器</title></head><body><form name="fquad">    <p align=&

Python高级应用实例对比:高效计算大文件中的最长行的长度_python

前2种方法主要用到了列表解析,性能稍差,而最后一种使用的时候生成器表达式,相比列表解析,更省内存 列表解析和生成器表达式很相似: 列表解析 [expr for iter_var in iterable if cond_expr] 生成器表达式 (expr for iter_var in iterable if cond_expr)  方法1:最原始 复制代码 代码如下: longest = 0f = open(FILE_PATH,"r")allLines = [line.strip()

visual studio 2015 未能计算子集/集合类型调试

问题描述 visual studio 2015 未能计算子集/集合类型调试 在使用visual studio 2015 企业版 sp1调试程序时,悬停在实例.集合上时展开,无法显示内部数据,提示"未能计算子集"尝试多个项目.管理员运行,均是一样.设置"选项-调试-常规"中的 "托管兼容模式"后一般实例显示正常,但对于List/Dictionary集合类型实例,没有 展开枚举 的选项,只能通过"非公共成员"的entries查看不

《CUDA高性能并行计算》----3.2 并行化dist_v2

本 节 书 摘 来 自 华 章 出 版 社 <CUDA高性能并行计算> 一 书 中 的 第3章,第3.2节, 作 者 CUDA for Engineers: An Introduction to High-Performance Parallel Computing[美] 杜安·斯托尔蒂(Duane Storti)梅特·尤尔托卢(Mete Yurtoglu) 著,苏统华 项文成 李松泽 姚宇鹏 孙博文 译 , 更 多 章 节 内 容 可 以 访 问 云 栖 社 区 "华 章 计 算

深度剖析阿里云ECS最强计算实例

阿里云ECS最强计算阵容 日前,阿里云在2017云栖大会·深圳峰会上宣布,华北3地域超大规模数据中心正式对外开放运营,云服务器ECS全系列降价20%.毫无疑问,这是阿里云技术红利和技术创新再次集中释放的表现,也是云计算规模效应的体现.作为这其中的主角,云服务器ECS"功不可没".近日,笔者和两位阿里云资深产品经理就云服务器ECS的研发工作做了深入沟通,首次披露阿里云十余种基于最新平台计算实例背后的那些研发秘密. 从场景出发,打造最强计算阵容 据了解,阿里云通过八年的努力,打造了面向不同

php计算给定时间之前的函数用法实例_php技巧

本文实例讲述了php计算给定时间之前的函数用法.分享给大家供大家参考.具体如下: 这里给定一个时间,计算这个时间在多久前,比如:2天前,1年前 <?php function prettyDate($date){ $time = strtotime($date); $now = time(); $ago = $now - $time; if($ago < 60){ $when = round($ago); $s = ($when == 1)?"second":"se