[英]IPC shared memory across Python scripts in separate Docker containers
我已經編寫了一個神經網絡分類器,該分類器可以獲取海量圖像(每張圖像約1-3 GB),將其打補丁,然后分別通過網絡傳遞這些補丁。 培訓的進行過程非常緩慢,因此我對其進行了基准測試,發現用大約50秒的時間將補丁從一個圖像加載到內存(使用Openslide庫 ),而僅需0.5秒的時間就可以將它們通過模型。
但是,我正在使用具有1.5Tb RAM的超級計算機,其中僅使用了約26 Gb。 數據集總計約500Gb。 我的想法是,如果我們可以將整個數據集加載到內存中,它將極大地加快訓練速度。 但是我正在與一個研究團隊合作,我們正在多個Python腳本之間進行實驗。 因此,理想情況下,我想將一個腳本中的整個數據集加載到內存中,並能夠在所有腳本中對其進行訪問。
更多細節:
.tif
格式存儲。 我發現了很多關於如何在多個Python腳本之間共享Python對象或內存中的原始數據的文章:
多處理模塊中具有SyncManager和BaseManager的服務器進程| 示例1 | 示例2 | Docs-服務器進程 | 文件-SyncManager
Manager
對象在發送對象之前先對其進行腌制,這可能會使速度變慢。 mmap
將文件映射到虛擬內存,而不是物理內存 -它創建一個臨時文件。 適用於Python的sysv_ipc模塊。 這個演示看起來很有希望。
multi-processing
模塊中可用的功能? 我還在Python中找到了IPC /網絡選項列表 。
有些人討論服務器-客戶端設置,有些人討論序列化/反序列化,這恐怕會比從磁盤讀取花費更多的時間。 我找不到任何答案可以解決我的問題,這些答案是否會導致I / O性能的提高。
我們不僅需要在腳本之間共享Python對象/內存; 我們需要在Docker容器之間共享它們。
Docker 文檔很好地解釋了--ipc
標志。 根據文檔的運行情況,對我來說有意義的是:
docker run -d --ipc=shareable data-server
docker run -d --ipc=container:data-server data-client
但是,當我在如上所述設置--ipc
連接的單獨容器中運行客戶端和服務器時,它們無法相互通信。 我讀過SO問題( 1 , 2 , 3 , 4 )不以單獨的Docker容器Python腳本之間共享存儲器的地址的集成。
docker run --ipc=<mode>
集成在一起? (共享IPC名稱空間甚至是跨Docker容器共享內存的最佳方法嗎?) 這是我在單獨容器中的Python腳本之間共享內存的幼稚方法。 當Python腳本在同一容器中運行時有效,但在單獨的容器中運行時無效。
server.py
from multiprocessing.managers import SyncManager
import multiprocessing
patch_dict = {}
image_level = 2
image_files = ['path/to/normal_042.tif']
region_list = [(14336, 10752),
(9408, 18368),
(8064, 25536),
(16128, 14336)]
def load_patch_dict():
for i, image_file in enumerate(image_files):
# We would load the image files here. As a placeholder, we just add `1` to the dict
patches = 1
patch_dict.update({'image_{}'.format(i): patches})
def get_patch_dict():
return patch_dict
class MyManager(SyncManager):
pass
if __name__ == "__main__":
load_patch_dict()
port_num = 4343
MyManager.register("patch_dict", get_patch_dict)
manager = MyManager(("127.0.0.1", port_num), authkey=b"password")
# Set the authkey because it doesn't set properly when we initialize MyManager
multiprocessing.current_process().authkey = b"password"
manager.start()
input("Press any key to kill server".center(50, "-"))
manager.shutdown
client.py
from multiprocessing.managers import SyncManager
import multiprocessing
import sys, time
class MyManager(SyncManager):
pass
MyManager.register("patch_dict")
if __name__ == "__main__":
port_num = 4343
manager = MyManager(("127.0.0.1", port_num), authkey=b"password")
multiprocessing.current_process().authkey = b"password"
manager.connect()
patch_dict = manager.patch_dict()
keys = list(patch_dict.keys())
for key in keys:
image_patches = patch_dict.get(key)
# Do NN stuff (irrelevant)
當這些腳本在同一容器中運行時,這些腳本可以很好地共享圖像。 但是,當它們在單獨的容器中運行時,如下所示:
# Run the container for the server
docker run -it --name cancer-1 --rm --cpus=10 --ipc=shareable cancer-env
# Run the container for the client
docker run -it --name cancer-2 --rm --cpus=10 --ipc=container:cancer-1 cancer-env
我收到以下錯誤:
Traceback (most recent call last):
File "patch_client.py", line 22, in <module>
manager.connect()
File "/usr/lib/python3.5/multiprocessing/managers.py", line 455, in connect
conn = Client(self._address, authkey=self._authkey)
File "/usr/lib/python3.5/multiprocessing/connection.py", line 487, in Client
c = SocketClient(address)
File "/usr/lib/python3.5/multiprocessing/connection.py", line 614, in SocketClient
s.connect(address)
ConnectionRefusedError: [Errno 111] Connection refused
我建議您嘗試使用tmpfs 。
它是一項Linux功能,可讓您創建一個虛擬文件系統,所有文件系統都存儲在RAM中。 這樣可以非常快速地訪問文件,並且只需設置一個bash命令即可。
除了非常快速和直接之外,它在您的情況下還具有許多優點:
cp
到tmpfs
tmpfs
可以調整頁面並將其交換到硬盤驅動器。 如果您必須在沒有可用RAM的服務器上運行此文件,則可以將所有文件放在具有普通文件系統的硬盤驅動器上,而根本不用觸摸代碼。 使用步驟:
sudo mount -t tmpfs -o size=600G tmpfs /mnt/mytmpfs
cp -r dataset /mnt/mytmpfs
在某些情況下, ramfs
可能比tmpfs
更快,因為它沒有實現頁面交換。 要使用它,只需按照上面的說明將tmpfs
替換為ramfs
。
我認為shared memory
或mmap
解決方案是正確的。
共享內存:
在服務器進程中首先讀取內存中的數據集。 對於python,只需使用multiprocessing
包裝器在進程之間的共享內存中創建對象,例如: multiprocessing.Value或multiprocessing.Array ,然后創建Process並將共享對象作為args傳遞。
mmap:
將數據集存儲在主機上的文件中。 然后,每個容器將文件安裝到容器中。 如果一個容器打開文件並將其映射到其虛擬內存,則另一個容器在打開文件時將不需要從磁盤讀取文件到內存,因為該文件已在物理內存中。
PS我不確定cpython如何在進程之間實現大共享內存,大概cpython共享內存使用mmap
內部。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.