hwcpipe.cpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. /*
  2. * Copyright (c) 2019 ARM Limited.
  3. *
  4. * SPDX-License-Identifier: MIT
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining a copy
  7. * of this software and associated documentation files (the "Software"), to
  8. * deal in the Software without restriction, including without limitation the
  9. * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  10. * sell copies of the Software, and to permit persons to whom the Software is
  11. * furnished to do so, subject to the following conditions:
  12. *
  13. * The above copyright notice and this permission notice shall be included in all
  14. * copies or substantial portions of the Software.
  15. *
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  19. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  22. * SOFTWARE.
  23. */
  24. #include "hwcpipe.h"
  25. #include "hwcpipe_log.h"
  26. #ifdef __linux__
  27. # include "vendor/arm/pmu/pmu_profiler.h"
  28. # include "vendor/arm/mali/mali_profiler.h"
  29. #endif
  30. #ifndef HWCPIPE_NO_JSON
  31. #include <json.hpp>
  32. using json = nlohmann::json;
  33. #endif
  34. #include <memory>
  35. namespace hwcpipe
  36. {
  37. #ifndef HWCPIPE_NO_JSON
  38. HWCPipe::HWCPipe(const char *json_string)
  39. {
  40. auto json = json::parse(json_string);
  41. CpuCounterSet enabled_cpu_counters{};
  42. auto cpu = json.find("cpu");
  43. if (cpu != json.end())
  44. {
  45. for (auto &counter_name : cpu->items())
  46. {
  47. auto counter = cpu_counter_names.find(counter_name.value().get<std::string>());
  48. if (counter != cpu_counter_names.end())
  49. {
  50. enabled_cpu_counters.insert(counter->second);
  51. }
  52. else
  53. {
  54. HWCPIPE_LOG("CPU counter \"%s\" not found.", counter_name.value().get<std::string>().c_str());
  55. }
  56. }
  57. }
  58. GpuCounterSet enabled_gpu_counters{};
  59. auto gpu = json.find("gpu");
  60. if (gpu != json.end())
  61. {
  62. for (auto &counter_name : gpu->items())
  63. {
  64. auto counter = gpu_counter_names.find(counter_name.value().get<std::string>());
  65. if (counter != gpu_counter_names.end())
  66. {
  67. enabled_gpu_counters.insert(counter->second);
  68. }
  69. else
  70. {
  71. HWCPIPE_LOG("GPU counter \"%s\" not found.", counter_name.value().get<std::string>().c_str());
  72. }
  73. }
  74. }
  75. create_profilers(std::move(enabled_cpu_counters), std::move(enabled_gpu_counters));
  76. }
  77. #endif
  78. HWCPipe::HWCPipe(CpuCounterSet enabled_cpu_counters, GpuCounterSet enabled_gpu_counters)
  79. {
  80. create_profilers(std::move(enabled_cpu_counters), std::move(enabled_gpu_counters));
  81. }
  82. HWCPipe::HWCPipe()
  83. {
  84. CpuCounterSet enabled_cpu_counters{CpuCounter::Cycles,
  85. CpuCounter::Instructions,
  86. CpuCounter::CacheReferences,
  87. CpuCounter::CacheMisses,
  88. CpuCounter::BranchInstructions,
  89. CpuCounter::BranchMisses};
  90. GpuCounterSet enabled_gpu_counters{GpuCounter::GpuCycles,
  91. GpuCounter::VertexComputeCycles,
  92. GpuCounter::FragmentCycles,
  93. GpuCounter::TilerCycles,
  94. GpuCounter::CacheReadLookups,
  95. GpuCounter::CacheWriteLookups,
  96. GpuCounter::ExternalMemoryReadAccesses,
  97. GpuCounter::ExternalMemoryWriteAccesses,
  98. GpuCounter::ExternalMemoryReadStalls,
  99. GpuCounter::ExternalMemoryWriteStalls,
  100. GpuCounter::ExternalMemoryReadBytes,
  101. GpuCounter::ExternalMemoryWriteBytes};
  102. create_profilers(std::move(enabled_cpu_counters), std::move(enabled_gpu_counters));
  103. }
  104. void HWCPipe::set_enabled_cpu_counters(CpuCounterSet counters)
  105. {
  106. if (cpu_profiler_)
  107. {
  108. cpu_profiler_->set_enabled_counters(std::move(counters));
  109. }
  110. }
  111. void HWCPipe::set_enabled_gpu_counters(GpuCounterSet counters)
  112. {
  113. if (gpu_profiler_)
  114. {
  115. gpu_profiler_->set_enabled_counters(std::move(counters));
  116. }
  117. }
  118. void HWCPipe::run()
  119. {
  120. if (cpu_profiler_)
  121. {
  122. cpu_profiler_->run();
  123. }
  124. if (gpu_profiler_)
  125. {
  126. gpu_profiler_->run();
  127. }
  128. }
  129. Measurements HWCPipe::sample()
  130. {
  131. Measurements m;
  132. if (cpu_profiler_)
  133. {
  134. m.cpu = &cpu_profiler_->sample();
  135. }
  136. if (gpu_profiler_)
  137. {
  138. m.gpu = &gpu_profiler_->sample();
  139. }
  140. return m;
  141. }
  142. void HWCPipe::stop()
  143. {
  144. if (cpu_profiler_)
  145. {
  146. cpu_profiler_->stop();
  147. }
  148. if (gpu_profiler_)
  149. {
  150. gpu_profiler_->stop();
  151. }
  152. }
  153. void HWCPipe::create_profilers(CpuCounterSet enabled_cpu_counters, GpuCounterSet enabled_gpu_counters)
  154. {
  155. // Automated platform detection
  156. #ifdef __linux__
  157. try
  158. {
  159. if (enabled_cpu_counters.size() != 0)
  160. {
  161. cpu_profiler_ = std::unique_ptr<PmuProfiler>(new PmuProfiler(enabled_cpu_counters));
  162. }
  163. }
  164. catch (const std::runtime_error &e)
  165. {
  166. HWCPIPE_LOG("PMU profiler initialization failed");
  167. }
  168. try
  169. {
  170. if (enabled_gpu_counters.size() != 0)
  171. {
  172. gpu_profiler_ = std::unique_ptr<MaliProfiler>(new MaliProfiler(enabled_gpu_counters));
  173. }
  174. }
  175. catch (const std::runtime_error &e)
  176. {
  177. HWCPIPE_LOG("Mali profiler initialization failed");
  178. }
  179. #else
  180. HWCPIPE_LOG("No counters available for this platform.");
  181. #endif
  182. }
  183. } // namespace hwcpipe