You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python程序无预警退出/卡顿(偶现段错误)问题求助

问题描述

运行Python脚本时,程序先正常生成部分正确图像,随后无预警退出或终端卡顿,偶发segment fault。磁盘与内存空间充足,注释image.save、image=Image.fromarray仍无法解决,仅注释图像数组生成逻辑后程序可运行完成。

原代码

import subprocess
from PIL import Image
import colorsys
import numpy as np

for t in range(1,49):
    in_file_name=f"Pf{t:02d}.bin"
    subprocess.run(f"sz3 -f -i /home/jzz/compress/SDRBENCH-Hurricane-ISABEL-100x500x500/P/{in_file_name} -z /home/jzz/simulation/dataset/sz3/temp.sz3 -o /home/jzz/simulation/dataset/sz3/temp.sz3.bin -M REL -R 0.1 -3 500 500 100",shell=True,check=True)
    in_data=np.fromfile(f"/home/jzz/compress/SDRBENCH-Hurricane-ISABEL-100x500x500/P/{in_file_name}",dtype=np.float32).reshape(100,500,500)
    out_data=np.fromfile(f"/home/jzz/simulation/dataset/sz3/temp.sz3.bin",dtype=np.float32).reshape(100,500,500)
    for h in range(100):
        print(h)
        mx=max(in_data[h,:,:].max(),out_data[h,:,:].max())
        mn=min(in_data[h,:,:].min(),out_data[h,:,:].min())
        data01=(in_data[h,:,:]-mn)/(mx-mn)
        image=(np.array([list(colorsys.hsv_to_rgb(data01[i,j],1,1)) for i in range(500) for j in range(500)]).reshape(500,500,3)*255).astype(np.uint8)
        image=Image.fromarray(image)
        image.save(f"/home/jzz/simulation/dataset/sz3/ISABEL_P_t={t}_h={h}_x.png")
        data01=(out_data[h,:,:]-mn)/(mx-mn)
        image=(np.array([list(colorsys.hsv_to_rgb(data01[i,j],1,1)) for i in range(500) for j in range(500)]).reshape(500,500,3)*255).astype(np.uint8)
        image=Image.fromarray(image)
        image.save(f"/home/jzz/simulation/dataset/sz3/ISABEL_P_t={t}_h={h}_y.png")
    subprocess.run(f"rm /home/jzz/simulation/dataset/sz3/temp.sz3",shell=True)
    subprocess.run(f"rm /home/jzz/simulation/dataset/sz3/temp.sz3.bin",shell=True)
问题分析与解决

问题核心是逐元素嵌套调用colorsys.hsv_to_rgb:这个纯Python函数循环500×500次会产生大量临时对象,引发频繁GC,甚至因内存碎片触发段错误。

优化方案

  1. 用numpy向量化操作替代逐元素循环,大幅减少内存开销与计算时间
  2. 封装图像生成逻辑,避免重复代码
  3. 显式释放临时变量,降低内存占用

优化后代码

import subprocess
from PIL import Image
import numpy as np

def hsv_to_rgb_vectorized(h, s=1, v=1):
    # 向量化实现HSV转RGB,替代逐元素调用colorsys
    h = np.asarray(h) % 1.0
    i = np.floor(h * 6.0).astype(np.int32)
    f = (h * 6.0) - i
    p = v * (1.0 - s)
    q = v * (1.0 - s * f)
    t = v * (1.0 - s * (1.0 - f))

    r, g, b = np.zeros_like(h), np.zeros_like(h), np.zeros_like(h)
    mask = i == 0
    r[mask], g[mask], b[mask] = v[mask], t[mask], p[mask]
    mask = i == 1
    r[mask], g[mask], b[mask] = q[mask], v[mask], p[mask]
    mask = i == 2
    r[mask], g[mask], b[mask] = p[mask], v[mask], t[mask]
    mask = i == 3
    r[mask], g[mask], b[mask] = p[mask], q[mask], v[mask]
    mask = i == 4
    r[mask], g[mask], b[mask] = t[mask], p[mask], v[mask]
    mask = i == 5
    r[mask], g[mask], b[mask] = v[mask], p[mask], q[mask]

    return np.stack([r, g, b], axis=-1)

def generate_image(data_slice, mn, mx):
    data01 = (data_slice - mn) / (mx - mn)
    rgb_array = hsv_to_rgb_vectorized(data01) * 255
    return Image.fromarray(rgb_array.astype(np.uint8))

for t in range(1,49):
    in_file_name = f"Pf{t:02d}.bin"
    subprocess.run(
        f"sz3 -f -i /home/jzz/compress/SDRBENCH-Hurricane-ISABEL-100x500x500/P/{in_file_name} -z /home/jzz/simulation/dataset/sz3/temp.sz3 -o /home/jzz/simulation/dataset/sz3/temp.sz3.bin -M REL -R 0.1 -3 500 500 100",
        shell=True, check=True
    )
    in_data = np.fromfile(f"/home/jzz/compress/SDRBENCH-Hurricane-ISABEL-100x500x500/P/{in_file_name}", dtype=np.float32).reshape(100,500,500)
    out_data = np.fromfile(f"/home/jzz/simulation/dataset/sz3/temp.sz3.bin", dtype=np.float32).reshape(100,500,500)
    
    for h in range(100):
        print(h)
        in_slice = in_data[h,:,:]
        out_slice = out_data[h,:,:]
        mx = max(in_slice.max(), out_slice.max())
        mn = min(in_slice.min(), out_slice.min())
        
        # 生成并保存输入图像
        img_in = generate_image(in_slice, mn, mx)
        img_in.save(f"/home/jzz/simulation/dataset/sz3/ISABEL_P_t={t}_h={h}_x.png")
        # 生成并保存输出图像
        img_out = generate_image(out_slice, mn, mx)
        img_out.save(f"/home/jzz/simulation/dataset/sz3/ISABEL_P_t={t}_h={h}_y.png")
        
        # 显式释放临时变量
        del img_in, img_out, in_slice, out_slice
    
    subprocess.run(f"rm /home/jzz/simulation/dataset/sz3/temp.sz3", shell=True)
    subprocess.run(f"rm /home/jzz/simulation/dataset/sz3/temp.sz3.bin", shell=True)
    
    # 释放当前批次的大数组
    del in_data, out_data

额外建议

  • 若仍有内存问题,可在t循环末尾添加import gc; gc.collect()强制触发垃圾回收
  • 执行ulimit -c unlimited开启核心转储,方便定位段错误的具体触发点
  • 检查sz3输出的二进制文件完整性,避免读入异常数据导致计算崩溃

内容的提问来源于stack exchange,提问作者Zizhe Jian

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 05:11:38