• 高性能并行计算华为云实验五:PageRank算法实验


    目录

    一、实验目的

    二、实验说明

    三、实验过程

    3.1 创建PageRank源码

    3.2 makefile的创建和编译

    3.3 主机配置文件建立与运行监测

    四、实验结果与分析

    4.1 采用默认的节点数量及迭代次数进行测试

    4.2 分析并行化下节点数量与耗时的变化规律

    4.3 分析迭代次数与耗时的变化规律

    五、实验思考与总结

    5.1 实验思考

    5.2 实验总结

    END~

    世界上第二难的事就是唱《普通朋友》了,那第一呢?


    一、实验目的

    1.1 掌握 PageRank 算法程序的编写以及编译运行。

    1.2 实现在多台主机上编译运行 PageRank 算法的程序。

    二、实验说明

    华为鲲鹏云主机、openEuler 20.03 操作系统;

    设置的四台主机名称及ip地址如下:

    122.9.37.146    zzh-hw-0001

    122.9.43.213    zzh-hw-0002

    116.63.11.160   zzh-hw-0003

    116.63.9.62     zzh-hw-0004

    三、实验过程

    3.1 创建PageRank源码

    以下步骤均在四台主机上,以 zhangsan 用户执行。

    首先输入以下命令,创建 pagerank 目录存放该程序的所有文件, 并进入 pagerank 目录mkdir /home/zhangsan/pagerank    cd /home/zhangsan/pagerank

    然后输入vim pagerank.cpp创建 PageRank 算法源码 pagerank.cpp(四台主机都执行),代码输入完毕后输入:wq完成文件保存。

    随后输入vim logging.h完成头文件的编写。关键代码如下所示:

    1. if (argc != 4) {
    2. cout << "Usage: " << argv[0] << " thread-num node-num iterations";
    3. exit(-1);
    4. }
    5. int t = atoi(argv[1]);
    6. int n = atoi(argv[2]);
    7. int m = atoi(argv[3]);
    8. omp_set_num_threads(t);
    9. subgraph sg;
    10. sg.G = graph(n);
    11. struct timeval start, stop;
    12. gettimeofday(&start, NULL);
    13. PageRank(sg, m, t);
    14. gettimeofday(&stop, NULL);
    15. double elapse = (stop.tv_sec - start.tv_sec) * 1000 +
    16. (stop.tv_usec - start.tv_usec) / 1000;
    17. cout << "当节点数量为 " << n << " 且迭代次数为 " << m << " 时,耗时为 " << elapse << " 秒。" << endl;

    3.2 makefile的创建和编译

    首先输入vim Makefile创建Makefile文件,文件具体内容如下:

    1. CC = g++
    2. CCFLAGS = -I . -O2 -fopenmp
    3. LDFLAGS = # -lopenblas
    4. all: pagerank
    5. pagerank: pagerank.cpp
    6. ${CC} ${CCFLAGS} pagerank.cpp -o pagerank ${LDFLAGS}
    7. clean:
    8. rm pagerank

    输入时需注意缩进,完成后输入“make”进行编译,可得到可执行文件pagerank

    3.3 主机配置文件建立与运行监测

    首先输入vim /home/zhangsan/pagerank/hostfile进行主机配置文件建立,添加如下内容

    zzh-hw-0001:2

    zzh-hw-0002:2

    zzh-hw-0003:2

    zzh-hw-0004:2

    并对文件进行保存。然后输入vim run.sh 创建脚本文件,内容如下:

    1. # 检查参数数量是否正确
    2. if [ "$#" -ne 4 ]; then
    3. echo "Usage: $0 "
    4. exit 1
    5. fi
    6. app=${1}
    7. thread_num=${2}
    8. node_num=${3}
    9. iterations=${4}
    10. if [ ${app} = "pagerank" ]; then
    11. ./pagerank ${thread_num} ${node_num} ${iterations}
    12. fi

    此处较原教程作出了较大改动,将节点数和迭代次数都设置为了命令行参数,可通过用户输入进行调整。原教程中节点数和迭代次数分别固定为了80000和10,做出此改动的目的也是为了探究节点数和迭代次数与运行耗时的关系。

    除此之外我还对程序的输出进行了优化,将原先输出为两组数字改为输出如下内容

    cout << "当节点数量为 " << n << " 且迭代次数为 " << m << " 时,耗时为 " << elapse << " 秒。" << endl; 这样可以更好的观察结果与变量之间的对应关系。

    四、实验结果与分析

    4.1 采用默认的节点数量及迭代次数进行测试

    测试结果如下:

    整理数据如下:

    处理机数量

    节点数量

    迭代次数

    耗时

    1

    80000

    10

    7880

    2

    80000

    10

    4650

    3

    80000

    10

    5498

    4

    80000

    10

    5633

    5

    80000

    10

    5494

    6

    80000

    10

    5074

    7

    80000

    10

    5421

    8

    80000

    10

    6238

    将上述结果进行可视化,如下所示:

    从整体结果可以看出,随着进程数量的增加,耗时越来越少。从开始的 8000 减少到 6000 左右。但处理机数从1变为2的过程,性能提升最大。而后可能由于处理机间同步或通信开销等原因,耗时增加。

    4.2 分析并行化下节点数量与耗时的变化规律

    受篇幅限制,我们仅对如下结果进行分析

    在节点数量从 80000 增加到 800000 时,耗时从 6238 秒增加到 139404 秒,即增加了约 22.33 倍。这不是一个严格的二次方变化关系,而是更接近线性增长。

    于是我开始计算每个节点的平均处理时间来分析规律:

    在第一个情况下,平均处理时间为 6238 秒 / 80000 = 0.078秒;

    在第二个情况下,平均处理时间为 139404 秒 / 800000 = 0.1743秒。这表明,随着节点数量增加,每个节点的平均处理时间也在增加,导致总体耗时的增加。

    原因分析:

    ①节点间通信开销:随着节点数量的增加,节点间通信开销也会增加,导致整体耗时增加。

    ②数据量增加:随着节点数量的增加,涉及的数据量也会增加,需要更多的计算资源和时间。

    并行计算效率:在并行计算中,随着节点数量的增加,可能会遇到负载均衡或通讯开销等问题,影响并行计算的效率。

    4.3 分析迭代次数与耗时的变化规律

    结果如下:

    将上述数据进行可视化,结果如下:

    观察实验结果可以很明显的发现并行运算耗时与迭代次数成线性关系。这种线性关系可能表明在当前的并行计算环境下,迭代次数对于整体耗时的影响比较明显,并且可能受到了一些固定的通信开销等因素的影响,使得整体的耗时增长较为稳定。当然需要注意的是当节点数量较大时,可能会产生非线性的耗时增长。

    五、实验思考与总结

    5.1 实验思考

    ①采用头文件有什么好处?

    头文件在C和C++编程中有许多好处,如下所述:

    模块化和组织性:头文件可以帮助将代码分割成逻辑模块,提高代码的组织性和可读性。通过将相关的函数原型、宏定义和结构声明放在头文件中,可以更清晰地了解每个模块的功能和接口。

    接口定义:头文件通常包含了公共接口的声明,这些接口定义了模块之间的通信方式和使用规范。通过头文件,可以明确地了解如何使用某个模块或库。

    依赖管理:使用头文件可以方便地管理代码之间的依赖关系。当一个源文件需要使用另一个模块的功能时,只需要包含相应的头文件即可,而不需要知道该模块的具体实现细节。

    编译优化:头文件可以帮助编译器进行优化和错误检查。通过包含必要的头文件,编译器可以在编译时检查函数调用的正确性,并优化代码生成过程。

    重用性:头文件可以被多个源文件重复引用,从而实现代码的重用。这种机制使得相同的函数或数据结构可以在不同的源文件中被共享和复用。

    ②简述pageRank算法的并行化原理

    PageRank算法的并行化原理是通过将网页图分解成多个子图,并在多个计算节点上同时进行排名计算。每个节点独立处理部分网页和链接,迭代更新其PageRank值。在迭代过程中,节点间需要交换排名信息以保证全局一致性。一旦所有节点达到收敛条件,局部的PageRank值将被汇总以形成最终的全局排名。并行化可以显著提高PageRank计算的效率,尤其是在处理大规模数据集时。

    简而言之,PageRank算法的并行化涉及分布式数据存储、局部迭代计算、节点间信息同步和全局收敛检测。通过这种方法,算法能够利用多个处理器的计算能力,加快网页排名的计算速度,同时保持算法的准确性和有效性。

    5.2 实验总结

    在华为鲲鹏云服务器上进行的PageRank算法实验中,我成功地实现了算法的并行化,并探究了节点数量和迭代次数对运行耗时的影响。

    实验过程中我观察到随着进程数量的增加,总体耗时逐渐减少,尤其是在从单进程过渡到双进程时,性能提升最为显著。然而,进程数量继续增加时,由于节点间的同步和通信开销,耗时减少的趋势放缓。当节点数量从80000增加到800000时,耗时呈现出超线性增长,这不仅因为数据量的增加,也因为节点间通信开销的上升。此外,迭代次数与耗时之间显示出线性关系,这可能与每次迭代时固定的通信开销有关,导致每次迭代的额外耗时保持稳定。实验结果让我意识到,在并行计算中,为了提高效率,需要重视负载均衡和节点间通信开销的优化。

    通过本实验,我不仅掌握了PageRank算法的编写、编译和运行,还学会了配置并行计算环境。实验过程中,我们深入了解了并行计算中影响性能的关键因素,包括进程数量、节点数量、迭代次数以及它们对总体耗时的具体影响。这些经验对于设计和实现高效的并行算法至关重要,有助于在未来的研究和应用中进一步优化算法性能。

    END~

    世界上第二难的事就是唱《普通朋友》了,那第一呢?

    天气☁️:⛈️暴雨!

  • 相关阅读:
    小米机型安全删除内置软件列表 miui12 miui13 可删除内置
    Java测试(12)---性能测试
    Zookeeper集群 + Kafka集群
    Python与数据分析--Pandas-1
    【单片机基础】单片机的时序概念
    Python用正则化Lasso、岭回归预测房价、随机森林交叉验证鸢尾花数据可视化2案例|数据分享...
    【数据结构】线性表的应用:稀疏一元多项式运算器
    企业架构LNMP学习笔记44
    机器人制作开源方案 | 扫地机器人
    开源两个月总结
  • 原文地址:https://blog.csdn.net/m0_64198455/article/details/139912813