深圳大学并行计算实验三简单排序的OpenMP并行程序

一. 实验目的

1. 实现简单排序的OpenMP并行程序;

2. 掌握for编译制导语句;

3. 对并行程序进行简单的性能分析。

二. 实验环境

1. 软件环境:Microsoft Visual Studio 2013。

三. 实验内容

1. 实验要求:排序数组a

l  数组大小n和线程数p都是可输入的参数。

l  数组a中的每个数都初始化为一个0到1之间的随机double型值(用rand()/double(RAND_MAX)实现)。

l  先将数组a分为p份,每个线程调用sort函数排序一份,然后调用merge函数将p个有序序列归并。

l  添加检测排序结果是否正确的代码。

l  添加计算排序时间的代码,注意不包含数组的初始化时间。

2. 程序代码和说明:

#include<iostream>

#include<algorithm>

#include <omp.h>

#include<vector>

using namespace std;

int n, p; //数组大小n和线程数p都是可输入的参数。

//判断数组是否有序

bool judge(double *a, double*c) {

    for (int i = 0;< n;i++) {

        if (a[i] != c[i]) {

            cout << "error!" << endl;

            return false;

        }

    }

    return true;

}

//借助temp 数组b来合并两段有序的数组a

void merge(double *a, double *b, int first, int middle, int endaddress)

{

    int i = first, j = middle + 1, k = first;

    while (<= middle && j <= endaddress) {

        if (a[i] > a[j]) {

            b[k++] = a[j++];

        }

        else {

            b[k++] = a[i++];

        }

    }

    //合并剩下多余的

    while (<= middle) b[k++] = a[i++];

    while (<= endaddress) b[k++] = a[j++];

    //重新赋值

    for (= first; i <= endaddress; i++) a[i] = b[i];

}

int main()

{

   

    clock_t start, end;

    //数组大小n和线程数p

    cout << "请输入数组大小:" << endl;

    cin >> n;

    cout << "请输入线程数:" << endl;

    cin >> p;

   

   

   

    for (int pi = 0;pi < 7;pi++) {//每次线程数*2,循环七次

        cout << "+++++++++++++++++++++++++++++++线程数为" << p << "时:++++++++++++++++++++++++" << endl;

        //记录并行运行时间的数组

        double multi_time[5];

        //归并函数中用作辅助的数组temp

        double* temp = new double[n];

        memset(temp, 0, n);

        for (int times = 0;times < 5;times++) {//循环五次

            cout << "---------------------" << times + 1 << "次并行计算:----------------------" << endl;

            start = 0;end = 0;

            //数组a中的每个数都初始化为一个01之间的随机double型值

            double* a = new double[n];//a数组存储并行结果

            double* b = new double[n];//b数组存储标准结果

            omp_set_num_threads(p);//设置并行线程数

            int i;

            //数组初始化

            for (= 0;< n;i++) {

                a[i] = rand() / double(RAND_MAX);

                b[i] = a[i];

            }

            sort(b, b + n);

            //并行开始计时

            start = clock();

            #pragma omp parallel   shared(a,temp) private(i)

            {

                //对数组分成p路排序

                int num = n / p;

                #pragma omp for schedule(static,1)

                for (= 0; i < p; i++) {

                    sort(+ i * num, a + (+ 1) * num);

                }

            }

            //利用temp数组对部分排序的a数组进行归并

            for (int block = n / p; block < n; block += block)

            {//分块归并,每次循环扩大块一倍

                for (int first = 0; first < n - block; first += (block + block))

                {//确定块内数组first middle end address

                    int middle = first + block - 1;

                    int endaddress = first + block + block - 1;

                    if (endaddress >= n) {

                        endaddress = n - 1;

                    }

                    merge(a, temp, first, middle, endaddress);

                }

            }

            end = clock();

            //存储并行时间

            multi_time[times] = (end - start) / 1000.0;

            cout << "并行时间为" << multi_time[times] << endl;

            //判断并行的结果数组是否有序

            judge(a, b);

            delete[]a;

            delete[]b;

        }

        cout << "--------------------------------------串行计算---------------------------------" << endl;

       

        double* c = new double[n];//串行测试数组

        double* d = new double[n];//标准数组

        memset(temp, 0, n);

        //数组初始化

        for (int i = 0;< n;i++) {

            c[i] = rand() / double(RAND_MAX);

            d[i] = c[i];

        }

        sort(d, d + n);

        //开始计时

        start = clock();

        //按照线程分开排序

        for (int i = 0; i < p; i++) {

            sort(+ i * (/ p), c + (+ 1) * (/ p));

        }

       

        //p路归并

        for (int block = n / p; block < n; block += block)

        {

            for (int first = 0; first < n - block; first += (block + block))

            {

                int middle = first + block - 1;

                int endaddress = first + block + block - 1;

                if (endaddress >= n) {

                    endaddress = n - 1;

                }

                merge(c, temp, first, middle, endaddress);

            }

        }

        end = clock();

        //判断是否数组已经有序

        judge(c, d);

        double single_time = (end - start) / 1000.0;

        cout << "串行消耗时间为:" << single_time << "" << endl;

        //计算并行平均时间

        double average;

        for (int i = 0;< 5;i++) {

            average += multi_time[i];

        }

        average /= 5;

        cout << "并行平均时间为:" << average << "" << endl;

        cout << "平均加速比为" << single_time / average << endl;

        p *= 2;

        delete []c;

        delete[]temp;

    }

}

3. 实验结果和分析:测试并行程序在不同线程数下的执行时间和加速比(串行执行时间/并行执行时间),并分析实验结果。其中,数组大小n固定为100000000,线程数分别取1、2、4、8、16、32、64时,为减少误差,每项实验进行5次,取平均值作为实验结果。

表1 并行程序在不同线程数下的执行时间(秒)和加速比

线程数

执行时间

1

2

4

8

16

32

64

第1次

10.025

6.357

5.682

5.563

6.024

6.537

6.683

第2次

9.828

6.189

5.29

5.347

5.542

6.039

6.504

第3次

9.906

6.356

5.21

5.243

5.505

6.466

6.478

第4次

9.79

6.269

5.274

5.207

5.478

6.076

6.544

第5次

9.791

6.219

5.034

5.363

5.889

6.171

6.461

平均值

9.868

8.2516

6.94832

6.73426

7.03445

7.66469

8.06694

加速比

1.00466

1.25527

1.56498

1.71867

1.71442

1.65643

1.63668

  • 25
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值