【问题标题】:Good resources on how to program PEBS (Precise event based sampling) counters?有关如何对 PEBS(基于事件的精确采样)计数器进行编程的好资源?
【发布时间】:2017-10-28 08:00:10
【问题描述】:

我一直在尝试记录程序的所有内存访问,在我看来这似乎是不可能的。我一直在尝试查看至少可以在多大程度上记录大部分内存访问,如果不是全部的话。因此,我希望对 PEBS 计数器进行编程,以便我可以看到收集的内存访问样本数量的变化。我想知道是否可以通过修改 PEBS 计数器的计数器重置值来做到这一点。 (通常这会归零,但我想将其设置为更高的值)

所以我希望自己对这些 pebs 计数器进行编程。有人有操作 PEBS 计数器的经验吗?具体来说,我正在寻找好的资源来了解如何对其进行编程。我已经阅读了英特尔文档并理解了这些步骤。但我想了解一些示例程序。我已经浏览了下面的 github 仓库:-

https://github.com/pyrovski/powertools

但我不太确定,如何以及从哪里开始。我还需要寻找其他好的资源吗?任何有关理解和开始编程的好资源的建议都会非常有帮助。

【问题讨论】:

  • Logging all memory accesses of any executable/process in Linux 的可能重复项。请不要提出新问题,但请解释您为什么不希望有任何开销,并在已经提出的问题中进行。您应该进行 2 次运行:一次在没有内存记录的情况下进行时间测量,另一次在内存记录和任何开销的情况下进行。你想记录什么:只有内存地址和序列,或者时间。为什么你认为你需要所有/每个/ 50% / 10% / 5 % 的所有内存访问,是为了什么?
  • 嗨@osgx,我只对记录所有内存地址感兴趣,我不需要序列。我尝试了各种方法——特别是我尝试使用 andi-kleen 的 pmu 工具。我们实际上是在尝试查看是否真的可以记录所有内存访问,如果没有,我们可以达到什么程度。此外,我们对使用任何动态二进制检测工具不感兴趣——我们想看看是否可以以低开销完成日志记录。
  • “记录程序的所有内存访问”是可能的,但开销很大。使用编译器工具或动态二进制工具,或一些特殊的硬件,如 PT/PEBS。记录每次访问都会产生开销(2x、3x 使用基于硬件的良好跟踪,10x-50x 使用 Valgrind 等工具减速)。记录 10% 或 1% 的内存请求(采样更多的硬件跟踪 PEBS/PT)将具有更少的开销。仅记录 L3 缓存未命中的开销较小,将每个请求记录到 L1 缓存的开销更大。

标签: performance memory cpu processor perf


【解决方案1】:

请不要在单次运行中混合跟踪和计时测量

不可能同时拥有最快的 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 Vol 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 中具有 PE​​BS 事件。 (查找您的 CPU 的 PEBS 部分并搜索内存事件。支持 PEBS 的事件非常少见。)

