Python多线程并行学习

Introduction:

因为效率需求,需要将一个单进程的Monte Carlo程序并行化处理。众所周知,Monte Carlo算法天生易于并行,然而主要的问题在于,所有的子进程运行时需要读取一个大小为几个GB的ndarray object,该对象由10^4量级个长度不同的子数组(同样为ndarray object)封装而成。所以,本文需要解决的问题在于,如何在考虑到内存优化的同时最简单的实现多线程并行?

Possible solutions:

  1. 使用多线程,从而共享内存
  2. 使用multiprocessing module 自带的内存共享方法Value 和 Array(例子),但是由于本问题中共享ndarray 对象的子数组长度不对齐,难以利用ctypes 的Array 封装。
  3. 使用multiprocessing module自带的第二种内存共享方法Manager(文档)。该方法适用于任意的对象,通过进程锁确保数据安全性,但是据说费时。用于read-only object 似乎有点浪费。
  4. 使用Linux系统。在Linux系统中multiprocessing 调用系统的fork() 程序来实现多进程,由于Linux 的Copy-on-Write 特性,子例程对于read-only 对象不会复制新的对象。

Tests:

利用同样的代码段,在windows 和Linux 平台分别测试:

from multiprocessing import Pool
import numpy as np

shared_mem = np.arange(10)

def target_fun(x, a=shared_mem):
    return "input x: "+str(x)+"; len(a) = "+str(len(a))+"; id(a) = "+str(id(a))

if __name__ == '__main__':
    # shared_mem = np.arange(10)

    inputs = list(range(10))
    pool = Pool(processes=4)
    res = pool.map(target_fun, inputs)
    pool.close()
    pool.join()

    for i in res:
        print(i)

Windows:

results:

input x: 0; len(a) = 10; id(a) = 2152628373184
input x: 1; len(a) = 10; id(a) = 1822852007536
input x: 2; len(a) = 10; id(a) = 1366939551344
input x: 3; len(a) = 10; id(a) = 2152628373184
input x: 4; len(a) = 10; id(a) = 1366939551344
input x: 5; len(a) = 10; id(a) = 2483693766176
input x: 6; len(a) = 10; id(a) = 1748360250992
input x: 7; len(a) = 10; id(a) = 1822852007536
input x: 8; len(a) = 10; id(a) = 2152628373184
input x: 9; len(a) = 10; id(a) = 2483693766176

Linux:

results:

input x: 0; len(a) = 10; id(a) = 47359601904656
input x: 1; len(a) = 10; id(a) = 47359601904656
input x: 2; len(a) = 10; id(a) = 47359601904656
input x: 3; len(a) = 10; id(a) = 47359601904656
input x: 4; len(a) = 10; id(a) = 47359601904656
input x: 5; len(a) = 10; id(a) = 47359601904656
input x: 6; len(a) = 10; id(a) = 47359601904656
input x: 7; len(a) = 10; id(a) = 47359601904656
input x: 8; len(a) = 10; id(a) = 47359601904656
input x: 9; len(a) = 10; id(a) = 47359601904656

注意这里的共享对象必须对子进程是可见的,即 shared_mem 的赋值必须在

if __name__ == '__main__':

前面。

Final solution:

from multiprocessing import Pool
import numpy as np

shared_mem = reader()

def target_fun(x):
    do_chunk(shared_mem)
    return res

if __name__ == '__main__':
    pool = Pool(processes=N)
    
    inputs = segemt()
    res = pool.map(target_fun, inputs)
    pool.close()
    pool.join()

    do_analysis(res)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值