1.问题描述

最近在用Python(Pyqt5)编写一个可以获取gpu信息(功耗、显存占用、利用率等)并将这些信息保存成csv文件的程序。在程序编写完成后,运行时却发现,随着程序的运行,所占用的内存每秒都会增加 0.3M,如下图的任务管理器中的任务 “Python(2)” 所示。


这是一个很致命的问题,尤其是对于一个用于记录信息的脚本来说,因为其需要长时间的运行。

2.问题分析

下面来看看我的代码结构,我只展示主要的部分:

class GpuTest(QThread):def __init__(self, *args, **kwargs):super(GpuTest, self).__init__()def run(self):  # 这是一个线程while running.is_set():  # 如果线程开启# 此处省略一万行# 检测一下当前系统的时间,并且看看是否已经创建了对应的csv文件(每1小时建一个新的csv文件记录显卡信息)while current_hour == last_hour and running.is_set():with open(csvpath, mode='a+', encoding='utf-8', newline="") as f:  # 打开csv文件并准备写入显卡数据csv_write = csv.writer(f)pynvml.nvmlInit()  # 显卡接口初始化systime = datetime.datetime.now().strftime('%H:%M:%S')  # 获取系统当前时间gpuDeviceCount = pynvml.nvmlDeviceGetCount()  # 获取 Nvidia GPU块数time.sleep(1)  # 等待1秒钟# 下面的代码不重要,可以不用看了# 下面就是读取显卡的相关数据和写入csv文件了for i in range(0, gpuDeviceCount):handle = pynvml.nvmlDeviceGetHandleByIndex(i)  # 获取GPU i的handle,后续通过handle来处理memoryInfo = pynvml.nvmlDeviceGetMemoryInfo(handle)  # GPU显存信息:总显存、已用显存、剩余显存gpuName = str(pynvml.nvmlDeviceGetName(handle), encoding='utf-8')  # 显卡名称gpuTemperature = pynvml.nvmlDeviceGetTemperature(handle, 0)  # 显卡温度gpuPower = pynvml.nvmlDeviceGetPowerUsage(handle)  # 显卡功耗gpuUtilRate = pynvml.nvmlDeviceGetUtilizationRates(handle).gpu  # gpu核心满速使用率gpuMemoryRate = pynvml.nvmlDeviceGetUtilizationRates(handle).memory  # gpu内存读写满速使用率time.sleep(1)show_list = [systime, str(round(gpuPower/1000, 0)), str(gpuTemperature),str(round(memoryInfo.used / memoryInfo.total*100, 0)) + '%',str(gpuUtilRate) + '%', str(gpuMemoryRate) + '%']csv_write.writerow(show_list)pynvml.nvmlShutdown()  # 关闭管理工具

我查阅了相关的资料,发现也有很多人遇到了Python脚本运行时内存越来越大的问题。如何解决这个问题呢,我首先按网上的方法进行了一些尝试。

2.1 尝试一: del 某变量 + gc collect()

在知乎上有个用户是这样解释的,大致意思就是说程序中有变量很占用内存,那么我们需要在每次循环后手动用 del 删除该变量,同时使用 gc collect():

我把所有变量都试了一遍,并没有解决问题,看来并不是变量的问题。

2.2 尝试二:修改 “while循环 + time.sleep() " 结构 为 定时器"Timer”

在这篇问题帖中有位兄弟说 “while循环 + sleep()” 的结构会导致脚本运行时内存越来越大。将结构修改为定时器的方式就可以解决。

我发现我的程序里也有这种 “while循环 + sleep()” 结构,因此我也尝试了这种方法,但是还是没有解决我的问题。看来我的程序问题也不在这。

3. 最终解决方法

我还试了许多其他的方法,但是都没有解决我的问题,就在我觉得没法解决时,我突然注意到我程序中的一个初始化函数貌似在线程中会运行很多次,如下所示。

pynvml.nvmlInit()  # 初始化显卡管理工具

为了方便大家理解这句代码在整个代码中的位置,我将代码进行简化:

while 【是否启动线程】while 【是否记录数据】pynvml.nvmlInit()  # 显卡接口管理工具初始化# 接下来开始记录数据# 省略一万行sleep(1)pynvml.nvmlShutdown()  # 关闭管理工具

可以看到,显卡接口管理工具在每次要记录数据时都会进行初始化,然后在记录结束后再关闭;即使从程序的角度出发,这也是一种重复操作。将这句初始化代码移动到启动线程前,并且在线程运行时不关闭显卡管理工具,修改后的代码结构如下所示:

while 【是否启动线程】pynvml.nvmlInit()  # 显卡接口管理工具初始化while 【是否记录数据】# 接下来开始记录数据# 省略一万行sleep(1)
pynvml.nvmlShutdown()  # 关闭管理工具

这样修改之后,问题被成功的解决了。

