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

使用Python Multiprocessing Pool出现‘too many open files’错误求助

解决multiprocessing.Pool spawn模式下"too many open files"错误

问题分析

你使用spawn模式创建20进程的Pool,循环100次处理约400个任务,出现OSError: too many open files,核心原因大概率是进程资源未彻底释放或任务内部存在文件句柄/资源泄漏:

  • spawn模式下,每个子进程都会重新初始化Python解释器、导入模块,若池长期复用,子进程积累的未释放资源(如Torch的CUDA句柄、IPC套接字)会导致句柄耗尽;
  • 任务函数中Torch张量未显式销毁,或循环中未正确消费任务结果,导致套接字/资源残留。

解决方案

1. 修正池的生命周期:每次迭代重新创建并销毁池

将Pool的创建移入循环内部,确保每次迭代后子进程被彻底销毁,避免长期运行的子进程积累资源:

C=100
dim_candidates = list(range(C))
best_dims = []

for i in range(C):
    print(f"Iteration {i+1}")
    # 每次迭代重新生成dargs(基于当前best_dims)
    dargs = [(best_dims + [dc], pos_embeddings[:, best_dims + [dc], :], neg_embeddings[:, best_dims + [dc], :]) 
             for dc in dim_candidates]
    print("Number of tasks to be executed (number of candidates):", len(dargs))
    # 每次迭代创建新池,with块结束自动close+join,销毁所有子进程
    with multiprocessing.get_context("spawn").Pool(n_workers) as pool:
        results = tqdm(pool.imap(calc, dargs))
        new_d, dim_scores = zip(*results)
    # 后续处理:移除最优维度、更新best_dims等
    # ...

2. 任务函数内显式释放资源

在calc函数末尾销毁所有Torch张量,避免子进程内存/句柄泄漏:

def calc(args):
    dim_selected, pos_embeddings, neg_embeddings = args

    I = torch.eye(len(dim_selected))
    max_dist = []
    
    N, C, HW = pos_embeddings.size()

    for p in range(HW):
        mean_neg = torch.mean(neg_embeddings[:, :, p], dim=0)
        cov_neg = torch.cov(neg_embeddings[:, :, p].T)
        covI = torch.inverse(cov_neg + 0.01 * I)
        # 用生成器表达式代替列表推导,减少内存占用
        current_max = max(mahalanobis(p_sample, mean_neg, VI=covI) for p_sample in pos_embeddings[:, :, p])
        max_dist.append(current_max)
        # 销毁当前循环的张量
        del mean_neg, cov_neg, covI
    
    # 销毁函数内的大张量
    del pos_embeddings, neg_embeddings, I
    # 若使用GPU,清空CUDA缓存
    if torch.cuda.is_available():
        torch.cuda.empty_cache()
    
    return dim_selected[-1], max(max_dist)

3. 确保任务结果被完全消费

imap返回的迭代器必须被完全遍历,否则Pool会保留未完成任务的套接字。zip(*results)会强制遍历所有结果,这一步没问题,但要避免中途中断迭代。

4. 临时调大系统文件句柄上限(治标)

如果以上方法仍未解决,可临时调大系统的文件句柄限制(仅Linux/macOS):

# 临时生效,重启后失效
ulimit -n 65535

长期生效需修改/etc/security/limits.conf(Linux)或/etc/sysctl.conf。

5. 排查句柄泄漏来源

用lsof命令定位哪个进程/资源占用大量句柄:

# 查看主进程的句柄情况
lsof -p <主进程PID> | wc -l
# 查看子进程的句柄情况
lsof -p <子进程PID> | grep -E "(TCP|CUDA|REG)"

若发现大量TCP套接字,说明Pool的IPC通信未正确释放;若出现大量CUDA相关句柄,说明Torch资源未销毁。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 10:03:19