Hyper-Threading and ProcessorAffinity

  • Thread starter Thread starter Guest
  • Start date Start date
G

Guest

I create new thread as following:
Thread mThread = new Thread(new ThreadStart(m_ClassThread.Go));
In my system I have 2 Process devices ,(CPU0 and CPU1) , I want to create 3
Threads, 2 of those thread to run in CPU0 and the last one in CPU1 , I get
some advice to use the ProcessThread.ProcessorAffinity which seems OK to me .
The problem is how and where to use it ?
Should I change the :
Thread mThread = new Thread(new ThreadStart(m_ClassThread.Go));
mThread.Start();
How to do that . is there any whay to do something like :
SetProcessorAffinity( ref hthread, int mask) ?????
 
Yosi,

You could try and do it, however, this isn't a good idea in .NET. In
..NET, the Thread class doesn't represent a physical thread. It is a logical
thread of execution. Because of this, you don't know how the current thread
you are running on maps to the physical OS thread that it is running on.

If you really need to do this, I would perform your tasks in unmanaged
code and set the affinity there.

Hope this helps.
 
I create new thread as following:
Thread mThread = new Thread(new ThreadStart(m_ClassThread.Go));
In my system I have 2 Process devices ,(CPU0 and CPU1) , I want to create
3
Threads, 2 of those thread to run in CPU0 and the last one in CPU1 , I
get
some advice to use the ProcessThread.ProcessorAffinity which seems OK to
me .
The problem is how and where to use it ?
Should I change the :
Thread mThread = new Thread(new ThreadStart(m_ClassThread.Go));
mThread.Start();
How to do that . is there any whay to do something like :
SetProcessorAffinity( ref hthread, int mask) ?????

Here is how you can do it.

using System;
using System.Runtime.InteropServices;

using System.Diagnostics;
using System.Threading;
namespace Tester
{
class Program
{
[DllImport("kernel32")]
static extern int GetCurrentThreadId();
static void Main()
{
Thread t = new Thread(
new ThreadStart(DoWork));
t.Start();
t.Join();
}
static void DoWork()
{
foreach(ProcessThread pt in Process.GetCurrentProcess().Threads)
{
int utid = GetCurrentThreadId();
if (utid == pt.Id)
{
pt.ProcessorAffinity = (IntPtr)(1); // Set affinity for this
thread to CPU #1
Console.WriteLine("Set");
}
}
}
}
}


Willy.
 
Willy,

"Willy Denoyette [MVP]" <[email protected]> schreef in bericht
[...]
How to do that . is there any whay to do something like :
SetProcessorAffinity( ref hthread, int mask) ?????

Here is how you can do it.

using System;
using System.Runtime.InteropServices;

using System.Diagnostics;
using System.Threading;
namespace Tester
{
class Program
{
[DllImport("kernel32")]
static extern int GetCurrentThreadId();
static void Main()
{
Thread t = new Thread(
new ThreadStart(DoWork));
t.Start();
t.Join();
}
static void DoWork()
{
foreach(ProcessThread pt in Process.GetCurrentProcess().Threads)
{
int utid = GetCurrentThreadId();

Does GetCurrentThread return the same ID each time in this loop? I heard
that .NET threads are logical threads, not physical threads. So technically,
wouldn't it be possible that another physical thread starts executing the
logical thread?
if (utid == pt.Id)
{
pt.ProcessorAffinity = (IntPtr)(1); // Set affinity for this
thread to CPU #1
Console.WriteLine("Set");
}
}
}
}
}

Willy.

Kind regards,
 
TT (Tom Tempelaere) said:
Willy,

"Willy Denoyette [MVP]" <[email protected]> schreef in bericht
[...]
How to do that . is there any whay to do something like :
SetProcessorAffinity( ref hthread, int mask) ?????

Here is how you can do it.

using System;
using System.Runtime.InteropServices;

