【教程】Python实时检测CPU和GPU的功耗

news2024/11/28 6:36:27

目录

前言

GPU功耗检测方法

CPU功耗检测方法

sudo的困扰与解决

完整功耗分析示例代码


转载请注明出处:小锋学长生活大爆炸[xfxuezhang.cn]

前言

        相关一些检测工具挺多的,比如powertop、powerstat、s-tui等。但如何通过代码的方式来实时检测,是个麻烦的问题。通过许久的搜索和自己的摸索,发现了可以检测CPU和GPU功耗的方法。如果有什么不对,或有更好的方法,欢迎评论留言!

        文末附完整功耗分析的示例代码

GPU功耗检测方法

        如果是常规的工具,可以使用官方的NVML。但这里需要Python控制,所以使用了对应的封装:pynvml。

        先安装:

pip install pynvml

     关于这个库,网上的使用教程挺多的。这里直接给出简单的示例代码:

import pynvml
pynvml.nvmlInit()

handle = pynvml.nvmlDeviceGetHandleByIndex(0)
powerusage = pynvml.nvmlDeviceGetPowerUsage(handle) / 1000

        这个方法获取的值,跟使用“nvidia-smi”指令得到的是一样的。

         附赠一个来自网上的获取更详细信息的函数:

def get_sensor_values():
    """
    get Sensor values
    :return:
    """
    values = list()
    # get gpu driver version
    version = pynvml.nvmlSystemGetDriverVersion()
    values.append("GPU_device_driver_version:" + version.decode())
    gpucount = pynvml.nvmlDeviceGetCount()  # 显示有几块GPU
    for gpu_id in range(gpucount):
        handle = pynvml.nvmlDeviceGetHandleByIndex(gpu_id)
        name = pynvml.nvmlDeviceGetName(handle).decode()
        meminfo = pynvml.nvmlDeviceGetMemoryInfo(handle)
        # print(meminfo.total)  # 显卡总的显存大小
        gpu_id = str(gpu_id)
        values.append("GPU " + gpu_id + " " + name + " 总共显存大小:" + str(common.bytes2human(meminfo.total)))
        # print(meminfo.used)  # 显存使用大小
        values.append("GPU " + gpu_id + " " + name + " 显存使用大小:" + str(common.bytes2human(meminfo.used)))
        # print(meminfo.free)  # 显卡剩余显存大小
        values.append("GPU " + gpu_id + " " + name + " 剩余显存大小:" + str(common.bytes2human(meminfo.free)))
        values.append("GPU " + gpu_id + " " + name + " 剩余显存比例:" + str(int((meminfo.free / meminfo.total) * 100)))

        utilization = pynvml.nvmlDeviceGetUtilizationRates(handle)
        # print(utilization.gpu)  # gpu利用率
        values.append("GPU " + gpu_id + " " + name + " GPU利用率:" + str(utilization.gpu))

        powerusage = pynvml.nvmlDeviceGetPowerUsage(handle)
        # print(powerusage / 1000) # 当前功耗, 原始单位是mWa
        values.append("GPU " + gpu_id + " " + name + " 当前功耗(W):" + str(powerusage / 1000))

        # 当前gpu power capacity
        # pynvml.nvmlDeviceGetEnforcedPowerLimit(handle)

        # 通过以下方法可以获取到gpu的温度,暂时采用ipmi sdr获取gpu的温度,此处暂不处理
        # temp = pynvml.nvmlDeviceGetTemperature(handle,0)
    print('\n'.join(values))
    return values

CPU功耗检测方法

        这个没有找到开源可以直接用的库。但经过搜索,发现大家都在用的s-tui工具是开源的!通过查看源码,发现他是有获取CPU功耗部分的代码,所以就参考他的源码写了一下。

        先安装:

sudo apt install s-tui
pip install s-tui

        先直接运行工具看一下效果(不使用sudo是不会出来Power的):

sudo s-tui

        说明这个工具确实能获取到CPU的功耗。其中package就是2个CPU,dram是内存条功耗(一般不准,可以不用)。

        直接给出简单的示例代码:

from s_tui.sources.rapl_power_source import RaplPowerSource

source.update()
summary = dict(source.get_sensors_summary())

cpu_power_total = str(sum(list(map(float, [summary[key] for key in summary.keys() if key.startswith('package')]))))

        不过注意!由于需要sudo权限,所以运行这个py文件时候,也需要sudo方式,比如:

