【问题标题】:python multiprocessing and mmappython多处理和mmap
【发布时间】:2021-09-02 17:10:33
【问题描述】:

我的目标是生成新进程,在后台运行并将mmap 对象作为参数传递给那里。玩具示例:

from multiprocessing import Process
import mmap
import time 


def modify(buf):
    time.sleep(10)
    buf[0:100] = b"xy" * 50


def main_job(t):
    time.sleep(t)
    
    
if __name__ == "__main__":
    BUF = mmap.mmap(-1, length=100, access=mmap.ACCESS_WRITE)
    BUF[0:100] = b"a" * 100
    p = Process(target=modify, args=(BUF,))
    p.daemon=True
    p.start() #background job started
    main_job(100) #man job started in parallel
    print(BUF[0:100])
    

TypeError: cannot pickle 'mmap.mmap' object

这里我有主要工作,它只是睡觉,我想用后台工作产生进程并将 mmap obj 作为参数传递给子进程。 问题是 mmap 对象不可拾取,并且无法同时使用 mmap 和多处理。 但我不知道如何创建后台作业,例如,我可以通过os.fork() 传递函数和参数。 如何解决这个问题?

【问题讨论】:

标签: python multiprocessing python-multiprocessing shared-memory mmap


【解决方案1】:

mmap.mmap,在 Windows 或 Posix 版本中,需要一个有效的文件描述符编号作为其第一个参数。 -1 不是有效的文件描述符编号。
EDIT-1 是正确的 fd 值,用于指示匿名 mmap

而且我认为你不明白 mmap 究竟做了什么。您没有将mmap 对象提供给您的其他进程,而是您的主进程和子进程都必须创建自己的mmap,但两者都由同一个文件支持。

这是您的代码,其中包含两个修复(并减少了睡眠时间):

from multiprocessing import Process
import mmap
import time


def modify(filename):
    time.sleep(5)
    with open(filename, "r+b") as file, \
            mmap.mmap(file.fileno(), length=100, access=mmap.ACCESS_WRITE) as buf:
        buf[0:100] = b"xy" * 50


def main_job(t):
    time.sleep(t)


if __name__ == "__main__":
    filename = "shared_mem_file"
    with open(filename, "r+b") as file, \
            mmap.mmap(file.fileno(), length=100, access=mmap.ACCESS_WRITE) as BUF:
        BUF[0:100] = b"a" * 100
        BUF.flush()
        p = Process(target=modify, args=(filename,))
        p.daemon = True
        p.start()  # background job started
        main_job(10)  # man job started in parallel
        print(BUF[0:100])
        BUF.close()

输出是:

b'xyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxy'

【讨论】:

  • 在 3.7 版中更改:添加了 ACCESS_DEFAULT 常量。要映射匿名内存,应将 -1 作为文件号和长度一起传递。
  • @Slavka 确实,-1 是表示匿名 mmap 的正确值,我的错。我将编辑我的答案。但是匿名映射更难共享:要么在 Windows 上指定 tagname(其行为类似于 文件名),要么你被困在同一个进程中使用共享的匿名未标记内存,只是被能够将其传输到forked 线程。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-08
  • 2012-10-24
  • 2014-11-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多