问题标签 [papi]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
0 回答
216 浏览

performance - 如何使用硬件性能计数器捕获退役指令事件的准确值?

硬件性能计数器测量的准确性在文献中被广泛讨论。使用硬件性能计数器,我们可以测量多种类型的微架构事件,例如缓存命中和未命中、加载和存储以及停用的指令。但是,这些测量仍然存在疑问,它们的准确度如何?正如许多论文中所说明的那样,使用不同的设备,结果可能会有所不同。其中一些事件,如存储指令,是确定性事件,即存储事件的测量结果不会随着程序的重新执行而改变,并捕获性能计数器值。退休指令不是。这意味着,如果我们测量代码的一部分,例如循环语句,我们可能会从 run 到另一个获得不同的计数器值。在【这篇文章】中,作者写道:

“当确定性计数器确实可用时,它们不仅会受到那些从事确定性重放和模拟器验证器工作的人的欢迎,而且也会受到性能计数器的所有用户的欢迎。”

顺便说一句,我们是否可以将确定性事件(如存储事件)与退役指令结合使用来引入确定性用户定义事件?

任何帮助将不胜感激

0 投票
0 回答
190 浏览

c - 在 virtualbox 上安装 papi(在虚拟机上使用计数器)

我在 Windows 10 上使用带有 virtualbox 的 ubuntu。我在使用 papi 库的任何函数时遇到问题,并且出现(PAPI_flops 中的错误:事件不存在)错误。当我运行安装指南的 make 测试时,我有这个:

错误列表

但是 perf 命令运行良好。我需要做什么来激活虚拟盒子上的计数器。如果这不是我的问题,那是什么?谢谢^^。

0 投票
1 回答
453 浏览

c - 无法使用 papi.h 运行 PAPI 代码,错误:无法在 GCC 中打开共享对象文件

我正在尝试学习 papi api 来监控各种 CPU 事件的性能。首先,我运行了 PAPI 官方文档中提到的示例片段之一。下面是代码

我使用包含文件路径编译它,如下所示

执行 a.out 时出现错误

我尝试通过导出 LD_PRELOAD 来解决这个问题,但这没有用。有人可以帮我吗?我以前从未使用过 PAPI api,所以我不确定我是否以正确的方式编译它。

0 投票
0 回答
541 浏览

c - PAPI_num_counters() 显示系统没有可用的计数器

我有一个关于 PAPI(性能应用程序编程接口)的问题。我下载并安装了 PAPI 库。仍然不确定如何正确使用它以及我需要什么额外的东西才能使它工作。我正在尝试在 C 中使用它。我有这个简单的程序:

我已经包含了 papi.h 库,并且正在使用 gcc -lpapi 标志进行编译。我在路径中添加了库,以便它能够编译和运行,但结果我得到了这个:

该系统有 0 个可用计数器。

思想初始化似乎有效,因为它没有给出错误代码。任何建议或建议将有助于确定我没有做对或错过正确运行它的地方。我的意思是,我的系统中应该有可用的计数器,更准确地说,我需要缓存未命中和缓存命中计数器。

在我运行另一个简单程序后,我尝试计算可用计数器,它给出了错误代码 -25:

更新:我只是尝试使用命令检查终端硬件信息:papi_avail | 更多的; 我得到了这个:

可用的 PAPI 预设和用户定义的事件以及硬件信息。


PAPI 版本:5.7.0.0

操作系统:Linux 4.15.0-45-generic

供应商字符串和代码:GenuineIntel (1, 0x1)

型号字符串和代码:Intel(R) Core(TM) i5-6200U CPU @ 2.30GHz (78, 0x4e)

CPU 修订版:3.000000

CPUID : 系列/型号/步进 6/78/3, 0x06/0x4e/0x03

CPU 最大频率:2800

CPU 最小 MHz : 400

总核心数:4

每个核心的 SMT 线程数:2

每个插槽的核心数:2

插座:1

每个 NUMA 区域的核心数:4

NUMA 地区:1

在虚拟机中运行:否

硬件计数器数量:0

最大复用计数器:384

快速计数器读取 (rdpmc):否

PAPI 预设事件

PAPI_L1_DCM 0x80000000 否 否 1 级数据缓存未命中

PAPI_L1_ICM 0x80000001 否 否 1 级指令高速缓存未命中

PAPI_L2_DCM 0x80000002 否 否 2 级数据缓存未命中

PAPI_L2_ICM 0x80000003 否 否 二级指令高速缓存未命中......

所以因为 Number Hardware Counters 是 0,我不能用这个工具用 PAPI 的预设事件来计算缓存未命中?是否有任何有用的配置,或者我应该在更换笔记本电脑之前忘记它?

0 投票
1 回答
849 浏览

c - 使用 PAPI_read_counters 计算 L1 缓存未命中会产生意想不到的结果

