没腿的鸟 发表于 2024-12-5 08:17:18

云计算基础实验

云计算基础实验报告

实验一 Linux环境下算法的测试

一, 根据基本计算头脑,验证和求解,设计算法。
根据运行需要,自行完成(C和Python)环境配置。
1.1验证卡布列克常数6174

原理过程:

[*] 循环输入一个1000-9999之间的数字,找出其最大数和其最小数,并进行相减。直到其末了值得到6174.
[*] 输出此卡布列克常数的运算过程以及结果
   
算法实现(在C语言环境运行)
#include<stdio.h>

void sort(int a[], int num)   //将数字按照从大到小的顺序排列
{
    int i, j, temp;
    for (i = 0; i < num; i++)
      for (j = i + 1; j < num; j++)
            if (a > a)
            {
                temp = a;
                a = a;
                a = temp;
            }
}

int main() {
    int n = 1000, count, result, s;
    int a;   //存储一个4位数
    int max, min;   //存放最大值最小值

    printf("验证卡布列克常数6174:");


    while (n <= 9999)
    {
      count = 1; result = 0;
      s = n;
      
      while (n != 6174 && result != 6174 && count <= 7)
      {
            a = s % 10;                        /*分别算出4位数,再将其存放在数组中*/
            a = s / 10 % 10;
            a = s / 100 % 10;
            a = s / 1000;

            sort(a, 4);   //调用函数

            max = 1000 * a + 100 * a + 10 * a + a; //计算最大值
            min = 1000 * a + 100 * a + 10 * a + a;//计算最小值

            printf("[%d] : %d - %d = %d\n", count, max, min, max - min);

            result = max - min;
            count++;    //统计进行了几次计算

            
            if (result == 6174 && count < 8)
            {
                printf("%d is the num.\n", n);
                printf("-----------------------\n");
            }

            
                  
            s = result; //将进行减的值赋给s,回到while循环判断
      }   

      n = n + 1;

    }
    return 0;
}

结果显示(运行截图)
https://i-blog.csdnimg.cn/direct/ebf80e6b8e5849b3a057263f85c8407b.png
1.2蒙特卡洛算法

原理过程:
定义一个常量NUM_POINTS,体现要天生的随机点的数量。
利用rand()函数天生随机点,并查抄这些点是否落在单位圆内(即x^2 + y^2 <= 1)
每天生一个落在单位圆内的点,计数器inside_circle就增长1
计算并输出π的估计值。
算法实现(
在C语言环境运行)
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define NUM_POINTS 1000000

int main() {
    int inside_circle = 0;
    double x, y;

    // 初始化随机数种子
    srand(time(NULL));

    // 生成NUM_POINTS个随机点
    for (int i = 0; i < NUM_POINTS; i++) {
      // 生成0到1之间的随机数作为x和y坐标
      x = (double)rand() / RAND_MAX;
      y = (double)rand() / RAND_MAX;

      // 检查点是否在单位圆内
      if (x * x + y * y <= 1.0) {
            inside_circle++;
      }
    }

    // 计算π的估计值
    double pi = 4.0 * inside_circle / NUM_POINTS;

    printf("估计的π值为: %.6f\n", pi);

    return 0;
}

结果显示(运行截图)
https://i-blog.csdnimg.cn/direct/f220822ca8514cedabebbaa147ff3b45.png
1.3冰雹猜想验证(验证范围1~100)

原理过程:
输入一个1-100之间的整数n,如果n为偶数,就将它变成n/2,如果除后变成奇数,则将它乘3加1,不断重复运算,经过有限步数后,是否可以得到1
算法实现(在C语言环境运行)
#include<stdio.h>
int main()
{
    int i,number,count=0;

    for(i=1; i<=100; i++)
    {
      number = i;
      printf("%d : ",number);
      while(number != 1)
      {
            if (number % 2 == 0)
            {
                number /= 2;
                printf("%d - ", number);
            }
            else
            {
                number = number * 3 + 1;
                printf("%d - ", number);
            }
            count++;
      }
      printf("共执行了%d步\n",count);
}
return 0;
}
结果显示(运行截图)
https://i-blog.csdnimg.cn/direct/64bb4db5ec64465db54edf7e8d6fa86a.png
1.4亲和数验证(验证范围1~10000)

