我一直在尝试记录程序的所有内存访问,这在我看来似乎是不可能的。我一直试图看看我能在多大程度上记录至少大部分内存访问,如果不是全部的话。因此,我希望以这样的方式对PEBS计数器进行编程,以便我可以看到收集的内存访问样本数量的变化。我想通过修改PEBS计数器的计数器重置值来知道我是否可以这样做。 (通常这会变为零,但我想将其设置为更高的值)
所以我想要自己编程这些pebs计数器。有没有人有操纵PEBS计数器的经验?具体来说,我一直在寻找好的资源来了解如何编程。我已经阅读了英特尔文档,并了解了相关步骤。但我想了解一些示例程序。我已经通过以下github回购: -
https://github.com/pyrovski/powertools
但我不太确定,如何以及从何处开始。我需要看看还有其他好的消息来源吗?任何有关理解和开始编程的良好资源的建议都将非常有用。
答案 0 :(得分:2)
只是不可能都有最快的Spec运行和所有跟踪的内存访问。一个用于计时,另一个用于内存访问跟踪(更长,更慢)。
在https://github.com/pyrovski/powertools中,收集事件的频率由pebs_init
的reset_val参数控制:
https://github.com/pyrovski/powertools/blob/0f66c5f3939a9b7b88ec73f140f1a0892cfba235/msr_pebs.c#L72
void
pebs_init(int nRecords, uint64_t *counter, uint64_t *reset_val ){
// 1. Set up the precise event buffering utilities.
// a. Place values in the
// i. precise event buffer base,
// ii. precise event index
// iii. precise event absolute maximum,
// iv. precise event interrupt threshold,
// v. and precise event counter reset fields
// of the DS buffer management area.
//
// 2. Enable PEBS. Set the Enable PEBS on PMC0 flag
// (bit 0) in IA32_PEBS_ENABLE_MSR.
//
// 3. Set up the IA32_PMC0 performance counter and
// IA32_PERFEVTSEL0 for an event listed in Table
// 18-10.
// IA32_DS_AREA points to 0x58 bytes of memory.
// (11 entries * 8 bytes each = 88 bytes.)
// Each PEBS record is 0xB0 byes long.
...
pds_area->pebs_counter0_reset = reset_val[0];
pds_area->pebs_counter1_reset = reset_val[1];
pds_area->pebs_counter2_reset = reset_val[2];
pds_area->pebs_counter3_reset = reset_val[3];
...
write_msr(0, PMC0, reset_val[0]);
write_msr(1, PMC1, reset_val[1]);
write_msr(2, PMC2, reset_val[2]);
write_msr(3, PMC3, reset_val[3]);
这个项目是访问PEBS的库,项目中没有包含它的用例(因为我发现tpatki在其他项目中只有一个disabled test)。
检查intel SDM Manual第3B卷(这是PEBS编程唯一的好资源),了解字段含义以及PEBS配置和输出: https://xem.github.io/minix86/manual/intel-x86-and-64-manual-vol3/o_fe12b1e2a880e0ce-734.html
18.15.7基于处理器事件的采样
PEBS允许在精确事件记录缓冲区中保存与一个或多个性能事件相关的精确架构信息,该缓冲区是DS保存区域的一部分(参见第17.4.9节“BTS和DS保存区域”)。 要使用此机制,计数器配置为在计算预设数量的事件后溢出。计数器溢出后,处理器将通用和EFLAGS寄存器和指令指针的当前状态复制到精确事件记录缓冲区中的记录中。然后,处理器重置性能计数器中的计数并重新启动计数器。当精确事件记录缓冲区接近满时,将生成中断,从而允许保存精确的事件记录。精确事件不支持循环缓冲区 记录。 ...启用PEBS的计数器溢出后,PEBS 录制记录
(因此,复位值可能为负,等于-1000以获得每第1000个事件,-10以获得每第10个事件。计数器将递增并且PEBS在计数器溢出时写入。)
和https://xem.github.io/minix86/manual/intel-x86-and-64-manual-vol3/o_fe12b1e2a880e0ce-656.html 18.4.4基于处理器事件的采样(PEBS)"表18-10" - 只有L1 / L2 / DTLB未命中在Intel Core中有PEBS事件。 (查找CPU的PEBS部分并搜索内存事件。支持PEBS的事件非常罕见。)
因此,要记录更多事件,您可能希望将此函数的reset
部分设置为较小的绝对值,如-50或-10。使用PEBS,这可能会起作用(并尝试perf -e cycles:upp -c 10
- 不要求以如此高的频率对内核进行分析,只需要用户空间:u
并要求与:pp
进行精确匹配并要求带有-c 10
的-10计数器.perf已经为MSR和缓冲区解析实现了所有PEBS机制。)
PMU(硬件性能监控单元)的另一个好资源也来自英特尔,PMU编程指南。它们对通常的PMU和PEBS都有简短而紧凑的描述。有公共" Nehalem核心PMU",大部分仍然适用于较新的CPU - https://software.intel.com/sites/default/files/m/5/2/c/f/1/30320-Nehalem-PMU-Programming-Guide-Core.pdf(并且有非核心PMU指南:E5-2600 Uncore PMU指南,2012 https://www.intel.com/content/dam/www/public/us/en/documents/design-guides/xeon-e5-2600-uncore-guide.pdf)
关于PEBS的外部pdf:https://www.blackhat.com/docs/us-15/materials/us-15-Herath-These-Are-Not-Your-Grand-Daddys-CPU-Performance-Counters-CPU-Hardware-Performance-Counters-For-Security.pdf#page=23 PMC:为PEBS设置 - 来自" Black Hat USA 2015 - 这些不是您的Grand Daddy的CPU性能计数器"
您可以从简短的程序(不是最近的SpecCPU的ref输入)和使用perf
linux工具(perf_events)开始,找到可接受的比率内存请求记录到所有内存请求。通过向事件说明符perf
添加:p
和:pp
后缀,PEBS与record -e event:pp
一起使用。同时尝试pmu-tools ocperf.py以便更轻松地进行英特尔事件名称编码。
尝试在内存测试中找到具有不同记录比率(1%/ 10%/ 50%)的实际(最大)开销,例如(最差情况下的内存记录开销,左侧部分位于Arithmetic Intensity scale { {3}} - STREAM是BLAS1,GUPS和memlat几乎是SpMV;实际任务通常不会留在规模上):
您是否要跟踪每个加载/存储命令,或者您只想记录错过所有(某些)缓存的请求并将其发送到PC的主RAM内存(到L3)?
为什么不需要开销和所有内存访问?这是不可能的,因为每个存储器访问都有几个字节的跟踪要记录到存储器中。因此,启用内存跟踪(超过10%或mem.access跟踪)显然会限制可用内存带宽,程序运行速度会变慢。甚至可以记录1%的跟踪,但它的影响(开销)更小。
您的CPU E5-2620 v4是Broadwell-EP 14nm,因此它可能还有一些英特尔PT的早期版本:lmbench https://software.intel.com/en-us/blogs/2013/09/18/processor-tracing https://github.com/torvalds/linux/blob/master/tools/perf/Documentation/intel-pt.txt,特别是Andi Kleen&#39} https://github.com/01org/processor-trace上的博客:pt"英特尔处理器跟踪的备忘单与Linux perf和gdb"
硬件中的PT支持:Broadwell(第5代Core,Xeon v4)更多开销。没有精细的时间。
PS:研究SpecCPU进行内存访问的学者使用内存访问转储/跟踪,并且转储生成缓慢:
仪表开销:仪表涉及 动态地或静态地将额外的代码注入到 目标应用。附加代码会导致 申请花费额外的时间来执行原件 应用程序...另外,对于多线程 应用程序,仪器可以修改排序 在不同线程之间执行的指令 应用。因此,IDS具有多线程 应用程序缺乏一些保真度
缺乏猜测:仪器只能观察到 在正确的执行路径上执行的指令。如 结果,IDS可能无法支持错误路径...
仅用户级流量:当前二进制检测 工具仅支持用户级检测。从而, 内核密集型应用程序不适合 用户级IDS。