GPGPU-Sim兼容性问题解决方案及脚本自动化运行方法的研究

2023-10-09 01:44曹建立仲怡宁赵晨阳
洛阳师范学院学报 2023年8期
关键词:配置文件脚本模拟器

曹建立, 仲怡宁, 赵晨阳

(洛阳师范学院 数学科学学院, 河南 洛阳 471934)

0 引言

GPGPU-Sim是一款用CPU来模拟GPU运行过程的模拟器软件[1]. 该模拟器的运行统计结果可以达到时钟周期的精度, 其代码和配置文件可根据用户需求来修改, 并且提供了可视化工具Aerial Vision[2]来帮助用户直观地观察Kerne内核的运行状态, 此外, 还集成了可以提供功耗报告的功耗分析模块GPUWattch[3]. 因此, GPGPU-Sim成为大量学者研究GPU体系结构、验证GPU新设计方案和调度算法的工具. 如Sahoo等[4]利用GPGPU-Sim来研究GPU缓存管理方案, Li等[5]利用GPGPU-Sim来研究Bypass技术在GPU上的应用效果, Mu等[6]利用GPGPU-Sim来研究GPU中的内存调度优化.

该模拟器基于Ubuntu10.10开发, 在Ubuntu 10.10版本和12.04版本上运行良好,但在16.04及之后的版本上运行时, 会出现动态链接库不兼容的问题. Ubuntu 10.10版本和12.04版本的操作系统分别于2010年10月和2012年4月发布, 目前看来已经比较陈旧, 大量主流的计算机硬件已经不再支持该版本的安装与运行. 于是, 对于众多通过GPGPU-Sim来研究GPU体系结构的学者来说, 继续使用该软件存在两个问题: 一方面, 目前主流的计算机硬件具备较高的运算能力, 但是因为不支持Ubuntu12.04之前的版本, 所以无法直接运行GPGPU-Sim; 另一方面, 能运行老版本Ubuntu系统的硬件大多比较陈旧, 且运行GPGPU-Sim时效率十分低下. 虽然这些问题可以通过在新硬件上运行虚拟机来解决, 但是经过实验对比, 虚拟机的运行效率很低, 性能大约是直接在硬件上运行时的2/3. 因此, 研究让GPGPU-Sim可以在新的软硬件平台上直接运行的方法, 对于广大模拟器使用者和研究者有着现实意义.

1 模拟器原理

GPGPU-Sim小组在说明文件中指出了开发GPGPU-Sim的目的: 一方面可以让研究者分析CUDA程序瓶颈或者分析调度算法的效果; 另一方面可以让没有安装Nvidia硬件的计算机也可以运行CUDA程序. 因此GPGPU-Sim提供了性能模拟和功能模拟两个模式: 功能模拟仅输出和真实硬件相同的运行结果; 性能模拟则在输出结果的同时, 还输出大量GPU内部寄存器、缓存、通信网络和功耗等信息.

GPGPU-Sim开发小组在内存中利用堆栈、队列、数组等数据结构模拟了GPU硬件中的流水线、缓存和寄存器等部件, 并利用CPU来模拟GPU中Kernel程序的数据流动和指令执行的过程. GPGPU-Sim编译后会产生libcudart.so和libOpenCL.so两个动态链接库. 之后使用这两个库替代系统中的默认库, 则应该由GPU硬件来执行的PTX指令会被拦截, 转由CPU来模拟执行[7]. Kernel程序的硬件执行方式和软件模拟调用关系如图1所示.

图1 Kernel程序的硬件执行方式和软件模拟调用关系

对于安装有Nvidia硬件的平台, 在运行时也可以选择使用真实硬件运行. 切换方式是修改名为LD_LIBRARY_PATH的系统变量, 根据要求指向驱动程序的动态链接库, 或者GPGPU-Sim产生的动态链接库.

2 兼容性问题及解决方案

研究者通过修改GPGPU-Sim的源代码来实现新的资源调度算法、新的缓存置换策略和新的设计的过程中, 往往需要用gdb来追踪、调试代码. 这就要求虚拟机调用的动态链接库以源码编译的方式得到, 且调试时能访问到源代码.

GPGPU-Sim的编译过程已经有大量的文献可以借鉴, 在此不再赘述. 在Ubuntu 12.04之前的版本上, 经过编译与环境变量配置, 即可顺利用模拟器来替代GPU硬件, 以实现CUDA程序的模拟.

但是在Ubuntu 16.04版本以及之后的版本上, 按照传统的方法安装配置后, 启动基准程序可能导致运行错误.

此时可以使用gdb调试工具加载程序错误产生的core文件, 并用bt命令查看调用堆栈, 会显示大量同C++动态链接库相关的错误报告信息.