原理过程:
如果整数A的全部因子(包括1,但不包括其本身)之和等于整数B,整数B的因子(包括1,但不包括其本身)之和等于整数A,则整数A与B称为密切数。
算法实现(在C语言环境运行)
#include<stdio.h>
int main()
{
    int a=1, i=1;
    int j=1;
    for(a=1; a<=10000; a++)
    {
      int B = 0, A = 0;
      for(i=1; i<a; i++)
      {
            if(a%i==0)
                {
                  B = B + i;
                }
      }

      for(j=1; j<B; j++)
      {
            if(B%j == 0)
                {
                  A = A + j;
                }
      }

      if(A == a )
            {
                printf("%d和%d是亲和数\n",a,B);
            }
    }
    return 0;
}
结果显示(运行截图)
https://i-blog.csdnimg.cn/direct/3bd121f47eab41fca269689b0ad20c59.png
实验二 MPI分布式运行框架设计

一、 实验目标
设计运行框架,了解运行环境需求。
nfs的应用
mpi的安装和利用
mpi的环境测试
二、 实验环境
Ubuntu 22.04 (LTS),
VM环境下,网络架构NAT,
计算节点数:4个
三、 基本步调介绍:
3.1 构建四台计算节点

[*]每个节点计算机的网络均采用NAT模式,构建一个内部的计算集群.
[*]设置每个节点的hostname,依次是node01, node02, node03, node04。
[*]根据上一步序次,依次设置每个节点ip,范围(192.168.26.111~114)。
https://i-blog.csdnimg.cn/direct/8c71af65117f487592784cbb1c4226f2.png
https://i-blog.csdnimg.cn/direct/1e30c537d73243008fffb5ae150727d4.png
https://i-blog.csdnimg.cn/direct/464678a1503a4554879396283ffc29eb.png
https://i-blog.csdnimg.cn/direct/748299d7eacc48b9a97b5f1d4b634875.png
四台主机都需要进行此配置
https://i-blog.csdnimg.cn/direct/c2a1773362fe4b16ae6b7dd49a7655e2.png
3.2 构建四台计算节点之间相互免密钥访问(利用rsa方式天生)
https://i-blog.csdnimg.cn/direct/e176c62f09ae48c79f239d6b2910b831.png
#公钥和密钥都已天生
https://i-blog.csdnimg.cn/direct/76f02cfcc93b4b2fa3716cb27dcd3dc3.png
https://i-blog.csdnimg.cn/direct/89718f245aa04893b8c1d8c55cda7da3.png
3.3 给四台主机安装nfs并实现永久挂载

[*]四台节点,全部安装nfs及nfs-utils
//下载nfs
https://i-blog.csdnimg.cn/direct/bbc0287f1c3d4c13a6895eb71f41a838.png

[*]node01节点作为运行主节点,启动并运行nfs服务程序,该程序随系统启动。
https://i-blog.csdnimg.cn/direct/88a1728ec9524a9c8fc2f224c314da95.png

[*]node01节点作为运行主节点,提供挂载的目次资源。
挂载目次/var/mpi4.0/,如果没有此目次,则先创建,再修改配置文件提供挂载。
https://i-blog.csdnimg.cn/direct/35939312ea0f42d98f603e57445db9b7.png

