利用华为鲲鹏云服务器进行MPI编程

举报
yd_215229242 发表于 2023/10/08 14:26:34 2023/10/08
【摘要】 利用利用华为鲲鹏云服务器进行MPI编程实验 1. 实现第5章课件中的梯形积分法的MPI编程熟悉并掌握MPI编程方法,规模自行设定,可探讨不同规模对不同实现方式的影响。 2. 对于课件中“多个数组排序”的任务不均衡案例进行MPI编程实现,规模可自己设定、调整。 3. 实现高斯消去法解线性方程组的MPI编程,与SSE(或AVX)编程结合,并与Pthread、OpenMP(结合SSE或AVX)版本

1. 梯形积分法

1.1 问题描述

实现第 5 章课件中的梯形积分法的 MPI 编程熟悉并掌握 MPI 编程方法,规模自行设定,可探讨 不同规模对不同实现方式的影响。

1.2 算法设计与实现

    MPI_Init(&argc, &argv);

    int rank;
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);

    int size;
    MPI_Comm_size(MPI_COMM_WORLD, &size);

    double a = 0.0;  // 积分区间的左端点
    double b = 8.0;  // 积分区间的右端点
    int n = 1000;    // 小区间的数量

    double h = (b - a) / n;  // 小区间的长度

    int local_n = n / size;  // 每个进程计算的小区间数量
    double local_a = a + rank * local_n * h;  // 每个进程计算的积分区间的左端点
    double local_b = local_a + local_n * h;   // 每个进程计算的积分区间的右端点

    double local_sum = (f(local_a) + f(local_b)) / 2.0;
    for (int i = 1; i < local_n; ++i) {
        double x = local_a + i * h;
        local_sum += f(x);
    }
    local_sum *= h;

    double total_sum;
    MPI_Reduce(&local_sum, &total_sum, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD);

    if (rank == 0) {
        printf("With n = %d trapezoids, our estimate\n", n);
        printf("The integral from %f to %f is %f", a, b, total_sum);
    }

    MPI_Finalize();
    return 0;

1.3 实验结果

本实验中,我使用了 MPI 方法来实现梯形积分法,梯形的积分区间为 [3.0, 8.0],被积函数为 x 2 , 积分区间分别被分为为 1000￿5000￿10000 个小区间,线程数为 6。实验结果如下图所示:
image.png

1.4 实验分析

从上图可以看出,随着划分的小区间规模增大,积分的值越来越接近真实值,但是当划分的小区间 规模增大到一定程度后,积分的值就不再变化,这是因为当划分的小区间规模增大到一定程度后,计 算机的精度就不够了,所以积分的值就不再变化了。

2 数组排序

2.1 问题描述

对于课件中“多个数组排序”的任务不均衡案例进行 MPI 编程实现,规模可自己设定、调整。

2.2 算法设计与实现

首先在数组初始化时,对于中“多个数组排序”的任务不均衡案例进行复现

    int ratio;
    srand(unsigned(time(NULL)));
    for (int i = 0; i < ARR_NUM; i++) {
        arr[i].resize(ARR_LEN);
        if (i < seg) {
            ratio = 0;
        } else if (i < seg * 2) {
            ratio = 32;
        } else if (i < seg * 3) {
            ratio = 64;
        } else {
            ratio = 128;
        }
        if (rand() && 127 < ratio) {
            for (int j = 0; j < ARR_LEN; j++) {
                arr[i][j] = ARR_LEN - j;
            }
        } else {
            for (int j = 0; j < ARR_LEN; j++) {
                arr[i][j] = j;
            }
        }
    }
 init();
    //记录开始时间
    clock_t start, finish;
    double duration;
    start = clock();
    int current_task = 0;//当前的任务
    MPI_Init(NULL, NULL);
    int rank, thread_num;
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    MPI_Comm_size(MPI_COMM_WORLD, &thread_num);
    MPI_Status status;
    int ready;
    bool done = false;
    if (rank == 0) {
        while (current_task < ARR_NUM) {
            //接受任何一个线程的状态
            MPI_Recv(&ready, 1, MPI_INT, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &status);
            MPI_Send(&current_task, 1, MPI_INT, status.MPI_SOURCE, 0, MPI_COMM_WORLD);
            current_task += seg;
        }
        done = true;
        //记录结束时间
        finish = clock();
        duration = (double) (finish - start) / CLOCKS_PER_SEC;
        cout << "ARR_NUM:" << ARR_NUM << endl;
        cout << "ARR_LEN:" << ARR_LEN << endl;
        cout << "time: " << duration << "ms" << endl;
        //唤醒所有线程
        for (int i = 1; i < thread_num; ++i) {
            MPI_Recv(&ready, 1, MPI_INT, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &status);
            MPI_Send(&current_task, 1, MPI_INT, status.MPI_SOURCE, 1, MPI_COMM_WORLD);
        }

    } else {
        while (!done) {
            int begin;
            MPI_Send(&rank, 1, MPI_INT, 0, 0, MPI_COMM_WORLD);
            MPI_Recv(&begin, 1, MPI_INT, 0, MPI_ANY_TAG, MPI_COMM_WORLD, &status);
            if (status.MPI_TAG == 1) {
                break;
            }
            doTask(begin);
        }
    }
    MPI_Finalize();
    return 0;