究其原因, 是因为GPGPU-Sim基于GCC 4.X.X版本开发, 而较新版本的Ubuntu系统使用了高版本的GCC和GC++编译器(5.X.X), 不同版本的CC++的动态运行库文件之间存在不兼容的问题, 从而导致了调用运行库出错. 其核心问题是GPGPU-Sim要求CC++动态链接库版本不能超过6.0.14.

解决该问题的常用办法是通过编译低版本GC++编译器源码, 或者用apt-get install命令通过参数指定低版本的方式来重装GCC和GC++编译器, 然后重新编译GPGPU-Sim. 该方法的缺点是操作比较复杂和耗时. 更重要的是, 将系统的GCC和GC++编译器强制降低版本后, 可能给其他软件的编译和运行带来诸多问题.

经过反复比较和实验, 笔者发现了一种便捷、不干扰其他程序运行的解决办法: 在运行GPGPU-Sim前, 用低版本GC++的库文件替代当前系统的库文件; 待运行结束后, 再将库文件替换回来. 替换操作无需反复复制和删除文件, 可以通过灵活的链接命令来实现.

例如, 本文实验平台中, 使用locate命令查找, 发现GPGPU-Sim需要的GC++动态链接库文件libstdcC++.so.6位于/usr/lib/x86_64-linux-gnu/目录下, 该文件其实是一个链接文件, 指向同目录下的库文件libstdcC++.so.6.0.21. 替换操作步骤如下.

(1)将老版本的动态链接库文件libstdcC++.so.6.0.14复制备份到库目录下, 该版本的链接库文件可以从GPGPU-Sim官网提供的虚拟机中提取.

(2)运行GPGPU-Sim前, 先将系统默认的链接文件libstdcC++.so.6删除, 然后重建该链接文件并指向低版本的动态链接库文件libstdcC++.so.6.0.14. 可以使用下面命令:

cd /usr/lib/x86_64-linux-gnu/

rm libstdcC++.so.6

ln -s libstdcC++.so.6.14 libstdcC++.so.6

(3)此时可以顺利运行GPGPU-Sim, 采集和分析GPU模拟数据.

(4)运行完成后, 需要把动态库修改回来, 否则可能造成其他程序运行不正常甚至操作系统不正常. 可以使用下面命令:

cd /usr/lib/x86_64-linux-gnu/

rm libstdcC++.so.6

ln-s libstdcC++.so.6.21 libstdcC++.so.6

如果忘记了将链接指向高版本的动态库, 并且进行了关机或者重启操作, 可能导致系统再次启动时发生异常, 并无法进入图形界面. 此时需要按下Ctrl+Alt+F1(F1到F6的文本模式均可, F7是正常启动的图形界面)切换到文本模式终端, 然后执行上面第(4)步的修改链接操作, 重新启动即可.

笔者还建议将第(2)步和第(4)步的命令写入shell脚本, 赋予执行权限, 并将第(2)步脚本加入系统启动服务, 在第(4)步加入系统关闭、重启服务, 让这些操作自动执行, 以避免忘记. 待对GPGPU-Sim的研究完成后, 再移除这些脚本.

3 动态链接库执行方式

通过对GPGPU-Sim编译过程和运行过程的分析, 发现编译源代码的目标是获得libcudart.so、libOpenCL.so两个动态链接库. 因此, 对于只需要运行模拟器获得输出结果, 而无需在运行期间追踪模拟器代码的应用场景, 可以省略下载、编译源码这一步, 即直接将编译好的动态链接库复制到本机, 并经过适当的环境配置(CUDA路径、so动态链接库路径和环境变量等)来运行模拟器. 当然, 模拟器运行所需要的其他依赖库也要提前安装.

具体步骤如下:

(1)复制已经编译好的libcudart.so、libOpenCL.so库文件目录到本计算机.

(2)配置LD_LIBRARY_PATH环境变量, 指向复制来的动态链接库文件, 替代系统中原有的库文件(在安装GPU硬件和驱动程序的情况下).

(3)复制GPGPU-Sim配置文件: gpgpusim.config、gpuwattch_gtx480.xml、config_fermi_islip.icnt到CUDA程序同一目录下. 该步骤建议使用链接文件完成, 避免冗余文件.

(4)启动CUDA程序.

该方法适合使用多台计算机来并行模拟基准测试程序的研究者, 可以有效避免在多台计算机上传输代码和编译代码的重复工作.

4 并行执行方式

GPGPU-Sim利用软件来模拟硬件执行过程, 大约有10万左右的减速因子, 每个benchmark过程需要执行时间少则几十分钟, 多则几天. 如果采用串行的方式来执行几十个benchmark, 则每轮测试会消耗数周时间, 这对使用者来说是非常高的时间成本. 目前无论服务器、台式机还是笔记本电脑, 大都配备了多核处理器, 合理利用多核并行, 能大大加速测试过程. 并行执行的关键是使用后台执行操作符nohup &, 并使用awk和grep工具将输出数据中的重要数据筛选出来, 存入指定的文件中, 以备分析. 以最常使用的ISPASS-2009基准程序集为例, 其脚本内容如下: 读取benlist文件中保存的需要运行的基准程序所在的文件夹名字, 然后进入文件夹, 并用后台方式执行README.GPGPU-Sim脚本, 以创建一个执行脚本时指定的名字的文件, 之后将输出结果中关于L1缓存、GPU运行周期数、Kernel名字的信息保存到该文件中. 其他的基准程序集也可用该技术来并行执行. 其主要代码如下:

