如何在Python中同时运行Blender渲染子进程与nvidia-smi监控子进程并解析输出?
如何在Python中同时运行Blender渲染子进程与nvidia-smi监控子进程并解析输出?
这个需求我之前也碰到过,其实用Python的subprocess模块就能轻松搞定——核心思路就是同时启动两个子进程,一边跑Blender渲染,一边让nvidia-smi持续输出监控数据,还能实时解析。下面给你一步步拆解实现方法:
1. 核心实现思路
我们可以用subprocess.Popen来分别启动Blender渲染进程和nvidia-smi监控进程,因为Popen是非阻塞的,所以两个进程能同时运行。然后我们可以实时读取nvidia-smi的输出流,一边解析数据,一边等待Blender进程结束后再终止监控进程。
2. 完整代码示例
直接上可运行的代码,里面加了详细注释,你可以根据自己的需求调整:
import subprocess import re def parse_nvidia_smi_output(line): """解析nvidia-smi的单行输出,提取已用显存""" # 匹配类似 "2048 MiB" 这样的格式 match = re.search(r'(\d+) MiB', line) if match: return int(match.group(1)) return None def main(): # 1. 定义你的Blender渲染命令(和你原来的逻辑一致) render_executable = "blender" # 换成你的Blender实际路径 file_to_render = "your_scene.blend" # 换成你的Blend文件路径 massager_script = "your_script.py" # 换成你的Python脚本路径 num_spheres = 10 new_filename_full_path = "output.png" render_command = [ render_executable, file_to_render, "--background", "--python", massager_script, "--", "--number", str(num_spheres), "--save", new_filename_full_path ] # 2. 启动Blender渲染子进程(非阻塞) render_process = subprocess.Popen( render_command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True ) # 3. 启动nvidia-smi监控子进程(非阻塞,每秒输出一次) nvidia_smi_command = [ "nvidia-smi", "--query-gpu=memory.used", "--format=csv", "-l", "1" ] nvidia_process = subprocess.Popen( nvidia_smi_command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, bufsize=1, # 行缓冲,保证实时读取输出 universal_newlines=True ) # 4. 实时监控+解析,同时等待Blender结束 print("开始渲染并监控GPU显存...") try: # 逐行读取nvidia-smi的输出 for line in nvidia_process.stdout: line = line.strip() # 跳过第一行的表头(内容是 "memory.used [MiB]") if line.startswith("memory.used"): continue # 解析显存数据 used_memory = parse_nvidia_smi_output(line) if used_memory is not None: print(f"当前已用显存: {used_memory} MiB") # 检查Blender进程是否已经结束 if render_process.poll() is not None: print("Blender渲染已完成!") break finally: # 确保监控进程被正确终止,避免后台残留 if nvidia_process.poll() is None: nvidia_process.terminate() nvidia_process.wait() print("GPU监控已停止") # 可选:读取Blender的输出用于调试 render_stdout, render_stderr = render_process.communicate() if render_stdout: print("\nBlender标准输出:") print(render_stdout) if render_stderr: print("\nBlender错误输出:") print(render_stderr) if __name__ == "__main__": main()
3. 关键细节说明
- 非阻塞启动:用
subprocess.Popen而非subprocess.run,因为run会阻塞主程序直到进程结束,而Popen会立即返回进程对象,让两个进程能并行运行。 - 实时输出读取:给
nvidia-smi的Popen设置bufsize=1和text=True,保证我们能逐行实时获取输出,不会因为缓冲区积压导致数据延迟。 - 可靠解析数据:用正则表达式匹配显存数值,比简单的字符串分割更稳定,能适配
nvidia-smi输出格式的小变动。 - 进程清理:在
finally块中终止监控进程,避免Blender结束后监控进程还在后台持续运行。
4. 针对短渲染的优化
你提到有些渲染只有5秒以内,这个方案完全适用——nvidia-smi每秒输出一次,短渲染也能捕捉到足够的监控数据。如果需要更精细的监控,你可以把-l 1改成-l 0.5(每0.5秒输出一次),不过注意太频繁的输出可能会增加一点系统开销,一般1秒一次足够了。
备注:内容来源于stack exchange,提问作者easythrees
相关产品推荐
相关产品推荐

