核心目的:减少运行时的 object time
方法一:改变运行的进程数
进入OpenCAEPoro目录下运行下述代码(进程数为4)
mpirun -np 4 ./testOpenCAEPoro ./data/case1/case1.data verbose=1
结果如下
可以看到,object time是很长的(真实的运行时间更长)
那么我来修改一下运行进程数(下面是readme中给出的要求)
那么我把进程数调节到10(最大),再来看一下运行结果
运行以下代码:
mpirun -np 10 ./testOpenCAEPoro ./data/case1/case1.data verbose=1
结果如下:
两次结果的对比可以看出,增加运行进程数,可以显著优化 object time
2.改变编译选项,更改数学库
PS:此后每次运行,进程数都是10
更改petsc的配置
有关petsc的介绍和编译时可添加选项,可以去网上找,作者也是去网上了解了一些相关信息
入手点还是我们在配置环境的时候所接触的那个build-petsc文件
在配置环境的时侯,作者由于配置build-petsc文件没有配置好,出现了 Fortran Error 这个错误,当时专门去了解了一下Fortran这个东西
Fortran的介绍:
Fortran是一种广泛使用的编程语言,特别是在科学计算和工程领域。它是由IBM开发的,最初于1957年发布。Fortran是Formula Translation的缩写,最初是为了数学和科学计算的目的而设计的。最新的版本是Fortran 2018,引入了一些现代编程语言的特性,如模块化编程和面向对象编程。具有丰富的数学计算能力和高性能计算特性。
了解之后发现,没什么用哈哈哈哈(又浪费了你10秒生命)
这个是配置环境的时候修改过的 build-petsc 文件
经过查找资料我们可以对箭头所指添加相关参数,变化为:
COPTFLAGS="-O3 -march=native"
CXXOPTFLAGS="-O3 -march=native"
-march=native:是一个 GCC(GNU Compiler Collection)编译器选项,用于针对当前编译机器的架构进行优化。当你使用这个选项时,编译器会自动检测你机器的 CPU 特性,并生成能够充分利用这些特性的代码
进一步考虑intel提供的高性能库(MKL,oneMKL,TBB,DAAL,IPP等)
DAAL专为数据分析和机器学习应用提供的优化库,支持多种算法和数据处理功能,这里不考虑
IPP这个库提供了用于信号处理、图像处理、数据压缩等的高性能函数,这里也不考虑
TBB是个开发工具套件,集成了多种高性能数学库(包括MKL),这里暂时不使用
在纠结是使用 MKL 库还是使用 oneMKL 库
经过网上搜索了解到:
- MKL:MKL 是一个经过高度优化的数学库,专注于 Intel 硬件。它通常能提供优越的性能,特别是在使用 Intel 处理器时,如果应用程序的需要最高的性能,且运行在 Intel 硬件上,直接使用 MKL 可能是更合适的选择
- oneMKL: oneMKL 是 Intel 提供的一个更高层次的 API,旨在简化对不同数学库的访问。它支持多种后端,包括 MKL、OpenBLAS 等,如果希望代码具有更好的可移植性,并且能够在不同的硬件和库之间轻松切换,oneMKL 可能是一个更好的选择,它也提供了一些高级功能,适合需要灵活性的应用
对于 petsc(可扩展的工具包用于科学计算),它通常与 MKL 有良好的兼容性,且很多用户在性能关键的应用中选择使用 MKL。如果对性能有严格要求,并且代码主要在 Intel 硬件上运行,直接使用 MKL 可能是最佳选择。然而,如果需要更好的灵活性和可移植性,oneMKL 也是一个不错的选择
经过上述了解之后,我选择MKL进行优化,因为核心目的是减少 object time
所以为了链接到MKL库,我们在build-petsc文件中**(./configure下)**加上下面这个语句
--with-blas-lapack-dir=/opt/intel/oneapi/mkl
继续加入一些编译时的选项
-funroll-loops:是一个编译选项,一方面可以用于优化循环的执行。在编译时,它会尝试展开循环,即将循环体的内容复制多次,以减少循环控制的开销和提高并行性,另一方面优化针对特定缓存结构的代码生成
-inline:使用内联函数可以减少函数调用的开销,提高程序的执行速度
-qmalloc:可以选择不同的内存分配策略,以优化内存使用
-qopenmp:启用 OpenMP 支持,以便利用多线程并行性
所以修改一下,修改为下述这样
结果如下
可以看到,优化结果还不是很明显
再加入一条编译选项试试:
-fp-model fast=2:是一个与浮点数处理相关的编译选项,通常用于 Intel 的编译器(如 ICC 或 icc)以及一些其他支持浮点优化的编译器。它的作用是优化浮点运算的性能,同时保持一定的数值准确性
最开始并不想加入这条语句,因为会导致最终运算结果的不准确,但是还是决定加上试试
最终修改成如下这样
结果如下
到这里我已经感觉,添加编译选项没啥用了,不过也可能是我没添加对
上网查找了一下资料,发现优化内存分配可能导致时间增加,所以去掉 -qopenmp和-qmalloc 再试一下
结果如下:
证明我的猜测是正确的
所以,编译选项还是应该一条一条的加,分别看效果,一次性加入过多编译条件可能适得其反
总结一下:纵然实现了少许优化,但是加入-fp-model fast=2 编译条件,会失去浮点精度,导致结果不准确,真实比赛时还是要权衡利弊
作者还是不甘心,决定去掉 -fp-model fast=2 条件,再跑一次(反证法)
可以看见,时间明显变长了,所以可以判断 -fp-model fast=2 是有显著效果的
3.尝试多机并行
在OpenCAEPoro_ASC2024目录下,执行以下命令
vim hostfile
将创建的hostfile文件修改为如图所示的结果
最终结果如下
这里是没有正确实现多机并行,在优化(2)中有改正
4.思考进程数问题
前面提到readme中要求,进程数不可以大于10,具体原因去网上了解了一下:
限制进程数是出于安全和性能考虑。在操作系统中,每个进程都需要系统资源来运行,包括内存、CPU等。如果没有限制进程数,可能会导致系统资源被耗尽,造成系统崩溃或变得不稳定
如果是这个原因,那么我认为进程数是可以大于10的
修改一下hostfile(仍然是多机并行),设置进程数为50看一下结果
可以看到,object time 有很明显的减少
再次增加5个进程试试(此时进程数为55)
可以看到,增加了五个进程之后,并没有明显的优化效果,那我们改为52个进程试一下
显然,在进程数为50的基础上增加进程,优化效果就不是很明显了
所以,我们推断(考虑电力消耗):进程数在50~52之间为最佳
5.总结:
- 改变进程数是最有效的优化方式
- 添加编译选项的优化效果不是很明显(可能因为模型包含了大量的矩阵计算)
- 增加进程数到合适的值,确实可以有效的优化object time
但是,正式比赛时要考虑功耗问题,所以过度增加进程数并不可取(进程数为50左右时)
后续会使用vtune找到耗时久的函数,也会对程序主要功能部分的代码进行优化,看看是否有效果