The following code sample comes from "Juice Up Your App with the Power of Hyper-Threading", an MSDN article:
public void SetProcessAffinityToPhysicalCPUForHyperthreadOnly(int processid)
{
int res;
int hProcess;
int ProcAffinityMask = 0, SysAffinityMask = 0;
hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, processid);
res = GetProcessAffinityMask(
hProcess, ref ProcAffinityMask, ref SysAffinityMask);
if (SysAffinityMask == 3) // 1 proc, 2 logical CPUs
res = SetProcessAffinityMask(hProcess, 1);
else if (SysAffinityMask == 15) //dual proc, 4 virtual CPUs
res = SetProcessAffinityMask(hProcess, 3);
res = CloseHandle(hProcess);
}
From the sample above, we see that the affinity mask is such that all physical processors come first in the mask, then the logical (Hyper-threaded) processors.
If your process is a heavy user of floating point instructions, setting the affinity mask to (number of processors/2) - 1 will make sure your threads will give preference for the physical processors which have FPU.
For a sample on how to detect if Hyper-Thread is on in C/C++, you could use this:
__inline BOOL hyperThreadingOn()
{
DWORD rEbx, rEdx;
__asm {
push eax // save registers used
push ebx
push ecx
push edx
xor eax,eax // cpuid(1)
add al, 0x01
_emit 0x0F
_emit 0xA2
mov rEdx, edx // Features Flags, bit 28 indicates if HTT (Hyper-Thread Technology) is
// available, but not if it is on; if on, Count of logical processors > 1.
mov rEbx, ebx // Bits 23-16: Count of logical processors.
// Valid only if Hyper-Threading Technology flag is set.
pop edx // restore registers used
pop ecx
pop ebx
pop eax
}
return (rEdx & (1<<28)) && (((rEbx & 0x00FF0000) >> 16) > 1);
}