python - 在python中使用threading/multiprocessing同时进行多个计算

标签 python multithreading multiprocessing python-multithreading

我有一个数字列表。我想对列表中的每个数字执行一些耗时的操作,并制作一个包含所有结果的新列表。这是我所拥有的简化版本:

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 是您最好的 friend 。它避免了很多麻烦,因为它隐藏了所有其他复杂的队列以及使它工作所需的其他东西。您需要做的就是设置池,为其分配最大进程数,将其指向函数和可迭代对象。请参阅下面的工作代码。

由于 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 - 在python中使用threading/multiprocessing同时进行多个计算,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21200884/

相关文章:

python - 使用 Python 从 oddsportal.com 抓取数据

c++ - 在另一个线程正在运行的情况下退出应用程序时出错

python - 如何使用多线程 ping 一个 IP 地址范围

multithreading - App Engine Channel API 的线程安全/原子性

python子类化multiprocessing.Process

python - 我如何在 python 中使用 multiprocessing.Pool.map 来处理对象中的函数?

python - 访问字典 VS 访问书架

python - 带有 MNIST 的 LSTM 示例

python - 从opencv中的图片中删除大对象

c - 如何使用 swapcontext() 恢复函数的执行(而不是再次启动)?