对于复杂对象,没有现成的方法可以直接在进程之间共享内存。如果您有简单的
ctypes
,可以使用C风格的共享内存,但它不能直接映射到Python对象。
如果您每次只需要数据的一部分而不是整个36GB,则有一个简单的解决方案可行。对此,您可以使用
multiprocessing.managers
中的
SyncManager
。使用这个,您设置一个服务器,为您的数据提供代理类(您的数据不存储在类中,代理只提供访问权限)。然后,您的客户端使用
BaseManager
连接到服务器,并调用代理类中的方法来检索数据。
在幕后,
Manager
类负责将您请求的数据进行pickling并通过从服务器到客户端的开放端口发送它。因为您每次调用都要进行pickling数据,所以如果您需要整个数据集,这不是有效率的。如果您只需要客户端数据的一小部分,则该方法可以节省很多时间,因为数据只需由服务器加载一次。
该解决方案在速度上与数据库解决方案相当,但如果您希望保持纯Python解决方案,则可以节省很多复杂性和学习数据库的时间。
以下是一些旨在与GloVe词向量配合使用的示例代码。
服务器端
import sys
from multiprocessing.managers import SyncManager
import numpy
gVectors = {}
class GloVeProxy(object):
def __init__(self):
pass
def getNVectors(self):
global gVectors
return len(gVectors)
def getEmpty(self):
global gVectors
return numpy.zeros_like(gVectors.values()[0])
def getVector(self, word, default=None):
global gVectors
return gVectors.get(word, default)
class GloVeServer(object):
def __init__(self, port, fname):
self.port = port
self.load(fname)
@staticmethod
def load(filename):
global gVectors
f = open(filename, 'r')
for line in f:
vals = line.rstrip().split(' ')
gVectors[vals[0]] = numpy.array(vals[1:]).astype('float32')
def run(self):
class myManager(SyncManager): pass
myManager.register('GloVeProxy', GloVeProxy)
mgr = myManager(address=('', self.port), authkey='GloVeProxy01')
server = mgr.get_server()
server.serve_forever()
if __name__ == '__main__':
port = 5010
fname = '/mnt/raid/Data/Misc/GloVe/WikiGiga/glove.6B.50d.txt'
print 'Loading vector data'
gs = GloVeServer(port, fname)
print 'Serving data. Press <ctrl>-c to stop.'
gs.run()
客户端
from multiprocessing.managers import BaseManager
import psutil
class GloVeClient(object):
def __init__(self, port):
assert self._checkForProcess('GloVeServer.py'), 'Must have GloVeServer running'
class myManager(BaseManager): pass
myManager.register('GloVeProxy')
self.mgr = myManager(address=('localhost', port), authkey='GloVeProxy01')
self.mgr.connect()
self.glove = self.mgr.GloVeProxy()
@staticmethod
def getGloVe(port):
return GloVeClient(port).glove
@staticmethod
def _checkForProcess(name):
for proc in psutil.process_iter():
if proc.name() == name:
return True
return False
if __name__ == '__main__':
port = 5010
glove = GloVeClient.getGloVe(port)
for word in ['test', 'cat', '123456']:
print('%s = %s' % (word, glove.getVector(word)))
请注意,
psutil
库仅用于检查服务器是否正在运行,它不是必需的。请确保将服务器命名为
GloVeServer.py
,或者在代码中更改
psutil
的检查,以便它寻找正确的名称。