Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/280.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 为什么psutil CPU使用率太低?_Python_Performance_Psutil - Fatal编程技术网

Python 为什么psutil CPU使用率太低?

Python 为什么psutil CPU使用率太低?,python,performance,psutil,Python,Performance,Psutil,我已经用Python编写了一个性能监视函数,它使用psutil来测量CPU、GPU和磁盘I/O,以便对另一个应用程序进行基准测试。在我的初始测试中,它工作得非常好,但我发现当它接近100%时,它明显低于报告的CPU使用率。我正在寻求帮助,找出为什么会发生这种情况 这个函数可能看起来过于复杂,但我尝试做两件事:实时显示当前使用情况;并在末尾报告最高的5秒滚动平均值。这是因为我无法预测子流程需要多长时间,我想消除短期波动 下面是该函数的简化版本。在本例中,我删除了所有GPU和磁盘测量,并稍微更改了打

我已经用Python编写了一个性能监视函数,它使用
psutil
来测量CPU、GPU和磁盘I/O,以便对另一个应用程序进行基准测试。在我的初始测试中,它工作得非常好,但我发现当它接近100%时,它明显低于报告的CPU使用率。我正在寻求帮助,找出为什么会发生这种情况

这个函数可能看起来过于复杂,但我尝试做两件事:实时显示当前使用情况;并在末尾报告最高的5秒滚动平均值。这是因为我无法预测子流程需要多长时间,我想消除短期波动

下面是该函数的简化版本。在本例中,我删除了所有GPU和磁盘测量,并稍微更改了打印语句以进行调试。虽然我尝试每秒采样一次,但我看到当CPU使用率非常高时,
经过的时间波动高达1.8

这是在Windows 10上运行的。任务管理器显示恒定的100%CPU使用率,没有波动,如果我在另一个窗口中运行
psutil.CPU\u times\u percent()
,该窗口也显示100%,而我的函数在这里显示大约90%

import psutil
import time
import shlex
import subprocess
from concurrent.futures import ThreadPoolExecutor


def perf_monitor(proc):
    # measure CPU, GPU, and Disk R/W every 1 seconds, and calculate a rolling average every 5 seconds
    # return the maximum of each rolling average
    rolling_interval = 5
    sample_interval = 1
    rolling_samples = []
    stats = {
        'cpu': 0,
    }
    cpu_count = psutil.cpu_count()

    while True: # loop until subprocess is finished
        # reset starting values
        start = time.time()
        cpu1 = psutil.cpu_times()
        cpu1 = cpu1.user + cpu1.system

        # measure again after the interval
        time.sleep(sample_interval)
        cpu2 = psutil.cpu_times()
        cpu2 = cpu2.user + cpu2.system
        
        # list starts at zero and counts up, then remains at 5
        elapsed = time.time() - start # may be slightly longer than sample_interval
        rolling_samples.append({
            'cpu': (cpu2 - cpu1) / cpu_count / elapsed,
        })
        # skip reporting for the first 5 seconds warm up
        if len(rolling_samples) < rolling_interval:
            continue
        
        # get the rolling average over a defined interval (5 seconds)
        rolling_avg_cpu = sum([sample['cpu'] for sample in rolling_samples]) / rolling_interval

        print([sample['cpu'] for sample in rolling_samples], elapsed) # for debugging
        print(f"CPU: {rolling_avg_cpu:.1%}  ", end='\n',)

        # update each stat only if it has increased
        if rolling_avg_cpu > stats['cpu']:
            stats['cpu'] = rolling_avg_cpu
        
        # remove oldest sample so we always keep 5
        del rolling_samples[0]

        # return stats when render is finished
        if proc.poll() is not None:
            return stats

if __name__ == "__main__":
    command = '"MyApp.exe'
    with ThreadPoolExecutor() as executor:
        proc = subprocess.Popen(shlex.split(command))
        thread = executor.submit(perf_monitor, proc)
        stats = thread.result()
    
    print(stats)
导入psutil
导入时间
导入shlex
导入子流程
从concurrent.futures导入ThreadPoolExecutor
def性能监视器(proc):
#每1秒测量一次CPU、GPU和磁盘R/W,每5秒计算一次滚动平均值
#返回每个滚动平均值的最大值
滚动间隔=5
样本间隔=1
滚动样本=[]
统计数据={
“cpu”:0,
}
cpu\u计数=psutil.cpu\u计数()
而True:#循环直到子流程完成
#重置起始值
开始=时间。时间()
cpu1=psutil.cpu\u次()
cpu1=cpu1.user+cpu1.system
#间隔后再次测量
睡眠时间(采样间隔)
cpu2=psutil.cpu\u次()
cpu2=cpu2.user+cpu2.system
#列表从零开始计数,然后保持在5
已用时间=时间。时间()-开始时间可能略长于采样时间间隔
滚动样本({
“cpu”:(cpu2-cpu1)/cpu计数/已用时间,
})
#跳过前5秒预热的报告
如果len(滚动样本)<滚动间隔:
持续
#获取定义间隔(5秒)内的滚动平均值
rolling_avg_cpu=总和([sample['cpu']用于rolling_样本中的样本])/rolling_间隔
打印([sample['cpu']用于滚动样本中的样本),已过)#用于调试
打印(f“CPU:{滚动平均CPU:.1%}”,结束='\n',)
#仅当每个属性增加时才更新
如果滚动平均cpu>stats['cpu']:
统计数据['cpu']=滚动平均cpu
#删除最旧的样本,以便我们始终保留5个
del rolling_样本[0]
#渲染完成时返回统计信息
如果proc.poll()不是无:
返回数据
如果名称=“\uuuuu main\uuuuuuuu”:
命令='“MyApp.exe”
使用ThreadPoolExecutor()作为执行器:
proc=subprocess.Popen(shlex.split(命令))
线程=执行器。提交(性能监视器,进程)
stats=thread.result()
打印(统计)

您正在让psutil将单调递增的值汇总为平均值,并对这些平均值进行操作。不要这样做。底层操作系统界面选择单调值的原因是:它们更容易计算,而且不会失去准确性。例如:您有高分辨率的每秒采样,但您想要5分钟的平均值?您得到的是mu如果您存储了5分钟开始和结束时使用的CPU总周期的单个值,并仅比较这两个值,而不是获取一系列紧张的1秒平均值,并试图从中得出5分钟平均值,则会得到更准确的结果…因此,一般来说:这是一个使用高级抽象这是一个失败的命题。了解引擎盖下的内容,并按设计使用。我得到的是5秒的平均值,而不是5分钟。如果我只每5秒采样一次,这将很容易。它变得复杂,因为我想每秒钟更新一次显示。(实际上我更喜欢每0.5秒采样一次)是的,但我的观点是,如果你根本不把事情累加起来,你可以计算出任何点之间的平均值,在这些点上你有一个(绝对时间,总cpu秒数)元组,而不需要看任何其他点,甚至不必关心它们的存在。