我正在考虑创建一个numpy表作为键/值数据库。 输入/更新将是多头的。
探索这个想法, 问题:GIL会阻止theads并且只允许一次更新。 问题:可以将numpy table(tablespace)变成红色。
答案 0 :(得分:4)
一些numpy函数不是原子的,所以如果两个线程通过调用一些非原子numpy函数在同一个数组上运行,那么该数组将会被破坏,因为操作的顺序会混淆在一些非预期的办法。
有很多例子,但具体来说,numpy.apply_along_axis是一长串的Python语句,显然不是原子的。
GIL不会帮助你,因为它可以阻止一个线程,而它只是部分通过一些非原子numpy函数,然后启动另一个在相同阵列上运行的线程......
因此,为了保证线程安全,您需要使用threading.Lock
并且仅在获取Lock之后对阵列进行操作:
with lock:
arr = ...
必须在任何地方使用锁都会让人质疑让多个线程在同一个阵列上运行是否有任何好处。请注意,有时 多线程处理CPU绑定问题may result in slower performance,而不是类似的单线程版本。
另请参阅ParallelProgramming with numpy and scipy wiki page以获取更多选择和讨论。
答案 1 :(得分:1)
我只是需要这样所以我写了.. 现在去尝试,所以不确定它是否按预期工作..
class LockedNumpyArray(object):
"""
Thread safe numpy array
"""
def __init__(self):
self.lock = threading.Lock()
self.val = None
def __get__(self, obj, objtype):
self.lock.acquire()
if self.val != None:
ret_val = self.val.copy()
else:
ret_val = None
self.lock.release()
# print('getting', ret_val)
return ret_val
def __set__(self, obj, val):
self.lock.acquire()
# print('setting', val)
self.val = val.copy()
self.lock.release()
这是numpy数组的类。然后我有一个控制类,因为后来我想让更多线程安全的numpy数组运行。
class CaptureControl():
"""
Shared class to control source capture execution
"""
frame = LockedNumpyArray()
def __init__(self):
print(self.frame)
self.frame = np.array([2])
print(self.frame)
最后,我将此CaptureControl类的一个实例放入线程中,如下所示。
class CaptureThread(threading.Thread):
"""
Thread running source capturing
"""
def __init__(self, capture_control):
threading.Thread.__init__(self)
self.capture_control = capture_control
self.sleepTime = 0.01
def run(self):
while True:
self.capture_control.capture_frame()
time.sleep(self.sleepTime)
if __name__ == '__main__':
capture_control = CaptureControl()
capture_thread = CaptureThread(capture_control)
capture_thread.start()
如果有人对此解决方案有任何想法,我会很高兴,不包括线程运行功能中的time.sleep,因为这只是一个例子;)。