sudo python demo.py

sudo的困扰与解决

        上面提到,由于必须要sudo方式,但sudo python就换了运行脚本的环境了呀,这个比较棘手。后来想了个方法,曲线救国一下。通过sudo运行一个脚本,并开启socket监听;而我们自己真正的脚本,在需要获取CPU功耗时候,连接一下socket就行。

        为什么这里使用socket而不是http呢?因为socket更高效一点!

我们写一个“power_listener.py”来监听:

from s_tui.sources.rapl_power_source import RaplPowerSource
import socket
import json

def output_to_terminal(source):
    results = {}
    if source.get_is_available():
        source.update()
        source_name = source.get_source_name()
        results[source_name] = source.get_sensors_summary()
    for key, value in results.items():
        print(str(key) + ": ")
        for skey, svalue in value.items():
            print(str(skey) + ": " + str(svalue) + ", ")


source = RaplPowerSource()
# output_to_terminal(source)

s = socket.socket()
host = socket.gethostname()
port = 8888
s.bind((host, port))
s.listen(5)
print("等待客户端连接...")
while True:
    c, addr = s.accept()
    source.update()
    summary = dict(source.get_sensors_summary())
    #msg = json.dumps(summary)
    # package表示CPU,dram表示内存(一般不准)
    power_total = str(sum(list(map(float, [summary[key] for key in summary.keys() if key.startswith('package')]))))
    print(f'发送给{addr}:{power_total}')
    c.send(power_total.encode('utf-8'))
    c.close()                # 关闭连接

        因此,在需要获取CPU功耗时候,只需要:

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = socket.gethostname()
port = 8888
s.connect((host, port))
msg = s.recv(1024)
s.close()
power_usage_cpu = float(msg.decode('utf-8'))

完整功耗分析示例代码

        提供一个我自己编写和使用的功耗分析代码,仅供参考。(注意上面的power_listener.py需要运行着)

import cv2
import socket
import sys
import threading
import json
import statistics
from psutil import _common as common
import pynvml
pynvml.nvmlInit()

class Timer: 
    def __init__(self, name = '', is_verbose = False):
        self._name = name 
        self._is_verbose = is_verbose
        self._is_paused = False 
        self._start_time = None 
        self._accumulated = 0 
        self._elapsed = 0         
        self.start()

    def start(self):
        self._accumulated = 0         
        self._start_time = cv2.getTickCount()

    def pause(self): 
        now_time = cv2.getTickCount()
        self._accumulated += (now_time - self._start_time)/cv2.getTickFrequency() 
        self._is_paused = True   

    def resume(self): 
        if self._is_paused: # considered only if paused 
            self._start_time = cv2.getTickCount()
            self._is_paused = False                      

    def elapsed(self):
        if self._is_paused:
            self._elapsed = self._accumulated
        else:
            now = cv2.getTickCount()
            self._elapsed = self._accumulated + (now - self._start_time)/cv2.getTickFrequency()        
        if self._is_verbose is True:      
            name =  self._name
            if self._is_paused:
                name += ' [paused]'
            message = 'Timer::' + name + ' - elapsed: ' + str(self._elapsed) 
            timer_print(message)
        return self._elapsed   

class PowerUsage:
    '''
    demo:
        power_usage = PowerUsage()
        power_usage.analyze_start()
        time.sleep(2)
        time_used, power_usage_gpu, power_usage_cpu = power_usage.analyze_end()
        print(time_used)
        print(power_usage_gpu)
        print(power_usage_cpu)
    '''
    def __init__(self):
        self.start_analyze = False
        self.power_usage_gpu_values = list()
        self.power_usage_cpu_values = list()
        self.thread = None
        self.timer = Timer(name='GpuPowerUsage', is_verbose=False)

    def analyze_start(self, gpu_id=0, delay=0.1):
        handle = pynvml.nvmlDeviceGetHandleByIndex(gpu_id)
        def start():
            self.power_usage_gpu_values.clear()
            self.power_usage_cpu_values.clear()
            self.start_analyze = True
            self.timer.start()
            while self.start_analyze:
                powerusage = pynvml.nvmlDeviceGetPowerUsage(handle)
                self.power_usage_gpu_values.append(powerusage/1000)

                s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                host = socket.gethostname()
                port = 8888
                s.connect((host, port))
                msg = s.recv(1024)
                s.close()
                self.power_usage_cpu_values.append(float(msg.decode('utf-8')))

                time.sleep(delay)
        self.thread = threading.Thread(target=start, daemon=True)
        self.thread.start()

    def analyze_end(self, mean=True):
        self.start_analyze = False
        while self.thread and self.thread.isAlive():
            time.sleep(0.01)
        time_used = self.timer.elapsed()
        self.thread = None
        power_usage_gpu = statistics.mean(self.power_usage_gpu_values) if mean else self.power_usage_gpu_values
        power_usage_cpu = statistics.mean(self.power_usage_cpu_values) if mean else self.power_usage_cpu_values
        return time_used, power_usage_gpu, power_usage_cpu