我正在尝试使用 PAPI 库来计算缓存未命中数。缓存命中性能计数器在我的硬件上不可用,这就是为什么我试图确定没有缓存未命中的缓存命中。我正在尝试一些事情。我的代码的第一个版本是这样的:

问题是这段代码应该给我缓存命中,所以 L1 缓存未命中应该非常低。但是我得到了miss_2的出乎意料的高结果。数组大小为 200 时,miss_2 接近 100。它没有给出任何有效的结果来判断它真的被命中,因为缓存未命中的次数很多。

我也尝试像这样重写它:

但这给出了更糟糕的结果,miss_2 超过 200。有什么我做错了吗?它应该给出更精确的结果,但现在它做得很糟糕。或者我错过了一些东西。
我试过不带栅栏,我相信至少它们不会造成任何伤害。我真的很感激任何建议。

PAPI_read_counters 的缺点是开销很大,而且性能不是很好,但现在我不在乎性能,我想正确确定缓存命中。

虽然我也在考虑使用 RDMPC,但我还没有找到一个在不覆盖 _asm 函数的情况下使用它的示例。这真的是使用 rdpmc 的唯一方法吗?不存在我不必覆盖的已定义函数?

编辑: 为 PAPI_read 添加编译器代码

我的对象大小为 64,并且还添加了初始化:

0 投票
1 回答
1295 浏览

caching - 在 Skylake 中使用 MSR 正确禁用硬件预取

我正在尝试在我的机器上禁用硬件预取:

CPU系列:6

型号:78

型号名称:Intel(R) Core(TM) i5-6200U CPU @ 2.30GHz

我已经检查过: gcc -march=native -Q --help=target|grep march - 命令,它是 Skylake 微架构。

我已经安装了 msr-tools。grep -i msr /boot/config-$(uname -r) 这给出了结果: CONFIG_X86_MSR=m - 我不确定是否有必要将其设置为 Y,或者如何设置。我试图使用这个帖子:

如何以编程方式禁用硬件预取?

无法在 Core i7 中禁用硬件预取器

但是我认为帖子有点旧并且不使用 0x1a4 地址。同样在评论中没有描述如何使用这个地址来做,或者修改 0x1a4 或 0x1a0 之间是否没有区别。

我已阅读这篇文章:https ://software.intel.com/en-us/articles/disclosure-of-hw-prefetcher-control-on-some-intel-processors说可以通过设置 0 禁用预取0x1A4 中的 -3 位到 1。modprobe msr - 执行此命令不会出错(也不会打印任何消息)。然后我正在尝试这两个命令:

sudo wrmsr -p 0 0x1a4 15 //对于核心 0

sudo wrmsr -p 2 0x1a4 15 //对于核心 2

15 用于将所有最后 4 位设置为 1

你能帮我确保我正确地禁用了预取器吗?由于我对 sudo wrmsr -p 0 0x1a4 15 - 命令做了很多假设,我不确定我是否正确使用它。我试图提供所有信息,但如果还有其他需要,请告诉我。(我已经缩短了帖子,因为我想它太长了,无法通过)

0 投票
1 回答
272 浏览

c - 为什么 _mm_mfence() 会为 ALL_LOADS perf 事件产生计数?

我正在测试一些内在操作的行为。当我注意到 _mm_mfence() 从用户空间发出加载指令时,我感到很惊讶,但它不计入 L1 数据缓存 - 未命中、命中或填充缓冲区命中。我正在使用 papi 的本机事件,例如 MEM_INST_RETIRED 和 MEM_LOAD_RETIRED 来读取性能计数器。这段代码:

计数 ALL_LOADS: 737030, L1_HIT: 99, L1_MISS: 10, FB_HIT: 25。没有 mfence 时,读取计数器的开销是这样的:ALL_LOADS: 125, L1_HIT: 94, L1_MISS: 11, FB_HIT: 24

我查了一下,sfence 和 lfence 没有这个影响。我正在使用 -O3 进行编译。从编译的文件中我猜它调用了 __builtin_ia32_mfence 函数,但我找不到太多关于它的内容。

我大致了解 _mm_mfence() 的作用以及我们为什么使用它,但现在的问题更多是关于它是如何工作的。如果有人可以解释或提供任何相关文章来理解这种行为,那就太好了。

0 投票
1 回答
308 浏览

assembly - 如何定义PAPI 测量的用户自定义事件?

当今的大多数处理器都配备了硬件性能计数器。此类计数器可用于对微架构事件进行计数,以便分析目标程序以提高其性能。通常,剖析和分析是这些计数器的主要目标。

根据文献中的研究论文,这些计数器缺乏准确性。例如,如果我们想计算给定代码中已退出指令的数量,则该值可能会从运行变为另一个扰动问题。已经讨论了一些指南以提高测量的准确性。监控多个事件可以更好地了解正在执行的程序,从而提高测量精度。

