84 lines
1.8 KiB
C++
84 lines
1.8 KiB
C++
|
|
||
|
// Copyright Oliver Kowalke 2014.
|
||
|
// Distributed under the Boost Software License, Version 1.0.
|
||
|
// (See accompanying file LICENSE_1_0.txt or copy at
|
||
|
// http://www.boost.org/LICENSE_1_0.txt)
|
||
|
|
||
|
#ifndef CYCLE_I386_H
|
||
|
#define CYCLE_I386_H
|
||
|
|
||
|
#include <algorithm>
|
||
|
#include <numeric>
|
||
|
#include <cstddef>
|
||
|
#include <vector>
|
||
|
|
||
|
#include <boost/assert.hpp>
|
||
|
#include <boost/bind.hpp>
|
||
|
#include <boost/cstdint.hpp>
|
||
|
|
||
|
#define BOOST_CONTEXT_CYCLE
|
||
|
|
||
|
typedef boost::uint64_t cycle_type;
|
||
|
|
||
|
#if _MSC_VER
|
||
|
inline
|
||
|
cycle_type cycles()
|
||
|
{
|
||
|
cycle_type c;
|
||
|
__asm {
|
||
|
cpuid
|
||
|
rdtsc
|
||
|
mov dword ptr [c + 0], eax
|
||
|
mov dword ptr [c + 4], edx
|
||
|
}
|
||
|
return c;
|
||
|
}
|
||
|
#elif defined(__GNUC__) || \
|
||
|
defined(__INTEL_COMPILER) || defined(__ICC) || defined(_ECC) || defined(__ICL)
|
||
|
inline
|
||
|
cycle_type cycles()
|
||
|
{
|
||
|
boost::uint32_t lo, hi;
|
||
|
|
||
|
__asm__ __volatile__ (
|
||
|
"xorl %%eax, %%eax\n"
|
||
|
"cpuid\n"
|
||
|
::: "%eax", "%ebx", "%ecx", "%edx"
|
||
|
);
|
||
|
__asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi) );
|
||
|
__asm__ __volatile__ (
|
||
|
"xorl %%eax, %%eax\n"
|
||
|
"cpuid\n"
|
||
|
::: "%eax", "%ebx", "%ecx", "%edx"
|
||
|
);
|
||
|
|
||
|
return ( cycle_type)hi << 32 | lo;
|
||
|
}
|
||
|
#else
|
||
|
# error "this compiler is not supported"
|
||
|
#endif
|
||
|
|
||
|
struct cycle_overhead
|
||
|
{
|
||
|
cycle_type operator()()
|
||
|
{
|
||
|
cycle_type start( cycles() );
|
||
|
return cycles() - start;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
inline
|
||
|
cycle_type overhead_cycle()
|
||
|
{
|
||
|
std::size_t iterations( 10);
|
||
|
std::vector< cycle_type > overhead( iterations, 0);
|
||
|
for ( std::size_t i( 0); i < iterations; ++i)
|
||
|
std::generate(
|
||
|
overhead.begin(), overhead.end(),
|
||
|
cycle_overhead() );
|
||
|
BOOST_ASSERT( overhead.begin() != overhead.end() );
|
||
|
return std::accumulate( overhead.begin(), overhead.end(), 0) / iterations;
|
||
|
}
|
||
|
|
||
|
#endif // CYCLE_I386_H
|