V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
nmecury
V2EX  ›  Python

请教在 shell 里启动的两个 Python 进程之间要如何共享一个对象?

  •  
  •   nmecury · 2021-12-22 19:04:18 +08:00 · 3883 次点击
    这是一个创建于 1099 天前的主题,其中的信息可能已经有所发展或是发生改变。

    请教各位一个问题:

    在 shell 里起两个 python 任务,这两个 python 进程之间是否有什么办法可以共享一个对象( OrderedDict 之类的),一个进程只读,一个进程只写? 我目前采用的方案是用 pickle.dumps 将这个对象(比如 OrderedDict )序列化成 bytes 类型,然后放到 SharedMemory 里,通过一个 name 来实现共享,但是感觉序列化这一步有点慢,求教有没有更快的方法。

    并非不想用 multiprocessing ,一方面 python 的多线程有点蛋疼,另一方面涉及到深度学习库和 GPU 运算,担心 multiprocessing 搞不定……

    24 条回复    2021-12-30 17:14:30 +08:00
    learningman
        1
    learningman  
       2021-12-22 19:12:00 +08:00
    一个只读,一个只写,任务队列?
    iBugOne
        2
    iBugOne  
       2021-12-22 19:12:16 +08:00 via Android   ❤️ 1
    自己造个轮子然后两个进程用 pipe 或者 socket 通信吧,如果单次修改量不大的话每次重新传输整个对象的效率其实不行,改成“变啥传啥”就好了
    thinkershare
        3
    thinkershare  
       2021-12-22 19:58:02 +08:00
    没有办法, 别折腾了, 想起它办法!
    qW7bo2FbzbC0
        4
    qW7bo2FbzbC0  
       2021-12-22 20:24:25 +08:00
    平行时空了属于,2 楼说的对
    ch2
        5
    ch2  
       2021-12-22 20:31:10 +08:00   ❤️ 1
    pickle 的方便是没有啥其他办法能比的,请参考这个来优化
    https://www.codenong.com/26860051
    yhvictor
        6
    yhvictor  
       2021-12-22 20:56:10 +08:00 via iPhone   ❤️ 1
    linux 下 pipe 不错
    heyjei
        7
    heyjei  
       2021-12-22 21:03:18 +08:00   ❤️ 1
    用 redis 做队列是最简单靠谱的方案
    ClericPy
        8
    ClericPy  
       2021-12-22 22:01:30 +08:00   ❤️ 1
    常用的就是 linux 下面的 pipe, A print 出来 B 从 stdin 里拿, 单进程挺烦

    Websocket 和 HTTP 不考虑么, RPC 啥的, Unix domain socket 也不行么

    消息队列不考虑么, 通过通信共享内存而不是反之

    mmap 忘了能不能了, 太久没动过了

    不让用 multiprocessing.Queue 对吧, (multiprocessing 也不是多线程啊)

    linux 下面 IPC 其实也就那几个三板斧, 随便搜搜就有了, 反正我是能用队列用队列, 其他的东西心智负担太多了
    ipwx
        9
    ipwx  
       2021-12-22 22:16:46 +08:00   ❤️ 1
    你得说说原始需求,你的问题抽象不可解
    kaneg
        10
    kaneg  
       2021-12-22 22:57:11 +08:00   ❤️ 1
    gRPC
    2i2Re2PLMaDnghL
        11
    2i2Re2PLMaDnghL  
       2021-12-23 00:11:02 +08:00   ❤️ 4
    你分解出来的这个子问题已经完全陷入糟糕实践范畴了,建议直接问原问题。
    tinytoadd
        12
    tinytoadd  
       2021-12-23 01:10:06 +08:00 via Android
    通过数据库处理
    Xs0ul
        13
    Xs0ul  
       2021-12-23 01:43:17 +08:00 via Android   ❤️ 1
    mingl0280
        14
    mingl0280  
       2021-12-23 04:59:16 +08:00 via Android   ❤️ 1
    mmap 啊 mmap 啊!用这个就够了!
    binux
        15
    binux  
       2021-12-23 07:14:09 +08:00 via Android
    干嘛不用 multiprocessing 啊,人家是多进程,没有你担心的多线程的问题啊。
    zhoudaiyu
        16
    zhoudaiyu  
       2021-12-23 08:57:32 +08:00   ❤️ 1
    mkfifo
    weyou
        17
    weyou  
       2021-12-23 09:02:48 +08:00 via Android   ❤️ 1
    Pyro4 或者 Pyro5
    nmecury
        18
    nmecury  
    OP
       2021-12-23 09:54:21 +08:00
    @iBugOne #2 #2 修改量还是挺大的,整个对象所有参数都改了……
    killva4624
        19
    killva4624  
       2021-12-23 10:10:52 +08:00
    可以写一个第三方服务,暴露写接口和读接口分别给外部访问?这样就抽象成一个存储体了……
    或者如 #11 所说,建议直接分享问题最原始的出发点,可能还有更好的办法。
    codehz
        20
    codehz  
       2021-12-23 10:22:02 +08:00   ❤️ 1
    不如一步到位直接起个数据库(划掉)
    如果可以序列化成数据库的话,同一台机器上可以使用 SQLite3 ,启用 WAL 模式后读写互不干扰,可以同时进行,性能大概比每次序列化强,但是单独访问的话就不一定比 OrderedDict 快(
    但是最主要的是不用自己解决复杂的线程同步问题了,而这个可是经常处理出错误的(
    Juszoe
        21
    Juszoe  
       2021-12-23 20:43:46 +08:00
    请直接提问原问题,深度学习那么多现成多机计算方案不用,一定要自己从头造吗
    nmecury
        22
    nmecury  
    OP
       2021-12-24 10:22:49 +08:00
    统一回复 #9 #11 #13 #21 ,感谢你们的建议,原始需求就是一个 environment 巨慢无比的 DRL 。我本来是做 DL 的,赶鸭子上架要搞 RL ,情况复杂只能在现有代码上做个快速迭代,就遇到了上述问题。用 ray 当然好,但是短时间内条件不允许,过阵子缓一缓再用 ray 重构一下。
    necomancer
        23
    necomancer  
       2021-12-29 15:45:20 +08:00
    看你还有后续需求的样子……试试 mpi4py ?
    Pho3nix
        24
    Pho3nix  
       2021-12-30 17:14:30 +08:00
    之前大概的方法就是获取内存地址,然后根据地址读取,中间用 socket 发送地址
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3560 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 00:47 · PVG 08:47 · LAX 16:47 · JFK 19:47
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.