periodic_sampling.cc 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. #include "periodic_sampling.h"
  2. #include "sampling_manager.h"
  3. #include "simulator.h"
  4. #include "core_manager.h"
  5. #include "performance_model.h"
  6. #include "fastforward_performance_model.h"
  7. #include "config.hpp"
  8. #include "average.h"
  9. PeriodicSampling::PeriodicSampling(SamplingManager *sampling_manager)
  10. : SamplingAlgorithm(sampling_manager)
  11. // Duration of a detailed interval
  12. , m_detailed_interval(SubsecondTime::NS(Sim()->getCfg()->getInt("sampling/periodic/detailed_interval")))
  13. // Duration of a fast-forward interval
  14. , m_fastforward_interval(SubsecondTime::NS(Sim()->getCfg()->getInt("sampling/periodic/fastforward_interval")))
  15. // Time between core synchronizations in fast-forward mode
  16. , m_fastforward_sync_interval(SubsecondTime::NS(Sim()->getCfg()->getInt("sampling/periodic/fastforward_sync_interval")))
  17. // Duration of a cache warmup interval
  18. , m_warmup_interval(SubsecondTime::NS(Sim()->getCfg()->getInt("sampling/periodic/warmup_interval")))
  19. , m_detailed_warmup_interval(SubsecondTime::NS(Sim()->getCfg()->getInt("sampling/periodic/detailed_warmup_interval")))
  20. // Whether to simulate synchronization during fast-forward (true, our method), or fast-forward using a per-core CPI that contains sync (false, COTSon method)
  21. , m_detailed_sync(Sim()->getCfg()->getBool("sampling/periodic/detailed_sync"))
  22. // Whether to randomly place the detailed interval inside the cycle (default: at the start)
  23. , m_random_placement(Sim()->getCfg()->getBool("sampling/periodic/random_placement"))
  24. , m_random_offset(SubsecondTime::Zero())
  25. , m_random_start(Sim()->getCfg()->getBool("sampling/periodic/random_start"))
  26. , m_periodic_last(SubsecondTime::Zero())
  27. , m_historic_cpi_intervals(Sim()->getConfig()->getApplicationCores(), NULL)
  28. , m_dispatch_width(Sim()->getCfg()->getInt("perf_model/core/interval_timer/dispatch_width"))
  29. {
  30. LOG_ASSERT_ERROR(m_fastforward_sync_interval > SubsecondTime::Zero() && m_fastforward_sync_interval <= std::max(m_fastforward_interval, m_warmup_interval), "fastforward_sync_interval must be between 0 and max(fastforward_interval, warmup_interval)");
  31. UInt32 num_intervals = Sim()->getCfg()->getInt("sampling/periodic/num_historic_cpi_intervals");
  32. LOG_ASSERT_ERROR(num_intervals != 0, "Expected num_intervals to be >= 1");
  33. for (uint32_t i = 0 ; i < Sim()->getConfig()->getApplicationCores() ; i++)
  34. m_historic_cpi_intervals[i] = new CircularQueue<SubsecondTime>(num_intervals);
  35. if (Sim()->getCfg()->getBool("sampling/periodic/oneipc")) {
  36. m_constant_ipc = true;
  37. m_constant_ipcs.resize(Sim()->getConfig()->getApplicationCores());
  38. for (uint32_t i = 0 ; i < Sim()->getConfig()->getApplicationCores() ; i++)
  39. m_constant_ipcs[i] = 1.0;
  40. } else if (Sim()->getCfg()->getBool("sampling/periodic/xipc_enabled")) {
  41. m_constant_ipc = true;
  42. m_constant_ipcs.resize(Sim()->getConfig()->getApplicationCores());
  43. for (uint32_t i = 0 ; i < Sim()->getConfig()->getApplicationCores() ; i++)
  44. m_constant_ipcs[i] = Sim()->getCfg()->getFloatArray("sampling/periodic/xipcs",i);
  45. } else {
  46. m_constant_ipc = false;
  47. }
  48. if (m_random_placement || m_random_start)
  49. {
  50. UInt64 seed = Sim()->getCfg()->getInt("sampling/periodic/random_placement_seed");
  51. if (seed == 0)
  52. seed = time(NULL);
  53. m_prng.seed(seed);
  54. }
  55. if (m_random_start)
  56. m_random_offset = (m_fastforward_interval + m_warmup_interval) * (m_prng.next() % 100) / 100;
  57. }
  58. void
  59. PeriodicSampling::callbackDetailed(SubsecondTime time)
  60. {
  61. if (m_random_start)
  62. {
  63. // First interval: do some extra detailed (but ignore it's IPC) to offset the sampling intervals
  64. if (time < m_random_offset)
  65. ; // Stay in detailed
  66. else {
  67. printf("Done initial detailed of %" PRId64 " ns, now starting detailed interval for real\n", m_random_offset.getNS());
  68. m_sampling_manager->resetCoreHistoricCPIs();
  69. m_periodic_last = time;
  70. m_random_start = false;
  71. }
  72. }
  73. else if (time > m_periodic_last + m_detailed_interval)
  74. {
  75. LOG_ASSERT_ERROR(m_detailed_warmup_time_remaining == SubsecondTime::Zero(), "Should not finish detailed simulation before detailed warmup is complete.")
  76. //printf("IPC =");
  77. for(unsigned int core_id = 0; core_id < Sim()->getConfig()->getApplicationCores(); ++core_id)
  78. {
  79. Core *core = Sim()->getCoreManager()->getCoreFromID(core_id);
  80. SubsecondTime period = core->getDvfsDomain()->getPeriod();
  81. SubsecondTime cpi;
  82. if (m_constant_ipc)
  83. {
  84. cpi = (1.0/m_constant_ipcs[core_id]) * period;
  85. }
  86. else
  87. {
  88. SubsecondTime historic_cpi = m_sampling_manager->getCoreHistoricCPI(core, m_detailed_sync, m_detailed_interval / 5);
  89. // Only add to the history if we have been executing instructions for at least 20% of the time
  90. if (historic_cpi != SubsecondTime::Zero() && historic_cpi != SubsecondTime::MaxTime())
  91. {
  92. m_historic_cpi_intervals[core_id]->pushCircular(historic_cpi);
  93. }
  94. // If not empty, use the historic cpi information
  95. // If it is empty, assume one-ipc
  96. if (!m_historic_cpi_intervals[core_id]->empty())
  97. cpi = arithmetic_mean(*m_historic_cpi_intervals[core_id]);
  98. else
  99. cpi = period;
  100. SubsecondTime min_cpi = period / m_dispatch_width;
  101. if (cpi < min_cpi)
  102. cpi = min_cpi; // max. m_dispatch_width IPC
  103. else if (cpi > period * 100)
  104. cpi = period * 100; // min. .01 IPC
  105. }
  106. //printf(" %5.3f", float(period.getInternalDataForced()) / float(cpi.getInternalDataForced()));
  107. core->getPerformanceModel()->getFastforwardPerformanceModel()->setCurrentCPI(cpi);
  108. }
  109. //printf("\n");
  110. if (m_random_placement) {
  111. // |FFFFFFWWWDFFFFFF|FFFFWWWDFFFFFFFF|
  112. // ^^^^^^ ^^^^=new offset
  113. // |= ffwd + warmup - old offset
  114. // Add whatever fast-forward we have left from the previous cycle
  115. m_fastforward_time_remaining = m_fastforward_interval + m_warmup_interval - m_random_offset;
  116. // Generate a new offset for this cycle
  117. m_random_offset = (m_prng.next() * m_fastforward_sync_interval) % (m_fastforward_interval + m_warmup_interval);
  118. // Fast-forward until the new offset
  119. m_fastforward_time_remaining += m_random_offset;
  120. } else {
  121. m_fastforward_time_remaining = m_fastforward_interval;
  122. }
  123. m_warmup_time_remaining = m_warmup_interval;
  124. bool done = stepFastForward(time, false);
  125. LOG_ASSERT_ERROR(done == false, "No fastforwarding to be done");
  126. m_periodic_last = time;
  127. }
  128. else if (m_detailed_warmup_time_remaining > SubsecondTime::Zero())
  129. {
  130. // If detailed warmup is enabled and we have simulated the requested detailed amount, reset the statistics and continue in detailed
  131. if (time > m_periodic_last + m_detailed_warmup_interval)
  132. {
  133. m_sampling_manager->resetCoreHistoricCPIs();
  134. m_detailed_warmup_time_remaining = SubsecondTime::Zero();
  135. }
  136. }
  137. }
  138. bool
  139. PeriodicSampling::stepFastForward(SubsecondTime time, bool in_warmup)
  140. {
  141. if (m_fastforward_time_remaining > SubsecondTime::Zero())
  142. {
  143. SubsecondTime time_to_fastforward = std::min(m_fastforward_time_remaining, m_fastforward_sync_interval);
  144. if (m_fastforward_time_remaining < time_to_fastforward)
  145. m_fastforward_time_remaining = SubsecondTime::Zero();
  146. else
  147. m_fastforward_time_remaining -= time_to_fastforward;
  148. m_sampling_manager->enableFastForward(time + time_to_fastforward, false, m_detailed_sync);
  149. return false;
  150. }
  151. else if (m_warmup_time_remaining > SubsecondTime::Zero())
  152. {
  153. SubsecondTime time_to_warmup = std::min(m_warmup_time_remaining, m_fastforward_sync_interval);
  154. if (m_warmup_time_remaining < time_to_warmup)
  155. m_warmup_time_remaining = SubsecondTime::Zero();
  156. else
  157. m_warmup_time_remaining -= time_to_warmup;
  158. m_sampling_manager->enableFastForward(time + time_to_warmup, true, m_detailed_sync);
  159. return false;
  160. }
  161. else
  162. {
  163. return true;
  164. }
  165. }
  166. void
  167. PeriodicSampling::callbackFastForward(SubsecondTime time, bool in_warmup)
  168. {
  169. bool done = stepFastForward(time, in_warmup);
  170. if (done)
  171. {
  172. m_sampling_manager->resetCoreHistoricCPIs();
  173. m_sampling_manager->disableFastForward();
  174. m_periodic_last = time;
  175. if (m_detailed_warmup_interval > SubsecondTime::Zero())
  176. {
  177. m_detailed_warmup_time_remaining = m_detailed_warmup_interval;
  178. }
  179. }
  180. }