// benchmark.cpp ---------------------------------------------------------------------// // Copyright Beman Dawes 2011 // Distributed under the Boost Software License, Version 1.0. // http://www.boost.org/LICENSE_1_0.txt #ifndef _SCL_SECURE_NO_WARNINGS # define _SCL_SECURE_NO_WARNINGS #endif #ifndef _CRT_SECURE_NO_WARNINGS # define _CRT_SECURE_NO_WARNINGS #endif #include #include #include #include #include #include #include using namespace boost; using std::cout; using std::cerr; using std::endl; using std::vector; namespace { std::string command_args; long long n_cases; int places = 2; bool verbose (false); #ifndef BOOST_TWO_ARG typedef int32_t (*timee_func)(int32_t); #else typedef void (*timee_func)(int32_t, int32_t&); #endif typedef boost::timer::nanosecond_type nanosecond_t; //--------------------------------------------------------------------------------------// nanosecond_t benchmark(timee_func timee, const char* msg, nanosecond_t overhead = 0) // Returns: total cpu time (i.e. system time + user time) { if (verbose) cout << "\nRunning benchmark..." << endl; int64_t sum = 0; boost::timer::cpu_times times; nanosecond_t cpu_time; boost::timer::auto_cpu_timer t(places); for (long long i = n_cases; i; --i) { # ifndef BOOST_TWO_ARG sum += timee(static_cast(i)) ; # else int32_t y; timee(static_cast(i), y); sum += y; # endif } t.stop(); times = t.elapsed(); cpu_time = (times.system + times.user) - overhead; const long double sec = 1000000000.0L; cout.setf(std::ios_base::fixed, std::ios_base::floatfield); cout.precision(places); cout << msg << " " << cpu_time / sec << endl; if (verbose) { t.report(); cout << " Benchmark complete\n" " sum is " << sum << endl; } return cpu_time; } void process_command_line(int argc, char * argv[]) { for (int a = 0; a < argc; ++a) { command_args += argv[a]; if (a != argc-1) command_args += ' '; } cout << command_args << '\n';; if (argc >=2) #ifndef _MSC_VER n_cases = std::atoll(argv[1]); #else n_cases = _atoi64(argv[1]); #endif for (; argc > 2; ++argv, --argc) { if ( *(argv[2]+1) == 'p' ) places = atoi( argv[2]+2 ); else if ( *(argv[2]+1) == 'v' ) verbose = true; else { cout << "Error - unknown option: " << argv[2] << "\n\n"; argc = -1; break; } } if (argc < 2) { cout << "Usage: benchmark n [Options]\n" " The argument n specifies the number of test cases to run\n" " Options:\n" " -v Verbose messages\n" " -p# Decimal places for times; default -p" << places << "\n"; return std::exit(1); } } inline void inplace(int32_t& x) { x = (static_cast(x) << 24) | ((static_cast(x) << 8) & 0x00ff0000) | ((static_cast(x) >> 8) & 0x0000ff00) | (static_cast(x) >> 24); } inline int32_t by_return(int32_t x) { return (static_cast(x) << 24) | ((static_cast(x) << 8) & 0x00ff0000) | ((static_cast(x) >> 8) & 0x0000ff00) | (static_cast(x) >> 24); } inline int32_t by_return_intrinsic(int32_t x) { return BOOST_ENDIAN_INTRINSIC_BYTE_SWAP_4(static_cast(x)); } inline int32_t by_return_pyry(int32_t x) { uint32_t step16; step16 = static_cast(x) << 16 | static_cast(x) >> 16; return ((static_cast(step16) << 8) & 0xff00ff00) | ((static_cast(step16) >> 8) & 0x00ff00ff); } inline int32_t two_operand(int32_t x, int32_t& y) { return y = ((x << 24) & 0xff000000) | ((x << 8) & 0x00ff0000) | ((x >> 24) & 0x000000ff) | ((x >> 8) & 0x0000ff00); } inline int32_t modify_noop(int32_t x) { int32_t v(x); return v; } inline int32_t modify_inplace(int32_t x) { int32_t v(x); inplace(v); return v; } inline int32_t modify_by_return(int32_t x) { int32_t v(x); return by_return(v); } inline int32_t modify_by_return_pyry(int32_t x) { int32_t v(x); return by_return_pyry(v); } inline int32_t modify_by_return_intrinsic(int32_t x) { int32_t v(x); return by_return_intrinsic(v); } inline void non_modify_assign(int32_t x, int32_t& y) { y = x; } inline void non_modify_two_operand(int32_t x, int32_t& y) { two_operand(x, y); } inline void non_modify_by_return(int32_t x, int32_t& y) { y = by_return(x); } } // unnamed namespace //-------------------------------------- main() ---------------------------------------// int main(int argc, char * argv[]) { process_command_line(argc, argv); nanosecond_t overhead; #ifndef BOOST_TWO_ARG overhead = benchmark(modify_noop, "modify no-op"); benchmark(modify_inplace, "modify in place"/*, overhead*/); benchmark(modify_by_return, "modify by return"/*, overhead*/); benchmark(modify_by_return_pyry, "modify by return_pyry"/*, overhead*/); benchmark(modify_by_return_intrinsic, "modify by return_intrinsic"/*, overhead*/); #else overhead = benchmark(non_modify_assign, "non_modify_assign "); benchmark(non_modify_two_operand, "non_modify_two_operand", overhead); benchmark(non_modify_by_return, "non_modify_by_return ", overhead); #endif return 0; }