可能误用perf_event_open系统调用

时间:2017-07-31 16:36:39

标签: c linux performance linux-kernel system-calls

我正在尝试使用PERF_EVENTS,这是Linux内核提供的性能事件接口。我通过perf_event_open系统调用成功地获得了性能参数(cpu cycles,...)。

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;

   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_idle = 1;
   pe.exclude_kernel = 1;
   pe.exclude_callchain_kernel = 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);

   printf("Measuring instruction count for this printf\n");

   ioctl(fd, PERF_EVENT_IOC_DISABLE, 0);
   read(fd, &count, sizeof(long long));

   printf("%lld \n", count);

   return 0;
}

但是,我并不完全了解perf_event_open的用法。我盲目地传递-1作为第4个参数。我不知道何时将活动分组,何时将它们分开,哪一个应该是小组"领导"。

下面是第4个参数的文档:

  

group_fd参数允许创建事件组。事件组有一个事件是组长。首先创建领导者,group_fd = -1。其余的组成员是使用后续的perf_event_open()调用创建的,其中group_fd设置为组长的fd。 (使用group_fd = -1创建一个单独的事件,并且被认为是只有一个成员的组。)事件组作为一个单元被安排到CPU上:它只会被放到CPU上组中的事件可以放在CPU上。这意味着成员事件的值可以彼此进行有意义的比较,添加,划分(以获得比率)等,因为它们已经计算了同一组执行指令的事件。

所以任何人都可以在第4天(如果可能的话,它与第5个关系)有所了解吗?做事的正确方法是什么? 还有一个例子可以让事情变得更好。

1 个答案:

答案 0 :(得分:1)

我不确定旗帜,但我可以给团队一些颜色,虽然我不知道这是否足以回答你的问题,而不只是改写你引用的文件

CPU硬件非常有限^因此必须共享对计数器的访问。因此,您的资源可能会被映射并重新映射,因为操作系统会不时决定谁可以使用底层物理资源。

如果您同时测量两个计数器,那么您可能进行的某些测量只会有意义:例如,分支数量与错误预测的分支数量之比。

为了确保您的两个计数器由操作系统一起安排在CPU上和从CPU安排,而不是独立安排,您需要创建一个组。其中一个应该是领导者,然后另一个将使用第一个计数器的fd作为其领导者。

然后你知道你读的任何计数都来自两个计数器启用并一起运行的时间。

^除了一些常见的事情,例如"周期退休",大多数英特尔CPU仅支持从数百个调色板中一次测量四种事件类型。