using System.Diagnostics;
using System.Threading;
namespace Tester
{
class Program
{
[DllImport("kernel32")]
static extern int GetCurrentThreadId();
static void Main()
{
Thread t = new Thread(
new ThreadStart(DoWork));
t.Start();
t.Join();
}
static void DoWork()
{
foreach(ProcessThread pt in Process.GetCurrentProcess().Threads)
{
int utid = GetCurrentThreadId();

Does GetCurrentThread return the same ID each time in this loop? I heard
that .NET threads are logical threads, not physical threads. So
technically, wouldn't it be possible that another physical thread starts
executing the logical thread?
if (utid == pt.Id)
{
pt.ProcessorAffinity = (IntPtr)(1); // Set affinity for this
thread to CPU #1
Console.WriteLine("Set");
}
}
}
}
}

Willy.

Kind regards,

Tom,

I'm not using any Logical thread Id here, both 'GetCurrentThreadId' and
'pt.Id ' return the OS thread id. I'm using the first to get the current OS
thread ID and use the ID to search the corresponding thread in the
ProcessThreadCollection, once I have the ProcessThread I can use
ProcessorAffinity to set the affinity mask. As long as the thread runs it
keeps the same Id (and the same logical thread which I don't care).
I ran this on an 8 way box, funny how you can disturb the system by playing
with this :-)). IMO this API (ProcessorAffinity) shouldnt be used from
managed code, honestly I don't see why it was included in the framework,
while other more important features are still missing, cheep to implement I
guess.

Willy.
 
Hi Willy,

Willy Denoyette said:
TT (Tom Tempelaere) said:
Willy,

"Willy Denoyette [MVP]" <[email protected]> schreef in bericht
[...]
How to do that . is there any whay to do something like :
SetProcessorAffinity( ref hthread, int mask) ?????

Here is how you can do it.

using System;
using System.Runtime.InteropServices;

using System.Diagnostics;
using System.Threading;
namespace Tester
{
class Program
{
[DllImport("kernel32")]
static extern int GetCurrentThreadId();
static void Main()
{
Thread t = new Thread(
new ThreadStart(DoWork));
t.Start();
t.Join();
}
static void DoWork()
{
foreach(ProcessThread pt in Process.GetCurrentProcess().Threads)
{
int utid = GetCurrentThreadId();

Does GetCurrentThread return the same ID each time in this loop? I heard
that .NET threads are logical threads, not physical threads. So
technically, wouldn't it be possible that another physical thread starts
executing the logical thread?
if (utid == pt.Id)
{
pt.ProcessorAffinity = (IntPtr)(1); // Set affinity for this
thread to CPU #1
Console.WriteLine("Set");
}
}
}
}
}

Willy.

Kind regards,

Tom,

I'm not using any Logical thread Id here, both 'GetCurrentThreadId' and
'pt.Id ' return the OS thread id. I'm using the first to get the current
OS thread ID and use the ID to search the corresponding thread in the
ProcessThreadCollection, once I have the ProcessThread I can use
ProcessorAffinity to set the affinity mask. As long as the thread runs it
keeps the same Id (and the same logical thread which I don't care).
I ran this on an 8 way box, funny how you can disturb the system by
playing with this :-)). IMO this API (ProcessorAffinity) shouldnt be used
from managed code, honestly I don't see why it was included in the
framework, while other more important features are still missing, cheep to
implement I guess.

Willy.

What I meant is that .NET has logical threads, the OS has physical threads
(if I read that correctly). Logical threads are executed on physical
threads, but I don't know if they need to execute on the same physical
thread each time the logical thread's time-slice phases in.

Actually I don't know the real details about how .NET framework implements
threading on WinOS. But if the logical thread can be executed by different
physical threads, then if the logical thread phases out right after the call
to GetCurrentThreadId, the logical thread could be rescheduled on a
different physical thread so the ID you got is no longer the correct one.
This is just my train of thought now, considering the difference between
physical and logical threads.

A sketch of my thoughts

