【问题标题】:How does threading or Multiprocessing work with recursions?线程或多处理如何与递归一起工作?
【发布时间】:2011-11-24 00:16:56
【问题描述】:

背景

我对开发有点陌生,并且有一个一般的 python/编程问题。如果您有一个递归方法,那么启用多线程或多处理涉及什么?我做了一些简单的阅读和一些示例,但他们似乎正在应用新代码的语法(而不是非常密集的 cpu 任务),我更想知道如何重新设计现有代码来做到这一点?

假设我有一些 CPU 密集型的东西(基本上会一直添加到自身直到达到限制):

def adderExample(sum, number):
    if sum > 1000:
        print 'sum is larger than 10. Stoping'
    else:
        sum = sum + number
        print sum
        number = number + 1
        adderExample(sum, number)


adderExample(0,0)

问题/思考过程

假设我有多个可用内核,我将如何处理它以使其运行得更快(我希望它最终希望它跨越机器,但我认为这是 hadoop 的一个单独问题,所以我将把这个例子保留在一个系统中多个cpu)?似乎线程不是最好的选择(因为产生新线程需要时间),如果那是真的,我应该只关注多处理吗?如果是这样,可以将递归拆分为不同的 cpu(我假设的队列,然后在完成后重新加入)?我可以为每个进程创建多个线程而不是将这些进程拆分到多个 cpu 上吗?最后,递归深度是否限制了总体限制,还是基于线程/进程,如果是,多处理/线程是否可以绕过它?

另一个问题(相关)那些试图通过蛮力编码(rsa、无线密钥等)的人如何克服这个问题?我假设他们正在以某种方式在多个 cpu 上扩展他们的数学过程。这个或任何建立我理解的例子都会很棒。

任何提示/建议都会很棒

谢谢!

【问题讨论】:

  • 一般来说,进程比线程需要更多的时间和开销。线程使用与启动程序相同的内存空间。进程必须创建新的内存开销。使用线程,您还可以轻松地合并信息结构的共享而无需复制它们,如果不使用基于操作系统(或其他)的“共享内存”IPC 实现,就无法通过多个进程轻松地做到这一点。

标签: python multithreading algorithm scalability multiprocessing


【解决方案1】:

这样的循环根本不会从线程中受益。假设您正在执行一系列添加,其中间值取决于先前的迭代。这不能并行化,因为线程会踩踏彼此的值并覆盖事物。您可以锁定数据,以便一次只有一个线程处理它,但这样您就失去了让多个线程处理该数据的任何好处。

线程在拥有独立数据集时工作得最好。例如图形渲染器就是一个很好的例子。每个线程渲染较大图像的一个子集-它们可能共享纹理/顶点/颜色/等数据的公共数据源,但是每个线程都有自己的整个图像的一小部分来工作,并且不接触图像的其他区域。无论线程 #1 在其一小部分像素上做什么,都不会影响线程 #2 在图像中其他地方所做的事情。

对于您的相关问题,密码破解是线程/多处理有意义的另一个示例。每个线程都会根据一个常见的“待破解”列表自行测试多个可能的密码。一个线程正在做的事情不会影响任何其他破解线程,除非你得到一个匹配,这可能意味着所有线程都中止,因为工作“完成”了。

一旦线程相互依赖,您就会失去拥有多个线程的许多好处。他们会花更多的时间等待对方完成,而不是花在实际工作上。当然,这并不是说你永远不应该使用线程。有时拥有多个线程确实有意义,即使它们是相互依赖的。例如。图形线程 + 音效线程 + 动作处理器线程 + A.I.计算线程等...在游戏中。每个人名义上是相互依赖的,但是当声音线程忙于为玩家刚刚开枪的枪生成砰+弹跳音频时,人工智能。线程已关闭计算游戏中的生物在做什么,图形线程正在背景中绘制一些云,等等...

【讨论】:

  • 我想我明白了一点,谢谢 Marc。只是为了进一步理解,我了解密码破解者使用字典并将其排队,但是如果破解者生成自己的密码(不是基于字典,例如 a、b、c、...aa、ab、ac 等)怎么办。如果我认为他们不能多处理组合的生成,我的理解是否正确(但多处理实际上可以尝试使用密码,因为组合被放入队列中)?
  • 您可以并行化流程,如果您可以拆分任务。例如对于数字顺序密码(1、2、3、4、5等...)的列表,您可以将其分成2个线程(一个做偶数,一个做赔率)等...只要你能让每个线程在整体列表中都有自己独立的部分,那么没问题。但是,如果您有 5 个线程,但将工作负载分成 4 个部分,那么您将浪费一些时间来复制工作。
【解决方案2】:

线程有点暗示多个堆栈,递归单个堆栈。也就是说,如果您到达左递归、右递归部分并决定在当前线程数“低”的情况下为子问题生成线程并进行直接递归,否则您可以组合这些概念。

但是常规的 Python 不是这种模式的好语言。 Python 线程都在同一个解释器硬件线程上运行,因此您实际上不会获得任何多处理优势。

【讨论】:

    【解决方案3】:

    Phunctor 是正确的,因为“全局解释器锁”会阻止多个线程并行执行 Python 代码,因此线程库对于并行化此类问题是一个糟糕的选择。

    线程库非常有用的地方在于,每个线程的代码都花费大量时间等待 I/O 发生。因此,例如,如果您正在实现一个必须访问磁盘或等待网络响应的服务器,那么在每个线程中为请求提供服务可能非常有效,因为线程库可以支持那些不等待 I /O 从而最大限度地利用 Python 解释器。 (在单个线程中,您必须使用紧密循环来检查 I/O 请求的状态,这会随着负载的增加而变得浪费。)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-27
      • 2016-03-06
      • 1970-01-01
      • 2020-07-31
      相关资源
      最近更新 更多