views:

497

answers:

6

I have a program that I would like to run on just one CPU so it doesn't take up too much system resources. The problem is, it makes a call into an external DLL that automatically uses all available CPU cores. I do not have the source code to the external DLL. How can I limit the DLL to only using one CPU?

EDIT: Thanks for the help, here is the code I used to limit to one 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);
}

EDIT: Turns out Brannon's approach of setting process priority works even better for what I want, which is to keep the process from chewing up resources. Here's that code (Windows):

// Make the process low priority so we don't chew up system resources
HANDLE ProcessHandle = GetCurrentProcess();
SetPriorityClass(ProcessHandle,BELOW_NORMAL_PRIORITY_CLASS);
+8  A: 

You could set the CPU affinity of your program. Try the SetProcessAffinityMask function on Windows or sched_setaffinity on Linux.

Ates Goral
A: 

Er...... why? Seriously, why would you limit a library that's capable of giving you additional performance in such a way? Are you trying to access a shared resource or something? One would think that a multi-threaded library would be capable of handling this safely.

Unless there's something you're not mentioning, I can't see any valid reason for even trying to limit a multi-threaded library to a single thread.

Randolpho
The program is designed to run unnoticed in the background as part of a distributed build system, but it's chewing up way too many resources by using all the CPUs.
+1 this is a very legitimate question. You should let the OS manage thread scheduling. Also, it would have helped if you had included this information in the question itself. It's natural to ask "why?", because what you are trying to do is out of the ordinary.
Brannon
A: 

So your program uses one thread, but you don't want the external DLL to use more than one thread? You don't have much control over what the external DLL does, but some approaches might be:

cpeterso
+1  A: 

Normally, a dll lives in the same thread/memory space as the code that calls it. The act of calling a DLL itself should not create threads. If calling the DLL seems to create more threads, that means that the DLL itself is creating the threads somewhere in it's code. If you don't have any source code or documentation for the DLL, there isn't much you can do about it (and if you want the DLL to do its job, there isn't much you should do about this).

You might try playing with the priority of your application - setting it to low might change the CPU usage even if it doesn't change what threads are created. But it seems likely that what you will really want is to get documentation for this beast. Without knowing how code works, in general, there isn't much you can do to change how it works. No super genius can change that.

Joe Soul-bringer
A: 

You didn't say what platform this is for. I'm going to assume windows here.

Create the child process and associate it with a Job Object. You can then set the processor affinity for that job object to include only one of the available CPU cores. The child process is not able to change the affinity mask to anything that is not a subset of the processor affinity for the job object. Additionally, you should remember not to set the limit JOB_OBJECT_LIMIT_BREAKAWAY_OK or the extended limit JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK on the job or else the child process will be able to break out of the job.

Additionally, you can set the priority and scheduling class for the job. Perhaps it will be sufficient to create the child process at a lower CPU and/or IO priority level?

1800 INFORMATION
The .DLL from the question clearly implies Windows or OS/2. The equivalent on *nix systems is .SO. Since OS/2 is pretty much a dead OS, you can safely assume Windows.
Randolpho
+5  A: 

Setting processor affinity is the wrong approach. Let the OS handle scheduling.

If the machine is sitting idle, you want to use as much processor as you can. Otherwise you're doing less work for no reason. If the machine is busy, then you want to make use of "free" cycles and not adversely affect other processes.

Windows has this functionality built-in. The proper solution for this is to set the base priority of the process.

See http://msdn.microsoft.com/en-us/library/ms686219(VS.85).aspx for details on SetPriorityClass().

If you want to test this without writing any code, use Task Manager to change the priority of your process.

Brannon