天秤源码优化工具
天秤源码优化工具是一款基于Clang/LLVM的静态代码分析工具,专注于C/C++代码的向量化优化。工具能够自动识别可向量化的循环模式,检测阻碍向量化的因素,并自动生成优化后的向量化代码,实现代码的自动化改写,帮助开发者快速将标量代码转换为高效的SIMD向量化代码,充分发挥NEON/
前提条件
- 已参照压缩包安装方式(以.tar.gz后缀结尾的软件包)安装天秤源码优化工具。
- 工具为单独压缩包承载(tiancheng-xxx-Linux-Kunpeng.tar.gz),请解压后切换至工具目录使用。
命令功能
自动识别可向量化的循环模式,检测阻碍向量化的因素,并自动生成优化后的向量化代码,实现代码的自动化改写。
命令格式
./tiancheng -h
参数说明
参数 |
参数选项 |
说明 |
|---|---|---|
-h/--help |
- |
可选参数,获取帮助信息。 |
-i |
- |
必选参数,指定输入的C/C++源文件。 |
-o |
- |
必选参数,指定输出的JSON报告文件目录及文件名,文件后缀为.json。 |
-r |
- |
可选参数,指定输入的C/C++源文件项目的根路径,用于头文件搜索,避免头文件缺失。 |
-v |
- |
可选参数,启用详细输出模式,显示更多调试信息和分析过程。默认不启用。 |
--simd-target |
neon/sve |
可选参数,指定转换的指令集,可指定为NEON或SVE,默认为NEON。
|
--enable-ifstmt-scan |
- |
可选参数,启用对if语句的扫描分析。 |
--version |
- |
可选参数,显示工具的版本信息。 |
使用示例
- 执行以下命令,查看天秤源码优化工具支持的功能信息。
./tiancheng -h
返回信息如下:OVERVIEW: ARM Intrinsics Analyzer USAGE: tiancheng [options] OPTIONS: -h/--help Display available options -i <filename> Specify input C/C++ source file -o <filename> Specify output report file -r <pathname> Inputfile root path -v Enable verbose output --simd-target=<value> Convert simd type selection =neon Convert to ARM NEON intrinsics =sve Convert to ARM SVE intrinsics --enable-ifstmt-scan Enable scanning of if statements --version Display the version of this program - 对源码文件进行扫描并输出分析报告。
./tiancheng -i /home/demo/input.cpp -o /home/demo/output.json -r /home/demo/code_project
扫描/“home/demo/”下的input.cpp文件,在“/home/demo/”下生成名为output.json的JSON报告文件。若源码文件为项目下的文件,可使用-r参数指定源码文件所属项目根目录,避免头文件缺失。
返回信息如下:
Analyzing file: /home/demo/input.cpp Output will be saved to: /home/demo/output.json Start to recognize process. Start to recognize file: /home/demo/input.cpp Start to scan code. In file included from /home/demo/input.cpp:5: In file included from /usr/lib/gcc/aarch64-linux-gnu/10.3.1/../../../../include/c++/10.3.1/iostream:39: In file included from /usr/lib/gcc/aarch64-linux-gnu/10.3.1/../../../../include/c++/10.3.1/ostream:38: In file included from /usr/lib/gcc/aarch64-linux-gnu/10.3.1/../../../../include/c++/10.3.1/ios:38: In file included from /usr/lib/gcc/aarch64-linux-gnu/10.3.1/../../../../include/c++/10.3.1/iosfwd:40: In file included from /usr/lib/gcc/aarch64-linux-gnu/10.3.1/../../../../include/c++/10.3.1/bits/postypes.h:40: In file included from /usr/lib/gcc/aarch64-linux-gnu/10.3.1/../../../../include/c++/10.3.1/cwchar:44: /usr/include/wchar.h:35:10: warning: 'stddef.h' file not found 35 | #include <stddef.h> | ^~~~~~~~~~ [FilterAnchors] Limiting from 22 to 10 anchors [CallDepth] Function 'main': original anchors=22, filtered=10 → disabling interprocedural analysis Recognized pattern: ForStmt OTHER_PATTERN Recognized pattern: ForStmt OTHER_PATTERN Recognized pattern: ForStmt OTHER_PATTERN 1 warning generated. End to recognize process.回显中显示需要修改的代码,详细修改可打开JSON报告文件查看。若提示头文件找不到,请参见使用天秤源码优化工具扫描源码文件提示头文件找不到进行处理。
- 打开生成的JSON报告文件,分析并确认修改点。
vim /home/demo/output.json
JSON文件详情如下:
{ "advisor_items": [ { "opt_file": { "begin_line": 18, "description": "", "end_line": 19, "fileName": "/home/demo/input.cpp", "headerFile": "#include <arm_neon.h>", "headerLocBegin": 9, "headerLocEnd": 9, "sample_code": " int64_t j = 0;\n for (; j + 4 < nb; j += 4) {\n vst1q_f32(dis + j, vaddq_f32(vdupq_n_f32(qNorm), vld1q_f32(bNorms + j)));\n }\n for (; j < nb; j++) dis[j] = qNorm + bNorms[j];" } }, { "opt_file": { "begin_line": 25, "description": "", "end_line": 27, "fileName": "/home/demo/input.cpp", "headerFile": "#include <arm_neon.h>", "headerLocBegin": 9, "headerLocEnd": 9, "sample_code": " int64_t j = 0;\n for (; j + 4 < nb; j += 4) {\n vst1q_f32(dis + j, vaddq_f32(vdupq_n_f32(qNorm), vld1q_f32(bNorms + j)));\n }\n for (; j < nb; j++) {\n dis[j] = qNorm + bNorms[j];\n }" } }, { "opt_file": { "begin_line": 48, "description": "", "end_line": 50, "fileName": "/home/demo/input.cpp", "headerFile": "#include <arm_neon.h>", "headerLocBegin": 9, "headerLocEnd": 9, "sample_code": " int64_t j = 0;\n for (; j + 4 < nb; j += 4) {\n vst1q_f32(dis + j, vaddq_f32(vld1q_f32(dis + j), vdupq_n_f32(qNorm)));\n }\n for (; j < nb; j++) {\n dis[j] += qNorm;\n }" } } ], "code": 0, "recognizedPattern": 3 }表2 字段说明 字段
字段说明
advisor_items
代码优化点建议数组,里面的每一项都是一个代码优化点建议。
opt_file
单个优化建议的详细信息。
begin_line
需要优化代码的起始行号。
示例中“18”为优化代码的起始行号。
description
优化建议的详细描述。
end_line
需要优化代码的结束行号。
示例中“19”为优化代码的结束行号。
fileName
当前分析的源文件所在路径。
示例中“/home/demo/input.cpp”为分析的源文件所在路径。
headerFile
需要添加的头文件。
示例中“#include <arm_neon.h>”表明此段代码需要添加ARM NEON的头文件,用于使用NEON指令集。
headerLocBegin
头文件插入的起始行号。
- 若为-1,表示头文件在原始代码中已经包含,无需手动添加。
- 若为正整数,表示头文件插入的起始行号。
示例中“9”为头文件插入的起始行号。
headerLocEnd
头文件插入的结束行号。
- 若为-1,表示头文件在原始代码中已经包含,无需手动添加。
- 如为正整数,表示头文件插入的结束行号。
示例中“9”为头文件插入的结束行号。
sample_code
推荐的向量化实现代码样例,可直接用于替换源文件的原始代码。
示例中以下代码为优化后的代码样例。
int64_t j = 0;\n for (; j + 4 < nb; j += 4) {\n vst1q_f32(dis + j, vaddq_f32(vdupq_n_f32(qNorm), vld1q_f32(bNorms + j)));\n }\n for (; j < nb; j++) dis[j] = qNorm + bNorms[j];code
工具执行状态码。
- 0表示工具执行成功。
- 非零值表示异常
中断 。
示例中“0”表明工具执行成功。
recognizedPattern
需要优化的代码段数量。
示例中“3”表明有3处代码需要优化。
- 根据JSON报告进行代码改写。
- 查看advisor_items,其中包含了所有识别到的优化建议。
- 对于每个优化建议,查看begin_line和end_line字段,确定需要替换的代码范围。
- 将sample_code字段中的向量化代码复制并替换源文件对应位置的代码(第begin_line行至第end_line行)。
- 检查headerLocBegin和headerLocEnd字段:
- 如果值为-1,表示头文件已存在,无需添加。
- 如果为正整数,需要在指定位置添加headerFile中的头文件声明。
- 保存修改后的文件,即可完成自动化改写。