完数的OpenMP并行程序设计-并行计算

目录

1.问题描述...1

2.算法设计...1

2.1 串行算法设计... 1

2.2 并行算法设计... 2

2.3 理论加速比分析... 2

3.基于OpenMP的并行算法实现...3

3.1 代码及注释(变量名 名字首字母 开头)... 3

3.2 执行结果截图... 4

3.3 实验加速比分析... 5

3.4 遇到的问题及解决方案... 5

3.4.1错误代码...5

3.4.2后果...6

3.4.3正确代码...6

3.4.4分析...6

 

1.问题描述

一个数如果恰好等于它的因子之和,这个数就称为“完数”。例如6=1+2+3,再如8的因子和是7(即1+2+4),8不是完数。输入一个数n,编程找出n以内的所有完数及其个数。

2.算法设计

2.1 串行算法设计

串行算法步骤如下

①因为1不算入一个完数,所以令数i=2,初始化答案值ans=0;

②因为1是任何数的一个因数,所以可初始化因数之和sum=1;

③令数k=2;

④如果数i能整除数k,说明k是i的一个因数,则sum += k;

⑤若k<=i/2(控制范围保证i%k能进行计算),++k,转到④,否则转到⑥;

⑥若sum = i,++ans;

⑦若i <=n,++i,转到②,否则转到⑧;

⑧函数返回答案值ans。

2.2 并行算法设计

并行算法步骤如下

①因为1不算入一个完数,所以令数i=2,初始化答案值ans=0;

②“#pragmaomp parallel for”

②因为1是任何数的一个因数,所以可初始化因数之和sum=1;

“#pragmaomp parallel for”

③令数k=2;

“#pragmaomp critical”

④如果数i能整除数k,说明k是i的一个因数,则sum += k;

⑤若k<=i/2(控制范围保证i%k能进行计算),++k,转到④,否则转到⑥;

⑥若sum = i,++ans;

⑦若i <=n,++i,转到②,否则转到⑧;

⑧函数返回答案值ans。

 

2.3 理论加速比分析

若p个处理器上数据量为n,则S=np/(n+2plogp)。

本机测试中,p=4:若n=10000,则S=3.9981;若n=100000,则S=3.9998。

3.基于OpenMP的并行算法实现

3.1 代码及注释(变量名 名字首字母 开头)

/*问题描述:一个数如果恰好等于它的因子之和,这个数就称为“完数”。例如6=1+2+3,再如8的因子和是7(即1+2+4),8不是完数。编程找出1000以内的所有完数。
*/
//test.cpp : 定义控制台应用程序的入口点。
//
 
#include "stdafx.h"
#include <cstdlib>
#include <iostream>
#include <cmath>
#include <ctime>
#include <omp.h>
#include <windows.h>
using namespace std;
 
int OMP_Perfect(long long n)       //并行计算n以内的完数个数
{
    int ans = 0;                 // n以内的完数个数
    long long i, k;                      //循环变量
#pragma omp parallel for
    for (i = 2; i <= n;i++)  //1不算入一个完数。
    {
       long long sum = 1;                //数的因数之和,1是任何数的一个因数。
#pragma omp parallel for reduction(+:sum)              //解决sum数据冲突
       for (k = 2; k <= i / 2; k++)  //k<=i/2是要保证i%k能进行计算。
           if(i%k == 0)
              sum += k;       //因数之和
       if (sum == i)       //找到一个完数
           ++ans;                 //函数返回答案值ans
    }
    return ans;
}
int Perfect(long long n)
{
    int ans = 0;                 // n以内的完数个数
    long long i, k;                      //循环变量
    for (i = 2; i <= n;i++)  //1不算入一个完数。
    {
       long long sum = 1;                //数的因数之和,1是任何数的一个因数。
       for (k = 2; k <= i / 2; k++)  //k<=i/2是要保证i%k能进行计算。
           if(i%k == 0)
              sum += k;       //因数之和
       if (sum == i)       //找到一个完数
           ++ans;                 //函数返回答案值ans
    }
    return ans;
}
int main()
{
    long long n;
    cin >> n;
    printf("%lld以内的完数有:\n",n);
    clock_t t1, t2;
    t1 = clock();
    printf("Sum= %d\n", OMP_Perfect(n)); //输出并行计算出的n以内的完数个数
    t2 = clock();
    printf("parallel time: %d\n", t2 - t1);//输出并行计算时间
    t1 = clock();
    printf("Sum= %d\n", Perfect(n)); //输出串行计算出的n以内的完数个数
    t2 = clock();
    printf("serail time: %d\n", t2 - t1); //输出串行计算时间
    system("pause");
    return 0;
}

