Python 计算特征值的多重处理

Python 计算特征值的多重处理,python,python-multiprocessing,Python,Python Multiprocessing,我正在生成100个随机整数矩阵,大小1000x1000。我正在使用多处理模块来计算100个矩阵的特征值 代码如下: import timeit import numpy as np import multiprocessing as mp def calEigen(): S, U = np.linalg.eigh(a) def multiprocess(processes): pool = mp.Pool(processes=processes) #Start timing here

我正在生成100个随机整数矩阵,大小
1000x1000
。我正在使用多处理模块来计算100个矩阵的特征值

代码如下:

import timeit
import numpy as np
import multiprocessing as mp

def calEigen():

 S, U = np.linalg.eigh(a)

def multiprocess(processes):
 pool = mp.Pool(processes=processes)
 #Start timing here as I don't want to include time taken to initialize the processes
 start = timeit.default_timer()
 results = [pool.apply_async(calEigen, args=())]
 stop = timeit.default_timer()
 print (processes":", stop - start) 

 results = [p.get() for p in results]
 results.sort() # to sort the results 


if __name__ == "__main__":

 global a
 a=[]

 for i in range(0,100):
  a.append(np.random.randint(1,100,size=(1000,1000)))

 #Print execution time without multiprocessing
 start = timeit.default_timer()
 calEigen()
 stop = timeit.default_timer()
 print stop - start 

 #With 1 process
 multiprocess(1)

 #With 2 processes
 multiprocess(2)

 #With 3 processes
 multiprocess(3)

 #With 4 processes
 multiprocess(4)
输出是

0.510247945786
('Process:', 1, 5.1021575927734375e-05)
('Process:', 2, 5.698204040527344e-05)
('Process:', 3, 8.320808410644531e-05)
('Process:', 4, 7.200241088867188e-05)
另一次迭代显示了以下输出:

 69.7296020985
 ('Process:', 1, 0.0009050369262695312)
 ('Process:', 2, 0.023727893829345703)
 ('Process:', 3, 0.0003509521484375)
 ('Process:', 4, 0.057518959045410156)
我的问题是:

  • 为什么执行时间不随着执行次数的增加而减少 进程增加?我是否正确使用多处理模块
  • 我是否正确计算了执行时间 我已经编辑了下面评论中给出的代码。我想让串行和多处理函数找到100个矩阵的相同列表的特征值。编辑的代码是-

    import numpy as np
    import time
    from multiprocessing import Pool
    
    a=[]
    
    for i in range(0,100):
     a.append(np.random.randint(1,100,size=(1000,1000)))
    
    def serial(z):
     result = []
     start_time = time.time()
     for i in range(0,100):    
      result.append(np.linalg.eigh(z[i])) #calculate eigen values and append to result list
     end_time = time.time()
     print("Single process took :", end_time - start_time, "seconds")
    
    
    def caleigen(c):  
     result = []        
     result.append(np.linalg.eigh(c)) #calculate eigenvalues and append to result list
     return result
    
    def mp(x):
     start_time = time.time()
     with Pool(processes=x) as pool:  # start a pool of 4 workers
      result = pool.map_async(caleigen,a)   # distribute work to workers
      result = result.get() # collect result from MapResult object
     end_time = time.time()
     print("Mutltiprocessing took:", end_time - start_time, "seconds" )
    
    if __name__ == "__main__":
    
     serial(a)
     mp(1,a)
     mp(2,a)
     mp(3,a)
     mp(4,a)
    

    随着进程数量的增加,时间不会减少。我哪里做错了?多处理是将列表划分为进程块还是我必须进行划分

    您没有正确使用多处理模块。正如@dopstar所指出的,您并不是在分配任务。流程池只有一个任务,因此无论您分配了多少工人,只有一个工人将获得该工作。至于你的第二个问题,我没有使用
    timeit
    来精确测量过程时间。我只是使用
    time
    模块粗略地了解事情的发展速度。不过,它在大多数情况下都起到了作用。如果我理解您试图正确执行的操作,那么这应该是您代码的单进程版本

    import numpy as np
    import time
    
    result = []
    start_time = time.time()
    for i in range(100):
        a = np.random.randint(1, 100, size=(1000,1000))  #generate random matrix
        result.append(np.linalg.eigh(a))                 #calculate eigen values and append to result list
    end_time = time.time()
    print("Single process took :", end_time - start_time, "seconds")
    
    单进程版本在我的计算机上花费了15.27秒。下面是多进程版本,在我的计算机上只花了0.46秒。我还包括了用于比较的单进程版本。(单进程版本也必须包含在
    if
    块中,并放在多进程版本之后。)因为您想重复计算100次,创建一个工作人员池并让他们自动完成未完成的任务要比手动启动每个流程并指定每个流程应该做什么容易得多。在我的代码中,
    caleigen
    调用的参数仅仅是跟踪任务执行了多少次。最后,
    map\u async
    通常比
    apply\u async
    快,其缺点是占用的内存稍多,函数调用只使用一个参数。使用
    map\u async
    而不是
    map
    的原因是,在这种情况下,返回结果的顺序无关紧要,
    map\u async
    map
    快得多

    from multiprocessing import Pool
    import numpy as np
    import time
    
    def caleigen(x):     # define work for each worker
        a = np.random.randint(1,100,size=(1000,1000))   
        S, U = np.linalg.eigh(a)                        
        return S, U
    
    
    if __name__ == "main":
        start_time = time.time()
        with Pool(processes=4) as pool:      # start a pool of 4 workers
            result = pool.map_async(caleigen, range(100))   # distribute work to workers
            result = result.get()        # collect result from MapResult object
        end_time = time.time()
        print("Mutltiprocessing took:", end_time - start_time, "seconds" )
    
        # Run the single process version for comparison. This has to be within the if block as well. 
        result = []
        start_time = time.time()
        for i in range(100):
            a = np.random.randint(1, 100, size=(1000,1000))  #generate random matrix
            result.append(np.linalg.eigh(a))                 #calculate eigen values and append to result list
        end_time = time.time()
        print("Single process took :", end_time - start_time, "seconds")
    

    您不是在划分工作并将其分配给流程。因此,问题在于没有合作。它更像是每个进程都在自己完成完整的计算,如果有更多的进程同时做同一件事,那么它的速度会比一个进程同时做同一件事时慢,这是因为CPU负载比一个进程做这件事时要多。如果你把你的工作分配给你的工人,应该会更快;但是,我的多处理机器无法进行多处理。需要0.s:)代码在您的计算机上运行吗?是的,它在我的计算机上运行。这就是我测量时间的方法;)似乎
    if uuuu name_uuu==“main”:
    块没有在您的计算机上运行。这很可能是因为您没有将其作为主进程运行。(这正是该生产线正在测试的条件)。你是如何测试代码的?您应该将上述文本保存在一个.py文件中,然后运行该文件。@user3667217我编辑了您的代码,因为我希望串行处理和多处理都能找到相同100个矩阵的特征值。如果要同时执行这两个操作,请先执行
    多处理
    一个操作,还必须将单进程版本放入
    If
    块中。请参阅我的最新答案。您可以尝试不这样做,然后看看会发生什么。@user3667217我编辑了代码以在单个进程之前执行多个处理。时间不会减少。为什么必须在单个进程之前执行多个进程?此外,我是否必须将100个矩阵的列表划分为多处理中每个进程的块?