#! /bin/bash

if [ -z MYM1 ]

then

echo "input log file name."

else

curdir=′pwd′

num=′wc -l benlist|awk ′{print MYM1}

for (( benno=1; benno <= MYMnum ; bennoC++))

do

xxx=′sed -n "MYM{benno} p" benlist′

echo "MYMbenno == MYM{xxx}"

if [ -d MYM{xxx} ]

then

cd MYMxxx

nohup ./README.GPGPU-Sim | egrep "g_fetch_access_L1I | gpu_sim_cycle| kernel_name">>MYM1 &

end=MYM(date +%s)

cd MYMcurdir

else

echo -e "MYM{benno} MYM{xxx} not run."

fi

done

fi

待模拟运行完成后, 可以编写脚本, 将不同benchmark的多个指标提取出来, 以表格的方式显示, 方便对比. 其主要代码如下:

#! /bin/bash

fsource1=MYM1

outfile=MYMfsource1.get

echo -e "name pre_mem tot_cycle tot_insn" >>MYMoutfile

num=′wc -l benlist|awk′{print MYM1}

for (( i=1; i <= MYMnum ; iC++))

do

xxx=′sed -n "MYM{i} p" benlist′

if [ -d MYM{xxx} ]

then

tail -n 19 MYM{xxx}/MYMfsource1 |grep "gpu_tot_sim_cycle" |awk ′{printf("%d ", MYM6) }′ >>MYMoutfile

tail -n 19 MYM{xxx}/MYMfsource1 |grep "gpu_tot_sim_insn" |awk ′{printf("%d ", MYM6) }′ >>MYMoutfile

tail -n 19 MYM{xxx}/MYMfsource1 lgrep "gpu_tot_ipc" |awk ′{printf("%f ", MYM6) }′ >>MYMoutfile

fi

done

研究者有时需要研究不同参数配置下的性能指标, 需要进行多轮的修改配置文件、运行benchmark过程. 此时需要提前修改好多个配置文件, 以不同名字命名, 然后在每轮测试开始前将链接指向不同的配置文件, 并利用sleep命令等待最长的benchamark完成. 这样可以自动化完成多种配置下整个基准程序集的模拟. 其主要代码如下:

run_dir=/home/sim/ispass2009-benchmarks #指向基准程序所在目录

config_dir=/home/sim/configs/GTX480 #指向GPUSim配置文件所在目录

for n in 4 8 16

do

cd MYMconfig_dir

rm gpgpusim.config

ln -s gpgpusim.config.ori.MYM{n}kL1I gpgpusim.config #指向不同配置文件

cd MYMrun_dir

./runall.sh out_MYM{n}kL1I_lrr.txt#调用脚本后台运行全部测试程序

sleep 2h # 等待本轮全部测试完成

done

5 中间文件和log文件分析

GPGPU-Sim运行过程中会先使用CUDA SDK的cuobjdump工具来分析CUDA程序, 从中提取出GPU Kernel的PTX和SASS代码, 并写入中间文件, 然后读取这些指令进行模拟. 在默认配置下, 这些文件会保留下来. 研究这些中间文件的内容, 对理解GPGPU-Sim的工作原理, 以及程序的运行状况有很大帮助. 例如, Liang等[8]基于PTX指令集的load.global指令展开研究, 设计了缓存Bypass编译器框架. Cao等[9]利用PTX指令文件分析了CUDA程序中Kernel容量的分布情况, 并设计了指令缓存预取机制.

log文件中记录了GPU各部件的功耗状况, 可用于GPU功耗研究. 中间文件和log文件含义如表1所示.

表1 中间文件和log文件含义

6 结语

本文分析了在高版本Ubuntu系统上运行GPGPU-Sim、调用动态库时发生的兼容性问题, 并提出了解决方案, 之后介绍了一种无需编译源代码即可运行GPGPU-Sim的简单方法. 以ISPASS-2009为例, 给出了可以自动运行测试、采集结果的脚本参考文件. 该方法可以极大提高工作效率.

猜你喜欢
配置文件脚本模拟器
酒驾
提示用户配置文件错误 这样解决
了不起的安检模拟器
盲盒模拟器
划船模拟器
安奇奇与小cool 龙(第二回)
互不干涉混用Chromium Edge
忘记ESXi主机root密码怎么办
数据库系统shell脚本应用
快乐假期