このBlogは移転しました。今後は aish.dev を御覧ください。

Python 3.8 の概要 (その4) - multiprocessing.shared_memory モジュール

multiprocessing.shared_memory モジュールで、共有メモリを使ってプロセス間でデータを交換できるようになりました。似たような処理は mmap モジュールで実現できましたが、マルチプラットフォームで簡単に利用できるようになります。

Numpyの ndarray オブジェクトを複数のプロセスで共有する場合、まず最初のプロセスで次のように共有メモリを作成します。この例では、共有メモリの名前は "sharedmemory_test1" とします。

import math
from multiprocessing import  shared_memory
import numpy as np

SHAPE = (3,3)

# 共有メモリ "sharedmemory_test1" を作成
size = math.prod(SHAPE) * numpy.dtype("float").itemsize
shm = shared_memory.SharedMemory(create=True, size=size, name="sharedmemory_test1")

# 共有メモリを利用するndarray オブジェクトを作成する
arr = np.ndarray(shape=SHAPE, dtype=float, buffer=shm.buf)

# ndarray を初期化
arr[:] = 0

他のプロセスでは、"sharedmemory_test1 という名前を指定して共有メモリを参照できます。

from multiprocessing import  shared_memory
import numpy as np

SHAPE = (3,3)

# "sharedmemory_test1" を指定して共有メモリを作成
shm = shared_memory.SharedMemory(name="sharedmemory_test1")

#nbarrayオブジェクトを作成
arr = np.ndarray(shape=SHAPE, dtype=float, buffer=shm.buf)

# 共有メモリを参照
print(arr[0:0])

# 共有メモリを開放
shm.close()

共有メモリが不要になったプロセスでは、close() メソッドでリソースを開放します。

SharedMemoryManager

共有メモリが不要になったら、 unlink() を一度だけ呼び出して、共有メモリを削除します。

SharedMemoryManagerを使うと、共有メモリを管理する専用のプロセスを起動し、共有メモリの寿命を制御できます。

from multiprocessing import Process
from multiprocessing.managers import SharedMemoryManager

def func1(shm, arg):
    shm.buf[0] = arg
    shm.close()

if __name__ == '__main__':

    # 共有メモリ管理プロセスを起動
    with SharedMemoryManager() as smm:

        # 共有メモリを作成し、初期値を設定
        shm1 = smm.SharedMemory(10)  
        shm1.buf[0] = 0

        # func1を異なるプロセスで起動
        p1 = Process(target=func1, args=(shm1, 100))

        # func1を異なるプロセスで起動
        p2 = Process(target=func1, args=(shm1, 200))

        p1.start()
        p2.start()

        p1.join()
        p2.join()
        
        print(shm1.buf[0])