Advertisement
Guest User

Untitled

a guest
Nov 19th, 2017
58
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.90 KB | None | 0 0
  1. #include <cstdio>
  2.  
  3. #if defined(_MSC_VER)
  4. #include <intrin.h>
  5. #elif defined(__GNUC__)
  6. #include <cpuid.h>
  7. #endif
  8.  
  9. struct X86CacheHierarchy {
  10. unsigned long l1d;
  11. unsigned long l1d_threads;
  12. unsigned long l2;
  13. unsigned long l2_threads;
  14. unsigned long l3;
  15. unsigned long l3_threads;
  16. bool l2_inclusive;
  17. bool l3_inclusive;
  18. bool valid;
  19. };
  20.  
  21. /**
  22. * Execute the CPUID instruction.
  23. *
  24. * @param regs array to receive eax, ebx, ecx, edx
  25. * @param eax argument to instruction
  26. * @param ecx argument to instruction
  27. */
  28. void do_cpuid(int regs[4], int eax, int ecx)
  29. {
  30. #if defined(_MSC_VER)
  31. __cpuidex(regs, eax, ecx);
  32. #elif defined(__GNUC__)
  33. __cpuid_count(eax, ecx, regs[0], regs[1], regs[2], regs[3]);
  34. #else
  35. regs[0] = 0;
  36. regs[1] = 0;
  37. regs[2] = 0;
  38. regs[3] = 0;
  39. #endif
  40. }
  41.  
  42. X86CacheHierarchy do_query_x86_cache_hierarchy_intel() noexcept
  43. {
  44. X86CacheHierarchy cache = { 0 };
  45. int regs[4];
  46.  
  47. unsigned l1d_threads = 0;
  48. unsigned l2_threads = 0;
  49. unsigned l3_threads = 0;
  50.  
  51. for (int i = 0; i < 8; ++i) {
  52. unsigned threads;
  53. unsigned long line_size;
  54. unsigned long partitions;
  55. unsigned long ways;
  56. unsigned long sets;
  57. unsigned long cache_size;
  58. int cache_type;
  59. bool inclusive;
  60.  
  61. do_cpuid(regs, 4, i);
  62. cache_type = regs[0] & 0x1F;
  63.  
  64. printf("cache type: %d\n", cache_type);
  65.  
  66. // No more caches.
  67. if (cache_type == 0)
  68. break;
  69.  
  70. // Not data or unified cache.
  71. if (cache_type != 1 && cache_type != 3)
  72. continue;
  73.  
  74. threads = ((static_cast<unsigned>(regs[0]) >> 14) & 0x0FFFU) + 1;
  75. line_size = ((static_cast<unsigned>(regs[1]) >> 0) & 0x0FFFU) + 1;
  76. partitions = ((static_cast<unsigned>(regs[1]) >> 12) & 0x03FFU) + 1;
  77. ways = ((static_cast<unsigned>(regs[1]) >> 22) & 0x03FFU) + 1;
  78. sets = static_cast<unsigned>(regs[2]) + 1;
  79.  
  80. cache_size = line_size * partitions * ways * sets;
  81. inclusive = regs[3] & (1U << 1);
  82.  
  83. // Cache level.
  84. switch ((regs[0] >> 5) & 0x07) {
  85. case 1:
  86. cache.l1d = cache_size;
  87. cache.l1d_threads = threads;
  88. break;
  89. case 2:
  90. cache.l2 = cache_size;
  91. cache.l2_threads = threads;
  92. cache.l2_inclusive = inclusive;
  93. break;
  94. case 3:
  95. cache.l3 = cache_size;
  96. cache.l3_threads = threads;
  97. cache.l3_inclusive = inclusive;
  98. break;
  99. default:
  100. break;
  101. }
  102. }
  103.  
  104. // Determine actual number of logical processors.
  105. for (int i = 0; i < 8; ++i) {
  106. unsigned logical_processors;
  107.  
  108. do_cpuid(regs, 0x0B, i);
  109.  
  110. if (((regs[2] >> 8) & 0xFF) == 0)
  111. break;
  112.  
  113. logical_processors = regs[1] & 0xFFFFU;
  114. if (logical_processors < cache.l1d_threads)
  115. l1d_threads = logical_processors;
  116. if (logical_processors < cache.l2_threads)
  117. l2_threads = logical_processors;
  118. if (logical_processors < cache.l3_threads)
  119. l3_threads = logical_processors;
  120. }
  121.  
  122. if (l1d_threads)
  123. cache.l1d_threads = l1d_threads;
  124. if (l2_threads)
  125. cache.l2_threads = l2_threads;
  126. if (l3_threads)
  127. cache.l3_threads = l3_threads;
  128.  
  129. cache.valid = true;
  130. return cache;
  131. }
  132.  
  133. X86CacheHierarchy do_query_x86_cache_hierarchy() noexcept
  134. {
  135. enum { GENUINEINTEL, AUTHENTICAMD, OTHER } vendor;
  136. int regs[4];
  137. int max_feature;
  138.  
  139. do_cpuid(regs, 0, 1);
  140. max_feature = regs[0] & 0xFF;
  141.  
  142. if (regs[1] == 0x756E6547U && regs[3] == 0x49656E69U && regs[2] == 0x6C65746EU)
  143. vendor = GENUINEINTEL;
  144. else if (regs[1] == 0x68747541U && regs[3] == 0x69746E65U && regs[2] == 0x444D4163U)
  145. vendor = AUTHENTICAMD;
  146. else
  147. vendor = OTHER;
  148.  
  149. if (vendor == GENUINEINTEL && max_feature >= 0x0B)
  150. return do_query_x86_cache_hierarchy_intel();
  151. else
  152. return{};
  153. }
  154.  
  155. int main()
  156. {
  157. auto cache = do_query_x86_cache_hierarchy();
  158.  
  159. if (!cache.valid) {
  160. puts("No cache!");
  161. return 0;
  162. }
  163.  
  164. printf("L1d: %lu / %u\n", cache.l1d, cache.l1d_threads);
  165. printf("L2: %lu / %u (%c)\n", cache.l2, cache.l2_threads, cache.l2_inclusive ? 'i' : 'x');
  166. printf("L3: %lu / %u (%c)\n", cache.l3, cache.l3_threads, cache.l3_inclusive ? 'i' : 'x');
  167. return 0;
  168. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement