如何将外部 DLL 限制为一个 CPU?
Posted
技术标签:
【中文标题】如何将外部 DLL 限制为一个 CPU?【英文标题】:How do I limit an external DLL to one CPU? 【发布时间】:2009-02-07 07:26:10 【问题描述】:我有一个程序,我想只在一个 CPU 上运行,这样它就不会占用太多系统资源。问题是,它调用了一个自动使用所有可用 CPU 内核的外部 DLL。我没有外部 DLL 的源代码。如何将 DLL 限制为仅使用一个 CPU?
编辑:感谢您的帮助,这是我用来限制一个 CPU (Windows) 的代码:
// Limit the process to only 1 thread so we don't chew up system resources
HANDLE ProcessHandle = GetCurrentProcess();
DWORD ProcessAffinityMask;
DWORD SystemAffinityMask;
if(GetProcessAffinityMask(ProcessHandle,&ProcessAffinityMask,&SystemAffinityMask)
&& SystemAffinityMask != 0)
// Limit to 1 thread by masking all but 1 bit of the system affinity mask
DWORD NewProcessAffinityMask = ((SystemAffinityMask-1) ^ SystemAffinityMask) & SystemAffinityMask;
SetProcessAffinityMask(ProcessHandle,NewProcessAffinityMask);
编辑:事实证明,Brannon 设置进程优先级的方法更适合我想要的,即防止进程占用资源。这是代码(Windows):
// Make the process low priority so we don't chew up system resources
HANDLE ProcessHandle = GetCurrentProcess();
SetPriorityClass(ProcessHandle,BELOW_NORMAL_PRIORITY_CLASS);
【问题讨论】:
我认为您混淆了您的术语。此代码将整个过程限制为单个处理器。此代码与线程无关。 好点,我会将术语从“线程”更改为“CPU”。 【参考方案1】:您可以设置程序的 CPU 亲和性。在 Windows 上尝试 SetProcessAffinityMask 函数或在 Linux 上尝试 sched_setaffinity。
【讨论】:
【参考方案2】:设置处理器亲和性是错误的方法。让操作系统处理调度。
如果机器处于空闲状态,您希望尽可能多地使用处理器。否则你会无缘无故地做更少的工作。如果机器很忙,那么您希望利用“空闲”周期而不会对其他进程产生不利影响。
Windows 已内置此功能。正确的解决方案是设置进程的基本优先级。
有关SetPriorityClass()
的详细信息,请参阅http://msdn.microsoft.com/en-us/library/ms686219(VS.85).aspx。
如果您想在不编写任何代码的情况下进行测试,请使用任务管理器更改进程的优先级。
【讨论】:
【参考方案3】:通常,dll 与调用它的代码位于同一线程/内存空间中。调用 DLL 本身的行为不应创建线程。如果调用 DLL 似乎会创建更多线程,则意味着 DLL 本身正在其代码中的某处创建线程。如果您没有 DLL 的任何源代码或文档,则您无能为力(如果您希望 DLL 完成它的工作,那么您无需做太多事情)。
您可以尝试使用应用程序的优先级 - 将其设置为低可能会改变 CPU 使用率,即使它不会改变创建的线程。但是,您真正想要的似乎很可能是获取此野兽的文档。在不知道代码是如何工作的情况下,一般来说,你无法改变它的工作方式。没有超级天才可以改变这一点。
【讨论】:
【参考方案4】:呃……为什么?说真的,您为什么要限制能够以这种方式为您提供额外性能的库?您是否尝试访问共享资源或其他东西?有人会认为多线程库能够安全地处理这个问题。
除非您没有提及某些内容,否则我看不出有任何正当理由可以尝试将多线程库限制为单个线程。
【讨论】:
该程序被设计为作为分布式构建系统的一部分在后台运行,但它使用所有 CPU 占用了太多资源。 +1 这是一个非常合理的问题。您应该让操作系统管理线程调度。此外,如果您在问题本身中包含此信息,也会有所帮助。问“为什么?”是很自然的,因为您尝试做的事情与众不同。【参考方案5】:所以你的程序使用一个线程,但你不希望外部 DLL 使用多个线程?您对外部 DLL 的功能没有太多控制权,但有些方法可能是:
使用 "Half-Sync/Half-Async: An Architectural Pattern for Efficient and Well-structured Concurrent I/O" 设计模式将工作项从您的一个线程排队到外部 DLL。 或者,由于另一个 DLL 将加载到您的进程中,您可以将您的进程或线程的处理器关联设置为仅一个 CPU。请参阅 Raymond Chen 的 "Psychic debugging: Why your expensive four-processor machine is ignoring three of its processors"。【讨论】:
【参考方案6】:你没有说这是针对什么平台的。我将假设这里有窗户。
创建子进程并将其与Job Object 关联。然后,您可以将该作业对象的处理器关联设置为仅包含一个可用的 CPU 内核。子进程无法将关联掩码更改为不是作业对象的处理器关联子集的任何内容。此外,您应该记住不要对作业设置限制JOB_OBJECT_LIMIT_BREAKAWAY_OK
或扩展限制JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK
,否则子进程将能够脱离作业。
此外,您可以设置作业的优先级和调度类。也许以较低的 CPU 和/或 IO 优先级创建子进程就足够了?
【讨论】:
问题中的 .DLL 清楚地暗示了 Windows 或 OS/2。 *nix 系统上的等价物是 .SO。由于 OS/2 几乎是一个死机,您可以放心地假设 Windows。以上是关于如何将外部 DLL 限制为一个 CPU?的主要内容,如果未能解决你的问题,请参考以下文章
如何将构建限制为仅支持 EN“Microsoft.Expression.Interactions.resources.dll”,并避免 DE、KR、FR、ES 等...?
如何在 CentOS / RHEL 中启用/禁用 CPU(限制 CPU 数量)