none
GetLogicalProcessorInformation

    Question

  • This board is so screwed up.

     

    This code which came from MS was translated from C# to VB. It doesn't work. I suspect the initalization of the Intptr:

     

    Dim Yellow As IntPtr = New IntPtr(alpha(0))

     

    The code return says that it requires about 238 butes on my x6800. That's filled in..but the array is blank.

     

    Public Class Form1

        Dim alpha(250) As Byte

        Dim Retlen As Integer

        Dim Yellow As IntPtr = New IntPtr(alpha(0))

        Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

            Lv1.Columns.Add("Address", 100) ' For Search

            Lv1.Columns.Add("Contents", 200)

            Dim stat As Integer = NativeMethods.GetLogicalProcessorInformation(Yellow, Retlen)

            For i = 0 To 249

                Lv1.Items.Add(alpha(i))

            Next

     

        End Sub

        <System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)> _

        Public Structure SYSTEM_LOGICAL_PROCESSOR_INFORMATION

            ''' ULONG_PTR->unsigned int

            Public ProcessorMask As UInteger

            ''' LOGICAL_PROCESSOR_RELATIONSHIP->_LOGICAL_PROCESSOR_RELATIONSHIP

            Public Relationship As LOGICAL_PROCESSOR_RELATIONSHIP

            ''' Anonymous_cfba373b_d315_405c_b345_eabbe699bc66

            Public Union1 As Anonymous_cfba373b_d315_405c_b345_eabbe699bc66

        End Structure

     

        <System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Explicit)> _

        Public Structure Anonymous_cfba373b_d315_405c_b345_eabbe699bc66

            ''' Anonymous_ccf454b1_fcd7_4ef6_bdd3_a1452ec5448e

            <System.Runtime.InteropServices.FieldOffsetAttribute(0)> _

            Public ProcessorCore As Anonymous_ccf454b1_fcd7_4ef6_bdd3_a1452ec5448e

            ''' Anonymous_6bf0fd06_e931_4db4_bf97_e2e2b7af523b

            <System.Runtime.InteropServices.FieldOffsetAttribute(0)> _

            Public NumaNode As Anonymous_6bf0fd06_e931_4db4_bf97_e2e2b7af523b

     

            ''' CACHE_DESCRIPTOR->_CACHE_DESCRIPTOR

            <System.Runtime.InteropServices.FieldOffsetAttribute(0)> _

            Public Cache As CACHE_DESCRIPTOR

            ''' ULONGLONG[2]

            <System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst:=2, ArraySubType:=System.Runtime.InteropServices.UnmanagedType.U8)> _

            <System.Runtime.InteropServices.FieldOffsetAttribute(0)> _

            Public Reserved As ULong()

     

        End Structure

     

        Public Enum LOGICAL_PROCESSOR_RELATIONSHIP

            RelationProcessorCore

            RelationNumaNode

            RelationCache

        End Enum

     

        <System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)> _

        Public Structure Anonymous_ccf454b1_fcd7_4ef6_bdd3_a1452ec5448e

            ''' BYTE->unsigned char

            Public Flags As Byte

        End Structure

     

        <System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)> _

        Public Structure Anonymous_6bf0fd06_e931_4db4_bf97_e2e2b7af523b

            ''' DWORD->unsigned int

            Public NodeNumber As UInteger

        End Structure

     

        <System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)> _

        Public Structure CACHE_DESCRIPTOR

            ''' BYTE->unsigned char

            Public Level As Byte

            ''' BYTE->unsigned char

            Public Associativity As Byte

            ''' WORD->unsigned short

            Public LineSize As UShort

            ''' DWORD->unsigned int

            Public Size As UInteger

            ''' PROCESSOR_CACHE_TYPE->_PROCESSOR_CACHE_TYPE

            Public Type As PROCESSOR_CACHE_TYPE

        End Structure

     

     

     

        Public Enum PROCESSOR_CACHE_TYPE

            CacheUnified

            CacheInstruction

            CacheData

            CacheTrace

        End Enum

     

        Partial Public Class NativeMethods

            ''' Return Type: BOOL->int

            '''Buffer:PSYSTEM_LOGICAL_PROCESSOR_INFORMATION>_SYSTEM_LOGICAL_PROCESSOR_INFORMATION*

            '''ReturnedLength: PDWORD->DWORD*

            <System.Runtime.InteropServices.DllImportAttribute("kernel32.dll", EntryPoint:="GetLogicalProcessorInformation")> _

            Public Shared Function GetLogicalProcessorInformation(ByRef Buffer As System.IntPtr, ByRef ReturnedLength As UInteger) As <System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.Bool)> Boolean

            End Function

        End Class

     

    End Class

     



    Wednesday, June 08, 2011 12:53 AM

Answers

  • I'm not an expert on P/Invoke, but I think the answer is to handle the first argument in the definition of the GetLogicalProcessorInformation function in the same way as in Hannes' post.  That is change it from ByRef buffer As System.IntPtr to ByVal buffer as SYSTEM_LOGICAL_PROCESSOR_INFORMATION(). You should then be able to call the function passing and array of SYSTEM_LOGICAL_PROCESSOR_INFORMATION as the first parameter. By the way, I'm always mixing up the definition of argument and parameter, so I may have them backwards in the preceding sentences.

    • Marked as answer by Renee Culver Wednesday, June 08, 2011 1:13 PM
    Wednesday, June 08, 2011 2:34 AM
  • This is the changed version ( without the lv1.. stuff ). This compiles without problems.

    Public Class Form1
    
      Dim alpha(250) As Integer
    
      Dim Retlen As UInteger
    
      Dim Yellow As IntPtr = New IntPtr(alpha(0))
    
      Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        Dim ret As Boolean = NativeMethods.GetLogicalProcessorInformation(alpha(0), Retlen)
        ret = NativeMethods.GetLogicalProcessorInformation(alpha(0), Retlen)
      End Sub
    
      <System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)> Public Structure SYSTEM_LOGICAL_PROCESSOR_INFORMATION
    
        ''' ULONG_PTR->unsigned int
    
        Public ProcessorMask As UInteger
    
        ''' LOGICAL_PROCESSOR_RELATIONSHIP->_LOGICAL_PROCESSOR_RELATIONSHIP
    
        Public Relationship As LOGICAL_PROCESSOR_RELATIONSHIP
    
        ''' Anonymous_cfba373b_d315_405c_b345_eabbe699bc66
    
        Public Union1 As Anonymous_cfba373b_d315_405c_b345_eabbe699bc66
    
      End Structure
    
    
    
      <System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Explicit)> Public Structure Anonymous_cfba373b_d315_405c_b345_eabbe699bc66
    
        ''' Anonymous_ccf454b1_fcd7_4ef6_bdd3_a1452ec5448e
    
        <System.Runtime.InteropServices.FieldOffsetAttribute(0)> Public ProcessorCore As Anonymous_ccf454b1_fcd7_4ef6_bdd3_a1452ec5448e
    
        ''' Anonymous_6bf0fd06_e931_4db4_bf97_e2e2b7af523b
    
        <System.Runtime.InteropServices.FieldOffsetAttribute(0)> Public NumaNode As Anonymous_6bf0fd06_e931_4db4_bf97_e2e2b7af523b
    
    
    
        ''' CACHE_DESCRIPTOR->_CACHE_DESCRIPTOR
    
        <System.Runtime.InteropServices.FieldOffsetAttribute(0)> Public Cache As CACHE_DESCRIPTOR
    
        ''' ULONGLONG[2]
    
        <System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst:=2, ArraySubType:=System.Runtime.InteropServices.UnmanagedType.U8)> <System.Runtime.InteropServices.FieldOffsetAttribute(0)> Public Reserved As ULong()
    
    
    
      End Structure
    
    
    
      Public Enum LOGICAL_PROCESSOR_RELATIONSHIP
    
        RelationProcessorCore
    
        RelationNumaNode
    
        RelationCache
    
      End Enum
    
    
    
      <System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)> Public Structure Anonymous_ccf454b1_fcd7_4ef6_bdd3_a1452ec5448e
    
        ''' BYTE->unsigned char
    
        Public Flags As Byte
    
      End Structure
    
    
    
      <System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)> Public Structure Anonymous_6bf0fd06_e931_4db4_bf97_e2e2b7af523b
    
        ''' DWORD->unsigned int
    
        Public NodeNumber As UInteger
    
      End Structure
    
    
    
      <System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)> Public Structure CACHE_DESCRIPTOR
    
        ''' BYTE->unsigned char
    
        Public Level As Byte
    
        ''' BYTE->unsigned char
    
        Public Associativity As Byte
    
        ''' WORD->unsigned short
    
        Public LineSize As UShort
    
        ''' DWORD->unsigned int
    
        Public Size As UInteger
    
        ''' PROCESSOR_CACHE_TYPE->_PROCESSOR_CACHE_TYPE
    
        Public Type As PROCESSOR_CACHE_TYPE
    
      End Structure
    
    
    
    
    
    
    
      Public Enum PROCESSOR_CACHE_TYPE
    
        CacheUnified
    
        CacheInstruction
    
        CacheData
    
        CacheTrace
    
      End Enum
    
    
    
      Partial Public Class NativeMethods
    
        ''' Return Type: BOOL->int
    
        '''Buffer:PSYSTEM_LOGICAL_PROCESSOR_INFORMATION>_SYSTEM_LOGICAL_PROCESSOR_INFORMATION*
    
        '''ReturnedLength: PDWORD->DWORD*
    
        <System.Runtime.InteropServices.DllImportAttribute _
        ("kernel32.dll", EntryPoint:="GetLogicalProcessorInformation")> _
        Public Shared Function GetLogicalProcessorInformation(ByRef Buffer As Integer, ByRef ReturnedLength As UInteger) As <System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.Bool)> Boolean
    
        End Function
    
      End Class
    
    
    
    End Class
    
    
    
    

    Hannes

    If you have got questions about this, just ask.

    In a perfect world,
    users would never enter data in the wrong form,
    files they choose to open would always exist
    and code would never have bugs.

    C# to VB.NET: http://www.developerfusion.com/tools/convert/csharp-to-vb/
    • Marked as answer by Renee Culver Wednesday, June 08, 2011 1:13 PM
    Wednesday, June 08, 2011 3:27 AM

