libm-bench.cpp 2.7 KB

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