我已经编写了一个神经网络分类器,它接收大量图像(每个图像约1-3gb),对它们进行修补,然后将这些补丁分别通过网络。训练进行得很慢,所以我对它进行了基准测试,发现从一个图像将补丁加载到内存中需要大约50秒(使用Openslide library),而通过模型只需要大约0.5秒。在
然而,我正在研制一台拥有1.5Tb内存的超级计算机,其中只有26GB的内存被利用。数据集总计约500Gb。我的想法是,如果我们能够将整个数据集加载到内存中,它将大大加快训练速度。但是我和一个研究团队合作,我们正在多个Python脚本上进行实验。所以理想情况下,我希望在一个脚本中将整个数据集加载到内存中,并能够跨所有脚本访问它。在
更多详情:
.tif
格式存储。在我发现了很多关于如何在多个Python脚本之间共享Python对象或内存中的原始数据的帖子:
在多处理模块| Example 1| Example 2| Docs - Server Processes| Docs - SyncManagers中使用SyncManager和BaseManager的服务器进程
Manager
对象在发送对象之前对其进行pickle处理,这可能会降低速度。在mmap
将文件映射到virtual memory, not physical memory-它创建了一个临时文件。在Python的sysv_ipc模块。This demo看起来很有前途。在
multi-processing
模块中可用的lower level exposure?在我还发现了Python中IPC/networking的this list选项。在
有些讨论服务器-客户机设置,有些讨论序列化/反序列化,这恐怕比从磁盘读取要花更长的时间。我找到的答案中没有一个能解决我的问题,即这些问题是否会导致I/O性能的提高
我们不仅需要跨脚本共享Python对象/内存,还需要跨Docker容器共享它们。在
Docker documentation很好地解释了--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
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
我认为}的解决方案是合适的。在
shared memory
或{共享内存:
第一次读取服务器进程内存中的数据集。对于python,只需使用
multiprocessing
包装器在进程之间的共享内存中创建对象,例如:multiprocessing.Value或{a2},然后创建进程并将共享对象作为参数传递。在mmap:
将数据集存储在主机上的文件中。然后每个容器将文件装入容器中。如果一个容器打开该文件并将其映射到其虚拟内存中,那么当打开该文件时,另一个容器将不需要将该文件从磁盘读取到内存,因为该文件已经在物理内存中。在
另外,我不确定cpython如何实现进程之间的大共享内存,可能cpython共享内存使用
mmap
内部。在我建议您尝试使用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
。在相关问题 更多 >
编程相关推荐