[*]别的节点node02~04,实现永久挂载主节点node01的共享目次,并具有读写权限。
770:可读可写,
sync:共享目次同步文件,
no_root_squash:root权限设置**
//现永久挂载主机 node01节点的共享目次
https://i-blog.csdnimg.cn/direct/42cf6b7f6c0d42c291134f6ec3b651fd.png
///在node02-04客户端上安装nfs-common(客户端包)
https://i-blog.csdnimg.cn/direct/4468ac6adf284eea8df1a2fd1d7301a3.png
///在node01上重启nfs服务器,在node02-04上挂载目次到node01实现目次共享
https://i-blog.csdnimg.cn/direct/3bc135de9c5c4ea2aa3fdce7ed817375.png
#mount:这是用来挂载文件系统的命令。
#-t nfs:这指定了文件系统的类型为NFS。
#-o nolock:这是挂载选项,nolock体现客户端不锁定文件,这可以提高性能,但可能不恰当需要严酷文件锁定的应用。
#192.168.26.111:/var/mpi4.0:这是NFS服务器的IP地点和要挂载的远程目次的路径。这里假设NFS服务器的IP地点是192.168.26.111,而且您想要挂载的目次是/var/mpi4.0。
/var/mp14.0:这是当地挂载点的路径,即您希望将远程目次挂载到当地的哪个位置。
https://i-blog.csdnimg.cn/direct/e0ad596e6f114dc682a234c549fe5c03.png
https://i-blog.csdnimg.cn/direct/008b9beac7614ef18495d3de9b57f1ad.png
//编辑配置文件实现永久挂载
3.4 在node01节点上安装mpi4.0

[*]通过官方网站链接,下载mpi4.0源码包(四台主机都要安装)
https://www.mpich.org/static/downloads/4.0/mpich-4.0.tar.gz
https://i-blog.csdnimg.cn/direct/1800cfafdf554ee08eaeb69b0088ef3c.png
编译安装mpi到/var/mpi4.0/(四台假造机都要实行)
解压缩文件包
//解压
https://i-blog.csdnimg.cn/direct/6d410731f516491592be81ea3a736e28.png
//安装编译软件
https://i-blog.csdnimg.cn/direct/a16c118d40ab4535a834c2049bddf991.png
a) 进入mpich解压目次,安装make
//绿色为可实行文件,蓝色为目次
https://i-blog.csdnimg.cn/direct/ad9801e7cf4545949d47609ef7c71569.png
b) 设置安装目次(以下配置信息,仅供参考,未写完备,实行会有错误提示。请根据错误提示,修改正确)
**#./configure –disable-fortran --prefix=/**var/mpi4.0
**报错:**configure: error: The Fortran compiler gfortran does not accept programs that call the same
#–disable-fortran:告诉配置脚本在编译过程中不利用Fortran编译器支持。
–prefix=/var/mpi4.0**:** 指定了软件安装的前缀路径,软件将被安装到**/var/mpi4.0****目次下,所有相关的可实行文件、库文件、头文件等都将被放置在这个目次及其子目次中。**
https://i-blog.csdnimg.cn/direct/ab650d1bab5545d295bdb27a6d6ff4c9.png
**//**配置安装乐成
https://i-blog.csdnimg.cn/direct/3a0b83401aa94127a0b4e63a05f8841d.png
c) make编译
https://i-blog.csdnimg.cn/direct/b25eb3f99ea743c098a1f65474e859f7.png
d) make install 安装
https://i-blog.csdnimg.cn/direct/d40c62e617984f2b94d6bbc9e5412ce4.png
#赋值放置程序的文件夹到共享目次/var/mpi4.0
https://i-blog.csdnimg.cn/direct/4e8b04383e994c208e28ff50ed8b429b.png
https://i-blog.csdnimg.cn/direct/10255993ff3e43b782ba13557193fb4b.png
#安装mpich
https://i-blog.csdnimg.cn/direct/6344dfd67ab647f3a0c8ba2b5e61f114.png
#切换到daisy用户(由于你如果用root用户编译运行程序,会导致权限过大)
https://i-blog.csdnimg.cn/direct/c6a9e57b8c6e4680b97b3414a4afbb2c.png
#利用6个进程实行./cpi(下面显示运行结果和运行时间)
https://i-blog.csdnimg.cn/direct/d44b8a12048e4c82980460fbe54af44a.png
e) 退出到用户的主目次
#cd
f) 通过编辑.bashrc文件修改环境变量(每次打开终端时都会加载的启动项)
vim .bashrc
https://i-blog.csdnimg.cn/direct/c5ec81513821474cbd201b47da7397b8.png
g) 测试环境变量设置
#source ~/.bashrc
#which mpicc 查察位置信息
#which mpiexec
https://i-blog.csdnimg.cn/direct/254e6665aa6e409da220ca223e578ab7.png
h) 在/var/mpi4.0/examples下,创建主机名称聚集文件csmpd.hosts,
vim csmpd.hosts
文件内容如下:
https://i-blog.csdnimg.cn/direct/bd0aa7114df3423bb926eb57270dfdca.png
3.5环境测试