power_usage = PowerUsage()
def power_usage_api(func, note=''):
    @wraps(func)
    def wrapper(*args, **kwargs):
        power_usage.analyze_start()
        result = func(*args, **kwargs)
        print(f'{note}{power_usage.analyze_end()}')
        return result
    return wrapper

def power_usage_api2(note=''):
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            power_usage.analyze_start()
            result = func(*args, **kwargs)
            print(f'{note}{power_usage.analyze_end()}')
            return result
        return wrapper
    return decorator

        用法示例:

power_usage = PowerUsage()
power_usage.analyze_start()
# ----------------------
# xxx 某一段待分析的代码
# 这里以sleep表示运行时长
time.sleep(2)
# ----------------------
time_used, power_usage_gpu, power_usage_cpu = power_usage.analyze_end()
print(f'time_used: {time_used}')
print(f'power_usage_gpu: {power_usage_gpu}')
print(f'power_usage_cpu: {power_usage_cpu}')

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/180311.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Unsafe Fileupload-基础篇(文件上传绕过技巧与upload-labs靶场)

数据来源 本文仅用于信息安全的学习,请遵守相关法律法规,严禁用于非法途径。若观众因此作出任何危害网络安全的行为,后果自负,与本人无关。 文件上传基础 01 什么是文件上传 02 文件上传产生漏洞的原因 03 文件上传漏洞危害 0…

济人药业更新招股书:计划在A股上市,中成药业务收入持续下滑

近日,安徽济人药业股份有限公司(下称“济人药业”)递交预披露更新招股书,准备在上海证券交易所主板上市。据贝多财经了解,济人药业于2022年7月1日递交上市申请,此次更新了截至2022年6月30日的财务数据等信息…

Android深入系统完全讲解(42)

红色部分 pc 000007cc 代表当前 pc 指向的位置。libnative-lib.so 代表在哪个库里面。于是我 们就需要知道,libnative-lib.so 库的 pc 000007cc 偏移位置,是个什么代码。 我们从 NDK 开发包中找到 D:\android-ndk-r19c\toolchains\arm-linux-androideabi…

远程控制软件

远程控制软件1. 概述2. TeamViewer3. Todesk4. 向日葵5. AnyDesk6. Splashtop结束语1. 概述 出门在外或者工作时突然需要访问家中的电脑拿取文件或者资料时,是直接跑回家拿去、还是委托家里人员帮忙呢? 这时候你就需要一类软件来完成这个任务了&#xf…

前端图片压缩方案及代码实现

1. 为什么要进行图片压缩? 随着互联网的发展,图片在各种网站和应用中铺天盖地,运营人员在后台管理系统中上传图片时常常忽略的图片的体积大小,随之产生的带宽和服务器容量也大大增加,图片压缩的需求随之产生。 常见的压缩图片的…

【笔记】SemGCN

一. 论文总结 1.1 核心贡献 提出了一种改进的图卷积操作,称为语义图卷积(SemGConv),它源自cnn。其关键思想是学习图中暗示的边的信道权值,然后将它们与核矩阵结合起来。这大大提高了图卷积的能力。其次,我们引入了SemGCN&#x…

GPU服务器上跑深度学习模型

1 问题来源 近期在本地 Windows 系统上跑深度学习人群计数模型时,由于笔记本 NVIDIA 显卡 NVIDIA GeForce GTX 1650 的专用 GPU 内存只有 4 GB,无法设置较大的 batchsize 进行训练,导致模型训练时间过长,且易发生内存溢出&#xf…

