开发者
我要评分
获取效率
正确性
完整性
易理解
在线提单
论坛求助

天秤源码优化工具

天秤源码优化工具是一款基于Clang/LLVM的静态代码分析工具,专注于C/C++代码的向量化优化。工具能够自动识别可向量化的循环模式,检测阻碍向量化的因素,并自动生成优化后的向量化代码,实现代码的自动化改写,帮助开发者快速将标量代码转换为高效的SIMD向量化代码,充分发挥NEON/SVE指令集的性能优势。

前提条件

命令功能

自动识别可向量化的循环模式,检测阻碍向量化的因素,并自动生成优化后的向量化代码,实现代码的自动化改写。

命令格式

./tiancheng -h

参数说明

表1 参数说明

参数

参数选项

说明

-h/--help

-

可选参数,获取帮助信息。

-i

-

必选参数,指定输入的C/C++源文件。

-o

-

必选参数,指定输出的JSON报告文件目录及文件名,文件后缀为.json。

-r

-

可选参数,指定输入的C/C++源文件项目的根路径,用于头文件搜索,避免头文件缺失。

-v

-

可选参数,启用详细输出模式,显示更多调试信息和分析过程。默认不启用。

--simd-target

neon/sve

可选参数,指定转换的指令集,可指定为NEON或SVE,默认为NEON。

  • NEON:ARM架构中的SIMD指令集,通过128位固定宽度矢量寄存器实现并行数据处理,支持8/16/32/64位整数及单精度浮点运算。支持基于鲲鹏920系列和鲲鹏950处理器的服务器。
  • SVE:可伸缩矢量扩展,一种矢量长度无关的SIMD指令集,让同一份代码能在不同宽度的ARM处理器上自动获得最佳性能。支持部分基于鲲鹏920新型号和鲲鹏950处理器的服务器。

--enable-ifstmt-scan

-

可选参数,启用对if语句的扫描分析。

--version

-

可选参数,显示工具的版本信息。

使用示例

  1. 执行以下命令,查看天秤源码优化工具支持的功能信息。
    ./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
  2. 对源码文件进行扫描并输出分析报告。
    ./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报告文件查看。若提示头文件找不到,请参见使用天秤源码优化工具扫描源码文件提示头文件找不到进行处理。

  3. 打开生成的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处代码需要优化。

  4. 根据JSON报告进行代码改写。
    1. 查看advisor_items,其中包含了所有识别到的优化建议。
    2. 对于每个优化建议,查看begin_line和end_line字段,确定需要替换的代码范围。
    3. 将sample_code字段中的向量化代码复制并替换源文件对应位置的代码(第begin_line行至第end_line行)。
    4. 检查headerLocBegin和headerLocEnd字段:
      • 如果值为-1,表示头文件已存在,无需添加。
      • 如果为正整数,需要在指定位置添加headerFile中的头文件声明。
    5. 保存修改后的文件,即可完成自动化改写。