Python共享读内存

6
我正在处理一个大小为 ~8GB 的数据集,同时我还在使用scikit-learn对其进行各种机器学习模型的训练。该数据集基本上是由整数一维向量列表组成。
如何使多个Python进程可以访问该数据集,或者如何对数据集进行编码以便可以使用multiprocessing的类呢?我一直在阅读ctypes和multiprocessing的文档,但我非常困惑。我只需要使每个进程都能读取数据,以便我可以用它进行模型训练。
我需要将共享的multiprocessing变量设置为ctypes吗?
如何用ctypes表示数据集?
2个回答

3
我假设您能够将整个数据集加载到numpy数组中,并且您正在使用Linux或Mac。 (如果您在Windows上或无法将数组放入RAM中,则应该将数组复制到磁盘上的文件中,并使用numpy.memmap来访问它。您的计算机将尽可能将数据从磁盘缓存到RAM中,并且这些缓存将在进程之间共享,因此这不是一个糟糕的解决方案。)
在上述假设下,如果您需要通过multiprocessing创建的其他进程对数据集进行只读访问,您可以简单地创建数据集,然后启动其他进程。他们将从原始命名空间中读取数据。他们可以更改原始命名空间中的数据,但这些更改不会对其他进程可见(内存管理器将每个更改的内存段复制到本地内存映射中)。
如果您的其他进程需要更改原始数据集并使这些更改对父进程或其他进程可见,您可以使用类似于以下内容的东西:
import multiprocessing
import numpy as np

# create your big dataset
big_data = np.zeros((3, 3))

# create a shared-memory wrapper for big_data's underlying data
# (it doesn't matter what datatype we use, and 'c' is easiest)
# I think if lock=True, you get a serialized object, which you don't want.
# Note: you will need to setup your own method to synchronize access to big_data.
buf = multiprocessing.Array('c', big_data.data, lock=False)

# at this point, buf and big_data.data point to the same block of memory, 
# (try looking at id(buf[0]) and id(big_data.data[0])) but for some reason
# changes aren't propagated between them unless you do the following:
big_data.data = buf

# now you can update big_data from any process:
def add_one_direct():
    big_data[:] = big_data + 1

def add_one(a):
    # People say this won't work, since Process() will pickle the argument.
    # But in my experience Process() seems to pass the argument via shared
    # memory, so it works OK.
    a[:] = a+1

print "starting value:"
print big_data

p = multiprocessing.Process(target=add_one_direct)
p.start()
p.join()

print "after add_one_direct():"
print big_data

p = multiprocessing.Process(target=add_one, args=(big_data,))
p.start()
p.join()

print "after add_one():"
print big_data

1

可能是在多进程之间共享大型只读Numpy数组的重复问题

您可以将数据集从当前表示转换为新的numpy memmap对象,并从每个进程中使用它。但无论如何,它都不会很快,它只是提供了一些抽象,使得可以从内存中处理数组,在现实中它将是来自HDD的文件,部分缓存在RAM中。因此,您应该优先选择具有partial_fit方法的scikit-learn算法,并使用它们。

https://docs.scipy.org/doc/numpy/reference/generated/numpy.memmap.html

实际上,joblib(用于并行化的scikit-learn库)会自动将您的数据集转换为memmap表示形式,以便从不同的进程中使用它(如果足够大的话)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接