python shared_memory 共享内存

  • 背景

    python利用多核就需要开启多进程,如果多进程之间需要共享数据又不希望引入第三方的服务,就需要使用共享内存。
  • multiprocessing.shared_memory

    python 3.8之后,python内置的multiprocessing库提供了一种新的共享内存方式,shared_memory。
    这种方式是直接让系统划出一块内存供多进程访问,进程访问这块内存时,无需经过代理等等过程,所以性能较高。
  • 简单使用

    import random
    import time
    from multiprocessing import Lock, Process
    from multiprocessing.shared_memory import SharedMemory


    def worker_on_sharememory(shared_mem: SharedMemory, lock):
       """
      操作共享内存
      """
       time.sleep(random.randint(1, 5))
       with lock:
           s = str(random.randint(0, 9))
           shared_mem.buf[12:13] = s.encode()
           print(shared_mem.buf[:13].tobytes().decode("utf-8"))

       # 关闭子进程对共享内存的访问
       shared_mem.close()


    if __name__ == "__main__":
       # 系统一般会按内存页大小分配内存,通常都是4kb,比如,申请1字节内存,系统实际会分配4kb,但是可以安全使用的还是1字节,剩余的是浪费的。
       # 实际使用中,一般不需要考虑这个问题,size指定多少就最多用多少,不要溢出。
       shared_mem = SharedMemory(
           create=True,
           size=4096,
           name="test_memory",
      )  # 申请4096字节内存

       # 使用共享内存
       shared_mem.buf[:12] = b"Hello World!"
       lock = Lock()
       process_list = []
       for i in range(5):
           p = Process(target=worker_on_sharememory, args=(shared_mem, lock))
           p.start()
           process_list.append(p)

       for p in process_list:
           p.join()

       # 关闭父进程对共享内存的访问
       shared_mem.close()

       # 标记共享内存区域为可删除,这是父进程必须要做的事情,否则共享内存可能不会被系统回收。
       shared_mem.unlink()
       
  • 注意事项

    1.共享内存的大小在创建时指定,且不能动态调整。
    # 创建 100 字节的共享内存
    shared_mem = SharedMemory(create=True, size=100)

    2.共享内存是无锁的,多进程数据同步问题需要自行加锁处理

    3.共享内存可以命名,在整个计算机中,命名必须唯一。通过name命名,以便多个进程访问同一块内存区域。
    # 创建命名共享内存
    shared_mem = SharedMemory(create=True, size=100, name='test_memory')
    # windows平台上,共享内存的名称不能包含反斜杠'\'

    # 在其他进程中访问同一块共享内存
    shared_mem = SharedMemory(name='test_memory')

    4.共享内存不会自动回收,必须显式调用close()和unlink()释放资源.
    **close()**:关闭当前进程对共享内存的访问。
    **unlink()**:标记共享内存区域为可删除,当所有进程都关闭访问后,系统会自动回收该内存区域。
    基本流程: 子进程访问完后关闭访问,父进程等子进程们结束后,关闭访问并标记可删除,系统自动回收。

    5.查看和删除共享内存
    linux中,通过ipcs -m和ipcrm -m <shm_id>来查看和删除共享内存。
    # windows系统会自动清理未释放的共享内存,但还是建议手动unlink清理。

    6.跟踪器警告
    """
    UserWarning: resource_tracker: There appear to be 1 leaked shared_memory objects to clean up at shutdown
    """
    未正确释放共享内存的程序,在程序执行之后,会发出以上警告内容。
  • 特点

    1.shared_memory的性能非常高,因为进程可以直接操作内存区域,避免了数据复制和进程间通信的开销。
    2.无锁,数据同步问题需要自行加锁,加锁也会影响性能。
posted @ 2025-03-13 09:45  CJTARRR  阅读(1071)  评论(0)    收藏  举报