【问题标题】:QRunnable in multiple cores多核中的 QRunnable
【发布时间】:2017-02-21 16:04:20
【问题描述】:

我正在学习 QRunnable,我有以下代码:

from PyQt5.QtCore import QThreadPool, QRunnable

class SomeObjectToDoComplicatedStuff(QRunnable):
    def __init__(self, name):
        QRunnable.__init__(self)
        self.name = name

    def run(self):
        print('running', self.name)
        a = 10
        b = 30
        c = 0
        for i in range(5000000):
            c += a**b
        print('done', self.name)


pool = QThreadPool.globalInstance()
pool.setMaxThreadCount(10)

batch_size = 100

workers = [None] * batch_size

for i in range(batch_size):
    worker = SomeObjectToDoComplicatedStuff('object ' + str(i))
    workers[i] = worker
    pool.start(worker)

print('All cued')
pool.waitForDone()

# processing the results back
for i in range(batch_size):
    print(workers[i].name, ' - examining again.')

我看到确实有不同的进程在交替进行,但是所有都发生在一个内核上。

如何让这段代码使用所有处理器内核运行?

PS:这段代码只是我正在制作的一个超级复杂的数字运算应用程序的简化。在其中,我想在多个线程中进行 Monte Carlo,而 worker 本身就是一个复杂的优化问题。 我已经尝试过 python 多处理模块,但它不能很好地处理 scipy。

【问题讨论】:

  • GIL.
  • 我完全了解 GIL,但问题仍然是如何使其在多个内核中运行。
  • 这似乎是一个矛盾。如果相关代码未发布 GIL,则不可能使您问题中的代码行为有任何不同。多处理模块正是因为这个问题而存在。因此,如果您不能使用它,则必须编写一个无需 GIL 即可运行代码的扩展。请参阅:Overcoming Python's GIL with Cython
  • 如果你能提供一个使用scipy和多处理模块的解决方案,我会标记为解决方案
  • 我以为你尝试过多处理?你遇到了什么具体问题?如果您发布一个 minimal reproducible example 来说明问题,那将非常有帮助。

标签: multithreading python-3.x pyqt5


【解决方案1】:

不确定这会有多大用处,但您的示例脚本的 multiprocessing 版本会是这样的:

from multiprocessing import Pool

class Worker(object):
    def __init__(self, name):
        self.name = name

    def run(self):
        print('running', self.name)
        a = 10
        b = 30
        c = 0
        for i in range(5000000):
            c += a**b
        print('done', self.name)
        return self.name, c

def caller(worker):
    return worker.run()

def run():
    pool = Pool()
    batch_size = 10
    workers = (Worker('object%d' % i) for i in range(batch_size))
    result = pool.map(caller, workers)
    for item in result:
        print('%s = %s' % item)

if __name__ == '__main__':

    run()

【讨论】:

  • 看起来是这样,虽然在 windows 上它会崩溃..我稍后会在 linux 上尝试
  • @SantiPeñate-Vera。我修复了示例代码。 Windows 没有 fork,因此必须保护脚本的入口点以避免无限回归。
  • 用生产代码在 linux 上试了试,效果很好
【解决方案2】:

如何让这段代码使用所有处理器内核运行?

使用 PyQt(QRunner/QThread 和可能),我认为这几乎是不可能的,因为它们(python 版本,而不是 C++)正在使用 GIL。

最简单的解决方案是使用multiprocessing,但由于您在使用 scipy 时遇到了一些问题,您应该寻找一些非标准库。

我建议你看看ipyparallel,AFAIK 它们是在同一个保护伞下开发的,所以它们很可能无缝地工作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-03-25
    • 1970-01-01
    • 1970-01-01
    • 2013-05-23
    • 1970-01-01
    • 2012-11-26
    • 2013-12-28
    相关资源
    最近更新 更多