libm-bench.cpp 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. // Benchmark on libm functions
  2. #include <math.h>
  3. #include <sys/time.h>
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. // Timing facilities
  7. #ifdef __MACH__
  8. #include <mach/mach_time.h>
  9. class stimer
  10. {
  11. public:
  12. typedef uint64_t time_type;
  13. stimer()
  14. {
  15. ::mach_timebase_info(&m_baseinfo);
  16. }
  17. time_type current() const
  18. {
  19. return ::mach_absolute_time();
  20. }
  21. double span(const time_type& t0, const time_type& t1) const
  22. {
  23. uint64_t d = (m_baseinfo.numer * (t1 - t0)) / m_baseinfo.denom;
  24. return static_cast<double>(d) / 1.0e9;
  25. }
  26. private:
  27. mach_timebase_info_data_t m_baseinfo;
  28. };
  29. #else
  30. class stimer
  31. {
  32. public:
  33. typedef timespec time_type;
  34. time_type current() const
  35. {
  36. time_type t;
  37. ::clock_gettime(CLOCK_REALTIME, &t);
  38. return t;
  39. }
  40. double span(const time_type& t0, const time_type& t1) const
  41. {
  42. return double(t1.tv_sec - t0.tv_sec) +
  43. double(t1.tv_nsec - t0.tv_nsec) * 1.0e-9;
  44. }
  45. };
  46. #endif
  47. inline double sec2mps(double s, long n)
  48. {
  49. return n / (s * 1e6);
  50. }
  51. const long ARR_LEN = 1024;
  52. double a[ARR_LEN];
  53. double b[ARR_LEN];
  54. double r[ARR_LEN];
  55. #define TFUN1(FNAME) \
  56. void test_##FNAME(long n) { \
  57. for (int j = 0; j < ARR_LEN; ++j) r[j] = FNAME(a[j]); \
  58. stimer tm; \
  59. stimer::time_type t0 = tm.current(); \
  60. for(int i = 0; i < n; ++i) { \
  61. for (int j = 0; j < ARR_LEN; ++j) r[j] = FNAME(a[j]); \
  62. } \
  63. double s = tm.span(t0, tm.current()); \
  64. double mps = sec2mps(s, n * ARR_LEN); \
  65. printf(" %-8s: %7.4f MPS\n", #FNAME, mps); }
  66. #define TFUN2(FNAME) \
  67. void test_##FNAME(long n) { \
  68. for (int j = 0; j < ARR_LEN; ++j) r[j] = FNAME(a[j], b[j]); \
  69. stimer tm; \
  70. stimer::time_type t0 = tm.current(); \
  71. for(int i = 0; i < n; ++i) { \
  72. for (int j = 0; j < ARR_LEN; ++j) r[j] = FNAME(a[j], b[j]); \
  73. } \
  74. double s = tm.span(t0, tm.current()); \
  75. double mps = sec2mps(s, n * ARR_LEN); \
  76. printf(" %-8s: %7.4f MPS\n", #FNAME, mps); }
  77. #define TCALL(FNAME) test_##FNAME(20000)
  78. // define benchmark functions
  79. TFUN2(pow)
  80. TFUN2(hypot)
  81. TFUN1(exp)
  82. TFUN1(log)
  83. TFUN1(log10)
  84. TFUN1(sin)
  85. TFUN1(cos)
  86. TFUN1(tan)
  87. TFUN1(asin)
  88. TFUN1(acos)
  89. TFUN1(atan)
  90. TFUN2(atan2)
  91. int main(int argc, char *argv[])
  92. {
  93. // initialize array contents
  94. for (int i = 0; i < ARR_LEN; ++i)
  95. {
  96. a[i] = rand() / (double) RAND_MAX;
  97. b[i] = rand() / (double) RAND_MAX;
  98. }
  99. TCALL(pow);
  100. TCALL(hypot);
  101. TCALL(exp);
  102. TCALL(log);
  103. TCALL(log10);
  104. TCALL(sin);
  105. TCALL(cos);
  106. TCALL(tan);
  107. TCALL(asin);
  108. TCALL(acos);
  109. TCALL(atan);
  110. TCALL(atan2);
  111. return 0;
  112. }