PDA

View Full Version : priority of processes on Win2k vs Linux



rbutcher
11-19-2005, 06:19 AM
I run a few Win2k and Linux machines. I find that Linux pretty accurately manages to run various dc projects at the specified priority i.e. if I set nice to -1 it gets 95% cpu, at 19 it gets 2% (with the exception of Einstein, which always runs at lowest).
On Win2k I find that almost all dc projects ignore the specified priority, just either taking a pro-rata cpu % whether priority is high or low, or in some cases always taking 100% (e.g. Chronos, Predictor, Folding). World Community Grid always takes lowest priority.
Is this a result of bad programming, or is there something about running jobs I need to know ?
thanks
Rod

Digital Parasite
11-21-2005, 05:04 PM
Windows is much more confusing when it comes to priority. In Linux its very simple, its a scale from -19 to 19. Anything with the same number has equal priority. So two DC apps running nice 19 should share the CPU 50/50.

In Windows, there is process priority *and* thread priority. Even if the process priority is Lowest (what you see in Task Manager), the thread priority might be something else causing it to get more processing time than another process.

You can find out what the process and thread priorities of your DC prorgams in Windows by using my SetPriority program here:
http://gilchrist.ca/jeff/SetPriority/index.html

As long as the process isn't a service, you can change the priority with that program to whatever you want. Once you take a look at the priority settings fro each DC app, I bet you will see that the ones that don't share nicely have different values.

Hope that helps.

Longbow
11-21-2005, 06:59 PM
Originally posted by Digital Parasite

Hope that helps.

Helps me a great deal. Thanks so much for that information as well as the program.

rbutcher
11-21-2005, 08:52 PM
I'll add my thanks too Jeff !

rbutcher
11-28-2005, 02:14 AM
I'v discovered that some DC programs like D2OL, BOINC, Chronos (BOINC based), UD have a habit of starting a new process for a new work unit, hence wrecking the good work done by SetPriority. On linux I've got round this for TSC and D2OL with a cron job that runs every 5 minutes and uses a shell script to find the pid for any current process containing the name Win and reset nice to 19. Looks like D2OLDaddy does something similar on Windows, am I correct ? Is the only way around this for me to write a script (e.g. Perl) which runs say every five minutes, gets the current PID and invoke SetPriority ? Is there a scheduling equivalent of cron on Windows ?
Thanks
Rod

Digital Parasite
11-28-2005, 05:47 PM
Right, D2OLDaddy does exactly that, designed for D2OL and TSC. It will reset your priority automatically every X seconds that you configure it to do.

Windows 2000 and XP have something called "Scheduled Tasks" that you can setup to run programs/scripts. Its usually found under Accessories -> System Tools from the start menu. If this is just for D2OL/TSC you need it for, I would suggest using D2OL Daddy in windows since it does all that for you automatically.

rbutcher
11-29-2005, 03:53 AM
Below is a Perl script (setpriority.pl) I hacked up which can be scheduled as you describe above, and will translate a (part of) process name to its PID and run SetPriority. It's not a very good Perl program but it works. Requires Perl (e.g. from activestate.com) and Win32::Process::Info to be installed.
Run it as :-
setpriority.pl partofprocessname priority threadpriority

e.g. for LHC :-
setpriority.pl sixtrack 16384 -1
========================================
#setpriority.pl

$procname = @ARGV[0];
$priority = @ARGV[1];
$threadpriority = @ARGV[2];

##print "Setting process $procname priority $priority thread priority $threadpriority\n";

use Win32::Process::Info;

my $pi = Win32::Process::Info->new ();
foreach $proc ($pi->GetProcInfo ()) {

foreach (sort keys %$proc) {

if ($_ =~ /\bHandle\b/) {
$thispid = $proc->{$_}
} # end if handle

if ($_ =~ /\bName\b/) {
$thisname = $proc->{$_};
if ($thisname =~ /$procname/){;
system("c\:\\SetPriority\\SetPriority.exe -p$priority -t$threadpriority $thispid");
exit;
} # end if thisname =

} # end if eq Name

} # end for each sort keys

} # end for each proc
========================================

rbutcher
11-29-2005, 11:57 PM
Latest state of play in the saga.. I added the following command line to the Win2k Scheduled Tasks - when it runs nothing happens, process priorities (e.g. for LHC sixtrack) stay at the low default value and don't get changed.. yet when I run it from the command line it works. Scheduler History shows the task was run at the correct time, with blank status which is supposed to mean success. The command :-
c:\Perl\site\lib\setpriority.pl sixtrack 16384 -1
This Perl script (see previous post) runs Jeff's SetPriority program. Works when runs from command line, not from the scheduler. Any ideas ?
Ahem.. I just discovered that the perl interpreter is not invoked by the Scheduler. If I prefix the Perl interpreter to the execution string it works :
c:\Perl\bin\perl c:\Perl\site\lib\setpriority.pl sixtrack 16384 -1

Bok
11-30-2005, 01:02 AM
Perl not in the environment ?

Same thing happens in unix often..

rbutcher
12-10-2005, 04:45 AM
Originally posted by Digital Parasite
Right, D2OLDaddy does exactly that, designed for D2OL and TSC. It will reset your priority automatically every X seconds that you configure it to do.

Windows 2000 and XP have something called "Scheduled Tasks" that you can setup to run programs/scripts. Its usually found under Accessories -> System Tools from the start menu. If this is just for D2OL/TSC you need it for, I would suggest using D2OL Daddy in windows since it does all that for you automatically.
Jeff, I'm trying to get my Perl script to change thread priorities, by using Win32::API, but I've been told that only the process that creates the thread can get a handle on it to modify it, or to create a "duplicate handle" that another process can use (this other process being the Perl interpreter). - which clearly is not the case with your setpriority C program. Care to share the source so I can see how it's done ?
thanks
Rod