// --> logical .NET thread [L_X] scheduled on physical WinOS thread [P_X]
int utId = GetCurrentThreadId( ); // utId == P_X
// --> the logical thread ends its time slice
....
// --> logical .NET thread [L_X] scheduled on physical WinOS thread [P_Y]
if (utId == pt.Id) // utId != P_Y

I'm not saying that this is possible, as I said I know too little of the
internal details. I think that the logical and the physical threads are
tightly coupled in the implementation of MS's .NET framework, but should
they be? Why did they make the distinction between logical and physical
threads otherwise? Does the documentation say that a logical thread is
always scheduled on the same physical thread?

Kind regards,
 
Tom, see inline...

Willy.

What I meant is that .NET has logical threads, the OS has physical threads
(if I read that correctly). Logical threads are executed on physical
threads, but I don't know if they need to execute on the same physical
thread each time the logical thread's time-slice phases in.

Logical thread don't execute, only physical threads do, and each logical
thread (an object instance) is associated with a physical thread. This
associating is fixed and exists for the lifetime of the logical thread.
Also logical threads do not get scheduled, so they aren't "time-sliced".
Actually I don't know the real details about how .NET framework implements
threading on WinOS. But if the logical thread can be executed by different
physical threads, then if the logical thread phases out right after the
call to GetCurrentThreadId, the logical thread could be rescheduled on a
different physical thread so the ID you got is no longer the correct one.
This is just my train of thought now, considering the difference between
physical and logical threads.

No, as said before a logical thread is associated with a physical thread
which ceases to exist when the thread procedure exists. Note, I'm not
talking about Threadpool threads, only regular self started threads.
A sketch of my thoughts

// --> logical .NET thread [L_X] scheduled on physical WinOS thread [P_X]
int utId = GetCurrentThreadId( ); // utId == P_X
// --> the logical thread ends its time slice
...
// --> logical .NET thread [L_X] scheduled on physical WinOS thread [P_Y]
if (utId == pt.Id) // utId != P_Y

I'm not saying that this is possible, as I said I know too little of the
internal details. I think that the logical and the physical threads are
tightly coupled in the implementation of MS's .NET framework, but should
they be? Why did they make the distinction between logical and physical
threads otherwise? Does the documentation say that a logical thread is
always scheduled on the same physical thread?

Again, a logical thread doesn't get scheduled, it's a CLR data structure not
an active OS object, the CLR keeps track of the asociations and the OS
threads keeps a reference (in TLS) to the corresponding CLR thread's data
structure.
The distinction is simply an abstraction, at the application level you
shouldn't care about the underlying implementation, that way the CLI
implementor has the freedom to implement threading as he sees fit (depending
on the available OS platform services). For instance the CLI (or an Hosting
process like SQL2005) could associate a Fiber instead of a OS thread to a
logical thread.
In such a case, multiple logical threads would run on the same OS thread,
and these logical threads would end on the same CPU if you set the OS thread
affinity.

Willy.
 
I can think of a couple of reasons you might/may want to set processor
affinity (even from managed code).

1. You're selling an application that you license by the processor.
They've only bought a one-processor license, so that's all they get.

2. You are USING an application that you license by the processor (SQL
Server) and you're not using all the processors for it. You might want
to have your application running on the non-SQL Server processors so
that it doesn't slow down the SQL Server ones. Memory would be a
separate issue, of course.

Chuck
 
I can think of a couple of reasons you might/may want to set processor
affinity (even from managed code).

1. You're selling an application that you license by the processor.
They've only bought a one-processor license, so that's all they get.

HT cores are not physical CPU's! You ain't gonna license your application
per logical CPU do you?
2. You are USING an application that you license by the processor (SQL
Server) and you're not using all the processors for it. You might want
to have your application running on the non-SQL Server processors so
that it doesn't slow down the SQL Server ones. Memory would be a
separate issue, of course.
Same here SQL server license is not per logical CPU, an HT P4 for instance
is considered one single CPU for SQL server (and for the Windows OS).

Willy.
 
Back
Top