multiprocessing.shared_memory —プロセス間で直接アクセスするための共有メモリを提供します—Pythonドキュメント
multiprocessing.shared_memory —プロセス間で直接アクセスするための共有メモリを提供します
ソースコード: :source: `Lib / multiprocessing / shared_memory.py`
バージョン3.8の新機能。
このモジュールは、マルチコアまたは対称型マルチプロセッサ(SMP)マシン上の1つ以上のプロセスがアクセスする共有メモリの割り当てと管理のためのクラス SharedMemory を提供します。 特に個別のプロセス間での共有メモリのライフサイクル管理を支援するために、 BaseManager サブクラスSharedMemoryManager
もmultiprocessing.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)
内部に格納されているすべての値が共有メモリブロックに格納されている、変更可能なリストのようなオブジェクトを提供します。 これにより、保存可能な値が
int
、float
、bool
、str
(それぞれ10Mバイト未満)、bytes
(未満)のみに制限されます。それぞれ1,000万バイト以上)、およびNone
組み込みデータ型。 また、これらのリストは全体の長さを変更できないという点で、組み込みのlist
タイプとは著しく異なります(つまり、 追加、挿入などはありません)、スライスによる新しい SharedList インスタンスの動的作成をサポートしていません。sequence は、値でいっぱいの新しい
ShareableList
を設定する際に使用されます。None
に設定すると、代わりに既存のShareableList
に一意の共有メモリ名で接続されます。name は、 SharedMemory の定義で説明されているように、要求された共有メモリの一意の名前です。 既存の
ShareableList
に接続する場合は、sequence
をNone
に設定したまま、共有メモリブロックの一意の名前を指定してください。- 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()