年初五,迎财神 | 一张码如何实现多渠道(微信、支付宝、云闪付...)收款

大家好,我是小悟 今天是正月初五,天气超级好,也是迎财神的日子,祝大家顺风顺水,财源滚滚,钱兔似锦。 既然要发财,那自然少不了收款咯。如果你是一个商家,肯定是想收款的方式越方便越…

【手写 Promise 源码】第三篇 - 实现一个简版 Promise

一,前言 上一篇,结合示例介绍了 Promise 相关功能与特性分析,包含以下内容: Promise 基础特性;Promise 实例 API(原型方法);Promise 静态 API(类方法)&…

【数据结构】极致详解:树与二叉树(中)——顺序存储实现

目录 📔前言📔: 📙一、顺序存储结构📙: 📘二、堆📘: 1.堆的概念及结构: 2.堆的性质: 3.堆的实现(本文重点)&#xf…

离线用户召回定时更新系列二

3.6.3 特征处理原则 离散数据 one-hot编码连续数据 归一化图片/文本 文章标签/关键词提取embedding3.6.4 优化训练方式 使用Batch SGD优化 加入正则化防止过拟合 3.6.5 spark LR 进行预估 目的:通过LR模型进行CTR预估步骤: 1、需要通过spark读取HIVE外…

Nacos学习笔记【part1】安装与注册服务

一、概述与安装 Nacos 是是一个构建云原生应用的动态服务发现、配置管理和服务管理平台,用于发现、配置和管理微服务,提供了一组简单易用的特性集,快速实现动态服务发现、服务配置、服务元数据及流量管理。 Nacos 更敏捷和容易地构建…

分享136个ASP源码,总有一款适合您

ASP源码 分享136个ASP源码,总有一款适合您 下面是文件的名字,我放了一些图片,文章里不是所有的图主要是放不下..., 136个ASP源码下载链接:https://pan.baidu.com/s/11db_K2QXns5pm8vMZBVPSw?pwds0lb 提取码&#x…

js 文字转语音 api SpeechSynthesisUtterance

SpeechSynthesisUtterance基本介绍 SpeechSynthesisUtterance是HTML5中新增的API,用于将指定文字合成为对应的语音.也包含一些配置项,指定如何去阅读(语言,音量,音调)等 官方文档地址(https://developer.mozilla.org/zh-CN/docs/Web/API/SpeechSynthesisUtterance…

【JavaEE初阶】第七节.多线程(基础篇)单例模式(案例一)

欢迎大家跟我一起来学习有关多线程的有关内容!!!!!!!!!! 文章目录 前言 一、单例模式的概念 二、单例模式的简单实 2.1 饿汉模式 2.2 懒汉模式 总结 前言…

搭建Linux环境

学习Linux之前,我们首先需要在电脑上搭建Linux操作系统环境。 就好比说你买了一台电脑,需要使用Windows10操作系统,那么首先应该安装Windows操作系统(刚买的电脑会引导你一步一步的安装)。 一、Linux环境搭建的三种方式…

数据结构 第三章 栈和队列(队列)

感谢:点击收听 1 基本知识点 1、允许删除的一端称为队头(front) 2、允许插入的一端称为队尾(rear) 3、当队列中没有元素时称为空队列 4、顺序队列: 1 使用顺序表来实现队列 2 两个指针分别指向队列的前端和尾端 **3 如果队列的大小为MaxSize个,那么元…

什么是倒排表(倒排索引)

这种搜索引擎的实现常常用的就是倒排的技术 文档(Document):一般搜索引擎的处理对象是互联网网页,而文档这个概念要更宽泛些,代表以文本形式存在的存储对象,相比网页来说,涵盖更多种形式,比如Word&#xff…

在Mac下如何创建文件

相比于windows中创建Mac是比较复杂的 第一步:打开启动台,依次打开「启动台-其他-自动操作」,可以按住「 Command 空格」直接搜索「自动操作」程序。 第二步:打开之后在「选取文稿类型」选项时,选择「快速操作」&#…

工地车辆未冲洗识别抓拍系统 yolov5网络

工地车辆未冲洗识别抓拍系统通过yolov5网络深度算法学习模型,自动对画面中每辆进出车辆的清洗实现自动识别判定。如果识别到车辆冲洗不合格,就会自动进行抓拍并将违规车辆信息回传。目标检测架构分为两种,一种是two-stage,一种是o…