繁体   English   中英

在python中使用线程化/多重处理来同时进行多个计算

[英]Using threading/multiprocessing in python to do multiple calculations at the same time

我有一个数字清单。 我想对列表中的每个数字执行一些耗时的操作,并使用所有结果创建一个新列表。 这是我所拥有的简化版本:

def calcNum(n):#some arbitrary, time-consuming calculation on a number
  m = n
  for i in range(5000000):
    m += i%25
    if m > n*n:
      m /= 2
  return m

nums = [12,25,76,38,8,2,5]
finList = []

for i in nums:
  return_val = calcNum(i)
  finList.append(return_val)

print(finList)

现在,我想利用CPU中的多个内核,并给每个内核一个处理一个数字的任务,并且由于“数字计算”功能自始至终都是自包含的,所以我认为这是相当简单,并且是多处理/线程的理想情况。

我的问题是,应该使用哪一个(多处理或线程处理?),最简单的方法是什么?

我用在其他问题中发现的各种代码进行了测试,以实现此目的,尽管它运行良好,但似乎并没有进行任何实际的多线程/处理,并且所需的时间与我的第一个测试一样长:

from multiprocessing.pool import ThreadPool

def calcNum(n):#some arbitrary, time-consuming calculation on a number
  m = n
  for i in range(5000000):
    m += i%25
    if m > n*n:
      m /= 2
  return m

pool = ThreadPool(processes=3)

nums = [12,25,76,38,8,2,5]
finList = []

for i in nums:
  async_result = pool.apply_async(calcNum, (i,))
  return_val = async_result.get()
  finList.append(return_val)

print(finList)

multiprocessing.poolpool.map是您最好的朋友。 它隐藏了所有其他复杂的队列,使您省去了很多麻烦。 您所需要做的就是设置池,为其分配最大进程数,将其指向该函数并且可迭代。 请参阅下面的工作代码。

由于该join和用例pool.map可以正常工作,因此该程序将等到所有进程都返回某些内容后再给出结果。

from multiprocessing.pool import Pool

def calcNum(n):#some arbitrary, time-consuming calculation on a number
  print "Calcs Started on ", n
  m = n
  for i in range(5000000):
    m += i%25
    if m > n*n:
      m /= 2
  return m

if __name__ == "__main__":
  p = Pool(processes=3)

  nums = [12,25,76,38,8,2,5]
  finList = []


  result = p.map(calcNum, nums)
  p.close()
  p.join()

  print result

那会给你这样的东西:

Calcs Started on  12
Calcs Started on  25
Calcs Started on  76
Calcs Started on  38
Calcs Started on  8
Calcs Started on  2
Calcs Started on  5
[72, 562, 5123, 1270, 43, 23, 23]

无论何时启动每个进程或何时完成,map都会等待每个进程完成,然后将它们全部以正确的顺序放回去(对应于可迭代的输入)。

正如@Guy所提到的,GIL在这里伤害了我们。 您可以在上面的代码中将Pool更改为ThreadPool ,并查看它如何影响计算时间。 由于使用了相同的函数,因此GIL仅允许一个线程一次使用calcNum函数。 因此它足够接近仍可以串行运行。 Multirocessingprocesspool本质上开始你的脚本,它周围的GIL的问题得到进一步的实例。 如果您在上述期间观察正在运行的进程,则将在池运行时看到“ python.exe”的其他实例启动。 在这种情况下,您会看到总数为4。

我想您会受到python Global Interpreter Lock的影响

GIL之所以引起争议,是因为它在某些情况下阻止多线程CPython程序充分利用多处理器系统。

尝试改用多处理

from multiprocessing import Pool

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM