profile.h 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. // ======================================================================== //
  2. // Copyright 2009-2017 Intel Corporation //
  3. // //
  4. // Licensed under the Apache License, Version 2.0 (the "License"); //
  5. // you may not use this file except in compliance with the License. //
  6. // You may obtain a copy of the License at //
  7. // //
  8. // http://www.apache.org/licenses/LICENSE-2.0 //
  9. // //
  10. // Unless required by applicable law or agreed to in writing, software //
  11. // distributed under the License is distributed on an "AS IS" BASIS, //
  12. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
  13. // See the License for the specific language governing permissions and //
  14. // limitations under the License. //
  15. // ======================================================================== //
  16. #pragma once
  17. #include "default.h"
  18. namespace embree
  19. {
  20. /*! helper structure for the implementation of the profile functions below */
  21. struct ProfileTimer
  22. {
  23. static const size_t N = 20;
  24. ProfileTimer () {}
  25. ProfileTimer (const size_t numSkip) : i(0), j(0), maxJ(0), numSkip(numSkip), t0(0)
  26. {
  27. for (size_t i=0; i<N; i++) names[i] = nullptr;
  28. for (size_t i=0; i<N; i++) dt_fst[i] = 0.0;
  29. for (size_t i=0; i<N; i++) dt_min[i] = pos_inf;
  30. for (size_t i=0; i<N; i++) dt_avg[i] = 0.0;
  31. for (size_t i=0; i<N; i++) dt_max[i] = neg_inf;
  32. }
  33. __forceinline void begin()
  34. {
  35. j=0;
  36. t0 = tj = getSeconds();
  37. }
  38. __forceinline void end() {
  39. absolute("total");
  40. i++;
  41. }
  42. __forceinline void operator() (const char* name) {
  43. relative(name);
  44. }
  45. __forceinline void absolute (const char* name)
  46. {
  47. const double t1 = getSeconds();
  48. const double dt = t1-t0;
  49. assert(names[j] == nullptr || names[j] == name);
  50. names[j] = name;
  51. if (i == 0) dt_fst[j] = dt;
  52. if (i>=numSkip) {
  53. dt_min[j] = min(dt_min[j],dt);
  54. dt_avg[j] = dt_avg[j] + dt;
  55. dt_max[j] = max(dt_max[j],dt);
  56. }
  57. j++;
  58. maxJ = max(maxJ,j);
  59. }
  60. __forceinline void relative (const char* name)
  61. {
  62. const double t1 = getSeconds();
  63. const double dt = t1-tj;
  64. tj = t1;
  65. assert(names[j] == nullptr || names[j] == name);
  66. names[j] = name;
  67. if (i == 0) dt_fst[j] = dt;
  68. if (i>=numSkip) {
  69. dt_min[j] = min(dt_min[j],dt);
  70. dt_avg[j] = dt_avg[j] + dt;
  71. dt_max[j] = max(dt_max[j],dt);
  72. }
  73. j++;
  74. maxJ = max(maxJ,j);
  75. }
  76. void print(size_t numElements)
  77. {
  78. for (size_t k=0; k<N; k++)
  79. dt_avg[k] /= double(i-numSkip);
  80. printf(" profile [M/s]:\n");
  81. for (size_t j=0; j<maxJ; j++)
  82. printf("%20s: fst = %7.2f M/s, min = %7.2f M/s, avg = %7.2f M/s, max = %7.2f M/s\n",
  83. names[j],numElements/dt_fst[j]*1E-6,numElements/dt_max[j]*1E-6,numElements/dt_avg[j]*1E-6,numElements/dt_min[j]*1E-6);
  84. printf(" profile [ms]:\n");
  85. for (size_t j=0; j<maxJ; j++)
  86. printf("%20s: fst = %7.2f ms, min = %7.2f ms, avg = %7.2f ms, max = %7.2fms\n",
  87. names[j],1000.0*dt_fst[j],1000.0*dt_min[j],1000.0*dt_avg[j],1000.0*dt_max[j]);
  88. }
  89. void print()
  90. {
  91. printf(" profile:\n");
  92. for (size_t k=0; k<N; k++)
  93. dt_avg[k] /= double(i-numSkip);
  94. for (size_t j=0; j<maxJ; j++) {
  95. printf("%20s: fst = %7.2f ms, min = %7.2f ms, avg = %7.2f ms, max = %7.2fms\n",
  96. names[j],1000.0*dt_fst[j],1000.0*dt_min[j],1000.0*dt_avg[j],1000.0*dt_max[j]);
  97. }
  98. }
  99. double avg() {
  100. return dt_avg[maxJ-1]/double(i-numSkip);
  101. }
  102. private:
  103. size_t i;
  104. size_t j;
  105. size_t maxJ;
  106. size_t numSkip;
  107. double t0;
  108. double tj;
  109. const char* names[N];
  110. double dt_fst[N];
  111. double dt_min[N];
  112. double dt_avg[N];
  113. double dt_max[N];
  114. };
  115. /*! This function executes some code block multiple times and measured sections of it.
  116. Use the following way:
  117. profile(1,10,1000,[&](ProfileTimer& timer) {
  118. // code
  119. timer("A");
  120. // code
  121. timer("B");
  122. });
  123. */
  124. template<typename Closure>
  125. void profile(const size_t numSkip, const size_t numIter, const size_t numElements, const Closure& closure)
  126. {
  127. ProfileTimer timer(numSkip);
  128. for (size_t i=0; i<numSkip+numIter; i++)
  129. {
  130. timer.begin();
  131. closure(timer);
  132. timer.end();
  133. }
  134. timer.print(numElements);
  135. }
  136. /*! similar as the function above, but the timer object comes externally */
  137. template<typename Closure>
  138. void profile(ProfileTimer& timer, const size_t numSkip, const size_t numIter, const size_t numElements, const Closure& closure)
  139. {
  140. timer = ProfileTimer(numSkip);
  141. for (size_t i=0; i<numSkip+numIter; i++)
  142. {
  143. timer.begin();
  144. closure(timer);
  145. timer.end();
  146. }
  147. timer.print(numElements);
  148. }
  149. }