From a quick scan through the MSDN for the function, it looks to me that various bits will be available within the mask,
one for each processor on the system, and this mask or all the processors is called the system affinity mask. The
process affinity mask defines which of these processors the specified process can run on, and as such is defined by one
or more of the bits within the system affinity mask (I would assume an affinity mask of 0 would be illegal since it
would indicate it couldn't run on any processor(s).)
If you want to examine the bit mask then use this function to break a DWord into it's binary representation:
http://groups-beta.google.com/group/microsoft.public.vb.general.discussion/msg/b65b7fc45b35a408
Hope this helps,
Mike
- Microsoft Visual Basic MVP -
E-Mail: ED...@mvps.org
WWW: Http://EDais.mvps.org/
So for the Dword in C++ we use the Long in VB6 since they're both 32bit
integer values.
I would assume the process mask will be a string of 0 and 1's then so
"00000000000........010" for example if I'm
followng up properly what you said.
It seems to me then we get the process mask, use the binary function to get
the string of binary 0's and 1's, re-configure
it to indicate an int value of 1, 2, 3 etc, translate it back in a Long and
feed it back into the process using the Set method.
So far it's logical............but for example whether a bit mask of 2 means
processor #2 or that the process's threads can
run on CPU 1 & 2 is not clear.
It seems to me as I can't find a VB example of this (though I'm quite sure
it's equally possible) I will need to hunt down
a C++ example and translate it line by line.
Thanks.
Adam
"Mike D Sutton" <ED...@mvps.org> wrote in message
news:uyMvF5DG...@TK2MSFTNGP09.phx.gbl...
Yep, C++'s DWord is unsigned where as VB's Long is signed however as long as you're careful with the sign bit Long's can
be used in the same way.
> I would assume the process mask will be a string of 0 and 1's then so
> "00000000000........010" for example if I'm followng up properly what you said.
Well yes, any value be that a number, string, UDT etc is stored in binary essentially, the function I linked to in my
prior post simply converts the value into it's bit-pattern which makes it easier for us to see how the value is stored.
> It seems to me then we get the process mask, use the binary function to get
> the string of binary 0's and 1's, re-configure
> it to indicate an int value of 1, 2, 3 etc, translate it back in a Long and
> feed it back into the process using the Set method.
>
> So far it's logical............but for example whether a bit mask of 2 means
> processor #2 or that the process's threads can
> run on CPU 1 & 2 is not clear.
I was looking for some kind of correlation between the individual bits and their position within the affinity mask when
scanning through the MSDN but couldn't find anything, does it really matter though? Since all the processors in a
system have to be equal (AFAIK) it shouldn't really matter which processor(s) you use, they should all be the same.
Perhaps there is some reason for you needing to specifically tie a process down to a specific processor that you've not
previously mentioned though, and in which case I would suggest simply playing around with sending different affinity
masks and stress the processor in your application - whichever CPU usage graph spikes in Task manager corresponds to
that particular bit. I wouldn't be surprised though if bit 1 was processor 1, bit 2, processor 2 etc.
> It seems to me as I can't find a VB example of this (though I'm quite sure
> it's equally possible) I will need to hunt down
> a C++ example and translate it line by line.
I would just use bit-wise mathematics to process the affinity mask, for example here's a little routine that will
extract the bit-masks for each bit set within a DWord:
'***
Private Sub Form_Load()
Dim BitMasks() As Long, NumMasks As Long, LoopMasks As Long
Const AffinityMask As Long = &HF ' 00001111b
BitMasks() = GetBitMasks(AffinityMask)
On Error Resume Next
NumMasks = UBound(BitMasks) + 1
On Error GoTo 0
For LoopMasks = 0 To NumMasks - 1
Debug.Print "Bit-mask #" & CStr(LoopMasks + 1) & _
" = 0x" & Hex(BitMasks(LoopMasks))
Next LoopMasks
End Sub
Private Function GetBitMasks(ByVal inValue As Long) As Long()
Dim RetArr() As Long, NumRet As Long
Dim LoopBits As Long, BitMask As Long
Const HighBit As Long = &H80000000
ReDim RetArr(0 To 31) As Long
For LoopBits = 0 To 30
BitMask = 2 ^ LoopBits
If (inValue And BitMask) Then
RetArr(NumRet) = BitMask
NumRet = NumRet + 1
End If
Next LoopBits
If (inValue And HighBit) Then
RetArr(NumRet) = HighBit
NumRet = NumRet + 1
End If
If (NumRet > 0) Then ' Trim unused array items and return array
If (NumRet < 32) Then ReDim Preserve RetArr(0 To NumRet - 1) As Long
GetBitMasks = RetArr
End If
End Function
'***
You can then create your affinity mask by combining these flags back into a single value by using the Or bitwise
operator:
'***
MyMask = BitMasks(0) Or BitMasks(1) ' Use first two processors only
'***
As far the API call goes, this seems to work fine here:
'***
Private Declare Function GetCurrentProcess Lib "Kernel32.dll" () As Long
Private Declare Function GetProcessAffinityMask Lib "Kernel32.dll" ( _
ByVal hProcess As Long, ByRef lpProcessAffinityMask As Long, _
ByRef SystemAffinityMask As Long) As Long
Private Sub Form_Load()
Dim ProcMask As Long, SysMask As Long
Call GetProcessAffinityMask(GetCurrentProcess(), ProcMask, SysMask)
Debug.Print "Process affinity mask: 0x" & Hex(ProcMask)
Debug.Print "SystemAffinityMask: 0x" & Hex(SysMask)
End Sub
'***
Here this returns 0xF and 0xF indicating a quad processor box (0xF == 00001111b == 4 bits set) and the application
should use all of them.
As it is I can instead concentrate on what I really want to do and that's
support Hyper Threading and SMP systems.
It seems I must concentrate on SetThreadAffinityMask() and possibly
SetThreadIdealProcessor()
From what I can see there is no GetThreadAffinityMask() API function.....
1) Reading the MSDN the affinity mask of the thread must match the processor
or am I reading it incorrectly? If this
is true when how does one force a thread to say CPU #2? What if the process
is MAXIMUM_PROCESSORS?
2) SetThreadIdealProcessor() seems like an easier method but then not a
guaranteed one (though I can't think
why it wouldn't always work, unless a CPU is 100% usage that is etc.). The
only problem here is I don't get what
MS means by saying this is a zero based value for dwIdealProcessor ???
Thanks,
Adam H.
"Mike D Sutton" <ED...@mvps.org> wrote in message
news:%23KvWb9E...@TK2MSFTNGP14.phx.gbl...
<quote src="MSDN">
Setting thread affinity should generally be avoided, because it can interfere with the scheduler's ability to schedule
threads effectively across processors. This can decrease the performance gains produced by parallel processing. An
appropriate use of thread affinity is testing each processor.
</quote>
> From what I can see there is no GetThreadAffinityMask() API function.....
<quote src="MSDN">
The thread affinity must be a subset of the process affinity. You can obtain the current process affinity by calling the
GetProcessAffinityMask function.
</quote>
> 1) Reading the MSDN the affinity mask of the thread must match the processor
> or am I reading it incorrectly? If this
> is true when how does one force a thread to say CPU #2? What if the process
> is MAXIMUM_PROCESSORS?
You either pass the function the index of the specific processor you wish it to run on or you pass it the constant
MAXIMUM_PROCESSORS to specify that you don't care which processor it's run on and let the scheduler decide at runtime.
> 2) SetThreadIdealProcessor() seems like an easier method but then not a
> guaranteed one (though I can't think
> why it wouldn't always work, unless a CPU is 100% usage that is etc.). The
> only problem here is I don't get what
> MS means by saying this is a zero based value for dwIdealProcessor ???
Since MAXIMUM_PROCESSORS is defined as 32 (at least in 32-bit programming, in 64-bit development it's defined as 64
however this is beyond the realm of VB ;) it makes sense that the values 0 to 31 define up to 32 separate processors.
What may be confusing you is that the Get/Set*AffinityMask() methods use a bit-masks to indicate one or more processors
where as SetThreadIdealProcessor() uses a index to indicate a single processor only.