sampling_manager.cc 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. #include "sampling_manager.h"
  2. #include "hooks_manager.h"
  3. #include "magic_server.h"
  4. #include "simulator.h"
  5. #include "core.h"
  6. #include "core_manager.h"
  7. #include "thread_manager.h"
  8. #include "performance_model.h"
  9. #include "fastforward_performance_model.h"
  10. #include "config.hpp"
  11. #include "magic_client.h"
  12. #include "sampling_provider.h"
  13. SamplingManager::SamplingManager(void)
  14. : m_sampling_enabled(Sim()->getCfg()->getBool("sampling/enabled"))
  15. , m_fastforward(false)
  16. , m_warmup(false)
  17. , m_target_ffend(SubsecondTime::Zero())
  18. , m_sampling_provider(NULL)
  19. , m_sampling_algorithm(NULL)
  20. , m_instructions(Sim()->getConfig()->getApplicationCores(), 0)
  21. , m_time_total(Sim()->getConfig()->getApplicationCores(), SubsecondTime::Zero())
  22. , m_time_nonidle(Sim()->getConfig()->getApplicationCores(), SubsecondTime::Zero())
  23. {
  24. if (! m_sampling_enabled)
  25. return;
  26. m_uncoordinated = Sim()->getCfg()->getBool("sampling/uncoordinated");
  27. LOG_ASSERT_ERROR(Sim()->getConfig()->getSimulationMode() == Config::PINTOOL, "Sampling is only supported in Pin mode");
  28. Sim()->getHooksManager()->registerHook(HookType::HOOK_INSTR_COUNT, (HooksManager::HookCallbackFunc)SamplingManager::hook_instr_count, (UInt64)this);
  29. Sim()->getHooksManager()->registerHook(HookType::HOOK_PERIODIC, (HooksManager::HookCallbackFunc)SamplingManager::hook_periodic, (UInt64)this);
  30. m_sampling_provider = SamplingProvider::create();
  31. m_sampling_algorithm = SamplingAlgorithm::create(this);
  32. }
  33. SamplingManager::~SamplingManager(void)
  34. {
  35. if (m_sampling_provider)
  36. delete m_sampling_provider;
  37. if (m_sampling_algorithm)
  38. delete m_sampling_algorithm;
  39. }
  40. void
  41. SamplingManager::periodic(SubsecondTime time)
  42. {
  43. if (m_fastforward)
  44. m_sampling_algorithm->callbackFastForward(time, m_warmup);
  45. else
  46. m_sampling_algorithm->callbackDetailed(time);
  47. #if 0
  48. if (m_fastforward) {
  49. // Debug: print out a skew report
  50. printf("[SKEW] %lu", Timer::now());
  51. UInt64 t = Sim()->getCoreManager()->getCoreFromID(0)->getPerformanceModel()->getElapsedTime().getNS();
  52. for(unsigned int c = 0; c < Sim()->getConfig()->getApplicationCores(); ++c)
  53. printf(" %ld", Sim()->getCoreManager()->getCoreFromID(c)->getPerformanceModel()->getElapsedTime().getNS() - t);
  54. printf("\n");
  55. }
  56. #endif
  57. }
  58. void
  59. SamplingManager::setInstrumentationMode(InstMode::inst_mode_t mode)
  60. {
  61. // We're counting on the barrier for callbacks (time is still running),
  62. // so tell Simulator not to disable it even when going out of DETAILED.
  63. Sim()->setInstrumentationMode(mode, false /* update_barrier */);
  64. }
  65. void
  66. SamplingManager::disableFastForward()
  67. {
  68. m_fastforward = false;
  69. m_warmup = false;
  70. SubsecondTime barrier_next = SubsecondTime::Zero();
  71. SubsecondTime core_last = SubsecondTime::MaxTime();
  72. for(unsigned int core_id = 0; core_id < Sim()->getConfig()->getApplicationCores(); ++core_id)
  73. {
  74. Core *core = Sim()->getCoreManager()->getCoreFromID(core_id);
  75. core->getPerformanceModel()->setFastForward(false, true);
  76. core->disableInstructionsCallback();
  77. if (Sim()->getThreadManager()->isThreadRunning(core_id)) {
  78. barrier_next = std::max(barrier_next, core->getPerformanceModel()->getElapsedTime());
  79. core_last = std::min(core_last, core->getPerformanceModel()->getElapsedTime());
  80. }
  81. }
  82. if (m_uncoordinated) {
  83. for(UInt32 core_id = 0; core_id < Sim()->getConfig()->getApplicationCores(); core_id++)
  84. {
  85. // In uncoordinated mode, some cores will be behind because they didn't reach their target instruction count.
  86. // Reset all their times to the same value so they won't have to catch up in detailed mode.
  87. PerformanceModel *perf = Sim()->getCoreManager()->getCoreFromID(core_id)->getPerformanceModel();
  88. perf->getFastforwardPerformanceModel()->incrementElapsedTime(barrier_next - perf->getElapsedTime());
  89. }
  90. }
  91. // Tell the barrier to go to detailed mode again, but make sure it skips over the fastforwarded section of time.
  92. // FIXME:
  93. // We restart the barrier at the maximum time, and have all threads make uncoordinated progress
  94. // towards the fastest thread. There won't be any HOOK_PERIODIC calls (which may not make much sense anyway,
  95. // as during this period at least one thread is way ahead and won't be running).
  96. // Alternatively, we could reset the barrier to the min time of all cores, this way, all cores that are behind
  97. // the fastest one, will start to make detailed progress again in lockstep. We'll also get HOOK_PERIODIC calls
  98. // during this time.
  99. if (Sim()->getClockSkewMinimizationServer())
  100. Sim()->getClockSkewMinimizationServer()->setFastForward(false, barrier_next);
  101. this->setInstrumentationMode(InstMode::DETAILED);
  102. }
  103. void
  104. SamplingManager::enableFastForward(SubsecondTime until, bool warmup, bool detailed_sync)
  105. {
  106. m_fastforward = true;
  107. m_warmup = warmup;
  108. // Approximate time we want to leave fastforward mode
  109. m_target_ffend = until;
  110. SubsecondTime barrier_next = SubsecondTime::Zero();
  111. for(unsigned int core_id = 0; core_id < Sim()->getConfig()->getApplicationCores(); ++core_id)
  112. {
  113. PerformanceModel *perf = Sim()->getCoreManager()->getCoreFromID(core_id)->getPerformanceModel();
  114. perf->setFastForward(true, detailed_sync);
  115. barrier_next = std::max(barrier_next, perf->getElapsedTime());
  116. recalibrateInstructionsCallback(core_id);
  117. }
  118. // Set barrier to fastforward, and update next_barrier_time to the maximum of all core times so we definitely release everyone
  119. if (Sim()->getClockSkewMinimizationServer())
  120. Sim()->getClockSkewMinimizationServer()->setFastForward(true, barrier_next);
  121. if (m_warmup)
  122. this->setInstrumentationMode(InstMode::CACHE_ONLY);
  123. else
  124. this->setInstrumentationMode(InstMode::FAST_FORWARD);
  125. if (m_sampling_provider)
  126. {
  127. m_sampling_provider->startSampling(until);
  128. }
  129. }
  130. SubsecondTime
  131. SamplingManager::getCoreHistoricCPI(Core *core, bool non_idle, SubsecondTime min_nonidle_time) const
  132. {
  133. UInt64 d_instrs = 0;
  134. SubsecondTime d_time = SubsecondTime::Zero();
  135. d_instrs = core->getPerformanceModel()->getInstructionCount() - m_instructions[core->getId()];
  136. if (non_idle)
  137. d_time = core->getPerformanceModel()->getNonIdleElapsedTime() - m_time_nonidle[core->getId()];
  138. else
  139. d_time = core->getPerformanceModel()->getElapsedTime() - m_time_total[core->getId()];
  140. if (d_instrs == 0)
  141. {
  142. return SubsecondTime::MaxTime();
  143. }
  144. else if (d_time <= min_nonidle_time)
  145. {
  146. return SubsecondTime::Zero();
  147. }
  148. else
  149. {
  150. return d_time / d_instrs;
  151. }
  152. }
  153. void
  154. SamplingManager::resetCoreHistoricCPIs()
  155. {
  156. for(UInt32 core_id = 0; core_id < Sim()->getConfig()->getApplicationCores(); core_id++)
  157. {
  158. Core *core = Sim()->getCoreManager()->getCoreFromID(core_id);
  159. m_instructions[core->getId()] = core->getPerformanceModel()->getInstructionCount();
  160. m_time_total [core->getId()] = core->getPerformanceModel()->getElapsedTime();
  161. m_time_nonidle[core->getId()] = core->getPerformanceModel()->getNonIdleElapsedTime();
  162. }
  163. }
  164. void
  165. SamplingManager::recalibrateInstructionsCallback(core_id_t core_id)
  166. {
  167. Core *core = Sim()->getCoreManager()->getCoreFromID(core_id);
  168. SubsecondTime now = core->getPerformanceModel()->getElapsedTime();
  169. if (now > m_target_ffend) {
  170. // Just a single instruction so we call into the barrier immediately
  171. core->setInstructionsCallback(1);
  172. } else {
  173. SubsecondTime cpi = core->getPerformanceModel()->getFastforwardPerformanceModel()->getCurrentCPI();
  174. // If CPI hasn't been set up, fall back to 1 IPC to avoid division by zero
  175. if (cpi == SubsecondTime::Zero())
  176. cpi = Sim()->getCoreManager()->getCoreFromID(core_id)->getDvfsDomain()->getPeriod();
  177. UInt64 ninstrs = SubsecondTime::divideRounded(m_target_ffend - now, cpi);
  178. core->setInstructionsCallback(ninstrs);
  179. }
  180. }
  181. void
  182. SamplingManager::instr_count(core_id_t core_id)
  183. {
  184. if (m_fastforward && Sim()->getMagicServer()->inROI()) {
  185. if (m_uncoordinated) {
  186. for(UInt32 core_id = 0; core_id < Sim()->getConfig()->getApplicationCores(); core_id++)
  187. {
  188. // In uncoordinated mode, the first processor to reach his target instruction count
  189. // ends fast-forward mode for everyone
  190. Sim()->getCoreManager()->getCoreFromID(core_id)->setInstructionsCallback(1);
  191. }
  192. }
  193. Sim()->getCoreManager()->getCoreFromID(core_id)->getClockSkewMinimizationClient()->synchronize(SubsecondTime::Zero(), true);
  194. }
  195. }