2.3 实验结果

image.png

2.4 实验分析

从图中可以看出,当数组长度为 8000 时,数组个数越多,排序时间越长,这是因为数组长度固定, 数组个数越多,每个数组的排序时间越长,而每个数组的排序时间是并行的,所以数组个数越多,排 序时间越长。可以看出,排序时间的增长趋势是线性的。

3 高斯消元法

3.1 问题描述

实现高斯消去法解线性方程组的 MPI 编程,与 SSE(或 AVX)编程结合,并与 Pthread、OpenMP (结合 SSE 或 AVX)版本对比,规模自己设定。

3.2 算法设计与实现

float **matrix_const = new float *[N];
    float *x_const = new float[N];
    matrix = new float *[N];
    for (int i = 0; i < N; i++) {
        matrix_const[i] = new float[N];
        matrix[i] = new float[N];
    }
    x = new float[N];

    init(N, matrix, x);
    int rank, thread_num;
    gettimeofday(&startTime, NULL);
    MPI_Init(&argc, &argv);
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    MPI_Comm_size(MPI_COMM_WORLD, &thread_num);
    MPI_Status status;
    int ready;
    bool done = false;
    if (rank == 0) {
        printf("size : %d\n", N);
        for (line = 0; line < N - 1; ++line) {
            next_task = line + 1;
            seg = (N - next_task) / (thread_num - 1) + 1;
            for (int i = 1; i < thread_num; i++) {
                int task = (i - 1) * seg + next_task;
                MPI_Send(&task, 1, MPI_INT, i , 0, MPI_COMM_WORLD);
            }
            //等待所有线程
            for (int j = 1; j < thread_num; ++j) {
                MPI_Recv(&ready, 1, MPI_INT, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &status);
            }
        }
        printf("all work done!!!!!\n");
        done = true;
        gettimeofday(&stopTime, NULL);
        double trans_mul_time =
                (stopTime.tv_sec - startTime.tv_sec) * 1000 + (stopTime.tv_usec - startTime.tv_usec) * 0.001;
        printf("time: %lf ms\n", trans_mul_time);
        //唤醒所有线程
        for (int i = 1; i < thread_num; i++) {
//            MPI_Recv(&ready, 1, MPI_INT, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &status);
            MPI_Send(&done, 1, MPI_INT, status.MPI_SOURCE, 1, MPI_COMM_WORLD);
        }
    } else {
        while (!done) {
            int task;
            MPI_Recv(&task, 1, MPI_INT, 0, MPI_ANY_TAG, MPI_COMM_WORLD, &status);
            if(done) break;
            int min = task + seg < N ? task + seg : N;
            for (int i = task; i < min; ++i) {
                GAUSS_EXITNCTION(line, i);
            }
            MPI_Send(&ready, 1, MPI_INT, 0, 0, MPI_COMM_WORLD);
        }
    }
    MPI_Finalize();
    return 0;

3.3 实验结果

image.png

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。