【问题标题】:Multithreaded Python script taking longer than non-threaded script多线程 Python 脚本比非线程脚本花费更长的时间
【发布时间】:2010-08-11 19:09:51
【问题描述】:

免责声明:我在多线程方面非常糟糕,所以我完全有可能做错了什么。

我已经用 Python 编写了一个非常基本的光线追踪器,并且我正在寻找可能加快它的方法。多线程似乎是一种选择,所以我决定尝试一下。然而,虽然原始脚本需要大约 85 秒来处理我的示例场景,但多线程脚本最终需要大约 125 秒,这似乎很不直观。

这是原始的样子(我不会在这里复制绘图逻辑和内容。如果有人认为需要找出问题所在,我会继续将其放回原处):

def getPixelColor(x, y, scene):
    <some raytracing code>

def draw(outputFile, scene):
    <some file handling code>
    for y in range(scene.getHeight()):
        for x in range(scene.getWidth()):
            pixelColor = getPixelColor(x, y, scene)
            <write pixelColor to image file>

if __name__ == "__main__":
    scene = readScene()
    draw(scene)

这是多线程版本:

import threading
import Queue

q = Queue.Queue()
pixelDict = dict()

class DrawThread(threading.Thread):
    def __init__(self, scene):
        self.scene = scene
        threading.Thread.__init__(self)

    def run(self):
        while True:
        try:
            n, x, y = q.get_nowait()
        except Queue.Empty:
            break
        pixelDict[n] = getPixelColor(x, y, self.scene)
        q.task_done()

    def getPixelColor(x, y, scene):
        <some raytracing code>

def draw(outputFile, scene):
    <some file handling code>
    n = 0
    work_threads = 4
    for y in range(scene.getHeight()):
        for x in range(scene.getWidth()):
            q.put_nowait((n, x, y))
            n += 1
    for i in range(work_threads):
        t = DrawThread(scene)
        t.start()
    q.join()
    for i in range(n)
        pixelColor = pixelDict[i]
        <write pixelColor to image file>

if __name__ == "__main__":
    scene = readScene()
    draw(scene)

有什么明显的我做错了吗?还是我假设多线程会提高这样的进程的速度是不正确的?

【问题讨论】:

  • 如果你正在做大量的数学运算并且不喜欢以“C”开头的语言,我会尝试使用 numpy 或者 Psyco。

标签: python multithreading


【解决方案1】:

我怀疑 Python 全局解释器锁会阻止您的代码同时在两个线程中运行。

What is a global interpreter lock (GIL)?

显然您想利用多个 CPU。你可以跨进程而不是线程分割光线追踪吗?

多线程版本显然做了更多的“工作”,所以我预计它在单个 CPU 上会更慢。

我也不喜欢继承Thread,只是用t = Thread(target=myfunc); t.run()构造一个新线程

【讨论】:

    【解决方案2】:

    要直接回答您的问题,Python 线程不会提高性能,GIL 实际上可能会使情况变得更糟。

    在更大的方案中,我喜欢 python 和光线追踪,但你不应该将它们结合起来。 Python 光线追踪器至少比 C 甚至 C++ 版本慢 2 个数量级。

    因此,虽然从 Python 程序员的角度来看,您的问题很有趣,但从光线追踪的角度来看,它却相当有趣。

    【讨论】:

    • 我知道 Python 不是解决这个问题的正确工具,它更像是一种学习练习。我用几乎相同的代码编写了一个 C++ 代码,它的速度有多快是荒谬的。这个真的只是为了好玩。
    【解决方案3】:

    我怀疑您可能有两个问题之一(或两者都有)。首先,我同意 Joe 的观点,即 Global Interpreter Lock 可能会导致问题。

    其次,看起来你在这个过程中写了很多文件(特别是在非线程版本中,当你每次迭代内部循环时都这样做)。您是否有可能在磁盘而不是 CPU 上受到时间限制?如果是这样,那么当您添加线程时,您会增加管理线程的开销,而不会解决实际的瓶颈。在优化时,请确保首先确定您的瓶颈,这样您至少可以猜测在解决这些瓶颈时哪些可能会给您带来最大的收益。

    【讨论】:

    • 我缓冲了写作,它确实节省了大量时间。感谢您指出这一点!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-08-24
    • 2014-04-23
    • 2017-06-29
    • 2021-09-01
    • 2020-12-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多