-
Notifications
You must be signed in to change notification settings - Fork 3
timing source
该文档讲述新的 llvm-prof 的TimingSource(时间源) 模型的计算过程。 TimingSource负责提供机器特征的参数,包括读取处理等。llvm-prof的timing模式则负责 结合PredBlockCounters计算出最后的时间。
不同的TimingSource种类:
名称 | 类别 | 描述 |
---|---|---|
lmbench | 计算 | 使用lmbench的数据计算基本块时间 |
irinst | 计算 | 使用inst-timing计算基本块ir指令时间和 |
irinst-max | 计算 | 在irinst基础上使用max(float,fix)模型来计算 |
mpbench | MPI | 使用MPBench模型来计算MPI通信时间 |
mpbench-re | MPI | 对应于新的MPIProfiling格式的mpbench |
libfn | Call | 统计sqrt,log,fabs函数时间 |
文件参考: src/inst-timing.c
, src/libtiming.c
, lib/InstTemplate.cpp
对于LmbenchTiming的输出,直接用lmbench里面的 lat_ops
和 ???
即可。
所以下面的都是我们自己实现的 IrinstTiming 的输出。
默认很简单,对于不同的LLVM IR进行测度,然后再输出时间即可。在 inst-timing.c
中使用了一个特殊的空声明(占位符)
int inst_template(const char* templ, ...);
在 lib/InstTemplate.cpp
中再根据使用的具体的模板的不同,生成IR指令,并填充
进去。因此我们在IR层面可以方便的控制生成什么样的IR指令。
文件参考: include/TimingSource.h
, lib/TimingSource.cpp
机器特征的数据储存使用一个double类型的数组来实现,并且用一个enum类来指定数组中 的每一个元素代表着何种含义。
TimingSource基类只提供数据储存,不提供使用方法。在其基础上派生出三个抽象类,提 供不同类别的计算方式。分别是:
- BBlockTiming:计算基本块时间
- MPITiming:计算MPI通信时间
- LibCallTiming:计算一些常见函数的时间
然后在这些抽象类的基础上派生出各种不同的TimingSource,方便切换使用不同的组合方 案。
例如: LmbenchTiming
和 IrinstTiming
是具体的两个实现类,继承自
BBlockTiming(提供数组数据)和_timing_source::T(提供enum定义)。前者有一个
params
成员。后者提供一个 get
方法。
class LmbenchTiming:
public BBlockTiming, public _timing_source::T<LmbenchInstGroups>
class IrinstTiming:
public BBlockTiming, public _timing_source::T<IrinstGroups>
一个标准的TimingSource约定提供但不限定的方法有:
classify :: 确定一条指令所映射到的enum类型 count :: 计算一条指令或一个基本块的时间
对于enum定义,不同的时间源没有具体的规定。从而保证了时间源的多样性。 LmbenchTiming 是使用的lmbench测试的数据,所以它的enum中是用的 数据长度 × 计算方法 来定义的。而 IrinstTiming 是用的LLVM的IR模型,所以它的定义即是LLVM 的IR指令的种类。
每种时间源不同的地方还在于提供各自不同的处理文件的方法。例如IrinstTiming的
load_irinst负责读取我们自定义的输出格式。默认会覆盖掉父类的
file_initializer
函数指针。从而实现 init_with_file
共有方法。
文件参考: src/passes.cpp
最后的总时间的计算是交给 ProfileTimingPrint::runOnModule
来实现的。包括应用
模型。由于时间源的可扩展设计没有抽取抽象方法,所以需要利用dyn_cast来转换到子类
,然后再去直接访问各种方法。