get_arch_linux_cpuinfo.h 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. /* Copyright (C) 2013-2017 Povilas Kanapickas <[email protected]>
  2. Distributed under the Boost Software License, Version 1.0.
  3. (See accompanying file LICENSE_1_0.txt or copy at
  4. http://www.boost.org/LICENSE_1_0.txt)
  5. */
  6. #ifndef LIBSIMDPP_DISPATCH_GET_ARCH_LINUX_CPUINFO_H
  7. #define LIBSIMDPP_DISPATCH_GET_ARCH_LINUX_CPUINFO_H
  8. #if __linux__ && (__arm__ || __aarch64__ || __i386__ || __amd64__)
  9. #define SIMDPP_HAS_GET_ARCH_LINUX_CPUINFO 1
  10. #include <algorithm>
  11. #include <iostream>
  12. #include <sstream>
  13. #include <fstream>
  14. #include <iterator>
  15. #include <map>
  16. #include <vector>
  17. #include <simdpp/dispatch/arch.h>
  18. namespace simdpp {
  19. /** Retrieves supported architecture from Linux /proc/cpuinfo file.
  20. Works on X86 and ARM.
  21. */
  22. inline Arch get_arch_linux_cpuinfo()
  23. {
  24. Arch res = Arch::NONE_NULL;
  25. std::map<std::string, Arch> features;
  26. std::string ident;
  27. #if __arm__
  28. ident = "Features\t";
  29. features["neon"] = Arch::ARM_NEON | Arch::ARM_NEON_FLT_SP;
  30. #elif __aarch64__
  31. ident = "Features\t";
  32. features["asimd"] = Arch::ARM_NEON | Arch::ARM_NEON_FLT_SP;
  33. #elif __i386__ || __amd64__
  34. Arch a_sse2 = Arch::X86_SSE2;
  35. Arch a_sse3 = a_sse2 | Arch::X86_SSE3;
  36. Arch a_ssse3 = a_sse3 | Arch::X86_SSSE3;
  37. Arch a_sse4_1 = a_ssse3 | Arch::X86_SSE4_1;
  38. Arch a_popcnt = Arch::X86_POPCNT_INSN;
  39. Arch a_avx = a_sse4_1 | Arch::X86_AVX;
  40. Arch a_avx2 = a_avx | Arch::X86_AVX2;
  41. Arch a_fma3 = a_sse3 | Arch::X86_FMA3;
  42. Arch a_fma4 = a_sse3 | Arch::X86_FMA4;
  43. Arch a_xop = a_sse3 | Arch::X86_XOP;
  44. Arch a_avx512f = a_avx2 | Arch::X86_AVX512F;
  45. Arch a_avx512bw = a_avx512f | Arch::X86_AVX512BW;
  46. Arch a_avx512dq = a_avx512f | Arch::X86_AVX512DQ;
  47. Arch a_avx512vl = a_avx512f | Arch::X86_AVX512VL;
  48. ident = "flags\t";
  49. features["sse2"] = a_sse2;
  50. features["pni"] = a_sse3;
  51. features["ssse3"] = a_ssse3;
  52. features["sse4_1"] = a_sse4_1;
  53. features["avx"] = a_avx;
  54. features["avx2"] = a_avx2;
  55. features["popcnt"] = a_popcnt;
  56. features["fma"] = a_fma3;
  57. features["fma4"] = a_fma4;
  58. features["xop"] = a_xop;
  59. features["avx512f"] = a_avx512f;
  60. features["avx512bw"] = a_avx512bw;
  61. features["avx512dq"] = a_avx512dq;
  62. features["avx512vl"] = a_avx512vl;
  63. #else
  64. return res;
  65. #endif
  66. std::ifstream in("/proc/cpuinfo");
  67. if (!in) {
  68. return res;
  69. }
  70. std::string line;
  71. while (std::getline(in, line)) {
  72. // Check whether identification string matches
  73. if (line.length() < ident.length()) {
  74. continue;
  75. }
  76. auto r = std::mismatch(ident.begin(), ident.end(), line.begin());
  77. if (r.first != ident.end()) {
  78. continue;
  79. }
  80. // Get the items
  81. std::istringstream sin(std::string(r.second, line.end()));
  82. std::vector<std::string> items;
  83. std::copy(std::istream_iterator<std::string>(sin),
  84. std::istream_iterator<std::string>(),
  85. std::back_inserter(items));
  86. // Match items to known features
  87. for (auto& item : items) {
  88. auto it = features.find(item);
  89. if (it == features.end()) {
  90. continue;
  91. }
  92. res |= it->second;
  93. }
  94. }
  95. return res;
  96. }
  97. } // namespace simdpp
  98. #endif
  99. #endif