title: Get the number of logical CPU cores sharing a cache (L1, L2, L3)
body: <p>Below is some C++ code that detects the size of the L1, L2 and L3 CPU caches on Windows using <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/ms683194%28v=vs.85%29.aspx?f=255&amp;MSPPError=-2147217396" rel="nofollow noreferrer">GetLogicalProcessorInformation</a>:</p>
  
  <pre><code>typedef BOOL (WINAPI *LPFN_GLPI)(PSYSTEM_LOGICAL_PROCESSOR_INFORMATION, PDWORD);
  
  LPFN_GLPI glpi = (LPFN_GLPI) GetProcAddress(
      GetModuleHandle(TEXT("kernel32")), "GetLogicalProcessorInformation");
  
  if (glpi)
  {
      DWORD bytes = 0;
      glpi(0, &amp;bytes);
      size_t size = bytes / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION);
      vector&lt;SYSTEM_LOGICAL_PROCESSOR_INFORMATION&gt; info(size);
      glpi(info.data(), &amp;bytes);
  
      for (size_t i = 0; i &lt; size; i++)
      {
          if (info[i].Relationship == RelationCache)
          {
              if (info[i].Cache.Level == 1)
                l1_cache_Size = info[i].Cache.Size;
              if (info[i].Cache.Level == 2)
                l2_cache_Size = info[i].Cache.Size;
              if (info[i].Cache.Level == 3)
                l3_cache_Size = info[i].Cache.Size;
          }
      }
  }
  </code></pre>
  
  <p>As a next step I would like to get the number of logical CPU cores sharing a cache. On a x64 CPU with hyper-threading two logical CPU cores usually share an L2 cache and all logical CPU cores share the L3 cache.</p>
  
  <p>After reading through MSDN I thought that <code>GetLogicalProcessorInformationEx</code> and <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/dd405483(v=vs.85).aspx" rel="nofollow noreferrer">CACHE_RELATIONSHIP</a> and <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/dd405500(v=vs.85).aspx" rel="nofollow noreferrer">GROUP_AFFINITY</a> where the data structures I was looking for but after trying it out these data structures seem useless for my purpose.</p>
  
  <p><strong>Question:</strong></p>
  
  <p>Is there a way to get the number of logical CPU cores sharing a cache on Windows using C/C++? (Ideally without using <code>cpuid</code> directly)</p>
  
  <hr>
  
  <p><strong>Solution:</strong></p>
  
  <p>The number of logical CPU cores sharing a cache can be obtained using <code>GetLogicalProcessorInformationEx</code> and the <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/dd405483(v=vs.85).aspx" rel="nofollow noreferrer">CACHE_RELATIONSHIP</a> and <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/dd405500(v=vs.85).aspx" rel="nofollow noreferrer">GROUP_AFFINITY</a> data structures. The <code>GROUP_AFFINITY.Mask</code> value contains one bit set for each CPU core that shares the current cache (<code>RelationCache</code>). As an example for most Intel CPUs with hyper-threading <code>GROUP_AFFINITY.Mask</code> will contain 2 bits set for the L2 cache and 8 bits set for the L3 cache for a CPU with 4 physical CPU cores and 8 logical CPU cores.</p>
  
  <p>Here is the C++ code:</p>
  
  <pre><code>#include &lt;windows.h&gt;
  #include &lt;vector&gt;
  #include &lt;iostream&gt;
  
  using namespace std;
  
  typedef BOOL (WINAPI *LPFN_GLPI)(LOGICAL_PROCESSOR_RELATIONSHIP,
      PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, PDWORD);
  
  int main()
  {
      LPFN_GLPI glpi = (LPFN_GLPI) GetProcAddress(
          GetModuleHandle(TEXT("kernel32")), "GetLogicalProcessorInformationEx");
  
      if (!glpi)
          return 1;
  
      DWORD bytes = 0;
      glpi(RelationAll, 0, &amp;bytes);
      vector&lt;char&gt; buffer(bytes);
      SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX* info;
  
      if (!glpi(RelationAll, (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*) &amp;buffer[0], &amp;bytes))
          return 1;
  
      for (size_t i = 0; i &lt; bytes; i += info-&gt;Size)
      {
          info = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*) &amp;buffer[i];
  
          if (info-&gt;Relationship == RelationCache &amp;&amp;
              (info-&gt;Cache.Type == CacheData ||
               info-&gt;Cache.Type == CacheUnified))
          {
              cout &lt;&lt; "info-&gt;Cache.Level: " &lt;&lt; (int) info-&gt;Cache.Level &lt;&lt; endl;
              cout &lt;&lt; "info-&gt;Cache.CacheSize: " &lt;&lt; (int) info-&gt;Cache.CacheSize &lt;&lt; endl;
              cout &lt;&lt; "info-&gt;Cache.GroupMask.Group: " &lt;&lt; info-&gt;Cache.GroupMask.Group &lt;&lt; endl;
              cout &lt;&lt; "info-&gt;Cache.GroupMask.Mask: " &lt;&lt; info-&gt;Cache.GroupMask.Mask &lt;&lt; endl &lt;&lt; endl;
          }
      }
  
      return 0;
  }
  </code></pre>
  
  <p><strong>Caveats:</strong></p>
  
  <p>I have found that when running Windows inside a virtual machine the code above was unable to correctly detect the number of CPU cores sharing the caches, e.g. on a VM with 2 virtual CPU cores the code above reports that each logical CPU core has a private L1, L2 and L3 cache.</p>