3.2 执行结果截图

(1)小数据量验证正确性的执行结果截图(不考虑加速比)


(2)大数据量获得较好加速比的执行结果截图

(体现串行时间、并行时间 和好的加速比)


3.3 实验加速比分析

若n=10000,S=Ts/Tp=3.7857;若n=100000,S=Ts/Tp=3.7420。

实验加速比与理论加速比相差不大,在误差允许范围内可认为结果正确。

3.4 遇到的问题及解决方案

3.4.1错误代码

int OMP_Perfect(longlong n)

{

    int ans = 0;                 

    long long i, k;                     

#pragma omp parallel for

    for (i = 2; i <= n;i++) 

    {

       long long sum = 1;                

#pragma omp parallel for

       for (k = 2; k <= i / 2; k++) 

           if(i%k == 0)

              sum += k;

       if (sum == i) ++ans;

    }

    return ans;

}

3.4.2后果

n以内的完数数量答案错误。

3.4.3正确代码

int OMP_Perfect(longlong n)       //并行计算n以内的完数个数

{

    int ans = 0;                  // n以内的完数个数

    long long i, k;                      //循环变量

#pragma omp parallel for

    for (i = 2; i <= n;i++)  //1不算入一个完数。

    {

       long long sum = 1;                //数的因数之和,1是任何数的一个因数。

#pragma omp parallel for reduction(+:sum)              //解决sum数据冲突

       for (k = 2; k <= i / 2; k++) //k<=i/2是要保证i%k能进行计算。

           if(i%k == 0)

              sum += k;       //因数之和

       if (sum == i)       //找到一个完数

           ++ans;                 //函数返回答案值ans

    }

    return ans;

}

3.4.4分析