[*]测试运行MPICH的例子程序
查询怎样编译mpi源代码,怎样运行mpi程序

[*]例子程序运行截图
#rank是你返回的进程号
#size就是进程数
https://i-blog.csdnimg.cn/direct/0e1a62e3770a497291a5575038d37826.png
四、 Helloworld程序代码实现及测试展示:
4.1程序源码:
/*hello.c*/
#include <stdio.h>
#include "mpi.h"

int main( int argc, char *argv[] )
{
    int rank;
    int size;

    MPI_Init( 0, 0 );
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    MPI_Comm_size(MPI_COMM_WORLD, &size);
    printf( "Hello world from process %d of %d\n", rank, size );
    MPI_Finalize();
    return 0;
}

https://i-blog.csdnimg.cn/direct/d23b2b56933c4b568a2b7f0e2ca04aa3.png
4.2程序编译输出文件
$mpicc –o hello hello.c
https://i-blog.csdnimg.cn/direct/5816e290db6142f895abf77d2c3aa633.png
4.3运行
$mpiexec –n <processes> ./hello

$mpiexec -f csmpd.hosts –n <processes> ./hello
【截图显示】
https://i-blog.csdnimg.cn/direct/68e761928eca4d91a039a10122ca44bd.png
实验三 基本MPI环境的程序测试

一、 实验目标
逐一测试,提供的mpi实验程序文件。
熟悉 MPI 编程,加深对其编程的明白。
二、实验环境
Ubuntu 22.04 (LTS),
VM环境下,网络架构NAT,
计算节点数:4个
三、代码测试与截图
3.1代码泉源程序5.4
详细代码如下:
/*文件名:who.c*/
#include "mpi.h"
#include <stdio.h>
int main(int argc,char **argv)
{
        int myid, numprocs;
        int namelen;
        char processor_name;
        MPI_Init(&argc,&argv);
        MPI_Comm_rank(MPI_COMM_WORLD,&myid);//获得本进程ID
        MPI_Comm_size(MPI_COMM_WORLD,&numprocs);//获得总的进程数目
        MPI_Get_processor_name(processor_name,&namelen);//获得本进程的机器名
        printf("Hello World! Process %d of %d on %s\n",myid, numprocs, processor_name);
        MPI_Finalize();
}
结果显示(运行截图)
https://i-blog.csdnimg.cn/direct/d44306e29e8d4d56a3e155877cee98a4.png
3.2代码泉源程序5.5
详细代码如下:
/*文件名:message.c*/
#include <stdio.h>
#include "mpi.h"
#include <string.h>
int main(int argc, char** argv)
{
   int myid,numprocs,source;
   MPI_Status status;
   char message;
   MPI_Init(&argc,&argv);
   MPI_Comm_rank(MPI_COMM_WORLD, &myid);
   MPI_Comm_size(MPI_COMM_WORLD,&numprocs);
   if (myid != 0)
   {
         strcpy(message, "Hello World!");//为发送字符串赋值
         //发送字符串时长度要加1,从而包括串结束标志
         MPI_Send(message,strlen(message)+1, MPI_CHAR, 0,99,MPI_COMM_WORLD);
   }
   else
   {
         //除0进程的其他进程接收来自于0进程的字符串数据
         for (source = 1; source < numprocs; source++)
          {
               MPI_Recv(message, 100, MPI_CHAR, source, 99,MPI_COMM_WORLD, &status);
               printf("I am process %d. I recv string '%s' from process %d.\n", myid, message,source);
          }
   }
   MPI_Finalize();
}
结果显示(运行截图)
https://i-blog.csdnimg.cn/direct/d2c272bbfa0c40518bc107797d4f5402.png
3.3代码泉源程序5.7
详细代码如下:
#define N 100000000
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "mpi.h"
int main(int argc, char** argv)
{
int myid,numprocs;
int i;
double local=0.0;
double inte,tmp=0.0,x;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &myid);
MPI_Comm_size(MPI_COMM_WORLD,&numprocs);
srand((int)time(0));//设置随机数种子
/*各节点分别计算一部分积分值*/
/*以下代码在不同节点运行的结果不同*/
for(i=myid;i<N;i=i+numprocs)
{
    x=10.0*rand()/(RAND_MAX+1.0);//求函数值
    tmp=x*x/N;
    local=tmp+local;//各节点计算面积和
}       
//计算总的面积和,得到积分值
MPI_Reduce(&local,&inte,1,MPI_DOUBLE,MPI_SUM,0,MPI_COMM_WORLD);
if(myid==0)
{
    printf("The integal of x*x=%16.15f\n",inte);
}
MPI_Finalize();
}
结果显示(运行截图)
https://i-blog.csdnimg.cn/direct/f6b37dfba8f7487088cc19b25a9d3c63.png
3.4代码泉源程序5.8
详细代码如下:

[*]初始化MPI****环境。
[*]获取当进步程的ID (myid) 和总进程数 (numprocs)****。
[*]利用随机数天生器天生 N*N* 个在 区间内的随机数 x*x*****。
[*]计算每个随机数 x*x* 对应的 x2*x*2 并累加到 local 变量中。
[*]调用自定义的归约函数 Myreduce**,将所有进程的 local** 值汇总到根节点(进程0**)。**
[*]如果当进步程是根节点,打印出积分结果。
[*]结束MPI****环境。
/*文件名 myreduce.c*/
#define N 100000000
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "mpi.h"

void Myreduce(double sendbuf, double *recvbuf, int root); // 修改函数原型

int main(int argc, char** argv) {
    int myid, numprocs;
    double local = 0.0;
    double inte;
    double x;
    MPI_Init(&argc, &argv);
    MPI_Comm_rank(MPI_COMM_WORLD, &myid);
    MPI_Comm_size(MPI_COMM_WORLD, &numprocs);

    // 采用归约对y=x*x在区间求积分
    srand((unsigned)time(NULL) + myid); // 使用myid作为种子的一部分
    int localN = N / numprocs; // 每个进程处理的随机数数量
    for (int i = 0; i < localN; i++) {
      x = 10.0 * rand() / (RAND_MAX / 10.0 + 1.0); // 生成区间的随机数
      local += x * x / N; // 累加到local变量中
    }
    Myreduce(local, &inte, 0); // 调用自定义的规约函数,传递local的值

    if (myid == 0) {
      printf("id:%d 总进程:%d The integral of x*x = %16.15f\n",myid,numprocs,inte);
    }
    MPI_Finalize();
    return 0;
}