Digital Parasite
12-10-2005, 02:57 PM
Originally posted by rbutcher
JCare to share the source so I can see how it's done ?

Here is the relevant piece of code:



HANDLE hProcessSnap = NULL;
BOOL bRet = FALSE;
THREADENTRY32 te32 = {0};

// Take a snapshot of all processes in the system.

hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);

if (hProcessSnap == INVALID_HANDLE_VALUE)
return (FALSE);

// Fill in the size of the structure before using it.
te32.dwSize = sizeof(THREADENTRY32);

// Get first process information
Thread32First(hProcessSnap, &te32)

// get the thread priority
HANDLE hThread;
hThread = OpenThread(THREAD_SET_INFORMATION|THREAD_QUERY_INFORMATION, FALSE, te32.th32ThreadID);

// set new priority class
if (SetThreadPriority(hThread, threadPriority) != TRUE)
{
cerr << "SetThreadPriority() ";
printError();
}
CloseHandle(hThread);

rbutcher
12-12-2005, 02:59 AM
Thanks for that Jeff. That pointed me to the MSDN website documentation - from that I understand I need to walk thru the Processes using Process32First and then Process32Next untill I find the Process I want, and then use Thread32First like your code shows, to position on the first (only) thread for the process - at least that's the impression I get from the MSDN articles on the subject. Correct ?
thanks
Rod

Digital Parasite
12-12-2005, 06:58 AM
Almost. Changing the priority of the first thread will do just that, change the priority of the first thread. If a process has multiple threads you will have to use the Next() function after you do the first to modify the rest.

If you look at Firefox for example you will see it has multiple threads, running at different priorities:


Process ID (PID): 3224
Current Priority Class : 32
Current Thread Priority: 0
Current Thread Priority: 0
Current Thread Priority: 0
Current Thread Priority: 0
Current Thread Priority: 0
Current Thread Priority: 1
Current Thread Priority: 0
Current Thread Priority: 0
Current Thread Priority: 0
Current Thread Priority: 15
Current Thread Priority: 15
Current Thread Priority: 0


Process Thread
------- ------
RealTime : 256 15
High : 128 2
AboveNormal: 32768 1
Normal : 32 0
BelowNormal: 16384 -1
Idle : 64 -2
Lowest : N/A -15

If you just set the priority of the first thread, it would miss the others. My code will actually walk through the list of all threads and set each one.

rbutcher
12-15-2005, 07:26 PM
Thanks a million Jeff. In case anybody is still interested, here's the Perl code to modify the first thread's priority given a PID. To modify all threads for the PID, we jwould just continue in the Thread32Next loop .

# set first thread for $pid to $hThreadPriority
my $pid = 952;
my $hThreadPriority = 0;
my $retcode;
my $hThreadSnap;
my $hThread;
my $Point;

use strict;
use Win32::API;

Win32::API->Import( 'Kernel32', q[ DWORD GetLastError( ) ] );

$retcode = Win32::API->Import( 'Kernel32',
q[ HANDLE CreateToolhelp32Snapshot
( DWORD dwFlags, DWORD th32ProcessID ) ] );
print "import CreateToolhelp32Snapshot code $retcode \n";

use constant TH32CS_SNAPTHREAD => 0x4;

$hThreadSnap=CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
$retcode = GetLastError();
print "CreateToolhelp32Snapshot error code $retcode \n";
print "hThreadSnap = $hThreadSnap \n";

# typedef for THREADENTRY32
typedef Win32::API::Struct TE32 => qw{
DWORD dwSize;
DWORD cntUsage;
DWORD th32ThreadID;
DWORD th32OwnerProcessID;
LONG tpBasePri;
LONG tpDeltaPri;
DWORD dwFlags;
};

$retcode = Win32::API->Import( 'Kernel32',
q[ BOOL Thread32First
( HANDLE hSnapshot, LPTE32 lpte)]);
print "import thread32first code $retcode \n";

$Point = Win32::API::Struct->new( 'TE32' );
$Point->{dwSize}=28;

Thread32First($hThreadSnap, $Point);
$retcode = GetLastError();
print "thread32first error $retcode \n";
print "pid = $Point->{th32OwnerProcessID} \n";

$retcode = Win32::API->Import( 'Kernel32',
q[ BOOL Thread32Next
( HANDLE hSnapshot, LPTE32 lpte)]);
print "import threadnext code $retcode \n";


until ( $Point->{th32OwnerProcessID} == $pid ) {
Thread32Next($hThreadSnap, $Point);
$retcode = GetLastError();
print "thread32next error $retcode \n";
print "pid = $Point->{th32OwnerProcessID} \n";
}


$retcode = Win32::API->Import( 'Kernel32', q[HANDLE OpenThread(
DWORD dwDesiredAccess,
BOOL bInheritHandle,
DWORD dwThreadId
) ] );
print "import openthread code $retcode \n";

use constant THREAD_SET_INFORMATION => 0x0020;
use constant THREAD_QUERY_INFORMATION => 0x0040;

$hThread = OpenThread(
THREAD_SET_INFORMATION|THREAD_QUERY_INFORMATION,
0,
$Point->{th32ThreadID}
);
$retcode = GetLastError();
print "openthread error code $retcode \n";

$retcode = Win32::API->Import( 'Kernel32', q[BOOL SetThreadPriority(
HANDLE hThread,
int nPriority
) ] );
print "import openthread code $retcode \n";

SetThreadPriority( $hThread, $hThreadPriority );
$retcode = GetLastError();
print "setthreadpriority error code $retcode \n";