Can';t使用Python进行大量计算的多处理

Can';t使用Python进行大量计算的多处理,python,numpy,multiprocessing,Python,Numpy,Multiprocessing,我必须加快当前代码的速度,以便在可行的时间内完成大约10^6个操作。在我在实际文档中使用多处理之前,我尝试在模拟案例中使用它。以下是我的尝试: def chunkIt(seq, num): avg = len(seq) / float(num) out = [] last = 0.0 while last < len(seq): out.append(seq[int(last):int(last + avg)]) last

我必须加快当前代码的速度,以便在可行的时间内完成大约10^6个操作。在我在实际文档中使用多处理之前,我尝试在模拟案例中使用它。以下是我的尝试:

def chunkIt(seq, num):
    avg = len(seq) / float(num)
    out = []
    last = 0.0

    while last < len(seq):
        out.append(seq[int(last):int(last + avg)])
        last += avg

    return out
 
def do_something(List):
    # in real case this function takes about 0.5 seconds to finish for each 
    iteration
    turn = []
    for e in List:
        turn.append((e[0]**2, e[1]**2,e[2]**2))
    return turn
    
t1 = time.time()

List = []
#in the real case these 20's can go as high as 150
for i in range(1,20-2):
    for k in range(i+1,20-1):
        for j in range(k+1,20):
            List.append((i,k,j))
            
t3 = time.time() 
test = []    

List = chunkIt(List,3)

if __name__ == '__main__':
    with concurrent.futures.ProcessPoolExecutor() as executor:
        results = executor.map(do_something,List)
        for result in results:
            test.append(result)       
    
test= np.array(test)
t2 = time.time()

T = t2-t1
T2 = t3-t1
def chunkIt(seq,num):
平均值=长度(顺序)/浮动(数量)
out=[]
last=0.0
而最后一个
然而,当我增加我的“列表”的大小时,我的计算机会耗尽我所有的RAM和CPU,并冻结。我甚至把我的“列表”分成3块,这样它只会使用我的3个核心。然而,一切都没有改变。此外,当我试图在较小的数据集上使用它时,我注意到代码运行速度比在单个内核上运行时慢得多。
我对Python中的多处理仍然很陌生,我是否做错了什么。如果您能帮助我,我将不胜感激。

为了减少内存使用,我建议您使用
多处理
模块,特别是方法(或方法)。与
multiprocessing.Pool
concurrent.futures.ProcessPoolExecutor
map
方法不同,iterable参数是惰性处理的。这意味着,如果对iterable参数使用生成器函数或生成器表达式,则不需要在内存中创建完整的参数列表;当池中的处理器空闲并准备执行更多任务时,将调用生成器为
imap
调用生成下一个参数

默认情况下,使用chunksize值1,这对于较大的iterable大小可能是低效的。当对chunksize参数使用
map
和默认值
None
时,池将查看iterable的长度,如有必要,首先将其转换为
列表
,然后根据该长度和池的大小计算它认为有效的chunksize。当使用
imap
imap\u unordered
时,将iterable转换为
列表
将破坏使用该方法的全部目的。但是,如果您知道如果iterable被转换为列表,该大小将是多少(或多或少),那么就没有理由不应用
map
方法将具有的相同chunksize计算,这就是下面所做的

以下基准测试首先执行与单个进程相同的处理,然后使用
imap
使用多处理,其中在我的桌面上每次调用
do\u something
大约需要0.5秒
do_something
现在已被修改为只处理单个i、k、j元组,因为不再需要将任何内容分解为更小的列表:

来自多处理导入池,cpu\u计数
导入时间
def半秒()
半秒迭代次数=10万次
总和=0
对于范围内的(半秒迭代):
总和+=1
回报金额
def do_某事(tpl):
#在实际情况中,每次迭代完成此函数大约需要0.5秒
半秒()#在我的桌面上
返回第三方物流[0]**2,第三方物流[1]**2,第三方物流[2]**2
"""
def生成\u tpls():
对于范围(1,20-2)内的i:
对于范围(i+1,20-1)内的k:
对于范围(k+1,20)内的j:
产量i,k,j
"""
#使用较少数量的元组,以便在合理的时间内完成:
def生成\u tpls():
#64元组:
对于范围(1,5)内的i:
对于范围(1,5)内的k:
对于范围(1,5)内的j:
产量i,k,j
def benchmark1():
“单一处理”
t=time.time()
对于generate_tpls()中的tpl:
结果=做某事(tpl)
打印('benchmark1 time:',time.time()-t)
def compute_chunksize(可分配大小、池大小):
“”“这或多或少是Pool.map方法使用的函数”“”
chunksize,余数=divmod(iterable\u大小,4*池大小)
如果剩余:
chunksize+=1
返回块大小
def benchmark2():
“多进程”
t=time.time()
池大小=cpu计数()#8个逻辑核(4个物理核)
N_TUPLES=64#将生成的元组数
池=池(池大小)
chunksize=compute\u chunksize(N\u元组、池大小)
对于pool.imap中的结果(do_something,generate_tpls(),chunksize=chunksize):
通过
打印('benchmark2 time:',time.time()-t)
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
基准1()
基准2()
印刷品:

benchmark1 time: 32.261038303375244
benchmark2 time: 8.174998044967651

每个子流程都将创建主
列表
变量,然后将其分块-这可能没有帮助。将所有设置代码放入
如果uuuu name_uuuuu==“uuuuu main_uuuuuuu”:
块中,不要使用变量名列表在Python
中它是一个保留名称,当我增加“列表”的大小时,我的计算机会使用我所有的RAM和CPU并冻结
。你的“名单”有多大?使用150x150x150可以列出大约300万个项目,这会使项目的容量增加到大约40MB。我想知道你是否使用了更大的数据集?@JawadAhmadKhan是否有可能你没有正确地使用它。
imap
的参数必须是生成器或生成器表达式。@JawadAhmadKhan I