更多内容请访问摩尔线程博客中心
1. 引言
近些年,NVIDIA及其CUDA生态占据着GPGUP的领先地位,国产厂商也在奋力追赶。基于现实的考量,追赶者们需要尊重业界现存大量CUDA代码的事实,因此我们推出了musify这一工具,旨在尽量将原有的CUDA代码便捷无痛地转化,迁移至MUSA平台上编译运行,从而达到间接兼容的效果。
2. 如何使用musify
2.1. 安装依赖
musify使用python编写,要运行musify首先需要系统中安装有python3,然后假设用户使用ubuntu为例,执行以下命令
# 使得python默认指向python3
sudo apt install python-is-python3 -y
# 安装python依赖管理工具
sudo apt install pip -y
# 如果最后一行依赖库安装存在网络问题可以按需配置更新源,取消下一行的注释是一种可行的选择
# pip config set global.index-url https://pypi.mirrors.ustc.edu.cn/simple/
# 安装musify的依赖库
pip install ahocorapy
2.2. 帮助信息
和一般的命令行程序一样,musify通过-h/--help提供了帮助信息,有经验的用户可以直接参考帮助信息进行使用
$ musify-text -h
usage: musify-text [-h] [-t | -c | -i] [-d {c2m,m2c}] [-m [MAPPING ...]] [--clear-mapping] [-l {DEBUG,INFO,WARNING}] [srcs ...]
positional arguments:
srcs source files to be transformed
options:
-h, --help show this help message and exit
-t, --terminal print code to stdout
-c, --create write code to newly created file, default action
-i, --inplace modify code inplace
-d {c2m,m2c}, --direction {c2m,m2c}
convert direction
-m [MAPPING ...], --mapping [MAPPING ...]
api mapping
--clear-mapping clear default and previous mapping
-l {DEBUG,INFO,WARNING}, --log-level {DEBUG,INFO,WARNING}
lowest log level to display
如上信息,本工具的使用方式是先设置一系列的选项,最后跟着需要转化的代码文件列表
以下是对选项的详细解释:
-t
,-c
,-i
是输出方式,使用时三选其一;分别为输出到屏幕,另外新建文件,直接修改原来的代码文件;默认行为是新建文件输出(但是如果代码有版本管理等保护,使用-i/--inplace直接原地修改比较方便)-d
设置方向c2m是cuda至musa,m2c是musa至cuda;默认为cuda至musa-m
指定替换使用的映射表,是映射表是json文件,内容为单层无嵌套的json object,其中每个name,value对分别表示相应的cuda和musa命名;一般不用指定使用默认即可,如果有特殊需求可自己生成映射表并指定,如果有多个映射表,使用如下格式-m a.json m b.json,即每个映射表前都有一个前置的-m-m
会添加新的映射表,不会覆盖原有的默认映射表,如果不想要默认映射表,需要使用--clear-mapping
,然后在这个选项右边使用-m
指定自己想要的映射表-l
指定日志等级,高于设置等级的日志都会被打印出来,默认为INFO
前面的选项顺序可以随意调整,如果使用默认值也可以不写,但是需要转化的代码文件必须跟在最后;同时为了防止存在以-
开头的文件路径被识别为选项,在所有选项之后,文件路径之前,加上--
2.3. 使用示例
经过了如上的解释后,我们可以来到一个最简单的例子,使用默认映射表,默认转化方向(cuda至musa),只有输出方式改为了原地修改
如下命令修改了当前目录下的a.cpp和b.cpp两个文件
musify-text --inplace -- a.cpp b.cpp
但是一般而言,我们并不想手动列举需要转化的文件,一般一个项目有大量的代码文件需要转化,此时我们可以借助shell的``语法和一些第三方的文件搜索工具,比如
# 递归查找目录${DIR}下所有后缀名为cu,cuh,cpp或h的文件并转化
musify-text --inplace -- `find ${DIR} -name '*.cu' -name '*.cuh' -name '*.cpp' -name '*.h'`
同时我们可以推荐一些更加现代化的工具
# 安装此处使用的工具
sudo apt install ripgrep -y
# 如果没有自己编写kernel,cuda程序可以是纯C/C++代码,ripgrep对于cpp的后缀名自带预设,-tcpp就可以调用,rg --files则递归搜索指定目录下所有符合要求的文件
musify-text --inplace -- `rg --files -tcpp ${DIR}`
# ripgrep没有内置cuda的后缀模式,但是我们可以通过--type-add指定,然后再当场调用
musify-text --inplace -- `rg --files --type-add 'cuda:*.cu' --type-add 'cuda:*.cuh' -tcuda -tcpp ${DIR}`
# 如果嫌上面两种复杂,也可以使用-g选项直接指定后缀名,和前面的find作用基本一致
musify-text --inplace -- `rg --files -g '*.cu' -g '*.cuh' -g '*.cpp' -g '*.h' ${DIR}`
2.4. 排除标记
可能有不少读者注意到了musify的命令名称为musify-text,其实这是因为它的算法是单纯的文本匹配。
这种实现方案的原因主要是发现语法分析会引入过重的依赖(尤其对C++这种上下文相关文法),给用户的使用带来不便,纯粹文本匹配的工具更加小巧灵活。
当然这样带来了一定的转化可能不够智能的问题,于是我们加入了类似于lcov行覆盖率工具的排除标记功能,可以标记一定范围的代码不受转化影响,保持原样。
使用排除标记需要一定程度上修改原有代码,加入排除标记。
MUSIFY_EXCL_LINE
包含本标记的行会被排除
MUSIFY_EXCL_START
从包含本标记的行开始,直到MUSIFY_EXCL_STOP之间的行会被排除;当前行也会被排除
MUSIFY_EXCL_STOP
结束由MUSIFY_EXCL_START开启的排除;当前行不会被排除
其中START和STOP成对使用
// MUSIFY_EXCL_START
char *str_array[] = {
"cuInit",
"cuMalloc"
};
// MUSIFY_EXCL_STOP
LINE单独使用
char str[] = "cuInit"; // MUSIFY_EXCL_LINE
3. 总结与展望
本文介绍了musify的设计意图,使用方法和当前的缺陷。可能有不少读者也意识到如果没有其他不同版本需要加以区分,单纯因为使用了文本匹配就将工具叫做musify-text是不充分的;事实上,介于语法分析过重,文本匹配不够智能,目前存在一个后续计划是引入词法分析进行一定的代码分析识别,准备使用musify-lexer作为命令名称。