由于是多线程执行,有超过两个线程同时访问一个内存区域,并且至少有一个线程的操作是写操作,这样就产生了数据竞争。如果不对数据竞争进行处理,结果会产生错误。

    第二个for语句并行使用“#pragma ompparallel for reduction(+:sum)”来解决sum的数据竞争问题。因为reduction子句为变量指定一个操作符,每个线程都会创建reduction变量的私有副本,在OpenMP区域结束处,将使用各个线程私有复制的值通过制定的操作符进行迭代运算,并赋值给原来的变量。

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1. 设计目的、意义(功能描述) 蒙特·卡罗方法(Monte Carlo method),也称统计模拟方法,是二十世纪四十年代中期由于科学技术的发展和电子计算机的发明,而被提出的一种以概率统计理论为指导的一类非常重要的数值计算方法。本次大作业主要是对蒙特·卡罗方法进行并行处理,通过OpenMP、MPI、.NET、Java、Win32API等一系列并行技术和并行机制对该算法进行并行处理,从而也进一步熟悉了蒙特·卡罗方法的串行算法和并行算法,实现了用蒙特·卡罗方法计算出半径为1单位的球体的体积,体会到了并行技术在实际生活中的应用。 2. 方案分析(解决方案) 蒙特·卡罗方法(Monte Carlo method)是指使用随机数(或更常见的伪随机数)来解决很多计算问题的方法。球的体积可以估算为:位于点模型内随机点个数与全体随机点个数的比值乘以包围盒的体积算的。 3. 设计分析 3.1 串行算法设计 假定球体用B表示,半径r=1单位,B1是包含B的参考立方体(在本例中是边长为2的正方体),在B1中产生N个均匀分布的伪随机点。对每个随机点检测其是否在B内,假设位于B内的随机点个数为N(in)(<=N),应用蒙特卡洛算法,则B的体积为 V=V1(N(in)/N) 其中V1是B1的体积。如果产生足够多的随机点,理论上可以获得任意逼近精度。 算法描述如下: BEGIN N=_MAX; FOR I=0;I<_MAX;I++ X=RANDOM(); Y=RANDOM(); Z=RANDOM(); IF (X*X+Y*Y+Z*Z)<=1 COUNT++; END IF; END FOR; BULK=V1*(COUNT/_MAX); END; 本算法主要是在参考立方体的选取上和定义的_MAX的值对结果影响较大,所以应该选择合适的数。 3.2 并行算法设计 对FOR循环进行划分使用两个处理器完成计算。例如对一个长为n的序列,首先划分得到两个长为n/2的序列,将其交给两个处理器分别处理;而后进一步划分得到四个长为n/4的序列,再分别交给四个处理器处理;如此递归下去最终得到结果。当然这是理想的划分情况,如果划分步骤不能达到平均分配的目的,那么结果的效率会相对较差。 伪代码如下: BEGIN N=_MAX; FOR1 I=0;I<_MAX/2;I++ X1=RANDOM(); Y1=RANDOM(); Z1=RANDOM(); IF (X1*X1+Y1*Y1+Z1*Z1)<=1 COUNT1++; END IF; END FOR1; FOR2 I=_MAX/2+1;I<_MAX;I++ X2=RANDOM(); Y2=RANDOM(); Z2=RANDOM(); IF (X2*X2+Y2*Y2+Z2*Z2)<=1 COUNT2++; END IF; END FOR2; BULK=V1*((COUNT1+ COUNT2)/_MAX); END; 3.3 理论加速比分析 实验中大量数据所产生的加速比比小量数据所产生的加速比要体现得更明显,并且数据生成的并行加速比随着处理器核的增加而增加。设处理器个数为p,数据量为n,由于正常情况下该快速排序算法的复杂度为O(nlogn),并行处理的时间复杂度为O(klogk),其中k=n/p,所以并行算法的时间复杂度为O((n/p)log(n/p)),理论加速比为nlogn/((n/p)log(n/p))=p+logp. 4. 功能模块实现与最终结果分析 4.1 基于OpenMP并行算法实现 4.1.1 主要功能模块与实现方法 利用了OpenMP里面的#omp parallel sections将对两个for循环用两个线程并行化执行,以多线程方式并行运行程序,并行的算法步骤如下: (1)初始化_max = 10000000; (2)创建两个线程; (3)由OpenMP编译指导语句控制产生并行执行代码区段; (4)将数据存放到tianqing_count; (5)各线程调用算法得出结果; 并行算法的部分代码如下: #pragma omp parallel for private(tianqing_x,tianqing_y,tianqing_z) reduction(+:tianqing_count2) for (tianqing_i = 0; tianqing_i<tianqing_max; tianqing_i++) { tianqing_x = rand(); tianqing_x = tianqing_x / 32767; tianqing_y = rand(); tianqing_y = tianqing_y / 32767; tianqing_z = rand(); tianqing_z = tianqing_z / 32767; if ((tianqing_x*tianqing_x + tianqing_y*tianqing_y + tianqing_z*tianqing_z) work1.pSumto(b, 0, MAXN - 1)); Thread newthread1 = new Thread(thread1); 创建Work类的对象work2; ThreadStart thread2 = new ThreadStart(() => work2.pSumto(c, 0, MAXN - 1)); Thread newthread2 = new Thread(thread2); stopwatch.Start(); 启动线程1和线程2; 等待进程结束; stopwatch.Stop(); 得到结果; 4.5.2 实验加速比分析 实验中创建了两个线程,通过多次测试,得出实验结果:由上面的理论加速比分析可知,当线程数为2时,理论加速比为2+log2=3.但由于实际操作中硬件设备以及内存分配的影响,实验加速比达不到理论值3.实验加速比在2.6~2.7左右。 4.6 并行计算技术在实际系统中的应用 4.6.1 主要功能模块与实现方法 该飞机订票系统主要实现了对机票的一些基本信息进行存储和管理的功能。在系统中实现了对机票信息的增删改查,考虑到查询的方便性,对机票按照航班号进行排序,而此排序方法用并行快速排序运用进来。利用OpenMP并行技术,对机票信息按顺序排列好,并分析了实验过程中的加速比。 4.6.2 实验加速比分析 实验中创建了两个线程,通过多次测试,得出实验结果:当数据量比较大时,加速比理论在1.9左右。数据量较大时体现出来的加速比更准确。由上面的理论加速比分析可知,当线程数为2时,理论加速比为2+log2=3.但由于实际操作中硬件设备以及内存分配的影响,实验加速比达不到理论值3.实验加速比在2.2~2.4左右。 5. 设计体会 虽然没有按时完成作业,但这份报告花了我好几天的时间,从开始的搭建并行计算平台到最后的程序运行成功可以说是对我的一个锻炼。每一次的遇到问题与每一次的解决问题都是一个成长。每一次遇到问题和解决问题都是一种锻炼,一种尝试,从我们上并行计算课我懂得了很多电脑硬件和软件的知识,这些可能对于我们这个专业以后都是没有机会接触的,所以我觉得选择了并行计算与多核多线程技术这门课是非常正确的。对OpenMP、MPI、WIN32API、Java、.NET的并行技术有了一定的了解。在搭建MPI并行程序这块,学习的知识尤为增加,这些都是在不断的摸索、学习中学会的。 这次的大作业虽然是对以前实验的整合,但它加深了我对并行计算的印象,也使我对并行计算知识的理解更加深刻,也使我认识到了自己很多不足之处。学习并行计算的历程不会因为完成本次大作业而停止,我们是为了用知识武装大脑而学习,通过学习充实自己的生活,要努力学习,争取以后能够完成规模更大的程序。
MPI(Message Passing Interface)和OpenMP(Open Multi-Processing)是两种常用的并行程序设计方法。 MPI是一种消息传递程序设计模型,主要用于分布式内存系统中的并行计算。在MPI编程中,程序中的各个进程通过发送和接收消息来进行通信和数据传递。每个进程都有自己的内存空间,并且可以直接访问和修改自己的内存,而不能直接访问其他进程的内存。MPI程序设计可以实现大规模的并行计算,适合于需要在多台计算机上进行并行计算的情况。 OpenMP是一种共享内存的并行程序设计模型,主要用于多核共享内存架构中的并行计算。在OpenMP编程中,程序运行在多个线程中,这些线程之间可以共享一部分或全部的内存。通过使用Pragmas和语句来指定并行区域和任务分配,开发者可以将串行程序转化为并行程序,以实现更高效的计算。OpenMP程序设计适用于多核心处理器上的并行计算,能够充分发挥多核处理器的计算能力。 MPI和OpenMP有各自适用的场景和优势。MPI适用于需要在多个计算节点之间进行通信和数据传递的并行计算,可以实现集群或分布式计算;而OpenMP适用于在同一计算节点上的多核共享内存并行计算,可以利用多核处理器的并行特性。 在一些计算任务中,可以结合使用MPI和OpenMP来充分利用多节点和多核心的并行能力。通过MPI将多个计算节点连接起来,每个节点上运行多个OpenMP线程,可以实现更大规模和更高效率的并行计算。 总之,MPI和OpenMP是两种常用的并行程序设计方法,它们分别适用于分布式内存和共享内存的并行计算。根据具体的应用场景和硬件环境,可以选择合适的并行程序设计方法来实现高效的并行计算

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值