【问题标题】:Creating Thousands of Threads Quickly and Executing Them Near Simultaneously快速创建数千个线程并近乎同时执行
【发布时间】:2010-10-12 21:22:22
【问题描述】:

我有一个 C#.NET 应用程序,它需要通知 4000 到 40,000 台连接的设备同时执行一项任务(或尽可能接近同时执行)。

应用程序运行良好;但是,我对性能并不满意。在一个完美的世界中,一旦我发送命令,我希望看到所有设备同时响应。然而,似乎存在延迟,因为我创建的所有线程都在启动并执行任务。

我使用了 .NET 4.0 ThreadPool,使用自定义线程创建了自己的解决方案,我什至调整了现有的 ThreadPool 以允许一次执行更多线程。

我仍然想要更好的表现,这就是我在这里的原因。有任何想法吗?评论?建议?谢谢。

-肖恩

让我补充一点,应用程序会通知这些“已连接的设备”,它们需要在多播地址上收听音频。

【问题讨论】:

  • 这是什么网络?是通过 UDP 多播发送选项吗?
  • 是的,告诉成千上万的设备去听一个多播地址上的音频。
  • 您有 4,000 到 40,000 个 CPU/内核吗?如果你这样做了,那么你可以同时执行所有线程......但是如果你可以在 UDP 上多播,那为什么还要麻烦线程呢?
  • 发送多播数据包只需要 1 个线程。
  • 4k 设备听起来是一个足够大的项目,足以证明修改设备(或制作自定义设备)以收听单个“开始音频”通知数据包是合理的。方式,更容易。即使完美的线程和完美的“启动”数据包一个接一个地发送到设备,没有延迟..您仍然在谈论通过网络串行发送的大量数据包以及第一个和最后一个设备之间的大量延迟' 通知(如果音频同步是主要问题)

标签: c# .net multithreading threadpool


【解决方案1】:

双核超线程处理器可能能够同时执行 4 个线程 - 取决于线程正在做什么(不存在 IO 或内存访问争用等)。四核超线程可能有 8 个。但 40K 物理上是不可能的。

如果您希望near 同时进行,则最好启动与计算机具有空闲内核的线程数一样多的线程,并让每个线程触发通知然后结束。您将通过这种方式摆脱一堆上下文切换。

或者,看看别处。正如 SB 在 cmets 中建议的那样,使用 UDP 多播来通知监听机器他们应该做点什么。

【讨论】:

  • 如果可以的话,我会再给你一个 +1 建议线程限制。
【解决方案2】:

不能同时执行 4000 个线程,更不用说 40k。充其量在具有超线程的台式机上,您最多可能会同时运行 8 个进程(假设为四核)。线程是伪并行的,这甚至没有深入探讨总线争用问题。

如果您绝对需要 40k 设备的同时性,您需要某种形式的硬件同步。

【讨论】:

  • 我敢打赌,任何可以同时执行 40k 个节点的硬件同步系统都会非常昂贵。
  • 感谢您的回复。我想这是可能的;但是,只是因为我相信我已经看到一些应用程序这样做了。也就是说,也许它是基于硬件的,就像你说的那样。谢谢。
【解决方案3】:

听起来您可以控制每台设备上运行的软件。在这种情况下,您可以查看 HPC 的使用情况并分层构建您的设备(节点)和/或使用 MPI 来执行您的远程进程。

对于层次结构示例:指定说,8 个节点作为主主节点,再有 8 个从节点,每个从节点也可以作为主节点,有 8 个从节点(您可能需要查看自动订阅算法来执行此操作)。您将拥有一个深度为 6 的层次结构以覆盖 40,000 个节点。每个主机都有一小部分代码不断运行,等待指令传递给从机。

然后您所做的就是将指令传递给 8 个主主节点,您的指令将由主节点异步传播到线路上的“集群”。该指令最多只需要传递 5 次,因此会 v-quickly 传播。

您也可以选择(或结合使用)查看 MPI,这是一种现成的解决方案。有一些已建立的 C# 实现。

【讨论】:

  • 我会调查的。谢谢。
【解决方案4】:

创建数千个线程的开销(非常)显着;我会寻求替代解决方案。这听起来像是异步 IO 的工作:您的计算机大概只有一个网络连接,因此一次只能发送一条消息 - 线程无法对此进行改进!

【讨论】:

    【解决方案5】:

    我猜测您在设备上使用同步 API 调用是否正确,这就是它必须在线程中执行的原因? API 是否有异步版本的调用?如果设备 API 真的可以支持 40k+ 设备,那么它应该。它还应该对同步回调的返回数据所需的任何等待句柄(或等效句柄)进行内部处理。这不是您可以在客户端应用程序端处理的事情。您对设备 API 的底层实现没有足够的了解,无法知道如何并行化任务。正如您所发现的,使用阻塞调用创建 40k 线程并不能解决问题。

    【讨论】:

      【解决方案6】:

      您应该对设备执行异步 IO。这是非常有效的,并且使用不同的(更大的)线程集来处理一些工作。当然,设备会更快地接收命令。 IO 线程池将处理回复(如果有)

      【讨论】:

        【解决方案7】:

        总是和这些旧的玩得开心。

        每个线程 1mb 意味着您至少需要 4-40gb 的 RAM 和 4k-40k 的内核。以及您有一个网络可以发送它的事实。

        意味着它将在途中的某个地方同步,在最近的交换机/路由器上(大部分可能甚至在你的网卡上,如果你甚至可以同时将所有的包拿到那里,并且它设法发送它没有缓存它或死在你身上)。简单地说,多线程的所有工作都是徒劳的,因为它不会同时到达端点。

        把它想象成在一条 40'000 车道的道路上放置 40'000 辆汽车,确保每个人同时到达道路上的同一点,但随后他们离开道路回家。每个人在不同的时间回家,即使他们在同一时间开始在 40k 路上行驶。

        你只是,不能,打败物理领域(还......)。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-08-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-06-22
          • 1970-01-01
          相关资源
          最近更新 更多