Linux 替代 Windows 高分辨率性能计数器 API
Posted
技术标签:
【中文标题】Linux 替代 Windows 高分辨率性能计数器 API【英文标题】:Linux alternative to Windows high-resolution performance counter API 【发布时间】:2011-12-15 15:05:48 【问题描述】:我正在寻找 Windows 高分辨率性能计数器 API 的 Linux 替代方案,尤其是以下 API 函数:
QueryPerformanceFrequency
QueryPerformanceCounter
谢谢。
【问题讨论】:
【参考方案1】:查看带有CLOCK_MONOTONIC_RAW
标志的clock_gettime()
和clock_getres()
。
这里也是一个如何使用它的例子:
stopwatch.h stopwatch.c stopwatch_example.c【讨论】:
我还是想不通:当我尝试使用clock_gettime(clock_id, &tp); tp 仅以微秒和秒为单位返回经过的时间,我需要的是周期数(=tickes)。 @user1087995:CPU 周期?什么CPU呢?除非您明确设置 CPU 亲和性,否则您的程序可以安排在不同的 CPU 上。这种衡量性能的方法几乎已经过时了。但如果你仍然想走那条路,看看 RDTSC - en.wikipedia.org/wiki/Time_Stamp_Counter 但是为了获得精度,您必须知道 CPU 频率才能将周期数转换为时间。但是,CPU 频率可能不是恒定的,即英特尔有 Turbo Boost 技术来节能等。这样说吧 - Windows 是有缺陷的。 @ScrollerBlaster:感谢您的提示。我提供了一个新链接。虽然现在它有点 C 并且也移植到了 OS X。 如果你想用 C99 支持编译stopwatch
,你必须使用 gcc 标志 -std=gnu99
而不是 -std=c99
才能工作。只是添加,因为我为此工作了一个小时:)【参考方案2】:
perf
工具已经随内核一起提供了一段时间,现在可能会满足您的需求。它有很多选项,所以请仔细研究;)
编辑:算了,我以为你在谈论 CPU 性能计数器。
【讨论】:
感谢您的快速回复。我需要在 cpp 程序中使用这些功能。我该怎么做? @user1087995:perf
是一个分析工具,可以为您提供许多指标,但它甚至与QueryPerformanceCounter
在 Windows 上所做的相比还差得远。所以perf
不是答案。 clock_gettime ()
是为您提供高精度(硬件)贴墙时间的原因。使用它。
嗯,好吧,当我看到“性能计数器”时,我真的以为 CPU 性能计数器是指的,但这里似乎不是这种情况。【参考方案3】:
Linux perf_event_open
系统调用
此系统调用以与架构无关的方式公开多个性能计数器。
man perf_event_open
记录了可用的计数器,其中包括您所期望的所有最基本的东西:
config = PERF_COUNT_HW_CPU_CYCLES
)
缓存命中和未命中 (type = PERF_TYPE_HW_CACHE
)
分支未命中 (config = PERF_COUNT_HW_BRANCH_MISSES
)
内核软件可见事件,例如页面错误 (PERF_COUNT_SW_PAGE_FAULTS
) 和上下文切换 (PERF_COUNT_SW_CONTEXT_SWITCHES
)
我在How to get the CPU cycle count in x86_64 from C++? 处给出了循环计数
perf_event_open.c
#include <asm/unistd.h>
#include <linux/perf_event.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <inttypes.h>
static long
perf_event_open(struct perf_event_attr *hw_event, pid_t pid,
int cpu, int group_fd, unsigned long flags)
int ret;
ret = syscall(__NR_perf_event_open, hw_event, pid, cpu,
group_fd, flags);
return ret;
int
main(int argc, char **argv)
struct perf_event_attr pe;
long long count;
int fd;
uint64_t n;
if (argc > 1)
n = strtoll(argv[1], NULL, 0);
else
n = 10000;
memset(&pe, 0, sizeof(struct perf_event_attr));
pe.type = PERF_TYPE_HARDWARE;
pe.size = sizeof(struct perf_event_attr);
pe.config = PERF_COUNT_HW_CPU_CYCLES;
pe.disabled = 1;
pe.exclude_kernel = 1;
// Don't count hypervisor events.
pe.exclude_hv = 1;
fd = perf_event_open(&pe, 0, -1, -1, 0);
if (fd == -1)
fprintf(stderr, "Error opening leader %llx\n", pe.config);
exit(EXIT_FAILURE);
ioctl(fd, PERF_EVENT_IOC_RESET, 0);
ioctl(fd, PERF_EVENT_IOC_ENABLE, 0);
/* Loop n times, should be good enough for -O0. */
__asm__ (
"1:;\n"
"sub $1, %[n];\n"
"jne 1b;\n"
: [n] "+r" (n)
:
:
);
ioctl(fd, PERF_EVENT_IOC_DISABLE, 0);
read(fd, &count, sizeof(long long));
printf("%lld\n", count);
close(fd);
【讨论】:
以上是关于Linux 替代 Windows 高分辨率性能计数器 API的主要内容,如果未能解决你的问题,请参考以下文章