编译器自动修复工具
未使用编译器自动修复工具
- (可选)下载GCC源码(请从GCC官网下载对应版本的源码)。本实践使用的是GCC 9.3.0源码包,编译并设置GCC环境变量,如图1所示。
具体编译过程,请参见GCC官网相关文档。
- 根据以下流程使用已安装的GCC 9.3.0,执行20000次源码包编译生成可执行文件测试,如图 复现内存一致性问题所示。
- 解压源码包并确认文件内容。
tar -zxvf fifo.tar.gz ls
- 编译源码。
make
- 运行生成的可执行文件。
./one_producer_one_consumer
源码中是一个单生产者单消费者的无锁队列,其中生产者会依次向栈中推入1,2,3三个int类型数据,消费者会读取栈中数据并向r1,r2,r3三个int类型变量赋值,在没有内存一致性错误发生时,预期结果应为r1=1,r2=2,r3=3。
执行结果:20000次测试中,复现内存一致性问题共计12次。
- 解压源码包并确认文件内容。
使用编译器自动修复工具
- 安装内存一致性修复组件。
- 获取内存一致性修复组件。
内存一致性修复组件: 从DevKit安装路径下,找到 “/opt/DevKit/devkitplugins/affinity/tools/weakconsistency/gccchecker/gcctool.tar.gz”。
“/opt/DevKit”为工具安装目录,请根据实际情况替换。
- 执行以下命令,解压安装包。
tar xf gcctool.tar.gz
解压后确认“gcctool/bin”目录下有以下文件:gcctool,gcctool-bin,libstdc++.so.6
- 配置环境变量。
将“gcctool”放入自定义目录,配置环境变量:export PATH=/path/to/gcctool/bin:$PATH
其中,“/path/to”为gcctool存放的自定义目录。
- 获取内存一致性修复组件。
- 下载GCC源码并解压(请从GCC官网下载对应版本的源码),本实践使用的是GCC 9.3源码包。
GCC修复工具 patch:https://github.com/kunpengcompute/devkitdriver/tree/main/gccchecker(Debian系列和Redhat系列操作系统都使用该依赖包。)
tar -xvf gcc-9.3.0.tar.gz
- 执行以下命令,合入GCC patch,如图3所示。
cd gcc-9.3.0/ patch -p1 < /path/to/gcc-9.3.0.patch
- 编译GCC,设置GCC环境变量,如图4所示。
- 具体编译过程,请参见GCC官网相关文档。
- 配置环境变量路径以实际编译安装路径为准。
- 编译fifo源码。
进入fifo源码目录,设置内存一致性修复组件优化等级“export HW_DEBUG=[ 0 | 1 | 2 ]”。当前实践内容设置组件优化等级为1,执行make命令进行编译。
export HW_DEBUG=1 make clean make
编译完成后再执行以下命令。objdump -d one_producer_one_consumer | grep dmb | head -20
即可显示20个自动修复的位置,如图5所示。
编译组件支持通过环境变量配置修复优化等级,不设置环境变量,修复工具不会生效。
export HW_DEBUG=[ 0 | 1 | 2 ]
- 0:不使用优化策略,性能损失最大。
- 1:使用最安全的修复策略,性能损失较大。
- 2:应用组件优化规则,可以减少性能损失。
- 验证源码修复效果。在源码目录执行以下指令:
./one_producer_one_consumer
连续执行可执行文件中的测试,执行20000次未出现内存一致性问题,编译器自动修复工具生效,如图6所示。
编译器自动修复工具验证结论
fifo源码在未使用修复工具时,共执行了20000次测试,其中12次执行异常。使用修复工具后,插入了20000个内存屏障指令,继续执行20000次测试,没有出现异常现象。