【问题标题】:Creating a thread for each operation or a some threads for various operations?为每个操作创建一个线程还是为各种操作创建一些线程?
【发布时间】:2012-04-01 15:43:57
【问题描述】:

对于一个班级项目,我正在用 Python 编写一个简单的矩阵乘法器。我的教授要求将其穿线。我现在处理这个问题的方法是为每一行创建一个线程并将结果扔到另一个矩阵中。

我想知道是否会更快,而不是为每一行创建一个线程,而是创建一些线程,每个线程处理不同的行。

例如:给定 Matrix1 100x100 * Matrix2 100x100(矩阵大小可以变化很大):

  • 4 个线程,每个线程处理 25 行
  • 10 个线程,每个线程处理 10 行

这可能是微调的问题,也可能是线程创建过程的开销仍然比上述分配机制快。

【问题讨论】:

    标签: python multithreading matrix distributed


    【解决方案1】:

    如果对运行应用程序的机器可用的每个 CPU 内核使用一个线程,您可能会获得最佳性能。运行多于处理器的线程不会获得任何性能优势。

    如果您计划在每次执行矩阵乘法时生成新线程,那么您的多线程应用程序几乎没有希望超越单线程版本,除非您正在乘以非常大的矩阵。相对于矩阵相乘所需的时间,线程创建所涉及的开销太高了。但是,如果您在进程启动时生成一次所有工作线程,然后一遍又一遍地重用它们来执行许多矩阵乘法,那么您可以获得显着的性能提升。

    对于要相乘的每一对矩阵,您需要将被乘数和乘数矩阵加载到内存中一次,然后允许所有工作线程同时访问内存。这应该是安全的,因为这些矩阵在乘法过程中不会改变。

    您还应该能够允许所有工作线程同时将其输出写入同一个输出矩阵,因为(由于矩阵乘法的性质)每个线程最终会将其输出写入矩阵的不同元素,然后不会有任何争执。

    我认为您应该通过维护一个由所有线程共享的整数NextRowToProcess 在线程之间分配行。每当一个线程准备好处理另一行时,它就会调用InterlockedIncrement(或您平台上可用的任何原子增量操作)来安全地处理下一行。

    【讨论】:

    • 值得一提的是,由于 GIL,在纯 Python 中使用线程进行矩阵乘法没有意义(在 CPython、Pypy 实现上)。
    • 糟糕。我像 C 程序员一样回答了这个问题,不是吗?
    • 但是如果你决定用真正支持多线程的语言来做你的类多线程项目,那么这可能会有用。
    • 使用 Ironpython 或 Jython 会让我的线程代码通过 GIL 的限制吗?我正在运行我的程序的一个无线程版本,即使使用 Ironpython,它仍然比线程版本运行得更快。它需要任何修改吗? (我的CPU是corei3)
    • @user1249212:IronPython 和 Jython 没有 GIL,因此线程版本可以提供性能优势,例如,在我的机器上 threaded version is two times faster 比单线程版本(尽管它比 numpy.dot() 慢 7 倍) )
    【解决方案2】:

    在任何情况下,CPU 密集型任务在 Python 中的多线程模式下都不会更快。由于Global Interpreter Lock,一次只能执行一个线程(除非您编写一些C扩展并显式释放锁)。

    这适用于标准 CPython 实现以及 PyPy。在 Jython 中尝试为每个内核使用一个线程,更多是没有意义的。

    还请查看David Beazley 的精彩 GIL 概述。

    另一方面,如果你的教授不介意,你可以使用multiprocessing

    【讨论】:

    • Ironpython 也可以为每个内核运行一个线程吗?如果是这样,有什么方法可以命令线程在某个核心中运行?为此我应该坚持多处理吗?
    • 抱歉,没用过 IronPython,但据说它没有 GIL。至于选择使用的核心,我想这是下层的,所以它必须足以确保你的代码是真正并行化的。
    猜你喜欢
    • 2020-04-04
    • 2010-12-03
    • 1970-01-01
    • 1970-01-01
    • 2011-03-25
    • 2021-08-29
    • 1970-01-01
    • 2019-08-16
    • 1970-01-01
    相关资源
    最近更新 更多