首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >CPU .进程/pid相对于最大CPU频率的CPU使用或CPU周期

CPU .进程/pid相对于最大CPU频率的CPU使用或CPU周期
EN

Stack Overflow用户
提问于 2017-05-09 15:12:18
回答 2查看 792关注 0票数 0

目前,我通过Python的psutil模块监视多个进程,并以百分比检索基于execution_time/total_time的CPU使用率。这样做的问题是动态电压和频率缩放(DVFS,或ACPI的P-状态,或cpufreq,等等)。当前CPU频率越低,进程执行的时间越长,CPU使用率就越高。与此形成对比的是,相对于CPU的最大性能,我需要固定的CPU使用率。

为了避免永久改变“当前频率”的多重重标,一种方法是直接使用进程所使用的CPU周期。原则上,这可以通过C中的perf_event.h或Linux命令行上的perf来完成。不幸的是,我找不到一个Python模块,它提供了类似的功能(基于上述功能)。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-05-30 14:15:50

感谢BlackJack的评论

如何在C中实现它作为共享库,并通过ctypes在Python中使用它呢? 库调用引入的开销较少。子进程调用启动整个外部进程,并在每次需要值时通过管道将结果作为字符串进行通信。共享库被加载到当前进程中一次,结果将传递到内存中。

我将其实现为一个共享库。库cpuccycles.c的源代码(很大程度上基于's man page的示例):

代码语言:javascript
复制
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/ioctl.h>
#include <linux/perf_event.h>
#include <asm/unistd.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;
}

long long
cpu_cycles(unsigned int microseconds,
            pid_t pid,
            int cpu,
            int exclude_user,
            int exclude_kernel,
            int exclude_hv,
            int exclude_idle)
{
    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_user = exclude_user;
    pe.exclude_kernel = exclude_kernel;
    pe.exclude_hv = exclude_hv;
    pe.exclude_idle = exclude_idle;

    fd = perf_event_open(&pe, pid, cpu, -1, 0);
    if (fd == -1) {
        return -1;
    }
    ioctl(fd, PERF_EVENT_IOC_RESET, 0);
    ioctl(fd, PERF_EVENT_IOC_ENABLE, 0);
    usleep(microseconds);
    ioctl(fd, PERF_EVENT_IOC_DISABLE, 0);
    read(fd, &count, sizeof(long long));

    close(fd);
    return count;
}

通过以下两个命令将此代码编译到共享库中:

代码语言:javascript
复制
$ gcc -c -fPIC cpucycles.c -o cpucycles.o
$ gcc -shared -Wl,-soname,libcpucycles.so.1 -o libcpucycles.so.1.0.1 cpucycles.o

最后,cpucycles.py中的Python可以使用这个库。

代码语言:javascript
复制
import ctypes
import os

cdll = ctypes.cdll.LoadLibrary(os.path.join(os.path.dirname(__file__), "libcpucycles.so.1.0.1"))
cdll.cpu_cycles.argtypes = (ctypes.c_uint, ctypes.c_int, ctypes.c_int,
                            ctypes.c_int, ctypes.c_int, ctypes.c_int,
                            ctypes.c_int)
cdll.cpu_cycles.restype = ctypes.c_longlong

def cpu_cycles(duration=1.0, pid=0, cpu=-1,
                exclude_user=False, exclude_kernel=False,
                exclude_hv=True, exclude_idle=True):
    """
    See man page of perf_event_open for all the parameters.

    :param duration: duration of counting cpu_cycles [seconds]
    :type duration: float
    :returns: cpu-cycle count of pid
    :rtype: int
    """
    count = cdll.cpu_cycles(int(duration*1000000), pid, cpu,
                            exclude_user, exclude_kernel,
                            exclude_hv, exclude_idle)
    if count < 0:
                raise OSError("cpu_cycles(pid={}, duration={}) from {} exited with code {}.".format(
                    pid, duration, cdll._name, count))

    return count
票数 2
EN

Stack Overflow用户

发布于 2017-05-11 07:57:16

最后,我通过perf命令行工具读取CPU周期,并将其封装到Python (简化代码)中:

代码语言:javascript
复制
import subprocess
maximum_cpu_frequency = 3e9
cpu_percent = []
while True:    # some stop criteria
    try:
        cpu_percent.append(int(
                subprocess.check_output(["perf", "stat", "-e", "cycles",
                        "-p", pid, "-x", ",", "sleep", "1"],
                        stderr=subprocess.STDOUT).decode().split(",")[0]
                )/maximum_cpu_frequency)
    except ValueError:
        cpu_percent.append(0.0)

不幸的是,由于不精确的sleep命令以及为每个示例生成一个新的perf进程,这是不精确的。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43873599

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档