【解决】Python程序运行时所占内存越来越大相关推荐

  1. 程序运行时对应的内存分布(BSS段、数据段、代码段、堆、栈)关系

    参考:程序运行时对应的内存分布关系 作者:嵌入式基地(公众号) 发布时间: 2021-04-28 网址:https://mp.weixin.qq.com/s/AVDPZawSjg9HtxEm8vsFB ...

  2. 【转】android IDE——通过DDMS查看app运行时所占内存情况

    在Android内存优化方面,我们不可能做到没有大内存的占用情况. 所以有时候要清楚我们的app到底占用了多少内存,哪一步操作占用了多少的内存. 这时候,android的ddms中提供了一个工具,是可 ...

  3. python运行过程中占用内存越来越大_Python 程序运行时CPU和内存高解决思路

    这篇文章是基于上篇文章的续章~ 一台机器要部署很多爬虫,每天定时执行的情况下,服务器CPU和内存占比较高的情况出现后 模拟一份代码,进行分析. 一个简单的爬虫程序,爬取10页数据共计150条,每天定时 ...

  4. 解决Golang程序运行时占用内存不断增加的问题

    日常开发时遇到了这样的问题:死循环程序打包为exe后执行exe文件,打开任务管理器,发现程序占用内存在不断增加. 解决方式: 删掉defer语句 删掉fmt.Print语句提高性能 循环语句中添加ru ...

  5. python 程序运行时出现DLL load error

    问题描述 系统环境:win8系统,安装了64bit的python versin 2.7.同时正确安装了numpy,scipy,gensim的package. 在程序的运行过程中,加载一个动态链接库时出 ...

  6. python怎么在运行中查看执行状态,Python程序运行时查看对象状态怎样设计才能实现...

    不知大家有没有用过Rthymbox的python console. Rthymbox可以在运行的时候,让它的 交互式命令行 对程序进行控制. 比如说可以调用player的play函数,让它播放, 还可 ...

  7. 如果python程序运行时进入了死循环_碰到python死循环后要怎么退出结束?

    每当编写代码行云流水,却突然碰到代码无限循环,这是非常让人头疼的,难道直接退出程序运行嘛?答案肯定是不行,怎么跳出呢?一起来看下吧~ 案例: 遇到的问题是这样的:如果我定义了一个死循环线程我该如何终止 ...

  8. python怎么在运行中查看执行状态_python,_python程序运行时 查看对象状态,python - phpStudy...

    python程序运行时 查看对象状态 不知大家有没有用过Rthymbox的python console. Rthymbox可以在运行的时候,让它的 交互式命令行 对程序进行控制. 比如说可以调用pla ...

  9. 解决python调用 ffmpeg时 ‘ffmpeg‘ 不是内部或外部命令,也不是可运行的程序

    解决 python 调用 ffmpeg时 'ffmpeg' 不是内部或外部命令,也不是可运行的程序 在windows系统下, 我们使用windows下,使用ffmpeg库调用FFmpeg工具来提取视频 ...

最新文章

  1. java开发常见的热词奇解
  2. java中jtextfield_java中的JTextField
  3. php pdo字符,PHP:(PDO)Mysql最有效的方式来添加字符串以返回db的值
  4. 用户路径分析:揭秘你的用户行为偏好习惯
  5. xyz后缀的网站_.XYZ五岁了
  6. LOOP WITH CONTROL 用法
  7. 找call写call_如何将Google Call Widget添加到任何网页
  8. 2招解决并发问题,省几百万设备费用!说穿了很简单...
  9. vue3.0 execle 导出功能实现
  10. Java--文本文档编写Java代码
  11. 群晖NPV套件(NPV Server)官方下载方法
  12. java kinect_使用java来做Kinect开发
  13. MT8377 MT8389 MT6589 MT6577解析
  14. hdu4939思维DP
  15. 解决出租屋网络故障的步骤及最佳组网方案
  16. 从入门到放弃:微信小程序入门个人指南Day 4
  17. 阿里云生态峰会实录(中)
  18. 在Ubuntu中出现权限不够和找不到文件的解决方法
  19. @JsonFormat将时间字符串2021-02-25T15:32:54+08:00解析成date
  20. 微信小程序 - 云开发data exceed max size 解决方案

热门文章

  1. python 中 np.sum()函数 通俗易懂理解!
  2. MathJax 引擎数学符号说明
  3. 数据标注是什么,如何进行数据标注?
  4. 粉丝来信:黑猫投诉对象给投诉错了,又无法撤销删除应该怎么办呢?
  5. macOS输入法导致系统卡住鼠标圈圈问题/风火轮
  6. 电脑卡住了怎么办,鼠标无法操作,那就试试快捷键吧
  7. GSM Sniffing入门之硬件篇
  8. github生成密钥步骤
  9. 用python把学习通导出成绩,未完善
  10. sqlmap的用法,sqlmap -r