// 自定义的归约函数
void Myreduce(double sendbuf, double *recvbuf, int root) {
    MPI_Status status;
    int myid, numprocs;
    MPI_Comm_rank(MPI_COMM_WORLD, &myid);
    MPI_Comm_size(MPI_COMM_WORLD, &numprocs);

    // 非root节点向root节点发送数据
    if (myid != root) {
      MPI_Send(&sendbuf, 1, MPI_DOUBLE, root, 99, MPI_COMM_WORLD);
    } else {
      *recvbuf = 0.0; // 初始化接收缓冲区
      // root节点接收数据并对数据求和,完成规约操作
      for (int i = 0; i < numprocs; i++) {
            if (i != root) {
                double tmp;
                MPI_Recv(&tmp, 1, MPI_DOUBLE, i, 99, MPI_COMM_WORLD, &status);
                *recvbuf += tmp; // 累加求和
            }
      }
    }
}
结果显示(运行截图)
https://i-blog.csdnimg.cn/direct/022ddb8f1c59446f9031c45e0d6b142f.png
实验四 卡布列克常数的MPI测试
一、 实验题目
用 MPI 方式遍历数据,证实卡布列克常数6174猜想。
二、实验目标
熟悉 MPI 编程,加深对其编程的明白。
三、实验环境
Ubuntu 22.04 (LTS),
VM环境下,网络架构NAT,
计算节点数:4个
四、原理介绍:
6174猜想:一个恣意的四位正整数(全雷同的除外,如1111)。将数字重新组合成一个最大的数和最小的数相减,重复这个过程,最多七步,必得6174。
例如:
输入:2000
输出:
第1步:2000-0002=1998
第2步:9981-1899=8082
第3步:8820-0288=8532
第4步:8532-2358=6174
分步解题:

[*]遍历所有的四位数,判断。
[*]分解数字的千位,百位,十位,个位,放置在4个变量中,排序,将最大的放在最前面,最小的放在末了面。
[*]利用4个变量的值,构建四位数,最大值及最小值,并计算差值
[*]如差值不是6174,则重复步调2.如果差值为6174,则程序打印输出最闭幕果,程序结束。
用各自节点分别计算的数据范围,分担计算任务。
例如,如果有4个节点呆板,就将10009999****分成四个小范围,分给****4****个节点计算验证。如果有****3****个节点呆板,就将****10009999分成三个小范围,分给3个节点计算验证。
五、 程序代码实现及测试:
#include <mpi.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

//找出最大值和最小值
void sort_digits(int num, int *sorted, int *largest, int *smallest) {
    for (int i = 0; i < 4; ++i) {
      sorted = num % 10;
      num /= 10;
    }
    // Sort the digits
    for (int i = 0; i < 3; ++i) {
      for (int j = i + 1; j < 4; ++j) {
            if (sorted > sorted) {
                int temp = sorted;
                sorted = sorted;
                sorted = temp;
            }
      }
    }
    //将排序好的数组数编排成最大的数和最小的数
    *largest = sorted * 1000 + sorted * 100 + sorted * 10 + sorted;
    *smallest = sorted * 1000 + sorted * 100 + sorted * 10 + sorted;
}

//检查是否能在7步以内得到6174,输出运行节点和步骤
void check_convergence(int num, int myid, char *hostname) {
    int steps = 0;
    int sorted, largest, smallest;
    printf("进程 %d: 数字 %d on %s\n",myid, num,hostname);
    while (num != 6174 && steps < 7) {
      sort_digits(num, sorted, &largest, &smallest);
      num = largest - smallest;
      steps++;
      printf("进程 %d: 第%d步: %d - %d = %d on %s\n", myid, steps, largest, smallest, num, hostname);
    }
    if (num == 6174) {
      printf("进程 %d: Convergence to 6174 after %d 步: %d - %d = 6174 on %s\n",myid, steps, largest, smallest,hostname);
    }
}

int main(int argc, char **argv) {
    int myid, numprocs;
    char hostname;
    MPI_Init(&argc, &argv);
    MPI_Comm_rank(MPI_COMM_WORLD, &myid);
    MPI_Comm_size(MPI_COMM_WORLD, &numprocs);

    gethostname(hostname, sizeof(hostname));

    int start = 1000 + myid * (9999 / numprocs);
    int end = 1000 + (myid + 1) * (9999 / numprocs);
    if (myid == numprocs - 1) {
      end = 9999;
    }

    for (int i = start; i <= end; ++i) {
      if (i % 1111 != 0) { //不包含四位数都相同的数
            check_convergence(i, myid, hostname);
      }
    }

    MPI_Finalize();
    return 0;
}
https://i-blog.csdnimg.cn/direct/e53c1cd28daf44eb840d8a0842219bbe.png
https://i-blog.csdnimg.cn/direct/055a1ebf084b460fbbe2809be018ea8e.png
实验五 基于蒙特卡洛算法求π值的MPI程序设计

