cycle_i386.hpp 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. // Copyright Oliver Kowalke 2014.
  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. #ifndef CYCLE_I386_H
  6. #define CYCLE_I386_H
  7. #include <algorithm>
  8. #include <numeric>
  9. #include <cstddef>
  10. #include <vector>
  11. #include <boost/assert.hpp>
  12. #include <boost/bind.hpp>
  13. #include <boost/cstdint.hpp>
  14. #define BOOST_CONTEXT_CYCLE
  15. typedef boost::uint64_t cycle_type;
  16. #if _MSC_VER
  17. inline
  18. cycle_type cycles()
  19. {
  20. cycle_type c;
  21. __asm {
  22. cpuid
  23. rdtsc
  24. mov dword ptr [c + 0], eax
  25. mov dword ptr [c + 4], edx
  26. }
  27. return c;
  28. }
  29. #elif defined(__GNUC__) || \
  30. defined(__INTEL_COMPILER) || defined(__ICC) || defined(_ECC) || defined(__ICL)
  31. inline
  32. cycle_type cycles()
  33. {
  34. boost::uint32_t lo, hi;
  35. __asm__ __volatile__ (
  36. "xorl %%eax, %%eax\n"
  37. "cpuid\n"
  38. ::: "%eax", "%ebx", "%ecx", "%edx"
  39. );
  40. __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi) );
  41. __asm__ __volatile__ (
  42. "xorl %%eax, %%eax\n"
  43. "cpuid\n"
  44. ::: "%eax", "%ebx", "%ecx", "%edx"
  45. );
  46. return ( cycle_type)hi << 32 | lo;
  47. }
  48. #else
  49. # error "this compiler is not supported"
  50. #endif
  51. struct cycle_overhead
  52. {
  53. cycle_type operator()()
  54. {
  55. cycle_type start( cycles() );
  56. return cycles() - start;
  57. }
  58. };
  59. inline
  60. cycle_type overhead_cycle()
  61. {
  62. std::size_t iterations( 10);
  63. std::vector< cycle_type > overhead( iterations, 0);
  64. for ( std::size_t i( 0); i < iterations; ++i)
  65. std::generate(
  66. overhead.begin(), overhead.end(),
  67. cycle_overhead() );
  68. BOOST_ASSERT( overhead.begin() != overhead.end() );
  69. return std::accumulate( overhead.begin(), overhead.end(), 0) / iterations;
  70. }
  71. #endif // CYCLE_I386_H