使用tqdm的process_map传参:大数组B并行处理内存问题
解决process_map传递大数组避免内存克隆的方案
针对你遇到的问题,有两种可靠的方案可以在不克隆大数组B的前提下,将其传递给process_map:
方法一:用functools.partial固定参数(适用于Linux/macOS)
利用functools.partial将B绑定到test函数的参数上,这样process_map只需要遍历agrid传单个参数a,避免重复打包B导致内存克隆。在基于fork的系统(Linux、macOS)中,子进程会直接继承父进程的内存空间,不会拷贝B的内容。
代码示例:
from functools import partial from tqdm.contrib.concurrent import process_map def test(a, B): entry = B[a,a] # 执行复杂计算 result = B[a,a] return result # 将B固定为test的参数 test_with_B = partial(test, B=B) # 调用process_map,仅传入agrid即可 parallel_results_tqdm = process_map(test_with_B, agrid, max_workers=4, chunksize=1)
方法二:用共享内存存储数组(跨平台通用)
如果需要兼容Windows系统(Windows用spawn方式启动进程,会序列化参数),可以将大数组B存入共享内存,所有子进程共享同一块内存空间,彻底避免内存克隆。
以numpy数组为例,使用multiprocessing.shared_memory实现:
import numpy as np from multiprocessing import shared_memory from tqdm.contrib.concurrent import process_map def test(a, shm_name, array_shape, array_dtype): # 连接到已创建的共享内存 existing_shm = shared_memory.SharedMemory(name=shm_name) # 从共享内存重建数组 B = np.ndarray(array_shape, dtype=array_dtype, buffer=existing_shm.buf) entry = B[a,a] # 执行复杂计算 result = B[a,a] # 关闭共享内存连接(不要unlink,父进程统一释放) existing_shm.close() return result # 假设B是numpy数组 # 创建共享内存块,大小等于B的字节数 shm = shared_memory.SharedMemory(create=True, size=B.nbytes) # 基于共享内存创建数组,并复制原数组数据 B_shared = np.ndarray(B.shape, dtype=B.dtype, buffer=shm.buf) B_shared[:] = B[:] # 调用process_map,传递共享内存名称、数组形状和数据类型 parallel_results_tqdm = process_map( test, agrid, [shm.name] * len(agrid), [B.shape] * len(agrid), [B.dtype] * len(agrid), max_workers=4, chunksize=1 ) # 所有任务完成后,释放共享内存 shm.close() shm.unlink()
内容的提问来源于stack exchange,提问作者user2944352
相关产品推荐
相关产品推荐

