Skip to content
xiehuc edited this page Apr 29, 2015 · 3 revisions

TimingSource

该文档讲述新的 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.csrc/libtiming.clib/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.hlib/TimingSource.cpp

机器特征的数据储存使用一个double类型的数组来实现,并且用一个enum类来指定数组中 的每一个元素代表着何种含义。

TimingSource基类只提供数据储存,不提供使用方法。在其基础上派生出三个抽象类,提 供不同类别的计算方式。分别是:

  • BBlockTiming:计算基本块时间
  • MPITiming:计算MPI通信时间
  • LibCallTiming:计算一些常见函数的时间

然后在这些抽象类的基础上派生出各种不同的TimingSource,方便切换使用不同的组合方 案。

例如: LmbenchTimingIrinstTiming 是具体的两个实现类,继承自 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来转换到子类 ,然后再去直接访问各种方法。

Clone this wiki locally