因此,要记录更多事件,您可能希望将此函数的 reset 部分设置为更小的绝对值,例如 -50 或 -10。对于 PEBS,这可能会起作用(并尝试 perf -e cycles:upp -c 10 - 不要要求以如此高的频率分析内核,只要求用户空间 :u 并使用 :pp 要求精确,并使用 -c 10 要求 -10 计数器。 perf 为 MSR 和缓冲区解析实现了所有 PEBS 机制。

另一个 PMU(硬件性能监控单元)的好资源也来自 Intel,PMU Programming Guides。它们也对常用的 PMU 和 PEBS 进行了简短而紧凑的描述。有公开的“Nehalem Core 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 Guide,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 PMCs:为 PEBS 设置 - 来自“Black Hat USA 2015 - 这些不是你爷爷的 CPU 性能计数器”


您可以从简短的程序(不是最近 SpecCPU 的 ref 输入)开始,使用perf linux 工具 (perf_events) 来找到可接受的内存比例请求记录到所有内存请求。通过将:p:pp 后缀添加到事件说明符record -e event:pp,PEBS 与perf 一起使用。还可以尝试pmu-tools ocperf.py 以简化英特尔事件名称编码。

尝试在内存测试(例如内存记录开销的最坏情况,Arithmetic Intensity scaleRoofline model - STREAM 是 BLAS1,GUPS 和 memlat 几乎是 SpMV;真正的任务通常不会那么留在规模上):

您想跟踪每个加载/存储命令,还是只想记录错过所有(某些)缓存并被发送到 PC 主 RAM 内存(到 L3)的请求?

为什么您不希望任何开销并记录所有内存访问?这是不可能的,因为每个内存访问都跟踪要记录到内存的几个字节。因此,启用内存跟踪(超过 10% 或 mem.access 跟踪)显然会限制可用内存带宽,并且程序运行速度会变慢。甚至可以注意到 1% 的跟踪,但它的影响(开销)较小。

您的 CPU E5-2620 v4 是 Broadwell-EP 14nm,因此它可能还有一些早期版本的 Intel PT:https://software.intel.com/en-us/blogs/2013/09/18/processor-tracinghttps://github.com/torvalds/linux/blob/master/tools/perf/Documentation/intel-pt.txthttps://github.com/01org/processor-trace,尤其是 Andi Kleen 在 pt 上的博客:http://halobates.de/blog/p/410"带有 Linux perf 和 gdb 的 Intel Processor Trace 备忘单"

硬件中的 PT 支持:Broadwell(第 5 代核心,至强 v4)更多开销。没有细粒度的时机。

PS:研究 SpecCPU 进行内存访问的学者使用内存访问转储/跟踪,转储生成缓慢:

仪器开销:仪器涉及 将额外的代码动态或静态注入 目标应用。附加代码会导致 应用程序花费额外的时间来执行原始 应用程序...此外,对于多线程 应用程序,仪器可以修改排序 不同线程之间执行的指令 应用。因此,具有多线程的 IDS 应用程序缺乏保真度

缺乏推测:仪器只观察 在正确的执行路径上执行的指令。作为 结果,IDS 可能无法支持错误路径...

仅限用户级流量:当前的二进制检测 工具仅支持用户级检测。因此, 内核密集型应用程序不适合 用户级IDS。

【讨论】:

  • 感谢@osgx,提供详细答案。我已经使用 andi-kleen 的 pmu-tools 来获取参考 PEBS 驱动程序 - 我正在尝试修改 pebs 计数器重置值(我正在考虑将重置值修改为较小的负值)。然后尝试加载驱动模块。您如何得出复位计数器值为负数的结论?一个正值也可能溢出,不是吗。
  • 另外你为什么建议我只记录用户空间地址?我注意到,如果我记录内核空间地址,大多数记录的地址通常是相同的。为什么会这样?
  • Kalita,请显示您的一些性能命令(PT/PEBS/mem 或任何东西)。如果没有 PEBS/PT(通过硬件将样本缓冲到某个内存位置),您不能在中断之前要求极低的计数:它会在计数启用后不久中断,并且用户代码将没有机会运行(并且还可能死锁系统)。在充满图灵机和具有无限内存/无限时间的模型的理论计算机科学中,64 位计数器将溢出。在现实世界中,4.3GHz CPU 单个 64 位计数器递增每个刻度可能会在 ... 2^32 秒 = 136 年(不会)内溢出。
  • 嗨@osgx,很抱歉回复晚了。我正在尝试与 PEBS 的各种组合。这是我的命令之一:-./perf record -e cpu/mem-stores/upp -c 1 ../../.././libquantum_base.arnab 100。我特别想以某种方式避免检测到任何可能的限制。
  • Kalita,即使没有插桩,将内存访问信息存储到某个缓冲区也是有开销的,而且大缓冲区在 RAM 中,占用了部分内存 bw。仍然可以记录一部分内存访问(不知道是否所有访问都可以),但是记录下的程序运行速度会变慢。你能描述一下获取内存访问样本的目标是什么,你的论文是关于什么的?
猜你喜欢
  • 2012-07-11
  • 1970-01-01
  • 2018-12-18
  • 2011-08-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多