用于硬件性能监控的用户定义事件的作者提出了一种新方法,使用户能够定义自己的事件以供 PAPI ( Performance API ) 使用,PAPI 是一种广泛用于以简单方式访问硬件性能计数器的基础设施。不幸的是,论文没有详细解释我们如何定义用户定义的事件并在我们的程序中使用它们。

例如(基于 PAPI),我试图定义一个新事件,该事件涉及n 个本机/预设事件,例如(PAPI_TOT_INS、PAPI_BR_TKN 和 PAPI_STR_INS),然后在我的代码中将其用作单个事件。


编辑:

基于上述论文,我设置了环境变量 PAPI USER_EVENTS FILE 来指示包含用户定义事件的文件,该文件将通过调用 PAPI_library_init 函数来启动和解析。event_file 非常简单(仅用于测试):

我的代码如下所示:

但是,计数和 counter_code 的输出似乎都很奇怪

我在一个文本文件(在 Linux Ubuntu OS 中)中定义了一个简单的事件,并设置了环境变量来指示这个文件。但在代码中,两者

返回一个不等于 PAPI_OK 的值。

任何帮助将不胜感激。

0 投票
0 回答
135 浏览

c - 为什么用 papi 读取硬件计数器的结果取决于 PAPI_library_init 位置?

我正在使用 PAPI 库来读取硬件计数器。我注意到调用 PAPI_library_init(PAPI_VER_CURRENT) 初始化的顺序对我得到的结果有影响。我对数组的初始化和读取是这样的:

我相信第二个循环读取数组的必要性是为了一致性协议,但在这里应该没什么大不了的。在此之后,我将 MEM_LOAD_RETIRED 的本机事件添加到要读取的事件集中,并在第三个循环周围使用 PAPI_read(我在循环之前和之后读取它,最后打印差异):

其中 arr_size 为 1000,数组的每个元素为 64 字节大小(等于缓存行)。我已禁用所有预取器。我使用 gcc -O3 标志进行编译以进行优化和 -lpapi 库。使用此代码,对于第三个循环,我得到:

L1_HIT:64,L1_MISS:1011,L2_HIT:15,L2_MISS:996。

但是,如果我在数组初始化之前取消注释 PAPI_library_init 并在之后注释它,我得到的结果是:

L1_HIT:73,L1_MISS:1004,L2_HIT:990,L2_MISS:14。

我正在 Skylake 服务器中对此进行测试,缓存大小为:

现在我有点困惑为什么 papi 初始化会影响这个结果。这是 L2 的命中和错过的变化。我只需要第三个循环,我相信前两个循环对计数器的影响没有被考虑在内。

因此,任何提示都会有所帮助,因为所有文档都说:“PAPI_library_init() 初始化 PAPI 库。必须在使用任何低级 PAPI 函数之前调用它。如果您的应用程序正在使用线程 PAPI_thread_init (3 ) 也必须在调用除 PAPI_library_init() 之外的库之前调用。"

0 投票
0 回答
64 浏览

c - 观察 PAPI 的 L1_MISS 本机事件计数器的意外结果

我正在使用 PAPI 来计算 L1 缓存访问结果。大多数原生事件都会给出预期的结果,但是有一种情况是 L1_MISS 不精确。我有一个大小为 64 的对象和 100,000 个元素的易失性数组,如代码所示:

我正在使用两个 NUMA 节点在 Skylake 处理器中进行测试。我禁用了预取器。使用 gcc -O3 编译。场景如下:从 NUMA1 中设置的主进程,我初始化一个数组并刷新缓存行。然后我创建 5 个线程,通过调用循环函数从 NUMA2 读取相同的数组。在所有这些都终止后,我从主进程循环遍历一个数组,读取每个元素并监控 L1 缓存访问结果:

我正在阅读这 5 个本机事件计数器:

期望看到 L1_MISS 大约为 100,000,因为未在缓存中获取元素,而 main 中的此读取会导致未命中。ALL_LOADS 也不等于三个计数器的总和:L1_HIT + L1_MISS + FB_HIT。尽管 L1D.REPLACEMENT 在这种情况下通过计算 L1D 数据线替换似乎是有意义的,但我不相信它,因为它在启用时也计算预取。

我不明白 MEM_LOAD_RETIRED.L1_MISS 计数器没有看到由 main 中的读取操作引起的事件的原因是什么,仅在这种特定情况下。例如,如果来自 NUMA2 的线程不是读取,而是修改一个数组元素,那么对于同一个循环,我会得到 L1_MISS:99818。所以任何建议都会有所帮助。我试图提供代码的主要框架。如果评论点的任何部分很重要,我也可以添加它们。