【问题标题】:Pyqt multiprocessing index out of rangePyqt 多处理索引超出范围
【发布时间】:2014-08-08 10:50:35
【问题描述】:

按照 Python 标准库中的多处理示例,我正在尝试使用多处理进行一些计算,但返回一个索引错误。

现在的结构是这样的,

main.py有应用类和一些加载数据的函数 run.py

if __name__=='__main__':
    import main
    main.show()

它调用main中的show()函数来显示gui。我使用其他 SO 帖子中的这种方法来阻止显示多个 GUI。

在 GUI 类之外我有这些功能

def start_process():
    print 'Starting', multiprocessing.current_process().name

def multimanager(start,end):
    inputs=range(start,end) 
    non_multi = map(mymod.algorithm, inputs)
    print non_multi

    pool_size = multiprocessing.cpu_count() * 2
    pool = multiprocessing.Pool(processes=pool_size,
                                initializer=start_process,
                                )

    pool_outputs = pool.map(mymod.algorithm,inputs)
    pool.close()
    pool.join()

    print "Pool :", pool_outputs

我注意到了一些事情。根据这本书,map() 函数应该具有相同的作用。因此,books 示例对输入进行了与处理相同的映射。我已经做到了,non_multi = map(mymod.algorithm, inputs) 有效。但是,多处理没有。

如果我将 mymod.algorithm 更改为仅 +1 输入数字,它似乎可以工作。除了,似乎从来没有调用过start_process() 函数,因为它没有print 'Starting'

虽然 Pool 确实打印了基本加法算法的结果,但我不确定它是否真的在不同的进程上,因为似乎没有调用 start_process() 函数。

如果是这样,我想知道算法是否做了多处理不允许的事情。在另一篇 SO 帖子中,一个答案提到多处理中的这个列表索引错误并不具体。如果更多信息可以帮助找到问题,算法会通过导入存储字典数组的globalvariable.py 文件来调用全局变量。 map 函数的输入是数组的索引,在不同的函数中,数据是通过矩阵运算等计算出来的,然后将一些数据存储到全局变量中。

这可能是我使用的全局变量的问题吗?如果是这样,是否有不同的方法来为每个进程传递变量? (程序有点大,所以不能只将变量复制到mymod.py文件中。

错误是

File "C...main.py", line 71, in multimanager
    pool_outputs = pool.map(mymod.algorithm,inputs)
  File "C:\Python27\lib\multiprocessing\pool.py", line 250, in map
    return self.map_async(func, iterable, chunksize).get()
  File "C:\Python27\lib\multiprocessing\pool.py", line 554, in get
    raise self._value
IndexError: list index out of range

编辑附加信息:

模块中有一个类myclass.py

class Data():
    def __init__(self):
        self.Mydata = None

globalvariable.py 文件有一个存储数据类的全局变量数组

data = []

main.pymymod.py 都导入 globalvariable.py。在main.py数据被加载,并且每次都会创建一个类实例(myclass.Data()),然后这个实例被追加到数组data存储在globalvariable.py中。所以在调用进程之前,打印全局变量数据会打印

[<myclass.Data instance at 0x050F6878>,<myclass.Data instance at 0x050F6879>]

但是,当进程启动时,它会打印为一个空数组。

mymod.py 看起来像:

import globalvariable as gv

def algorithm(index):
    print gv.data

打印[]

我也仅使用基本变量进行了尝试,但没有成功。让进程在启动时加载正确变量的方法是什么?注意,我不想在进程之间共享,只是让每个进程从头开始使用相同的数据。

【问题讨论】:

  • 您是否在 IDLE 中运行此代码?这可能可以解释为什么您没有看到您在start_process 中输入的print 语句的输出。直接从 Windows CLI 运行它,您可能会看到输出。
  • @dano 是的,我正在使用空闲,感谢您的提示!

标签: python python-2.7 runtime-error multiprocessing pool


【解决方案1】:

初始化器在工作进程中被调用。为了让他们的输出立即显示出来,您可能应该在print 之后调用sys.stdout.flush()

一般来说,指定比cpu_count的返回值更多的工作进程并不是一个好主意。

multiprocessing.Pool.map 背后的想法是,worker 被重复调用,并使用来自可迭代对象的值。由于多处理使用多个进程,因此没有全局共享变量。

当一个工作进程启动时,它拥有父进程中所有内容的副本。但除了显式共享内存(如multiprocessing.Valuemultiprocessing.Array)之外,这些变量独立

我的经验法则是,如果您要发送给工作人员的数据很小(最多几千字节),请使用您提供给 map 函数的可迭代对象将数据发送给工作人员。

如果您要发送给每个工作人员的数据量很大,请将数据写入一个或多个文件,然后发送工作人员,例如一个元组('filename', offset, length),这样每个工作人员都可以使用mmap读取它需要的数据。

【讨论】:

  • 当你提到全局共享变量时,你是说进程不能共享变量,还是进程启动时不能使用预定义的全局变量。我试图使用后者。
  • @user1938107 除了共享内存,进程不共享变量。当您启动一个工作器时,该工作器从父级中定义的变量继承一个副本
  • 因此,如果启动 worker 的 main.py 和算法所在的 mymod.py 都导入包含数组的 globalvar.py 文件,这是否会被视为已定义的变量在父母?对不起,如果我问了很多,但我无法理解导入何时被视为在该模块中定义
  • 它与定义的位置无关。当您使用池时,Python 会创建父进程的独立副本。他们都有相同数据的副本,但他们不共享​​>它。
  • 好吧,这就是我从你那里了解到的。我不尝试让进程共享相同的数据,数组中有 4000 个索引。此数组已定义。每个进程获取该数组的一个索引并计算它。他们不需要其他人的任何信息。我会尝试更多的调试,感谢指导
猜你喜欢
  • 2014-11-03
  • 2022-01-22
  • 1970-01-01
  • 2012-06-04
  • 1970-01-01
  • 1970-01-01
  • 2018-03-01
  • 1970-01-01
相关资源
最近更新 更多