Skip to content

Latest commit

 

History

History
executable file
·
82 lines (66 loc) · 4.11 KB

readme.md

File metadata and controls

executable file
·
82 lines (66 loc) · 4.11 KB

简介

目的:用于获取算子的理论计算量。
实现思路:
(1)以编译器前端扫描的方式,识别各个语句的计算量。
(2)通过 theory_ops_ 变量记录理论计算量,逐语句(或块)来更新 theory_ops_。
(3)在运行时, theory_ops_ 会跟 cpuCompute 函数一起计算,theory_ops_ 的值作为参考的理论计算量。
用法:
(1)gtest 中 op.h 增加 theory_ops_ 变量,op.cpp 给需要统计计算量的函数(一般为 cpuCompute 和 调用的函数)
头尾增加 // count_ops_begin, // count_ops_end。
(2)在 main 文件中,输入 op.cpp 的路径,可以设置 show_theoryOps 的参数来输出结果。
(3)cpuCompute 函数中有些寻址语句或冗余写法不需要统计计算量,可以将其先注释掉。

依赖项

yaml; ply (词法语法解析器); clang-format (格式对齐使用)

文件结构

base_config.yaml

配置文件,记录了 Cpp 语言常用的关键字和运算符。

config_read.py

解析 base_config.yaml

lexer_rules.py

词法解析规则

parser_rules.py

语法解析规则

parser.out 和 parsetab.py

parser_rules 运行生成的文件

main.py

扫描代码,解析代码,按时间输出带有 theory_ops_ 记录的代码

统计的计算量说明

  1. 注释和[]之间的内容均忽略
  2. 函数调用的计算量均视为 1(待优化)
  3. 后置运算符 ++, -- 的计算量视为 3
  4. 后置运算符 ., -> 的计算量视为 0
  5. static_cast 等 cast 特殊运算符的计算量视为 1
  6. sizeof, typeId 的计算量视为 0
  7. 前置运算符 ++, -- 的计算量视为 2
  8. 前置运算符 -, !, ~ 修饰的是数字时计算量视为 0,其他为1
  9. 前置运算符 +, *, & 的计算量为 0
  10. 类型强转的计算量均视为 1
  11. >, >=, <, <=, !=, == 比较运算符的计算量为 0
  12. 赋值运算符的计算量视为 0
  13. 特殊赋值运算符(+=, -= 等)的计算量为 2
  14. 其他双元运算符(+, -, *, / ,&&, || 等)的计算量为 1
  15. 三元运算符(expr1 ? expr2 : expr3) 的计算量视为 expr1 + (expr2 + expr3) / 2
  16. if, switch, for, while 这些控制语句的计算量单独处理
  17. 普通语句的计算量逐条记录
  18. 块会统计块内普通语句的计算量之和,但作用域被打断时(例如:continue,break 或者子作用域),就立即统计之前累计的计算量。

限制说明

  1. 有设想能够设置配置文件中的计算量,但有两个问题: (1)有些运算符的计算量是动态的,需要与语法配套使用,会更加复杂。 (2)用户自己设置的话,有更多的操作量。

  2. 有设想增加一个 op_config.yaml 配置文件,该文件中可以注册函数的计算量。

  3. 暂时无法识别类和结构体的声明

  4. 类型强转的写法只能是 '(' + type + ')' 的形式,不管实际有没有强转,计算量均视为 1。

  5. 变量声明初始化不支持(),{} 等写法

  6. 逻辑判断是希望不统计计算量,但 &&, || 的计算量视为 1

  7. 暂时无法识别模板和宏。<> 目前只能在函数调用中识别。

  8. if 如果只跟单语句而没有带 {},暂时无法写到对应的作用域中

  9. block 合并计算量写入在 "}" 上一行,如果之前语句有 continue, break, goto, return 等会使得统计量偏少。

  10. 期望寻址计算是不统计计算量,[] 之间是不考虑计算量,但是 * 解引用的寻址方法难以区分; 数组索引的计算最好不视作计算量,这也属于寻址计算,但是从语义角度难以区分,这部分计算量会统计起来。 TODO: 索引变量不统计计算量。

  11. 赋值语句的计算量均视为 0,是因为 cpu 写法中会用到大量的临时变量,这些都统计的话,会使得理论计算量较高 TODO:赋值运算如果是初始化运算量视为 0,非初始化运算量视为 1

  12. 只能识别命名空间函数,不支持命名空间其他的识别,不会统计这部分的计算量。 例如:无法识别 std::vector A

  13. 冗余写法的计算量也会统计,例如: 乘以 1, 除以 1,加减 0 仍然会统计计算量