fork download
  1. #if _MSC_VER
  2. #pragma warning(disable: 4996) // _CRT_SECURE_NO_WARNINGS
  3. #include <intrin.h>
  4. #else
  5. #include <x86intrin.h>
  6. #endif
  7.  
  8. #include <iostream>
  9. #include <stdio.h> // printf
  10. #include <string.h> // memcmp
  11. #define min_( a, b ) ( (a) < (b) ? (a) : (b) )
  12.  
  13. //------------------------------+---------------------------------------------------------------
  14.  
  15. #ifndef SYS_BITS
  16. #define CHAR_BITS 8
  17. #define SYS_BYTES sizeof( std::size_t )
  18. #define SYS_BITS ( SYS_BYTES * CHAR_BITS )
  19. #endif
  20.  
  21. //------------------------------+---------------------------------------------------------------
  22.  
  23. using ON_RUN = void( & )( void* );
  24. using ON_PREPARE = void( & )( void* );
  25. using ON_COMPARE = bool( & )( void*, void*, std::size_t );
  26.  
  27. //------------------------------+---------------------------------------------------------------
  28. // BENCH 에 의해서만 접근되기 때문에 모든 멤버가 private ( class default ) 입니다
  29. class RUNNER
  30. {
  31. friend class BENCH;
  32. const char* name;
  33. unsigned long long elapsed;
  34. const ON_RUN on_run;
  35. void* result;
  36.  
  37. RUNNER( const char* name, ON_RUN& on_run, void* result )
  38. : name( name )
  39. , on_run( on_run )
  40. , elapsed( -1 )
  41. , result( result )
  42. {
  43. }
  44.  
  45. void run()
  46. {
  47. auto begin = __rdtsc();
  48. on_run( result );
  49. elapsed = min_( elapsed, __rdtsc() - begin );
  50. }
  51. };
  52. ///-----------------------------+---------------------------------------------------------------
  53.  
  54. #include <vector>
  55.  
  56. class BENCH
  57. {
  58. private:
  59. const char* title;
  60. std::vector< RUNNER* > runners;
  61. ON_PREPARE on_prepare;
  62. ON_COMPARE on_compare;
  63. void* answer;
  64. std::size_t answer_size;
  65. const unsigned int trial;
  66.  
  67. public:
  68. BENCH( const char* title, const int trial,
  69. ON_PREPARE& prepare, ON_COMPARE& compare
  70. )
  71. : title( title )
  72. , trial( trial )
  73. , on_prepare( prepare )
  74. , on_compare( compare )
  75. {
  76. };
  77. ~BENCH()
  78. {
  79. for( auto runner : runners )
  80. delete[] runner;
  81. runners.clear();
  82. }
  83.  
  84. auto record( unsigned int index ) const
  85. {
  86. return runners[ index ]->elapsed;
  87. }
  88.  
  89. auto runner_count() const
  90. {
  91. return runners.size();
  92. }
  93.  
  94. void solution( ON_RUN& correct_function,
  95. void* result, const std::size_t bytes )
  96. {
  97. answer = result;
  98. answer_size = bytes;
  99. on_prepare( result );
  100. correct_function( result );
  101. }
  102.  
  103. template< typename T >
  104. void solution( ON_RUN& correct_function,
  105. T& result, const std::size_t bytes )
  106. {
  107. solution( correct_function, &result, bytes );
  108. }
  109.  
  110. void add( const char* name, ON_RUN& on_run, void* result )
  111. {
  112. runners.emplace_back( new RUNNER( name, on_run, result ) );
  113. }
  114.  
  115. template< typename T >
  116. void add( const char* name, ON_RUN& on_run, T& result )
  117. {
  118. add( name, on_run, &result );
  119. }
  120.  
  121. void run() const
  122. {
  123. if( runners.empty() )
  124. return;
  125.  
  126. printf( "\n < %d bits %d trial > %s\n", (int)SYS_BITS, trial, title );
  127. puts( " ----------------+---------------------------------+-----------------------" );
  128. puts( " | CHECKER | function name | minimum clocks |" );
  129. puts( " ----------------+---------------------------------+-----------------------" );
  130.  
  131. unsigned long long min_clocks = -1;
  132. unsigned long long max_clocks = 0;
  133. RUNNER* min_runner = runners[ 0 ];
  134. RUNNER* max_runner = runners[ 0 ];
  135.  
  136. for( const auto runner : runners )
  137. {
  138. int pass_count = 0;
  139. for( unsigned int i = 0; i < trial; ++i )
  140. {
  141. on_prepare( runner->result );
  142. runner->run();
  143. pass_count += on_compare( runner->result, answer, answer_size );
  144. }
  145.  
  146. if( min_clocks > runner->elapsed )
  147. {
  148. min_runner = runner;
  149. min_clocks = runner->elapsed;
  150. }
  151. if( max_clocks < runner->elapsed )
  152. {
  153. max_runner = runner;
  154. max_clocks = runner->elapsed;
  155. }
  156.  
  157. char temp[ 14 ];
  158. if( trial == pass_count )
  159. sprintf( temp, " PASSED" );
  160. else
  161. sprintf( temp, "FAILED%7d", trial - pass_count );
  162.  
  163. printf( " [ %s ] %32s %15llu clocks\n", temp, runner->name, runner->elapsed );
  164. }
  165. puts( " --------------------------------------------------------------------------" );
  166. printf( " Winner is %s ( %.2f times faster )\n\n",
  167. min_runner->name, float( max_clocks ) / min_clocks );
  168. }
  169. };
  170.  
  171. #define FUN( function_name ) #function_name, function_name
  172.  
  173. //==============================================================================================
  174. //------------------------------+---------------------------------------------------------------
  175.  
  176. using SOURCE = char;
  177. using RESULT = char;
  178.  
  179. SOURCE src[ 65536 ];
  180.  
  181. constexpr std::size_t SIZE = sizeof src / sizeof *src;
  182.  
  183. RESULT dst0[ SIZE ], dst1[ SIZE ], dst2[ SIZE ], dst3[ SIZE ], dst4[ SIZE ];
  184.  
  185. //------------------------------+---------------------------------------------------------------
  186. // 테스트전에 불려질 초기화 함수
  187. void prepare( void* result )
  188. {
  189. for( auto& v : src )
  190. v = '1';
  191. src[ sizeof src - 1 ] = 0;
  192. // memcpy( result, src, sizeof src );
  193. }
  194. // 테스트후에 불려질 점검 함수
  195. bool compare( void* result, void* answer, std::size_t bytes )
  196. {
  197. return memcmp( result, answer, bytes ) == 0;
  198. }
  199. //------------------------------+---------------------------------------------------------------
  200. // 테스트할 함수들
  201.  
  202. namespace cose
  203. {
  204.  
  205. inline int radix( const char* buf, const int mul )
  206. {
  207. if( mul == 1 )
  208. return *buf & 0xF;
  209. return ( *buf & 0xF ) * mul + radix( buf + 1, mul / 10 );
  210. }
  211.  
  212. void run( void* dst )
  213. {
  214. for( int i = 0; i < 10000; ++i )
  215. ((int*)dst)[ i ] = radix( src + i * 10, 1000000000 );
  216. }
  217.  
  218. }
  219.  
  220. namespace pooper
  221. {
  222. long getHeadLen( char *out )
  223. {
  224. return ((out[6] -'0') *1000000000+
  225. (out[7] -'0') *100000000+
  226. (out[8] -'0') *10000000+
  227. (out[9] -'0') *1000000+
  228. (out[10]-'0') *100000+
  229. (out[11]-'0') *10000+
  230. (out[12]-'0') *1000+
  231. (out[13]-'0') *100+
  232. (out[14]-'0') *10+
  233. (out[15]-'0'));
  234. }
  235.  
  236. void run( void* dst )
  237. {
  238. for( int i = 0; i < 10000; ++i )
  239. ((int*)dst)[ i ] = getHeadLen( src + i * 10 );
  240. }
  241. };
  242.  
  243. namespace cose2
  244. {
  245. inline long ascDec( const char* s )
  246. {
  247. return ( s[ 0 ] -'0' ) * 1000000000 + ( s[ 1 ] -'0' ) * 100000000 +
  248. ( s[ 2 ] -'0' ) * 10000000 + ( s[ 3 ] -'0' ) * 1000000 +
  249. ( s[ 4 ] -'0' ) * 100000 + ( s[ 5 ] -'0' ) * 10000 +
  250. ( s[ 12 ] -'0' ) * 1000 + ( s[ 13 ] -'0' ) * 100 +
  251. ( s[ 14 ] -'0' ) * 10 + ( s[ 15 ] -'0' );
  252.  
  253. }
  254.  
  255. inline long getHeadLen( const char *out )
  256. {
  257. return ascDec( out + 6 );
  258. }
  259.  
  260. void run( void* dst )
  261. {
  262. for( int i = 0; i < 10000; ++i )
  263. ((int*)dst)[ i ] = getHeadLen( src + i * 10 );
  264. }
  265. };
  266. //------------------------------+---------------------------------------------------------------
  267.  
  268. int main()
  269. {
  270. BENCH bench( "ascii to decimal", 1000, prepare, compare );
  271. bench.solution( pooper::run, dst0, sizeof dst0 );
  272.  
  273. bench.add( FUN( pooper::run ), dst3 );
  274. bench.add( FUN( cose::run ), dst2 );
  275. bench.add( FUN( cose2::run ), dst1 );
  276.  
  277. bench.run();
  278.  
  279. getchar();
  280. return 0;
  281. }
Success #stdin #stdout 0.24s 16448KB
stdin
strcmp 2
stdout
   < 64 bits 1000 trial >    ascii to decimal
   ----------------+---------------------------------+-----------------------
   |    CHECKER    |          function name          |    minimum clocks    |
   ----------------+---------------------------------+-----------------------
   [        PASSED ]                      pooper::run           97321 clocks
   [ FAILED   1000 ]                        cose::run          318389 clocks
   [ FAILED   1000 ]                       cose2::run           85821 clocks
   --------------------------------------------------------------------------
   Winner is cose2::run  ( 3.71 times faster )