0

我创建了大约 5000 个后台工作人员,他们在控制台应用程序中进行密集工作。我还使用了一个实例化对象的外部库,比如 ObjectX。在某个时刻,比如 t0,ObjectX 尝试从 os 线程池中获取一个线程并启动它,但我无法控制它如何获取该线程。对于 100 名后台工作人员来说一切正常。对于 1000 个后台工作人员,ObjectX 在 t0 之后大约需要 10 分钟才能获取并启动一个线程。

  1. 有没有办法提前为对象将来启动的任何线程设置高优先级?

  2. 正如我认为 1 的答案是“否”,有没有办法限制后台工作人员的优先级,以便以某种方式支持其他一切?即使我只想“支持”ObjectX。

目标是始终拥有可用资源来运行由 ObjectX 启动的线程,无论机器有多过载。

我在 Windows 64 位机器上使用 C# 和 .Net fr 3.5。

4

3 回答 3

3

线程的工作方式是操作系统为它们提供处理器时间。当这种情况发生时,这称为上下文切换。上下文切换大约需要 2000-8000 个周期(即取决于处理器 2000-8000 条指令)。如果操作系统有许多 CPU 或内核,它可能不需要将 CPU 从一个线程中取出并交给另一个线程——避免上下文切换。每个 CPU 一次只能运行一个线程,当您需要 CPU 的线程多于 CPU 时,您将强制进行上下文切换。上下文切换的执行速度不超过系统时间片(客户端每 20 毫秒,服务器每 120 毫秒)。

如果您有 5000 个后台工作人员,那么您实际上有 5000 个线程。这些线程中的每一个都可能在争夺 CPU 时间。在客户端版本的 Windows 上,这意味着每秒 250,000 次上下文切换。即每秒 500,000,000 到 2,000,000,000 个周期仅用于线程之间的切换。(即超过你的线程正在执行的工作)如果它甚至可以每秒处理那么多上下文切换

推荐的做法是每个处理器只有一个 CPU 绑定线程。CPU-bound 线程是一个花费很少时间“等待”的线程。UI 线程不是 CPU 绑定线程。如果您的后台工作线程花费大量时间等待锁定,那么它们也可能不受 CPU 限制——但一般来说,后台工作线程受 CPU 限制。(否则,使用后台工作人员有什么意义?)。

此外,操作系统会花费大量时间来确定接下来需要哪个线程来获取 CPU。当您开始更改线程优先级时,您会干扰它,并且大多数时候最终会使您的整个系统(不仅仅是您的应用程序)变慢而不是更快。

更新:

与之相关的是,创建一个新线程大约需要 200,000 个周期,而销毁一个线程大约需要 100,000 个周期。

更新 2:

如果问题的推动力不仅仅是“如果可以做到”,而是能够扩展工作负载,那么正如@JoshW/@Servy 提到的那样,使用生产者/消费者模式之类的东西将允许可扩展性,从而促进横向通过队列或服务总线扩展到多台计算机/节点。简单地启动大量线程是不可扩展的,超出了 CPU 的数量。如果您真正想要的是一种可以横向扩展的架构,因为“可用资源......机器的过载程度”根本不可能。

于 2013-03-12T15:11:34.610 回答
0

但是,我个人认为这是一个坏主意……鉴于您对其他答案的评论以及您的要求“无论创建了多少后台工作人员,ObjectX 都会尽快运行”……您可以想象强制您的后台工作人员使用 ManualResetEvent 进行阻止。

例如,在您的工作代码的顶部,您可以使用 WaitOne 方法阻止手动重置事件。此手动重置可以是静态的,也可以作为输入参数传递,并且无论您的 ObjectX 被实例化/调用或其他什么,您都可以在 ManualResetEvent 上调用 .Reset 方法。这将阻止 WaitOne 线上的所有工作人员。接下来在运行 ObjectX 的代码的底部,调用 ManualResetEvent.Set() 方法,这将解除对工作人员的阻塞。

请注意,这不是管理线程的有效方法,但如果您“只需要让它工作”并且以后有时间改进它......我想这是一种可能的解决方案。

于 2013-03-12T15:26:07.853 回答
-1

目标是始终拥有可用资源来运行由 ObjectX 启动的线程,无论机器有多过载。

那么线程优先级可能不是正确的工具。请记住,线程优先级是邪恶的

一般来说,windows 不是实时操作系统;特别是,win32 甚至没有尝试软实时(IIRC,NT 内核在某些时候尝试过至少支持软实时子系统,但我可能错了)。因此,无法保证可用资源或时间。

另外,您是否担心系统中的其他线程?这些线程不在您的控制范围内(如果其他线程已经处于系统最大优先级怎么办?)。如果您担心应用程序中的线程......您可以控制和限制它们,使用更少的线程/工作人员来做更多的工作(例如,以更大的单位批量工作,并将其提交给工作人员,或者使用 TPL 或其他将为您处理和限制线程使用的工具)

也就是说,您可以在创建线程时进行拦截(例如查看这个问题https://stackoverflow.com/a/3802316/863564)查看它是否是为 ObjectX 创建的(例如,检查其名称)并使用 SetThreadPriority 来增强它。

于 2013-03-12T15:01:56.937 回答