一、 实验题目
用 MPI 技术计算π的值,运行代码参考程序5.6。
二、实验目标
熟悉 MPI 编程,加深对其编程的明白。
三、实验环境
Ubuntu 22.04 (LTS),
VM环境下,网络架构NAT,
计算节点数:4个
四、程序代码实现及测试
/*文件名:mtpi.c*/
#include "mpi.h"
#include <stdio.h>
#include <stdlib.h>
#include <time.h> // 包含 time.h 头文件

int main(int argc, char **argv) {
    int myid, numprocs;
    int namelen;
    long count = 1000000;
    char processor_name;
    MPI_Status status;
    MPI_Init(&argc, &argv); // 初始化 MPI 环境
    MPI_Comm_rank(MPI_COMM_WORLD, &myid); // 得到当前进程的进程号
    MPI_Comm_size(MPI_COMM_WORLD, &numprocs); // 得到通信域中的总进程数
    MPI_Get_processor_name(processor_name, &namelen); // 得到节点主机名称
    srand((int)time(0)); // 设置随机种子
    double y;
    double x;
    long m = 0, m1 = 0, i = 0;
    double pi = 0.0, n = 0.0;
    for (i = 0; i < count; i++) {
      x = (double)rand() / (double)RAND_MAX; // 得到0~1之间的随机数,x坐标
      y = (double)rand() / (double)RAND_MAX; // 得到0~1之间的随机数,y坐标
      if ((x - 0.5) * (x - 0.5) + (y - 0.5) * (y - 0.5) < 0.25) // 判断产生的随机点坐标是否在圆内
            m++;
    }
    n = 4.0 * m / 1000000;
    printf("Process %d of %d on %s pi= %f\n", myid, numprocs, processor_name, n);
    if (myid != 0) { // 判断是否是主节点
      MPI_Send(&m, 1, MPI_LONG, 0, 1, MPI_COMM_WORLD); // 子节点向主节点传送结果
    } else {
      long p = m; // 主进程也参与计算,所以初始化 p 为 m
      // 分别接收来自于不同子节点的数据
      for (int source = 1; source < numprocs; source++) {
            MPI_Recv(&m1, 1, MPI_LONG, source, 1, MPI_COMM_WORLD, &status); // 主节点接收数据
            p += m1;
      }
      pi = 4.0 * p / (count * numprocs); // 汇总计算 pi 值
      printf("pi= %f\n", pi);
    }
    MPI_Finalize(); // 结束 MPI 环境
    return 0;
}

五、运行结果效果图
https://i-blog.csdnimg.cn/direct/075b2a4b63f148e0b6a4d5ea10e9770f.png
实验六 并行计算的综合设计

一、 实验题目
用 MPI 技术去验证角谷猜想,要求验证数据的范围尽可能的大。
二、实验目标
熟悉 MPI 编程,加深对其编程的明白。
三、实验环境
Ubuntu 22.04 (LTS),
VM环境下,网络架构NAT,
计算节点数:4个
四、程序代码实现及测试
#include <stdio.h>
#include <mpi.h>

// 函数用于验证角谷猜想,并返回到达1所需的步骤数
int collatzSteps(int number) {
    int steps = 0;
    while (number != 1) {
      if (number % 2 == 0) {
            number /= 2;
      } else {
            number = number * 3 + 1;
      }
      steps++;
    }
    return steps;
}

