Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/345.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python多处理池/进程的结果不一致_Python_Multiprocessing_Pool - Fatal编程技术网

Python多处理池/进程的结果不一致

Python多处理池/进程的结果不一致,python,multiprocessing,pool,Python,Multiprocessing,Pool,我的共享字典对象的条目数不一致。它应该有500个,但大多数测试的结果都在450到465之间。我还尝试使用map和Process而不是apply\u async map稍微好一点,因为共享字典有大约480个条目,而不是大约450个条目,但仍然不一致,而且并非如预期的全部500个条目 我也尝试使用这个过程,但结果是共享字典中的条目数最少——大约420个 下面是使用apply\u async的完整代码: import numpy as np from PIL import Image from os

我的共享字典对象的条目数不一致。它应该有500个,但大多数测试的结果都在450到465之间。我还尝试使用
map
Process
而不是
apply\u async

map
稍微好一点,因为共享字典有大约480个条目,而不是大约450个条目,但仍然不一致,而且并非如预期的全部500个条目

我也尝试使用这个过程,但结果是共享字典中的条目数最少——大约420个

下面是使用
apply\u async
的完整代码:

import numpy as np
from PIL import Image
from os import listdir
from multiprocessing import Manager, Pool

def processImage(path, d):
  image = np.array(Image.open(source + "/" + path))

  # Copy lists from shared dictionary since updates don't work otherwise
  w = d["width"]
  h = d["height"]
  w.append(image.shape[0])
  h.append(image.shape[1])
  d["width"] = w
  d["height"] = h

if __name__ == "__main__":
  source = "./sample/images"
  p = Pool()
  m = Manager()
  d = m.dict()
  d["width"], d["height"] = [], []

  for path in listdir(source):
    p.apply_async(processImage, (path, d))
  p.close()
  p.join()
下面是使用
map
的完整代码:

def processImage(obj):
  image = np.array(Image.open(source + "/" + obj[1]))

  w = obj[0]["width"]
  h = obj[0]["height"]
  w.append(image.shape[0])
  h.append(image.shape[1])
  obj[0]["width"] = w
  obj[0]["height"] = h

if __name__ == "__main__":
  source = "./sample/images"
  p = Pool()
  m = Manager()
  d = m.dict()
  d["width"], d["height"] = [], []

  p.map(processImage, zip(itertools.repeat(d), listdir(source)))
下面是使用
过程的完整代码

def processImage(path, d):
  image = np.array(Image.open(source + "/" + path))

  w = d["width"]
  h = d["height"]
  w.append(image.shape[0])
  h.append(image.shape[1])
  d["width"] = w
  d["height"] = h

if __name__ == "__main__":
  source = "./sample/images"
  p = Pool()
  m = Manager()
  d = m.dict()
  d["width"], d["height"] = [], []

  jobs = []
  for img in listdir(source):
    p = Process(target=processImage, args=(img, d))
    p.start()
    jobs.append(p)

  for j in jobs:
    j.join()

这是竞赛条件的一个经典示例。您需要某种同步原语来更新
d

考虑以下情况:有两个线程(在您的例子中是子进程)正在执行
processImage
。首先获得
w
h
,然后获得
w
h
。首先,将某个内容附加到两者,然后将其放回
d
。第二个线程对自己的
w
h
执行某些操作,这些操作不再考虑第一个线程所做的更改,并将其放回
d
。此时,第一个线程所做的更改将丢失

要解决这个问题,您需要保护使用
d
的部分代码:

from multiprocessing import Manager, Pool, Lock
...
lock = Lock()
...
def processImage(path, d):
    image = np.array(Image.open(source + "/" + path))

    lock.acquire()
    d["width"].append(image.shape[0])
    d["height"].append(image.shape[1])
    lock.release()

感谢您的解释——这是有道理的,但不幸的是,并不能解决我的问题:/忽略我上面的评论,将锁获取和释放移动到复制列表之前和之后解决了问题!