multiprocessing.shared_memory —プロセス間で直接アクセスするための共有メモリを提供します—Pythonドキュメント

提供:Dev Guides
< PythonPython/docs/3.8/library/multiprocessing.shared memory
移動先:案内検索

multiprocessing.shared_memory —プロセス間で直接アクセスするための共有メモリを提供します

ソースコード: :source: `Lib / multiprocessing / shared_memory.py`

バージョン3.8の新機能。



このモジュールは、マルチコアまたは対称型マルチプロセッサ(SMP)マシン上の1つ以上のプロセスがアクセスする共有メモリの割り当てと管理のためのクラス SharedMemory を提供します。 特に個別のプロセス間での共有メモリのライフサイクル管理を支援するために、 BaseManager サブクラスSharedMemoryManagermultiprocessing.managersモジュールで提供されます。

このモジュールでは、共有メモリは「System Vスタイル」の共有メモリブロックを指し(必ずしも明示的に実装されているとは限りません)、「分散共有メモリ」を指しません。 このスタイルの共有メモリを使用すると、個別のプロセスが揮発性メモリの共通(または共有)領域に対して読み取りと書き込みを行う可能性があります。 プロセスは従来、独自のプロセスメモリスペースにのみアクセスできるように制限されていましたが、共有メモリを使用すると、プロセス間でデータを共有できるため、そのデータを含むプロセス間でメッセージを送信する必要がなくなります。 メモリを介して直接データを共有すると、ディスクやソケット、またはデータのシリアル化/逆シリアル化とコピーを必要とするその他の通信を介してデータを共有する場合と比較して、パフォーマンスが大幅に向上します。

class multiprocessing.shared_memory.SharedMemory(name=None, create=False, size=0)

新しい共有メモリブロックを作成するか、既存の共有メモリブロックに接続します。 各共有メモリブロックには一意の名前が割り当てられます。 このようにして、1つのプロセスが特定の名前で共有メモリブロックを作成し、別のプロセスが同じ名前を使用して同じ共有メモリブロックに接続できます。

プロセス間でデータを共有するためのリソースとして、共有メモリブロックは、それらを作成した元のプロセスよりも長持ちする場合があります。 1つのプロセスが、他のプロセスが引き続き必要とする可能性のある共有メモリブロックにアクセスする必要がなくなった場合は、 close()メソッドを呼び出す必要があります。 どのプロセスでも共有メモリブロックが不要になった場合は、 unlink()メソッドを呼び出して、適切なクリーンアップを確保する必要があります。

name は、要求された共有メモリの一意の名前であり、文字列として指定されます。 新しい共有メモリブロックを作成するときに、名前にNone(デフォルト)を指定すると、新しい名前が生成されます。

create は、新しい共有メモリブロックを作成するか(True)、既存の共有メモリブロックを接続するか(False)を制御します。

size は、新しい共有メモリブロックを作成するときに要求されるバイト数を指定します。 一部のプラットフォームは、そのプラットフォームのメモリページサイズに基づいてメモリのチャンクを割り当てることを選択するため、共有メモリブロックの正確なサイズは、要求されたサイズ以上になる場合があります。 既存の共有メモリブロックに接続する場合、sizeパラメータは無視されます。

close()

このインスタンスから共有メモリへのアクセスを閉じます。 リソースの適切なクリーンアップを確実にするために、インスタンスが不要になったら、すべてのインスタンスがclose()を呼び出す必要があります。 close()を呼び出しても、共有メモリブロック自体は破棄されないことに注意してください。

unlink()

基になる共有メモリブロックを破棄するように要求します。 リソースを適切にクリーンアップするには、共有メモリブロックを必要とするすべてのプロセスでunlink()を1回(1回だけ)呼び出す必要があります。 破棄を要求した後、共有メモリブロックはすぐに破棄される場合とされない場合があり、この動作はプラットフォーム間で異なる場合があります。 unlink()が呼び出された後に共有メモリブロック内のデータにアクセスしようとすると、メモリアクセスエラーが発生する可能性があります。 注:共有メモリブロックの保持を放棄する最後のプロセスは、unlink()および close()をいずれかの順序で呼び出すことができます。

buf

共有メモリブロックの内容のメモリビュー。

name

共有メモリブロックの一意の名前への読み取り専用アクセス。

size

共有メモリブロックのサイズ(バイト単位)への読み取り専用アクセス。

次の例は、 SharedMemory インスタンスの低レベルの使用法を示しています。