All replies

  • Renee,

    i have found some working code here: http://blogs.adamsoftware.net/Engine/DeterminingthenumberofphysicalCPUsonWindows.aspx and converted it to vb.net:

    Imports System.Collections.Generic
    Imports System.Globalization
    Imports System.Runtime.InteropServices
    Imports System.Security
    Imports System.Text
    
    Namespace CpuCount
      Public NotInheritable Class Machine
        Private Sub New()
        End Sub
        Private Const ERROR_INSUFFICIENT_BUFFER As Integer = 122
        Private Enum PROCESSOR_CACHE_TYPE
          ''' <summary>
          ''' The cache is unified.
          ''' </summary>
          UnifiedCache = 0
          ''' <summary>
          ''' InstructionThe cache is for processor instructions.
          ''' </summary>
          InstructionCache = 1
          ''' <summary>
          ''' The cache is for data.
          ''' </summary>
          DataCache = 2
          ''' <summary>
          ''' TraceThe cache is for traces.
          ''' </summary>
          TraceCache = 3
        End Enum
        <StructLayout(LayoutKind.Sequential)> _
        Private Structure CACHE_DESCRIPTOR
          Private Level As Byte
          Private Associativity As Byte
          Private LineSize As UInt16
          Private Size As UInt32
          <MarshalAs(UnmanagedType.U4)> _
          Private Type As PROCESSOR_CACHE_TYPE
        End Structure
        Private Enum RelationProcessorCore
          ''' <summary>
          ''' The specified logical processors share a 
          ''' single processor core.  
          ''' </summary>
          RelationProcessorCore = 0
          ''' <summary>
          ''' The specified logical processors are part 
          ''' of the same NUMA node.
          ''' </summary>
          RelationNumaNode = 1
          ''' <summary>
          ''' The specified logical processors share a cache. 
          ''' Windows Server 2003: This value is not supported 
          ''' until Windows Server 2003 SP1 and Windows XP 
          ''' Professional x64 Edition.
          ''' </summary>
          RelationCache = 2
          ''' <summary>
          ''' The specified logical processors share a physical 
          ''' package (a single package socketed or soldered 
          ''' onto a motherboard may contain multiple processor 
          ''' cores or threads, each of which is treated as a 
          ''' separate processor by the operating system). 
          ''' Windows Server 2003: This value is not 
          ''' supported until Windows Vista.
          ''' </summary>
          RelationProcessorPackage = 3
        End Enum
        <StructLayout(LayoutKind.Explicit)> _
        Private Structure SYSTEM_LOGICAL_PROCESSOR_INFORMATIONx86
          <FieldOffset(0)> _
          Public ProcessorMask As UInteger
          <FieldOffset(4), MarshalAs(UnmanagedType.U4)> _
          Public Relationship As RelationProcessorCore
          <FieldOffset(8)> _
          Public Flags As Byte
          <FieldOffset(8)> _
          Public Cache As CACHE_DESCRIPTOR
          <FieldOffset(8)> _
          Public NodeNumber As UInt32
          <FieldOffset(8)> _
          Public Reserved1 As UInt64
          <FieldOffset(16)> _
          Public Reserved2 As UInt64
        End Structure
        <DllImport("kernel32.dll", SetLastError:=True)> _
        Private Shared Function GetLogicalProcessorInformation(<Out()> ByVal infos As SYSTEM_LOGICAL_PROCESSOR_INFORMATIONx86(), ByRef infoSize As UInteger) As Boolean
        End Function
        <StructLayout(LayoutKind.Explicit)> _
        Private Structure SYSTEM_LOGICAL_PROCESSOR_INFORMATIONx64
          <FieldOffset(0)> _
          Public ProcessorMask As UInteger
          <FieldOffset(8), MarshalAs(UnmanagedType.U4)> _
          Public Relationship As RelationProcessorCore
          <FieldOffset(12)> _
          Public Flags As Byte
          <FieldOffset(12)> _
          Public Cache As CACHE_DESCRIPTOR
          <FieldOffset(12)> _
          Public NodeNumber As UInt32
          <FieldOffset(12)> _
          Public Reserved1 As UInt64
          <FieldOffset(20)> _
          Public Reserved2 As UInt64
        End Structure
        <DllImport("kernel32.dll", SetLastError:=True)> _
        Private Shared Function GetLogicalProcessorInformation(<Out()> ByVal infos As SYSTEM_LOGICAL_PROCESSOR_INFORMATIONx64(), ByRef infoSize As UInteger) As Boolean
        End Function
        Private Class ProcessorInfo
          Private _Relationship As RelationProcessorCore
          Private _Flags As Byte
          Private _ProcessorMask As UInteger
          Public Sub New(ByVal relationShip As RelationProcessorCore, ByVal flags As Byte, ByVal processorMask As UInteger)
            _Relationship = relationShip
            _Flags = flags
            _ProcessorMask = processorMask
          End Sub
          Public ReadOnly Property Relationship() As RelationProcessorCore
            Get
              Return _Relationship
            End Get
          End Property
          Public ReadOnly Property Flags() As Byte
            Get
              Return _Flags
            End Get
          End Property
          Public ReadOnly Property ProcessorMask() As UInteger
            Get
              Return _ProcessorMask
            End Get
          End Property
        End Class
        ''' <summary>
        ''' Gets <b>true</b> if this process is running in a 64 bit
        ''' environment, <b>false</b> otherwise.
        ''' </summary>
        Public Shared ReadOnly Property Is64BitProcess() As Boolean
          Get
            Return Marshal.SizeOf(GetType(IntPtr)) = 8
          End Get
        End Property
        ''' <summary>
        ''' Gets <b>true</b> if this is a 64 bit Windows.
        ''' </summary>
        Public Shared ReadOnly Property Is64BitWindows() As Boolean
          Get
            ' The purpose is to know if we're running in pure 32-bit 
            ' or if we're running in an emulated 32-bit environment.
            ' Earlier versions of this method checked for the existence 
            ' of the HKLM\Software\Wow6432Node node, but this turned 
            ' out to be not realiable. Apparently, this node can exist 
            ' on a 32-bit Windows as well.
            Try
              Dim sArchitecture As String = Environment.GetEnvironmentVariable("PROCESSOR_ARCHITECTURE", EnvironmentVariableTarget.Machine)
              If sArchitecture Is Nothing Then
                Return False
              Else
                Return sArchitecture.Contains("64")
              End If
            Catch generatedExceptionName As NotSupportedException
              Return False
            Catch generatedExceptionName As ArgumentException
              Return False
            End Try
          End Get
        End Property
        ''' <summary>
        ''' Returns <b>true</b> if this is a 32-bit process 
        ''' running on a 64-bit server.
        ''' </summary>
        Public Shared ReadOnly Property IsWow64Process() As Boolean
          Get
            Return Machine.Is64BitWindows AndAlso Not Machine.Is64BitProcess
          End Get
        End Property
        Private Shared Function GetProcessorInfo86() As List(Of ProcessorInfo)
          ' First we're going to execute GetLogicalProcessorInformation 
          ' once to make sure that we determine the size of the data 
          ' that it is going to return.
          ' This call should fail with error ERROR_INSUFFICIENT_BUFFER.
          Dim iReturnLength As UInteger = 0
          Dim oDummy As SYSTEM_LOGICAL_PROCESSOR_INFORMATIONx86() = Nothing
          Dim bResult As Boolean = GetLogicalProcessorInformation(oDummy, iReturnLength)
          If bResult Then
            Throw Fail("GetLogicalProcessorInformation failed.", "x86")
          End If
          ' Making sure that the error code that we got back isn't that 
          ' there is insufficient space in the buffer.
          Dim iError As Integer = Marshal.GetLastWin32Error()
          If iError <> ERROR_INSUFFICIENT_BUFFER Then
            Throw Fail("Insufficient space in the buffer.", "x86", iError.ToString())
          End If
          ' Now that we know how much space we should reserve, 
          ' we're going to reserve it and call 
          ' GetLogicalProcessorInformation again.
          Dim iBaseSize As UInteger = CUInt(Marshal.SizeOf(GetType(SYSTEM_LOGICAL_PROCESSOR_INFORMATIONx86)))
          Dim iNumberOfElements As UInteger = iReturnLength \ iBaseSize
          Dim oData As SYSTEM_LOGICAL_PROCESSOR_INFORMATIONx86() = New SYSTEM_LOGICAL_PROCESSOR_INFORMATIONx86(Convert.ToInt32(Convert.ToUInt32(iNumberOfElements - 1))) {}
          Dim iAllocatedSize As UInteger = iNumberOfElements * iBaseSize
          If Not GetLogicalProcessorInformation(oData, iAllocatedSize) Then
            Throw Fail("GetLogicalProcessorInformation failed", "x86", Marshal.GetLastWin32Error().ToString())
          End If
          ' Converting the data to a list that we can easily interpret.
          Dim oList As New List(Of ProcessorInfo)()
          For Each oInfo As SYSTEM_LOGICAL_PROCESSOR_INFORMATIONx86 In oData
            oList.Add(New ProcessorInfo(oInfo.Relationship, oInfo.Flags, oInfo.ProcessorMask))
          Next
          Return oList
        End Function
        Private Shared Function GetProcessorInfo64() As List(Of ProcessorInfo)
          ' First we're going to execute GetLogicalProcessorInformation 
          ' once to make sure that we determine the size of the data 
          ' that it is going to return.
          ' This call should fail with error ERROR_INSUFFICIENT_BUFFER.
          Dim iReturnLength As UInteger = 0
          Dim oDummy As SYSTEM_LOGICAL_PROCESSOR_INFORMATIONx64() = Nothing
          Dim bResult As Boolean = GetLogicalProcessorInformation(oDummy, iReturnLength)
          If bResult Then
            Throw Fail("GetLogicalProcessorInformation failed.", "x64")
          End If
          ' Making sure that the error code that we got back is not 
          ' that there is in sufficient space in the buffer.
          Dim iError As Integer = Marshal.GetLastWin32Error()
          If iError <> ERROR_INSUFFICIENT_BUFFER Then
            Throw Fail("Insufficient space in the buffer.", "x64", iError.ToString())
          End If
          ' Now that we know how much space we should reserve, 
          ' we're going to reserve it and call 
          ' GetLogicalProcessorInformation again.
          Dim iBaseSize As UInteger = CUInt(Marshal.SizeOf(GetType(SYSTEM_LOGICAL_PROCESSOR_INFORMATIONx64)))
          Dim iNumberOfElements As UInteger = iReturnLength \ iBaseSize
          Dim oData As SYSTEM_LOGICAL_PROCESSOR_INFORMATIONx64() = New SYSTEM_LOGICAL_PROCESSOR_INFORMATIONx64(Convert.ToInt32(Convert.ToUInt32(iNumberOfElements - 1))) {}
          Dim iAllocatedSize As UInteger = iNumberOfElements * iBaseSize
          If Not GetLogicalProcessorInformation(oData, iAllocatedSize) Then
            Throw Fail("GetLogicalProcessorInformation failed", "x64", Marshal.GetLastWin32Error().ToString())
          End If
          ' Converting the data to a list tha we can easily interpret.
          Dim oList As New List(Of ProcessorInfo)()
          For Each oInfo As SYSTEM_LOGICAL_PROCESSOR_INFORMATIONx64 In oData
            oList.Add(New ProcessorInfo(oInfo.Relationship, oInfo.Flags, oInfo.ProcessorMask))
          Next
          Return oList
        End Function
        Private Shared Function Fail(ByVal ParamArray data As String()) As Exception
          Return New NotSupportedException("GetPhysicalProcessorCount unexpectedly failed " & "(" & [String].Join(", ", data) & ")")
        End Function
        Public Shared Function GetPhysicalProcessorCount() As Integer
          If Not Is64BitProcess Then
            Dim oVersion As Version = Environment.OSVersion.Version
            If oVersion < New Version(5, 1, 2600) Then
              Throw New NotSupportedException("GetPhysicalProcessorCount is not supported " & "on this operating system.")
            ElseIf oVersion.Major = 5 AndAlso oVersion.Minor = 1 AndAlso Not Environment.OSVersion.ServicePack.Equals("Service Pack 3", StringComparison.OrdinalIgnoreCase) Then
              Throw New NotSupportedException("GetPhysicalProcessorCount is not supported " & "on this operating system.")
            End If
          End If
          ' Getting a list of processor information
          Dim oList As List(Of ProcessorInfo)
          If Is64BitProcess Then
            oList = GetProcessorInfo64()
          Else
            oList = GetProcessorInfo86()
          End If
          ' The list will basically contain something like this at this point:
          '
          ' E.g. for a 2 x single core
          ' Relationship       Flags   ProcessorMask
          ' ---------------------------------------------------------
          ' RelationProcessorCore   0     1
          ' RelationProcessorCore   0     2
          ' RelationNumaNode     0     3
          '
          ' E.g. for a 2 x dual core
          ' Relationship       Flags   ProcessorMask
          ' ---------------------------------------------------------
          ' RelationProcessorCore   1     5
          ' RelationProcessorCore   1     10
          ' RelationNumaNode     0     15
          '
          ' E.g. for a 1 x quad core
          ' Relationship       Flags   ProcessorMask
          ' ---------------------------------------------------------
          ' RelationProcessorCore   1     15
          ' RelationNumaNode     0     15
          '
          ' E.g. for a 1 x dual core
          ' Relationship       Flags   ProcessorMask 
          ' ---------------------------------------------------------
          ' RelationProcessorCore   0     1       
          ' RelationCache       1     1       
          ' RelationCache       1     1       
          ' RelationProcessorPackage 0     3       
          ' RelationProcessorCore   0     2       
          ' RelationCache       1     2       
          ' RelationCache       1     2       
          ' RelationCache       2     3       
          ' RelationNumaNode     0     3
          ' 
          ' Vista or higher will return one RelationProcessorPackage 
          ' line per socket. On other operating systems we need to 
          ' interpret the RelationProcessorCore lines.
          '
          ' More information:
          ' http://msdn2.microsoft.com/en-us/library/ms683194(VS.85).aspx
          ' http://msdn2.microsoft.com/en-us/library/ms686694(VS.85).aspx
    
          ' First counting the number of RelationProcessorPackage lines
          Dim iCount As Integer = 0
          For Each oItem As ProcessorInfo In oList
            If oItem.Relationship = RelationProcessorCore.RelationProcessorPackage Then
              iCount += 1
            End If
          Next
          If iCount > 0 Then
            Return iCount
          End If
          ' Now we're going to use the information in RelationProcessorCore.
          iCount = 0
          For Each oItem As ProcessorInfo In oList
            If oItem.Relationship = RelationProcessorCore.RelationProcessorCore Then
              iCount += 1
            End If
          Next
          If iCount > 0 Then
            Return iCount
          End If
          Throw Fail("No cpus have been detected.")
        End Function
      End Class
    End Namespace


     


    Hannes

    If you have got questions about this, just ask.

    In a perfect world,
    users would never enter data in the wrong form,
    files they choose to open would always exist
    and code would never have bugs.

    C# to VB.NET: http://www.developerfusion.com/tools/convert/csharp-to-vb/
    • Edited by Heslacher Wednesday, June 08, 2011 5:41 AM codeeditor problem
    Wednesday, June 08, 2011 1:31 AM
  • I think

    Dim Yellow As IntPtr = New IntPtr(alpha(0))
    

    Is going to assign the current value of alpha(0) to Yellow (zero at the time this initialisation is done), but I believe you are wanting Yellow to contain the address of alpha(0) rather than its value.

    Wednesday, June 08, 2011 1:38 AM
  • That's correct. How do I initialize that intptr so it points to the byte array?

    Hannes,

    I've seen that code. What I have to do is to discriminate between hyperthread processors and primaries. The hyperthreaded prcessors only do about 30% of work as far as I can tell and .....I'm afraid of running our of colors in an activity monitor I'm redoing.

    Renee

    Wednesday, June 08, 2011 2:01 AM
  • Ok,

    for your code:

    change:

    'NativeMethods
    
    'From
    Public Shared Function GetLogicalProcessorInformation(ByRef Buffer As IntPtr, 
    
    'To
    Public Shared Function GetLogicalProcessorInformation(ByRef Buffer As Integer, .......
    
    
    


    and call it by passing the first element of your array.

    After the first call only the RetLen value will be updated. You need to run it a second time to get your array filled. Btw, you need to change the byte array to an integer array.


    Hannes

    If you have got questions about this, just ask.

    In a perfect world,
    users would never enter data in the wrong form,
    files they choose to open would always exist
    and code would never have bugs.

    C# to VB.NET: http://www.developerfusion.com/tools/convert/csharp-to-vb/
    Wednesday, June 08, 2011 2:25 AM
  • I'm not an expert on P/Invoke, but I think the answer is to handle the first argument in the definition of the GetLogicalProcessorInformation function in the same way as in Hannes' post.  That is change it from ByRef buffer As System.IntPtr to ByVal buffer as SYSTEM_LOGICAL_PROCESSOR_INFORMATION(). You should then be able to call the function passing and array of SYSTEM_LOGICAL_PROCESSOR_INFORMATION as the first parameter. By the way, I'm always mixing up the definition of argument and parameter, so I may have them backwards in the preceding sentences.

    • Marked as answer by Renee Culver Wednesday, June 08, 2011 1:13 PM
    Wednesday, June 08, 2011 2:34 AM
  • "After the first call only the RetLen value will be updated".

    This exactly what I saw. It never occured to me to call it again....

    Renee


    Wednesday, June 08, 2011 2:52 AM
  • Now I am confused....because the code was like that when I received it.

    Renee

    Wednesday, June 08, 2011 3:02 AM
  • It will not compile.

    The compile errors have to do with the intptr definitions in the now two calls.

    Renee


    Wednesday, June 08, 2011 3:13 AM
  • This is the changed version ( without the lv1.. stuff ). This compiles without problems.

    Public Class Form1
    
      Dim alpha(250) As Integer
    
      Dim Retlen As UInteger
    
      Dim Yellow As IntPtr = New IntPtr(alpha(0))
    
      Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        Dim ret As Boolean = NativeMethods.GetLogicalProcessorInformation(alpha(0), Retlen)
        ret = NativeMethods.GetLogicalProcessorInformation(alpha(0), Retlen)
      End Sub
    
      <System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)> Public Structure SYSTEM_LOGICAL_PROCESSOR_INFORMATION
    
        ''' ULONG_PTR->unsigned int
    
        Public ProcessorMask As UInteger
    
        ''' LOGICAL_PROCESSOR_RELATIONSHIP->_LOGICAL_PROCESSOR_RELATIONSHIP
    
        Public Relationship As LOGICAL_PROCESSOR_RELATIONSHIP
    
        ''' Anonymous_cfba373b_d315_405c_b345_eabbe699bc66
    
        Public Union1 As Anonymous_cfba373b_d315_405c_b345_eabbe699bc66
    
      End Structure
    
    
    
      <System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Explicit)> Public Structure Anonymous_cfba373b_d315_405c_b345_eabbe699bc66
    
        ''' Anonymous_ccf454b1_fcd7_4ef6_bdd3_a1452ec5448e
    
        <System.Runtime.InteropServices.FieldOffsetAttribute(0)> Public ProcessorCore As Anonymous_ccf454b1_fcd7_4ef6_bdd3_a1452ec5448e
    
        ''' Anonymous_6bf0fd06_e931_4db4_bf97_e2e2b7af523b
    
        <System.Runtime.InteropServices.FieldOffsetAttribute(0)> Public NumaNode As Anonymous_6bf0fd06_e931_4db4_bf97_e2e2b7af523b
    
    
    
        ''' CACHE_DESCRIPTOR->_CACHE_DESCRIPTOR
    
        <System.Runtime.InteropServices.FieldOffsetAttribute(0)> Public Cache As CACHE_DESCRIPTOR
    
        ''' ULONGLONG[2]
    
        <System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst:=2, ArraySubType:=System.Runtime.InteropServices.UnmanagedType.U8)> <System.Runtime.InteropServices.FieldOffsetAttribute(0)> Public Reserved As ULong()
    
    
    
      End Structure
    
    
    
      Public Enum LOGICAL_PROCESSOR_RELATIONSHIP
    
        RelationProcessorCore
    
        RelationNumaNode
    
        RelationCache
    
      End Enum
    
    
    
      <System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)> Public Structure Anonymous_ccf454b1_fcd7_4ef6_bdd3_a1452ec5448e
    
        ''' BYTE->unsigned char
    
        Public Flags As Byte
    
      End Structure
    
    
    
      <System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)> Public Structure Anonymous_6bf0fd06_e931_4db4_bf97_e2e2b7af523b
    
        ''' DWORD->unsigned int
    
        Public NodeNumber As UInteger
    
      End Structure
    
    
    
      <System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)> Public Structure CACHE_DESCRIPTOR
    
        ''' BYTE->unsigned char
    
        Public Level As Byte
    
        ''' BYTE->unsigned char
    
        Public Associativity As Byte
    
        ''' WORD->unsigned short
    
        Public LineSize As UShort
    
        ''' DWORD->unsigned int
    
        Public Size As UInteger
    
        ''' PROCESSOR_CACHE_TYPE->_PROCESSOR_CACHE_TYPE
    
        Public Type As PROCESSOR_CACHE_TYPE
    
      End Structure
    
    
    
    
    
    
    
      Public Enum PROCESSOR_CACHE_TYPE
    
        CacheUnified
    
        CacheInstruction
    
        CacheData
    
        CacheTrace
    
      End Enum
    
    
    
      Partial Public Class NativeMethods
    
        ''' Return Type: BOOL->int
    
        '''Buffer:PSYSTEM_LOGICAL_PROCESSOR_INFORMATION>_SYSTEM_LOGICAL_PROCESSOR_INFORMATION*
    
        '''ReturnedLength: PDWORD->DWORD*
    
        <System.Runtime.InteropServices.DllImportAttribute _
        ("kernel32.dll", EntryPoint:="GetLogicalProcessorInformation")> _
        Public Shared Function GetLogicalProcessorInformation(ByRef Buffer As Integer, ByRef ReturnedLength As UInteger) As <System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.Bool)> Boolean
    
        End Function
    
      End Class
    
    
    
    End Class
    
    
    
    

    Hannes

    If you have got questions about this, just ask.

    In a perfect world,
    users would never enter data in the wrong form,
    files they choose to open would always exist
    and code would never have bugs.

    C# to VB.NET: http://www.developerfusion.com/tools/convert/csharp-to-vb/
    • Marked as answer by Renee Culver Wednesday, June 08, 2011 1:13 PM
    Wednesday, June 08, 2011 3:27 AM
  • Oof, so far Hannes suggestion has worked !Now to decode the numbers and see if I got anything. I will let you all know....

    Renee


    Wednesday, June 08, 2011 3:32 AM
  • The development system is the x6800 which is a dual processor extreme made during the era in which hyperthreading was not used. To run the program the first execution of the code required something like 216 bytes.

    The test system is a new Lenovo W520 with 8 virtual processors making that 4 regular processors and 4 hyperthreaded processors. It requires 608 bytes. As per usual I have the numbers to analyze. The final code is:

    Public Class Form1

        Dim alpha(250 / 4) As Integer

        Dim Retlen As Integer

        Dim Yellow As IntPtr = New IntPtr(alpha(0))

        Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

            Lv1.Columns.Add("Address", 100) ' For Search

            Lv1.Columns.Add("Contents", 200)

            Dim stat As Integer = NativeMethods.GetLogicalProcessorInformation(alpha(0), Retlen)

            Redim Alpha(Retlen)

            stat = NativeMethods.GetLogicalProcessorInformation(alpha(0), Retlen)

            For i = 0 To 249

                Lv1.Items.Add(alpha(i))

            Next

     

        End Sub

        <System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)> _

        Public Structure SYSTEM_LOGICAL_PROCESSOR_INFORMATION

            ''' ULONG_PTR->unsigned int

            Public ProcessorMask As UInteger

            ''' LOGICAL_PROCESSOR_RELATIONSHIP->_LOGICAL_PROCESSOR_RELATIONSHIP

            Public Relationship As LOGICAL_PROCESSOR_RELATIONSHIP

            ''' Anonymous_cfba373b_d315_405c_b345_eabbe699bc66

            Public Union1 As Anonymous_cfba373b_d315_405c_b345_eabbe699bc66

        End Structure

     

        <System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Explicit)> _

        Public Structure Anonymous_cfba373b_d315_405c_b345_eabbe699bc66

            ''' Anonymous_ccf454b1_fcd7_4ef6_bdd3_a1452ec5448e

            <System.Runtime.InteropServices.FieldOffsetAttribute(0)> _

            Public ProcessorCore As Anonymous_ccf454b1_fcd7_4ef6_bdd3_a1452ec5448e

            ''' Anonymous_6bf0fd06_e931_4db4_bf97_e2e2b7af523b

            <System.Runtime.InteropServices.FieldOffsetAttribute(0)> _

            Public NumaNode As Anonymous_6bf0fd06_e931_4db4_bf97_e2e2b7af523b

     

            ''' CACHE_DESCRIPTOR->_CACHE_DESCRIPTOR

            <System.Runtime.InteropServices.FieldOffsetAttribute(0)> _

            Public Cache As CACHE_DESCRIPTOR

            ''' ULONGLONG[2]

            <System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst:=2, ArraySubType:=System.Runtime.InteropServices.UnmanagedType.U8)> _

            <System.Runtime.InteropServices.FieldOffsetAttribute(0)> _

            Public Reserved As ULong()

     

        End Structure

     

        Public Enum LOGICAL_PROCESSOR_RELATIONSHIP

            RelationProcessorCore

            RelationNumaNode

            RelationCache

        End Enum

     

        <System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)> _

        Public Structure Anonymous_ccf454b1_fcd7_4ef6_bdd3_a1452ec5448e

            ''' BYTE->unsigned char

            Public Flags As Byte

        End Structure

     

        <System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)> _

        Public Structure Anonymous_6bf0fd06_e931_4db4_bf97_e2e2b7af523b

            ''' DWORD->unsigned int

            Public NodeNumber As UInteger

        End Structure

     

        <System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)> _

        Public Structure CACHE_DESCRIPTOR

            ''' BYTE->unsigned char

            Public Level As Byte

            ''' BYTE->unsigned char

            Public Associativity As Byte

            ''' WORD->unsigned short

            Public LineSize As UShort

            ''' DWORD->unsigned int

            Public Size As UInteger

            ''' PROCESSOR_CACHE_TYPE->_PROCESSOR_CACHE_TYPE

            Public Type As PROCESSOR_CACHE_TYPE

        End Structure

     

     

     

        Public Enum PROCESSOR_CACHE_TYPE

            CacheUnified

            CacheInstruction

            CacheData

            CacheTrace

        End Enum

     

        Partial Public Class NativeMethods

            ''' Return Type: BOOL->int

            '''Buffer:PSYSTEM_LOGICAL_PROCESSOR_INFORMATION>_SYSTEM_LOGICAL_PROCESSOR_INFORMATION*

            '''ReturnedLength: PDWORD->DWORD*

            ' <System.Runtime.InteropServices.DllImportAttribute("kernel32.dll", EntryPoint:="GetLogicalProcessorInformation")> _

            'Public Shared Function GetLogicalProcessorInformation(ByRef Buffer As System.IntPtr, ByRef ReturnedLength As UInteger) As <System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.Bool)> Boolean

            <System.Runtime.InteropServices.DllImportAttribute("kernel32.dll", EntryPoint:="GetLogicalProcessorInformation")> _

            Public Shared Function GetLogicalProcessorInformation(ByRef Buffer As Integer, ByRef ReturnedLength As UInteger) As <System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.Bool)> Boolean

            End Function

        End Class

     

    End Class

    Renee



    Wednesday, June 08, 2011 1:07 PM
  • And this board IS messed up. It barely works as I had tremendous difficulty posting that last message.

    Renee

    Wednesday, June 08, 2011 1:10 PM
  • You might try posting to stackoverflow.com in the future.  It's not VB specific, but VB questions are asked and answered there all the time and you'll get a timely response.
    Wednesday, June 08, 2011 8:32 PM
  • Chyris,

    The code is actually in VB. Of course GetlogicalProcessors is not.

    Renee

    Saturday, June 11, 2011 6:29 PM
  • For this one an array of structures won't work. You can do that sometimes if you either know the size beforehand, or can tell it which parameter holds the number of elements in the array. For this function though the other parameter tells you the number of bytes required rather than the number of structures.

    So you have to do it manually. This means you allocate a buffer and send the buffer and its size, then pull the structures back out the buffer. My results are pretty meaningless. Maybe it's wrong...

    (Edit: ok I found the problem that made it give crappy results. I forgot to move offset on so it read the first structure 19 times. Lol.)

     

    Option Strict On
    Option Explicit On
    
    Imports System.Runtime.InteropServices
    Imports System.ComponentModel
    Imports System.Text
    
    Public Class Form1
    
     Private tb As New TextBox
    
     Private Class NativeMethods
    
     <DllImport("kernel32", SetLastError:=True)> _
     Public Shared Function GetLogicalProcessorInformation( _
      ByVal pProcessorInfos As IntPtr, ByRef infoSize As Integer) As Boolean
     End Function
    
     End Class
    
     ' We can't put the union into this structure because the first field is a pointer and so
     ' we can't use FieldOffset because the second field is a offet 4 on x86 and 8 on x64...
     <StructLayout(LayoutKind.Sequential)> _
     Private Structure ProcessorInformation
     ' This has to be a uintptr as the C is a ULONG_PTR.
     Public ProcessorMask As UIntPtr
     Public Relationship As Relationship
     Public Union As ProcessUnion
     End Structure
    
     <StructLayout(LayoutKind.Explicit, Size:=16)> _
     Private Structure ProcessUnion
     <FieldOffset(0)> Public ProcessorCoreFlags As Byte
     <FieldOffset(0)> Public NumaNodeNumber As Integer
     <FieldOffset(0)> Public Cache As CacheDescriptor
     End Structure
    
     <StructLayout(LayoutKind.Sequential, Pack:=1)> _
     Private Structure CacheDescriptor
     Public Level As Byte
     Public Associativity As Byte
     Public LineSize As Short
     Public Size As Integer
     Public Type As ProcessorCacheType
     End Structure
    
     Private Enum Relationship
     ProcessorCore = 0
     NumaNode = 1
     Cache = 2
     ProcessorPackage = 3
     End Enum
    
     Private Enum ProcessorCacheType
     CacheUnified
     CacheInstruction
     CacheData
     CacheTrace
     End Enum
    
     Sub New()
    
     ' This call is required by the designer.
     InitializeComponent()
    
     ' Add any initialization after the InitializeComponent() call.
     Me.Controls.Add(tb)
     tb.Multiline = True
     tb.Anchor = AnchorStyles.Top Or AnchorStyles.Left Or AnchorStyles.Right Or AnchorStyles.Bottom
     tb.Bounds = New Rectangle(5, 5, Me.ClientSize.Width, Me.ClientSize.Height)
     ShowInfo()
     End Sub
    
     Sub ShowInfo()
     Dim infos() As ProcessorInformation = GetProcessorInformation()
     Dim numaNodeCount As Integer
     Dim processorCoreCount As Integer
     Dim processorPackageCount As Integer
     Dim logicalProcessorCount As Integer
     Dim processorL1CacheCount As Integer
     Dim processorL2CacheCount As Integer
     Dim processorL3CacheCount As Integer
     For Each info As ProcessorInformation In infos
      Select Case info.Relationship
      Case Relationship.Cache
       Select Case info.Union.Cache.Level
       Case 1
        processorL1CacheCount += 1
       Case 2
        processorL2CacheCount += 1
       Case 3
        processorL3CacheCount += 1
       End Select
      Case Relationship.NumaNode
       numaNodeCount += 1
      Case Relationship.ProcessorCore
       processorCoreCount += 1
       logicalProcessorCount += CountSetBits(info.ProcessorMask.ToUInt64)
      Case Relationship.ProcessorPackage
       processorPackageCount += 1
      End Select
     Next
     Const fmt As String = "Number of NUMA nodes: {0}{1}Number of physical processor packages: {2}{1}" & _
        "Number of processor cores: {3}{1}Number of logical processors: {4}{1}" & _
        "Number of processor L1/L2/L3 caches: {5}/{6}/{7}"
     tb.AppendText(String.Format(fmt, numaNodeCount, vbCrLf, processorPackageCount, _
         processorCoreCount, logicalProcessorCount, processorL1CacheCount, _
         processorL2CacheCount, processorL3CacheCount))
    
     End Sub
    
     Private Function GetProcessorInformation() As ProcessorInformation()
     ' Call #1 determine the buffer size in bytes required to store all the processor information structs
     Dim size As Integer
     Const ERROR_INSUFFICIENT_BUFFER As Integer = 122
     Dim result As Boolean = NativeMethods.GetLogicalProcessorInformation(Nothing, size)
     If result = False AndAlso Marshal.GetLastWin32Error <> ERROR_INSUFFICIENT_BUFFER Then Throw New Win32Exception
     ' So we should have this many structures
     Dim structSize As Integer = Marshal.SizeOf(GetType(ProcessorInformation))
     Dim numStructures As Integer = size \ structSize
     tb.AppendText(String.Format("{0} bytes required to hold {1} structures of size {2} bytes.{3}", size, numStructures, structSize, vbCrLf))
     ' And we can stick them into this array:
     Dim infos(numStructures - 1) As ProcessorInformation
     ' Call #2 get the structs into a buffer
     Dim pBlob As IntPtr = Marshal.AllocHGlobal(size)
     Try
      result = NativeMethods.GetLogicalProcessorInformation(pBlob, size)
      ' Now the memory pointed to by pBlob has our structures, so read them back 1 at a time:
      Dim offset As Integer = 0
      For i As Integer = 0 To infos.Length - 1
      Dim pNextStructure As IntPtr = IntPtr.Add(pBlob, offset)
      ' The above is .Net 4.0 only, for older versions:
      ' Dim pNextStructure As New IntPtr(pBlob.ToInt64 + offset)
      infos(i) = MarshalStruct(Of ProcessorInformation)(pNextStructure)
      offset += structSize
      Next
     Finally
      Marshal.FreeHGlobal(pBlob)
     End Try
     Return infos
     End Function
    
     ' This is really long-winded on one line, so I like to put it in its own function
     Private Shared Function MarshalStruct(Of T As Structure)(ByVal p As IntPtr) As T
     Return DirectCast(Marshal.PtrToStructure(p, GetType(T)), T)
     End Function
    
     Private Shared Function CountSetBits(ByVal val As ULong) As Integer
     Dim count As Integer
     While val > 0
      val = val And (val - 1UL)
      count += 1
     End While
     Return count
     End Function
    
    End Class
    

     x86 Output:

    456 bytes required to hold 19 structures of size 24 bytes.
    Number of NUMA nodes: 1
    Number of physical processor packages: 1
    Number of processor cores: 4
    Number of logical processors: 4
    Number of processor L1/L2/L3 caches: 8/4/1

    x64 Output:

     

    608 bytes required to hold 19 structures of size 32 bytes.
    Number of NUMA nodes: 1
    Number of physical processor packages: 1
    Number of processor cores: 4
    Number of logical processors: 4
    Number of processor L1/L2/L3 caches: 0/0/0
    Guess it still needs some work - it's not getting the cache counts on x64, probably a structure misalignment...

     

     




    • Edited by jo0ls Sunday, June 12, 2011 1:35 AM
    Sunday, June 12, 2011 1:27 AM
  • "For this one an array of structures won't work. You can do that sometimes if you either know the size beforehand, or can tell it which parameter holds the number of elements in the array. For this function though the other parameter tells you the number of bytes required rather than the number of structures. "

    Yes jooles, I know. You have to call GetLogicalProcessors twice. The first call is an allocation call, to find out how much to allocatw. Allocate the buffer and makethe call a second time.

    Let me look at your code. I think I have a working model, now I don't have the bit definitiond or if I do, they dont make sense when viewed.

    Renee


    Sunday, June 12, 2011 1:35 AM
  • The trick will be to seperate the hyperthreaded processors from the real processor in code. I'm hoping that possible with the flags but I don't know that their definitions exist.

    Renee


    Sunday, June 12, 2011 1:38 AM
  • It's getting good results for me with an x86 build, but running x64 or AnyCPU in an x64 environment shows that the structures are misaligned. I'll figure it out. Too tired now though...

    Sunday, June 12, 2011 2:03 AM
  • Hmmmm,,, I find that mine works for both 32 and 64 bit nodes but the author had to duplicate 64 and 32 bit code in order to get it to do that. DEFINATELY the structures for 32 and 64 bits are different.

     

    I don't have bit definitions. Thats the trouble I'm having now.

     

    I wish I could print the thing here to serve as a resource.

     

    Renee

     



    • Marked as answer by Renee Culver Sunday, June 12, 2011 2:13 AM
    • Unmarked as answer by Renee Culver Sunday, June 12, 2011 2:15 AM
    Sunday, June 12, 2011 2:10 AM
  • Uh-oh. I just looked your code. That not quite what I needed. I need to have a routine that can discriminate between hyperthreaded processors and normal ones. They are not the same.

    BUT

    "Number of processor cores: 4
    Number of logical processors: 4"

    This may do it!!! I

    have a new lenovo with hyperthread and an X6800 (without hyperthreading) for testing. I would guess that yours is not hyperthreaded.

    Renee


    Sunday, June 12, 2011 2:32 AM
  • I dont care about cache sizes. What I do care about is being able to not assign a thread to a hyperthreaded pseudoprocessor.

    Renee



    Sunday, June 12, 2011 2:37 AM
  • Yes, the structures differ. I used C to dump out the structure sizes, and the field offsets.

    On x86 the ProcessorMask field takes 4 bytes of memory. On x64 it takes 8 bytes because the type is ULONG_PTR.

    On x86 fields are aligned to 4 byte boundaries by default, on x64 they are aligned to 8 byte boundaries by default.

    On x86 the struct size is 24, on x64 it is 32.

    On x86 the Relationship field starts at byte 4 and the next field (the first field of the union) starts at byte 8.

    On x64 the Relationship field starts at byte 8 and the next field (the first field of the union) starts at byte 16 (because of padding).

    This makes it very difficult to emulate in .Net. A crude hack to get it to work is to use an IntPtr for Relationship too, and trim off the padding bytes with an AND (otherwise you have junk values in there which could have any value). Here's the changed bits:

    
     ' We can't put the union into this structure because the first field is a pointer and so
     ' we can't use FieldOffset because the second field is a offet 4 on x86 and 8 on x64...
     <StructLayout(LayoutKind.Sequential)> _
     Private Structure ProcessorInformation
      ' This has to be a uintptr as the C is a ULONG_PTR.
      Public ProcessorMask As UIntPtr
      Public Relationship As IntPtr        '<--- Using IntPtr
      Public Union As ProcessUnion
     End Structure
    
     Sub ShowInfo()
      Dim infos() As ProcessorInformation = GetProcessorInformation()
      Dim numaNodeCount As Integer
      Dim processorCoreCount As Integer
      Dim processorPackageCount As Integer
      Dim logicalProcessorCount As Integer
      Dim processorL1CacheCount As Integer
      Dim processorL2CacheCount As Integer
      Dim processorL3CacheCount As Integer
      For Each info As ProcessorInformation In infos
       Select Case info.Relationship.ToInt64 And UInteger.MaxValue  ' <-Mask off junk bits on x64<br/>    Case Relationship.Cache
         Select Case info.Union.Cache.Level
          Case 1
    
    

    I think that rather than resorting to a hack it would be best to dig the structures out in two goes - the first to get the ProcessorMask and then read the rest depending on what that was. Anyway it sounds like you are saying this API isn't what you were looking for!

    Sunday, June 12, 2011 2:41 AM
  • Right now the fora are not allowing me to post the code. (Damn these Fora).

    Allow the following comments Hesslacher code is a good rendition that can either run 32 or 64 bir code.

    Renee

    Sunday, June 12, 2011 3:07 AM
  • On x86 fields are aligned to 4 byte boundaries by default, on x64 they are aligned to 8 byte boundaries by default.

    On x86 the struct size is 24, on x64 it is 32.

    On x86 the Relationship field starts at byte 4 and the next field (the first field of the union) starts at byte 8.

    On x64 the Relationship field starts at byte 8 and the next field (the first field of the union) starts at byte 16 (because of padding).

    THIS IS THE KIND OF INFORMATION I"VE NEEDED. I still think Heslacher's code is good for 32/64bits.

    Renee

    Sunday, June 12, 2011 3:13 AM
  • I find it easier to read the byte array and hex dump it to compare it to what should be there.  Then read the bytes into structures using a BinaryReader.  I don't see much info.
    Sunday, June 12, 2011 3:26 AM
  • Hi John,

    I've never worked this much in the dark before. Right now im trying to get herslacher"s working. If i do that I have yet another one that has some fatal flaw. Yuck... The truble I dont know what should be there.

    I hope you are doing well.

    Renee

    Sunday, June 12, 2011 3:32 AM
  • This probably won't help, but here's what I got for an I7-920 in  X64 and  X86:

    Public Class Form1
      
    Declare Function GetLogicalProcessorInformation Lib "kernel32" (ByVal Buffer() As ByteByRef BufferLength As IntegerAs Boolean
      Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        
    Dim BufferLength As Integer
        GetLogicalProcessorInformation(Nothing, BufferLength)
        
    Dim Buffer(BufferLength - 1) As Byte
        GetLogicalProcessorInformation(Buffer, BufferLength)
        
    'IO.File.WriteAllBytes("X64Dump-" + BufferLength.ToString + ".bin", Buffer)
        IO.File.WriteAllBytes("X86Dump-" + BufferLength.ToString + ".bin", Buffer)
      
    End Sub
    End
     Class

    X64Dump-608.bin
    00000000 03 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  01 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ........ ........ ........ ........ 
    00000020 03 00 00 00 00 00 00 00  02 00 00 00 00 00 00 00  01 08 40 00 00 80 00 00  02 00 00 00 00 00 00 00  ........ ........ ..@.......... 
    00000040 03 00 00 00 00 00 00 00  02 00 00 00 00 00 00 00  01 04 40 00 00 80 00 00  01 00 00 00 00 00 00 00  ........ ........ ..@.......... 
    00000060 03 00 00 00 00 00 00 00  02 00 00 00 00 00 00 00  02 08 40 00 00 00 04 00  00 00 00 00 00 00 00 00  ........ ........ ..@..... ........ 
    00000080 0c 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  01 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ........ ........ ........ ........ 
    000000a0 0c 00 00 00 00 00 00 00  02 00 00 00 00 00 00 00  01 08 40 00 00 80 00 00  02 00 00 00 00 00 00 00  ........ ........ ..@.......... 
    000000c0 0c 00 00 00 00 00 00 00  02 00 00 00 00 00 00 00  01 04 40 00 00 80 00 00  01 00 00 00 00 00 00 00  ........ ........ ..@.......... 
    000000e0 0c 00 00 00 00 00 00 00  02 00 00 00 00 00 00 00  02 08 40 00 00 00 04 00  00 00 00 00 00 00 00 00  ........ ........ ..@..... ........ 
    00000100 30 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  01 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  0....... ........ ........ ........ 
    00000120 30 00 00 00 00 00 00 00  02 00 00 00 00 00 00 00  01 08 40 00 00 80 00 00  02 00 00 00 00 00 00 00  0....... ........ ..@.......... 
    00000140 30 00 00 00 00 00 00 00  02 00 00 00 00 00 00 00  01 04 40 00 00 80 00 00  01 00 00 00 00 00 00 00  0....... ........ ..@.......... 
    00000160 30 00 00 00 00 00 00 00  02 00 00 00 00 00 00 00  02 08 40 00 00 00 04 00  00 00 00 00 00 00 00 00  0....... ........ ..@..... ........ 
    00000180 ff 00 00 00 00 00 00 00  03 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ........ ........ ........ ........ 
    000001a0 c0 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  01 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ........ ........ ........ ........ 
    000001c0 c0 00 00 00 00 00 00 00  02 00 00 00 00 00 00 00  01 08 40 00 00 80 00 00  02 00 00 00 00 00 00 00  ........ ........ ..@.......... 
    000001e0 c0 00 00 00 00 00 00 00  02 00 00 00 00 00 00 00  01 04 40 00 00 80 00 00  01 00 00 00 00 00 00 00  ........ ........ ..@.......... 
    00000200 c0 00 00 00 00 00 00 00  02 00 00 00 00 00 00 00  02 08 40 00 00 00 04 00  00 00 00 00 00 00 00 00  ........ ........ ..@..... ........ 
    00000220 ff 00 00 00 00 00 00 00  02 00 00 00 00 00 00 00  03 10 40 00 00 00 80 00  00 00 00 00 00 00 00 00  ........ ........ ..@........... 
    00000240 ff 00 00 00 00 00 00 00  01 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ........ ........ ........ ........

    X86Dump-456.bin
    00000000 03 00 00 00 00 00 00 00  01 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  03 00 00 00 02 00 00 00  ........ ........ ........ ........ 
    00000020 01 08 40 00 00 80 00 00  02 00 00 00 00 00 00 00  03 00 00 00 02 00 00 00  01 04 40 00 00 80 00 00  ..@.......... ........ ..@..
    00000040 01 00 00 00 00 00 00 00  03 00 00 00 02 00 00 00  02 08 40 00 00 00 04 00  00 00 00 00 00 00 00 00  ........ ........ ..@..... ........ 
    00000060 0c 00 00 00 00 00 00 00  01 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  0c 00 00 00 02 00 00 00  ........ ........ ........ ........ 
    00000080 01 08 40 00 00 80 00 00  02 00 00 00 00 00 00 00  0c 00 00 00 02 00 00 00  01 04 40 00 00 80 00 00  ..@.......... ........ ..@..
    000000a0 01 00 00 00 00 00 00 00  0c 00 00 00 02 00 00 00  02 08 40 00 00 00 04 00  00 00 00 00 00 00 00 00  ........ ........ ..@..... ........ 
    000000c0 30 00 00 00 00 00 00 00  01 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  30 00 00 00 02 00 00 00  0....... ........ ........ 0....... 
    000000e0 01 08 40 00 00 80 00 00  02 00 00 00 00 00 00 00  30 00 00 00 02 00 00 00  01 04 40 00 00 80 00 00  ..@.......... 0....... ..@..
    00000100 01 00 00 00 00 00 00 00  30 00 00 00 02 00 00 00  02 08 40 00 00 00 04 00  00 00 00 00 00 00 00 00  ........ 0....... ..@..... ........ 
    00000120 ff 00 00 00 03 00 00 00  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  c0 00 00 00 00 00 00 00  ........ ........ ........ ........ 
    00000140 01 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  c0 00 00 00 02 00 00 00  01 08 40 00 00 80 00 00  ........ ........ ........ ..@..
    00000160 02 00 00 00 00 00 00 00  c0 00 00 00 02 00 00 00  01 04 40 00 00 80 00 00  01 00 00 00 00 00 00 00  ........ ........ ..@.......... 
    00000180 c0 00 00 00 02 00 00 00  02 08 40 00 00 00 04 00  00 00 00 00 00 00 00 00  ff 00 00 00 02 00 00 00  ........ ..@..... ........ ........ 
    000001a0 03 10 40 00 00 00 80 00  00 00 00 00 00 00 00 00  ff 00 00 00 01 00 00 00  00 00 00 00 00 00 00 00  ..@........... ........ ........ 
    000001c0 00 00 00 00 00 00 00 00                                                                             ........

    Sunday, June 12, 2011 3:57 AM
  • Thanks John, I'm not sure if it helps or not. Right now I'm trying to figure out Herslacker's code. Then I'll start to figure yours and mine out.

    M'm not sure, but the maybe some big and little indian problems. For instace, In some of my Lenovo W520 data I see 400801 (32bit data). Yet in you data I see (in X86Dump-456.bin, at 20, 01,08,40:. I doubt it's significant. We'll see.

    Thank you.

    Renee


    Sunday, June 12, 2011 4:14 AM
  • My data is a raw dump.  It's definitely little endian.
    Sunday, June 12, 2011 4:23 AM
  • I read you code. It's nice test code. Deep into the larager problem and heslacker's code......

    Renee

    Sunday, June 12, 2011 4:26 AM
  • This might help.  From a hyperthreaded single core P4:

    X86Dump-120.bin
     00000000 03 00 00 00 03 00 00 00  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  03 00 00 00 00 00 00 00  ........ ........ ........ ........ 
     00000020 01 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  03 00 00 00 02 00 00 00  01 08 40 00 00 40 00 00  ........ ........ ........ ..
    @..@.. 
     00000040 02 00 00 00 00 00 00 00  03 00 00 00 02 00 00 00  02 08 80 00 00 00 10 00  00 00 00 00 00 00 00 00  ........ ........ .......... 
     00000060 03 00 00 00 01 00 00 00  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00                           ........ ........ ........  



    From a singlethreaded 
    single core P4:

    X86Dump-72.bin
     00000000 01 00 00 00 03 00 00 00  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  01 00 00 00 00 00 00 00 ........ ........ ........ ........
     00000020 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  01 00 00 00 01 00 00 00  00 00 00 00 00 00 00 00 ........ ........ ........ ........
     00000040 00 00 00 00 00 00 00 00  ........ ........ ........ 


    Sunday, June 12, 2011 7:43 AM
  • Heslacker's code uses the platform invoke signature toolkit to automatically generate the structures. It's a great tool, but not 100% accurate. It's also very verbose and hard to read. The first field is wrong. It has used a UIntger for a ULONG_PTR - this throws off the rest of the fields on x64.

    When I dumped out the fields I found that the offsets of the fields on x86/x64 are:

    x86 x64 Field
    
    0  0  ProcessorMask
    4  8  RelationShip
    8  16 ProcessorCore.Flags
    8  16 NumaNode.NodeNumber
    8  16 Cache.Level
    9  17 Cache.Assoc
    10 18 Cache.LineSize
    12 20 Cache.Size
    16 24 Cache.Type
    8  16 Reserved[1]
    16 24 Reserved[2]
    ------------------------
    24 32 Total size

    In .Net you can mimic a union using StructLayout.Explicit with FieldOffset attributes. This allows you to say exactly where to place the fields. Unfortunately this structure has a field that varies in size as the first field so the rest cannot be stated with constant values. Sometimes you can use the Pack property of the StructLayout attribute and some messing about to get the structure layout correct. But I couldn't with this one.

    So the last option is to do it manually. The union occurs at 8 on x86 and 16 on x64 and so we can just pull out a union structure from that offset, calculating it at runtime from the size of an IntPtr:

    Option Strict On
    Option Explicit On
    
    Imports System.Runtime.InteropServices
    Imports System.ComponentModel
    Imports System.Text
    
    Public Class Form1
    
      Private tb As New TextBox
    
      Private Class NativeMethods
    
        <DllImport("kernel32", SetLastError:=True)> _
        Public Shared Function GetLogicalProcessorInformation( _
          ByVal pProcessorInfos As IntPtr, ByRef infoSize As Integer) As Boolean
        End Function
    
      End Class
    
      <StructLayout(LayoutKind.Sequential)> _
      Private Structure ProcessorInformation
        Public ProcessorMask As UIntPtr
        Public Relationship As Relationship
        Public Union As ProcessorUnion
    
        Public Function DumpInfo() As String
          Select Case Relationship
            Case Form1.Relationship.Cache
              Return Me.Union.Cache.Dump
            Case Form1.Relationship.NumaNode
              Return "Numa node. Numa Node Number: " & Me.Union.NumaNodeNumber
            Case Form1.Relationship.ProcessorCore
              Return String.Format("Processor. Logical Processor count {0} Processor Mask {1}", _
                         CountSetBits(ProcessorMask.ToUInt64), Me.Union.ProcessorCoreFlags)
            Case Form1.Relationship.ProcessorPackage
              Return "Processor Package"
            Case Else
              Return "Invalid Relationship"
          End Select
        End Function
      End Structure
    
      <StructLayout(LayoutKind.Explicit, Size:=16)> _
      Private Structure ProcessorUnion
        <FieldOffset(0)> Public ProcessorCoreFlags As Byte
        <FieldOffset(0)> Public NumaNodeNumber As Integer
        <FieldOffset(0)> Public Cache As CacheDescriptor
      End Structure
    
      <StructLayout(LayoutKind.Sequential)> _
      Private Structure CacheDescriptor
        Public Level As Byte
        Public Associativity As Byte
        Public LineSize As Short
        Public Size As Integer
        Public Type As ProcessorCacheType
        Public Function Dump() As String
          Return String.Format("Cache Level {0} Associativity {1} LineSize {2} Size {3} Type {4}", _
                     Level, If(Associativity = &HFF, "Full", Associativity.ToString), _
                     LineSize, Size, Me.Type.ToString)
        End Function
      End Structure
    
      Private Enum Relationship
        ProcessorCore = 0
        NumaNode = 1
        Cache = 2
        ProcessorPackage = 3
      End Enum
    
      Private Enum ProcessorCacheType
        CacheUnified
        CacheInstruction
        CacheData
        CacheTrace
      End Enum
    
      Sub New()
        InitializeComponent()
        Me.Controls.Add(tb)
        tb.Multiline = True
        tb.Anchor = AnchorStyles.Top Or AnchorStyles.Left Or AnchorStyles.Right Or AnchorStyles.Bottom
        tb.Bounds = New Rectangle(5, 5, Me.ClientSize.Width, Me.ClientSize.Height)
        ShowInfo()
      End Sub
    
      Sub ShowInfo()
        Dim infos() As ProcessorInformation = GetProcessorInformation()
        For Each info As ProcessorInformation In infos
          tb.AppendText(info.DumpInfo & vbCrLf)
        Next
      End Sub
    
      Private Function GetProcessorInformation() As ProcessorInformation()
        Dim size As Integer
        Const ERROR_INSUFFICIENT_BUFFER As Integer = 122
        Dim result As Boolean = NativeMethods.GetLogicalProcessorInformation(Nothing, size)
        If result = False AndAlso Marshal.GetLastWin32Error <> ERROR_INSUFFICIENT_BUFFER Then Throw New Win32Exception
        Dim structSize As Integer = Marshal.SizeOf(GetType(ProcessorInformation))
        Dim numStructures As Integer = size \ structSize
        tb.AppendText(String.Format("{0} bytes required to hold {1} structures of size {2} bytes.{3}", size, numStructures, structSize, vbCrLf))
        Dim infos(numStructures - 1) As ProcessorInformation
        Dim pBlob As IntPtr = Marshal.AllocHGlobal(size)
        Try
          result = NativeMethods.GetLogicalProcessorInformation(pBlob, size)
          Dim offset As Integer = 0
          For i As Integer = 0 To infos.Length - 1
            Dim pNextStructure As IntPtr = IntPtr.Add(pBlob, offset)
            Dim pNextStructuresUnion As IntPtr = IntPtr.Add(pBlob, offset + (IntPtr.Size * 2))
            infos(i) = MarshalStruct(Of ProcessorInformation)(pNextStructure)
            infos(i).Union = MarshalStruct(Of ProcessorUnion)(pNextStructuresUnion)
            offset += structSize
          Next
        Finally
          Marshal.FreeHGlobal(pBlob)
        End Try
        Return infos
      End Function
    
      Private Shared Function MarshalStruct(Of T As Structure)(ByVal p As IntPtr) As T
        Return DirectCast(Marshal.PtrToStructure(p, GetType(T)), T)
      End Function
    
      Private Shared Function CountSetBits(ByVal val As ULong) As Integer
        Dim count As Integer
        While val > 0
          val = val And (val - 1UL)
          count += 1
        End While
        Return count
      End Function
    
    End Class
    

     

    Sunday, June 12, 2011 11:19 AM
  • 216 bytes required to hold 9 structures of size 24 bytes.
    Processor. Logical Processor count 1 Processor Mask 0
    Cache Level 1 Associativity 8 LineSize 64 Size 32768 Type CacheData
    Cache Level 1 Associativity 8 LineSize 64 Size 32768 Type CacheInstruction
    Processor Package
    Processor. Logical Processor count 1 Processor Mask 0
    Cache Level 1 Associativity 8 LineSize 64 Size 32768 Type CacheData
    Cache Level 1 Associativity 8 LineSize 64 Size 32768 Type CacheInstruction
    Cache Level 2 Associativity 16 LineSize 64 Size 4194304 Type CacheUnified
    Numa node. Numa Node Number: 0

    Several thingss.....

    I can hardly wait to cut the cache out. I hope there is enough data to do some thing with
    it afterwards. I'm going to try this on the Lenovo.

    Renee

    Sunday, June 12, 2011 1:30 PM
  • This is from the WS520 with 4 logical processors and 4 hyperthreaded processors. This presents the processors in pairs. One is hyperthreadded and one is a regular processor. I will have to think on this a while.

    608 bytes required to hold 19 structures of size 32 bytes.
    Processor. Logical Processor count 2 Processor Mask 1
    Cache Level 1 Associativity 8 LineSize 64 Size 32768 Type CacheData
    Cache Level 1 Associativity 8 LineSize 64 Size 32768 Type CacheInstruction
    Cache Level 2 Associativity 8 LineSize 64 Size 262144 Type CacheUnified
    Processor. Logical Processor count 2 Processor Mask 1
    Cache Level 1 Associativity 8 LineSize 64 Size 32768 Type CacheData
    Cache Level 1 Associativity 8 LineSize 64 Size 32768 Type CacheInstruction
    Cache Level 2 Associativity 8 LineSize 64 Size 262144 Type CacheUnified
    Processor. Logical Processor count 2 Processor Mask 1
    Cache Level 1 Associativity 8 LineSize 64 Size 32768 Type CacheData
    Cache Level 1 Associativity 8 LineSize 64 Size 32768 Type CacheInstruction
    Cache Level 2 Associativity 8 LineSize 64 Size 262144 Type CacheUnified
    Processor Package
    Processor. Logical Processor count 2 Processor Mask 1
    Cache Level 1 Associativity 8 LineSize 64 Size 32768 Type CacheData
    Cache Level 1 Associativity 8 LineSize 64 Size 32768 Type CacheInstruction
    Cache Level 2 Associativity 8 LineSize 64 Size 262144 Type CacheUnified
    Cache Level 3 Associativity 16 LineSize 64 Size 8388608 Type CacheUnified
    Numa node. Numa Node Number: 0

    Renee

    Sunday, June 12, 2011 1:59 PM
  • I cut the cache data out (not on the above output) and have noticed that the processor status mask is 1. Thusly hyperthreadiing is detected (I hope). Here's hoping that there is ordinal presentation or all of this has been a waste of time.

    On to processor affinity.

    608 bytes required to hold 19 structures of size 32 bytes.
    Processor. Logical Processor count 2 Processor Mask 1
    Processor. Logical Processor count 2 Processor Mask 1
    Processor. Logical Processor count 2 Processor Mask 1
    Processor Package
    Processor. Logical Processor count 2 Processor Mask
    Numa node. Numa Node Number: 0

    Here what the new output looks like on yhe W520.

    Renee



    Sunday, June 12, 2011 2:48 PM
  • I must give Jules most of the credit.

     

    I was right so far, Bit 0 in the Union processor core flags seems to be the one to recognize if a logical processor is hyperthreaded. The final step remains to be done which is to set the processor affinity bit on procesors that are actual cores and not to set the on hyperthreaded cores.

     

    So far, this has been run on two systems. A non-hyperthreaded dual core and a quad-core and so far everything has worked,

     

    Renee

     

    Option Strict On

    Option Explicit On

    Imports System.Runtime.InteropServices

    Imports System.ComponentModel

    Imports System.Text

    Public Class Form1

        Const SS_Normal As Integer = 1

        Private tb As New TextBox

        Private Class NativeMethods

            <DllImport("kernel32", SetLastError:=True)> _

            Public Shared Function GetLogicalProcessorInformation( _

          ByVal pProcessorInfos As IntPtr, ByRef infoSize As Integer) As Boolean

            End Function

        End Class

        <StructLayout(LayoutKind.Sequential)> _

        Private Structure ProcessorInformation

            Public ProcessorMask As UIntPtr

            Public Relationship As Relationship

            Public Union As ProcessorUnion

            Public Function DumpInfo() As String

                Select Case Relationship

                    Case Form1.Relationship.Cache

                        Return ""

                    Case Form1.Relationship.NumaNode

                        Return "Numa node. Numa Node Number: " & Me.Union.NumaNodeNumber

                    Case Form1.Relationship.ProcessorCore

                        Return String.Format("Processor. Logical Processor count {0}", CountSetBits(ProcessorMask.ToUInt64))

                        ' Return String.Format("Processor Mask {0}", Me.Union.ProcessorCoreFlags)

                    Case Form1.Relationship.ProcessorPackage

                        Return "Processor Package"

                    Case Else

                        Return "Invalid Relationship"

                End Select

            End Function

        End Structure

        <StructLayout(LayoutKind.Explicit, Size:=16)> _

        Private Structure ProcessorUnion

            <FieldOffset(0)> Public ProcessorCoreFlags As Byte

            <FieldOffset(0)> Public NumaNodeNumber As Integer

        End Structure

        Private Enum Relationship

            ProcessorCore = 0

            NumaNode = 1

            Cache = 2

            ProcessorPackage = 3

        End Enum

        Sub New()

            InitializeComponent()

            Me.Controls.Add(tb)

            tb.Multiline = True

            tb.Anchor = AnchorStyles.Top Or AnchorStyles.Left Or AnchorStyles.Right Or AnchorStyles.Bottom

            tb.Bounds = New Rectangle(5, 5, Me.ClientSize.Width, Me.ClientSize.Height)

            ShowInfo()

        End Sub

        Sub ShowInfo()

            Dim infos() As ProcessorInformation = GetProcessorInformation()

            Static message As String = "Has no Virproc"

            For Each info As ProcessorInformation In infos

                If info.Relationship = Relationship.ProcessorCore Then

                    tb.AppendText(info.DumpInfo & vbCrLf)

                    If info.Union.ProcessorCoreFlags = 1 Then

                        message = "Has VirProc"

                    End If

                    tb.AppendText(message & vbCrLf)

                End If

                Dim a As UInteger = CUInt(info.ProcessorMask)

            Next

        End Sub

        Private Function GetProcessorInformation() As ProcessorInformation()

            Dim size As Integer

            Const ERROR_INSUFFICIENT_BUFFER As Integer = 122

            Dim result As Boolean = NativeMethods.GetLogicalProcessorInformation(Nothing, size)

            If result = False AndAlso Marshal.GetLastWin32Error <> ERROR_INSUFFICIENT_BUFFER Then Throw New Win32Exception

            Dim structSize As Integer = Marshal.SizeOf(GetType(ProcessorInformation))

            Dim numStructures As Integer = size \ structSize

            tb.AppendText(String.Format("{0} bytes required to hold {1} structures of size {2} bytes.{3}", size, numStructures, structSize, vbCrLf))

            Dim infos(numStructures - 1) As ProcessorInformation

            Dim pBlob As IntPtr = Marshal.AllocHGlobal(size)

            Try

                result = NativeMethods.GetLogicalProcessorInformation(pBlob, size)

                Dim offset As Integer = 0

                For i As Integer = 0 To infos.Length - 1

                    Dim pNextStructure As IntPtr = IntPtr.Add(pBlob, offset)

                    Dim pNextStructuresUnion As IntPtr = IntPtr.Add(pBlob, offset + (IntPtr.Size * 2))

                    infos(i) = MarshalStruct(Of ProcessorInformation)(pNextStructure)

                    infos(i).Union = MarshalStruct(Of ProcessorUnion)(pNextStructuresUnion)

                    offset += structSize

                Next

            Finally

                Marshal.FreeHGlobal(pBlob)

            End Try

            Return infos

        End Function

        Private Shared Function MarshalStruct(Of T As Structure)(ByVal p As IntPtr) As T

            Return DirectCast(Marshal.PtrToStructure(p, GetType(T)), T)

        End Function

        Private Shared Function CountSetBits(ByVal val As ULong) As Integer

            Dim count As Integer

            While val > 0

                val = val And (val - 1UL)

                count += 1

            End While

            Return count

        End Function

    End Class

     



    Monday, June 13, 2011 12:21 AM
  • Toms hardware gave the answer to my questiom on old Xeons. I hope the answer doesn't change with the I-7s.

    For those interested, the article of Tom's is:

    http://www.tomshardware.com/reviews/bang-dual-processing-buck,815-2.html

    Bach to work...

    Renee

    Tuesday, June 14, 2011 12:48 AM
  • I thought I'd detected an error in my program as the hyperthread piece went in an old XP notebook I had, but no it wasn't an error. The taskmanager showed two processors. The taskmanager is unable to discriminate between hyperthreaded processors and regular processors. They are each counted and the task manager shows two processors. I think one of them is a hyperthreaded processor.

    The task is correct on the Extreme and on the Lenovo now it appears to be correct on the Dell.

    Renee





    Tuesday, June 14, 2011 1:58 AM