int main(int argc, char** argv) {
    int rank, size;
    int start, end, step;
    int namelen;
    char processor_name;

    MPI_Init(&argc, &argv); // 初始化MPI环境
    MPI_Comm_size(MPI_COMM_WORLD, &size); // 获取进程总数
    MPI_Comm_rank(MPI_COMM_WORLD, &rank); // 获取当前进程标识
    MPI_Get_processor_name(processor_name, &namelen); // 获取节点名称

    // 确定每个进程的起始和结束值
    int total_numbers = 100; // 总共需要计算的数
    start = rank * (total_numbers / size) + 1;
    if (rank == size - 1) {
      // 最后一个进程需要处理剩余的数
      end = total_numbers;
    } else {
      end = start + (total_numbers / size) - 1;
    }

    // 输出当前进程的编号和所在节点名称
    printf("Process %d is on %s\n", rank, processor_name);

    // 验证角谷猜想并输出结果
    for (int i = start; i <= end; i++) {
      step = collatzSteps(i);
      printf("%d 执行了 %d 步, 等于1 on %s\n",i, step,processor_name);
    }

    MPI_Finalize(); // 结束MPI环境
    return 0;
}
五、运行结果效果图
https://i-blog.csdnimg.cn/direct/d82aed9d790749bb88235a36b0c510e1.png
实验七 并行计算的综合设计

一、 实验题目
用 MPI 技术去验证亲和数组合的个数。
要求验证数据,程序运行时间大于20分钟以上。
二、实验目标
熟悉 MPI 编程,加深对其编程的明白。
三、实验环境
Ubuntu 22.04 (LTS),
VM环境下,网络架构NAT,
计算节点数:4个
四、程序代码实现及测试
#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>

// 函数用于计算一个数的约数之和
int sum_of_divisors(int n) {
    int sum = 0;
    for (int i = 1; i <= n / 2; i++) {
      if (n % i == 0) {
            sum += i;
      }
    }
    return sum;
}

// 主程序
int main(int argc, char** argv) {
    int rank, size;
    char processor_name;
    int namelen;

    MPI_Init(&argc, &argv);
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    MPI_Comm_size(MPI_COMM_WORLD, &size);
    MPI_Get_processor_name(processor_name, &namelen); // 获取进程所在的节点名称

    // 设置验证的上限值
    int limit = 10000;

    // 计算每个进程的起始和结束值
    int start = rank * (limit / size);
    int end = (rank + 1) * (limit / size) - 1;
    if (rank == size - 1) {
      end = limit;
    }

    // 寻找亲和数并输出结果
    for (int a = start; a <= end; a++) {
      int B = sum_of_divisors(a);
      int A = sum_of_divisors(B);
      if (A == a) {
            printf(" 进程 %d: 亲和数: %d and %d on %s\n", rank, a, B,processor_name);
      }
    }

    MPI_Finalize();
    return 0;
}

五、运行结果效果图
#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>

// 函数用于计算一个数的约数之和
int sum_of_divisors(int n) {
    int sum = 0;
    for (int i = 1; i <= n / 2; i++) {
      if (n % i == 0) {
            sum += i;
      }
    }
    return sum;
}

// 主程序
int main(int argc, char** argv) {
    int rank, size;
    char processor_name;
    int namelen;

    MPI_Init(&argc, &argv);
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    MPI_Comm_size(MPI_COMM_WORLD, &size);
    MPI_Get_processor_name(processor_name, &namelen); // 获取进程所在的节点名称

    // 设置验证的上限值
    int limit = 10000;

    // 计算每个进程的起始和结束值
    int start = rank * (limit / size);
    int end = (rank + 1) * (limit / size) - 1;
    if (rank == size - 1) {
      end = limit;
    }

    // 寻找亲和数并输出结果
    for (int a = start; a <= end; a++) {
      int B = sum_of_divisors(a);
      int A = sum_of_divisors(B);
      if (A == a) {
            printf(" 进程 %d: 亲和数: %d and %d on %s\n", rank, a, B,processor_name);
      }
    }

    MPI_Finalize();
    return 0;
}

五、运行结果效果图
https://i-blog.csdnimg.cn/direct/d973fae05cc0467aa5eaabb22fe0a821.png

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: 云计算基础实验