如今的cpu都很强大,比方我用的至强2620有24核能够同时工做,并行执行进程程序。这在计算密集型的程序是很须要的,如沙漠中的绿洲,使人重获新生。那么,问题接踵而来,python中多进程可否共享一个变量,由于我须要更新矩阵。python
个人办法是用list存储三元组信息,信息包括矩阵位置以及value。那么首先咱们设定一个全局变量叫result_list就能够了?安全
答案是NO.app
进程间共享变量就须要独立开辟一块内存空间或是文件共享,在python里很方面,直接用一个模块能够解决这个问题,那就是 multiprocessing 里的 Manager。固然,这是针对咱们须要的是list而言,若是咱们只是共享一个简单的变量如一个整数,能够直接用 multiprocessing 里的 value。async
下面的实例是怎么去共享变量。函数
from multiprocessing import Process, Manager, Lock import os lock = Lock() manager = Manager() sum = manager.list() def testFunc(cc, lock): with lock: sum.append(1) if __name__ == '__main__': threads = [] for ll in range(1000): t = Process(target=testFunc, args=(1, lock)) t.daemon = True threads.append(t) sum = manager.list() for i in range(len(threads)): threads[i].start() for j in range(len(threads)): threads[j].join() print "------------------------" print 'process id:', os.getpid() print sum
很简单,manager这个模块实现了开辟一块共享内存空间,就比如c中的 shmget 方法同样,有兴趣的同窗能够去查阅。 传送门spa
这样简单的处理并不能知足我。
首先,我须要一个线程池,固然,实现线程池也是很是简单的。可是就会遇到一个问题。线程
lock = multiprocessing.Lock() pool = multiprocessing.Pool(processes=3) for i in range(0,3): pool.apply_async(child_worker, ((my_parameter, lock),)) pool.close() pool.join()
以上代码执行时会出错。code
RuntimeError: Lock objects should only be shared between processes through inheritance
查了下资料,multiprocessing.Manager()返回的manager对象控制了一个server进程,可用于多进程之间的安全通讯,其支持的类型有list,dict,Namespace,Lock,RLock,Semaphore,BoundedSemaphore,Condition,Event,Queue,Value和Array等。 server
因此代码修改为这样后就能够正常运行了:对象
lock = multiprocessing.Manager().Lock() pool = multiprocessing.Pool(processes=3) for i in range(0,3): pool.apply_async(child_worker, ((my_parameter, lock),)) pool.close() pool.join()
因此,lock的问题解决了,真是厉害咱们如今能够充分地(往死里)用咱们的电脑了。
But,还不够,我想要屡次执行这个并行化计算sum的函数。也就是说我须要每次去清空result_list的内容,这个但是一个很关键的细节,由于这个须要明白一个细节,你不能用sum = [] 这样的方式去重置,我我的认为是局部变量的缘由,我后来找到了del sum[:]的方法,解决了个人大问题,so,final version 以下。
from multiprocessing import Process, Manager,Pool import os lock = Manager().Lock() manager = Manager() sum = manager.list() def testFunc(cc, lock): with lock: sum.append(1) # 配合 multiprocessing pool 对多参数的要求添加的函数 def multi_test(args): testFunc(*args) def testing(): threads = [] _pool = Pool(24) del sum[:] lst_vars = [] for shot in range(1000): lst_vars.append((1,lock)) _pool.map(multi_test, lst_vars) _pool.close() _pool.join() print "------------------------" print 'process id:', os.getpid() print sum if __name__ == '__main__': testing() testing()
这些实例是我方便写博客想的,其实我是在写一个大工程遇到了这些个问题,忙的我焦头烂额,可是总结出了人生经验,但愿帮到你,让你多活几年~~