>>> from multiprocessing import shared_memory
>>> shm_a = shared_memory.SharedMemory(create=True, size=10)
>>> type(shm_a.buf)
<class 'memoryview'>
>>> buffer = shm_a.buf
>>> len(buffer)
10
>>> buffer[:4] = bytearray([22, 33, 44, 55])  # Modify multiple at once
>>> buffer[4] = 100                           # Modify single byte at a time
>>> # Attach to an existing shared memory block
>>> shm_b = shared_memory.SharedMemory(shm_a.name)
>>> import array
>>> array.array('b', shm_b.buf[:5])  # Copy the data into a new array.array
array('b', [22, 33, 44, 55, 100])
>>> shm_b.buf[:5] = b'howdy'  # Modify via shm_b using bytes
>>> bytes(shm_a.buf[:5])      # Access via shm_a
b'howdy'
>>> shm_b.close()   # Close each SharedMemory instance
>>> shm_a.close()
>>> shm_a.unlink()  # Call unlink only once to release the shared memory

次の例は、 SharedMemory クラスと NumPy配列の実際の使用法を示し、2つの異なるPythonシェルから同じnumpy.ndarrayにアクセスします。

>>> # In the first Python interactive shell
>>> import numpy as np
>>> a = np.array([1, 1, 2, 3, 5, 8])  # Start with an existing NumPy array
>>> from multiprocessing import shared_memory
>>> shm = shared_memory.SharedMemory(create=True, size=a.nbytes)
>>> # Now create a NumPy array backed by shared memory
>>> b = np.ndarray(a.shape, dtype=a.dtype, buffer=shm.buf)
>>> b[:] = a[:]  # Copy the original data into shared memory
>>> b
array([1, 1, 2, 3, 5, 8])
>>> type(b)
<class 'numpy.ndarray'>
>>> type(a)
<class 'numpy.ndarray'>
>>> shm.name  # We did not specify a name so one was chosen for us
'psm_21467_46075'

>>> # In either the same shell or a new Python shell on the same machine
>>> import numpy as np
>>> from multiprocessing import shared_memory
>>> # Attach to the existing shared memory block
>>> existing_shm = shared_memory.SharedMemory(name='psm_21467_46075')
>>> # Note that a.shape is (6,) and a.dtype is np.int64 in this example
>>> c = np.ndarray((6,), dtype=np.int64, buffer=existing_shm.buf)
>>> c
array([1, 1, 2, 3, 5, 8])
>>> c[-1] = 888
>>> c
array([  1,   1,   2,   3,   5, 888])

>>> # Back in the first Python interactive shell, b reflects this change
>>> b
array([  1,   1,   2,   3,   5, 888])

>>> # Clean up from within the second Python shell
>>> del c  # Unnecessary; merely emphasizing the array is no longer used
>>> existing_shm.close()

>>> # Clean up from within the first Python shell
>>> del b  # Unnecessary; merely emphasizing the array is no longer used
>>> shm.close()
>>> shm.unlink()  # Free and release the shared memory block at the very end
class multiprocessing.managers.SharedMemoryManager([address[, authkey]])

プロセス間で共有メモリブロックを管理するために使用できる BaseManager のサブクラス。

SharedMemoryManager インスタンスで start()を呼び出すと、新しいプロセスが開始されます。 この新しいプロセスの唯一の目的は、プロセスを通じて作成されたすべての共有メモリブロックのライフサイクルを管理することです。 そのプロセスによって管理されているすべての共有メモリブロックの解放をトリガーするには、インスタンスで shutdown()を呼び出します。 これにより、そのプロセスによって管理されているすべての SharedMemory オブジェクトでSharedMemory.unlink()呼び出しがトリガーされ、プロセス自体が停止します。 SharedMemoryManagerを介してSharedMemoryインスタンスを作成することにより、共有メモリリソースの解放を手動で追跡およびトリガーする必要がなくなります。

このクラスは、 SharedMemory インスタンスを作成および返すためのメソッドと、共有メモリに裏打ちされたリストのようなオブジェクト( ShareableList )を作成するためのメソッドを提供します。

継承されたアドレスおよび authkey オプションの入力引数の説明と、それらを使用して既存のSharedMemoryManager他のプロセスからのサービス。

SharedMemory(size)

指定されたsizeをバイト単位で含む新しい SharedMemory オブジェクトを作成して返します。

ShareableList(sequence)

入力sequenceからの値によって初期化された、新しい ShareableList オブジェクトを作成して返します。

次の例は、SharedMemoryManagerの基本的なメカニズムを示しています。

>>> from multiprocessing.managers import SharedMemoryManager
>>> smm = SharedMemoryManager()
>>> smm.start()  # Start the process that manages the shared memory blocks
>>> sl = smm.ShareableList(range(4))
>>> sl
ShareableList([0, 1, 2, 3], name='psm_6572_7512')
>>> raw_shm = smm.SharedMemory(size=128)
>>> another_sl = smm.ShareableList('alpha')
>>> another_sl
ShareableList(['a', 'l', 'p', 'h', 'a'], name='psm_6572_12221')
>>> smm.shutdown()  # Calls unlink() on sl, raw_shm, and another_sl

次の例は、 with ステートメントを介してSharedMemoryManagerオブジェクトを使用し、すべての共有メモリブロックが不要になった後に解放されるようにするための潜在的により便利なパターンを示しています。

>>> with SharedMemoryManager() as smm:
...     sl = smm.ShareableList(range(2000))
...     # Divide the work among two processes, storing partial results in sl
...     p1 = Process(target=do_work, args=(sl, 0, 1000))
...     p2 = Process(target=do_work, args=(sl, 1000, 2000))
...     p1.start()
...     p2.start()  # A multiprocessing.Pool might be more efficient
...     p1.join()
...     p2.join()   # Wait for all work to complete in both processes
...     total_result = sum(sl)  # Consolidate the partial results now in sl

with ステートメントでSharedMemoryManagerを使用する場合、そのマネージャーを使用して作成された共有メモリブロックは、 with ステートメントのコードブロックの実行が終了するとすべて解放されます。

class multiprocessing.shared_memory.ShareableList(sequence=None, *, name=None)

内部に格納されているすべての値が共有メモリブロックに格納されている、変更可能なリストのようなオブジェクトを提供します。 これにより、保存可能な値がintfloatboolstr(それぞれ10Mバイト未満)、bytes(未満)のみに制限されます。それぞれ1,000万バイト以上)、およびNone組み込みデータ型。 また、これらのリストは全体の長さを変更できないという点で、組み込みのlistタイプとは著しく異なります(つまり、 追加、挿入などはありません)、スライスによる新しい SharedList インスタンスの動的作成をサポートしていません。

sequence は、値でいっぱいの新しいShareableListを設定する際に使用されます。 Noneに設定すると、代わりに既存のShareableListに一意の共有メモリ名で接続されます。

name は、 SharedMemory の定義で説明されているように、要求された共有メモリの一意の名前です。 既存のShareableListに接続する場合は、sequenceNoneに設定したまま、共有メモリブロックの一意の名前を指定してください。

count(value)

valueの出現回数を返します。

index(value)

valueの最初のインデックス位置を返します。 valueが存在しない場合、 ValueError を発生させます。

format

現在保存されているすべての値で使用される struct パッキング形式を含む読み取り専用属性。

shm

値が格納されている SharedMemory インスタンス。

次の例は、 SharedList インスタンスの基本的な使用法を示しています。

>>> from multiprocessing import shared_memory
>>> a = shared_memory.ShareableList(['howdy', b'HoWdY', -273.154, 100, None, True, 42])
>>> [ type(entry) for entry in a ]
[<class 'str'>, <class 'bytes'>, <class 'float'>, <class 'int'>, <class 'NoneType'>, <class 'bool'>, <class 'int'>]
>>> a[2]
-273.154
>>> a[2] = -78.5
>>> a[2]
-78.5
>>> a[2] = 'dry ice'  # Changing data types is supported as well
>>> a[2]
'dry ice'
>>> a[2] = 'larger than previously allocated storage space'
Traceback (most recent call last):
  ...
ValueError: exceeds available storage for existing str
>>> a[2]
'dry ice'
>>> len(a)
7
>>> a.index(42)
6
>>> a.count(b'howdy')
0
>>> a.count(b'HoWdY')
1
>>> a.shm.close()
>>> a.shm.unlink()
>>> del a  # Use of a ShareableList after call to unlink() is unsupported

次の例は、1つ、2つ、または多くのプロセスが、背後にある共有メモリブロックの名前を指定することにより、同じ SharedableList にアクセスする方法を示しています。

>>> b = shared_memory.ShareableList(range(5))         # In a first process
>>> c = shared_memory.ShareableList(name=b.shm.name)  # In a second process
>>> c
ShareableList([0, 1, 2, 3, 4], name='...')
>>> c[-1] = -999
>>> b[-1]
-999
>>> b.shm.close()
>>> c.shm.close()
>>> c.shm.unlink()