|
1 | | -# HWCPipe |
| 1 | +<!-- |
| 2 | +- Copyright (c) 2019, Arm Limited and Contributors |
| 3 | +- |
| 4 | +- SPDX-License-Identifier: MIT |
| 5 | +- |
| 6 | +- Permission is hereby granted, free of charge, |
| 7 | +- to any person obtaining a copy of this software and associated documentation files (the "Software"), |
| 8 | +- to deal in the Software without restriction, including without limitation the rights to |
| 9 | +- use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, |
| 10 | +- and to permit persons to whom the Software is furnished to do so, subject to the following conditions: |
| 11 | +- |
| 12 | +- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. |
| 13 | +- |
| 14 | +- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, |
| 15 | +- INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 16 | +- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. |
| 17 | +- IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, |
| 18 | +- WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| 19 | +- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| 20 | +- |
| 21 | +--> |
2 | 22 |
|
| 23 | +# HWCPipe |
3 | 24 |
|
4 | 25 | ## Introduction |
5 | 26 |
|
6 | | -HWCPipe is an interface to the Arm Hardware Counters, designed to allow for easily interfacing with and reading the hardware counters built into Arm hardware. |
7 | | - |
| 27 | +HWCPipe is a simple and extensible interface for reading CPU and GPU hardware counters. |
8 | 28 |
|
9 | 29 | ## License |
10 | 30 |
|
11 | | -The software is provided under an MIT license. Contributions to this project are accepted under the same license. |
| 31 | +The software is provided under an MIT license. |
| 32 | + |
| 33 | +This project has a third-party dependency, which may have independent licensing: |
| 34 | + |
| 35 | +- [nlohmann/json](https://github.com/nlohmann/json): A JSON library for modern C++ |
12 | 36 |
|
| 37 | +## Contributions |
| 38 | + |
| 39 | +All contributions are accepted under the same [LICENSE](LICENSE). |
13 | 40 |
|
14 | 41 | ## Building |
15 | 42 |
|
16 | | -To use HWCPipe, build it as a shared library in your Android Project, to do this it must be integrated into your project with CMake. |
| 43 | +To use HWCPipe, build it as a shared library in your project. |
17 | 44 |
|
| 45 | +If your project uses CMake, you can add the following to your `CMakeLists.txt`: |
18 | 46 |
|
19 | | -## Using |
| 47 | +``` |
| 48 | +add_subdirectory(hwcpipe) |
| 49 | +``` |
20 | 50 |
|
21 | | -### Performance data |
| 51 | +## Usage |
22 | 52 |
|
23 | | -In order for performance data to be displayed, profiling needs to be enabled on the device. |
24 | | -Some devices may disable it by default. |
| 53 | +### Using HWCPipe |
25 | 54 |
|
26 | | -Profiling can be enabled via adb: |
| 55 | +Basic usage for HWCPipe is simple: |
27 | 56 |
|
28 | 57 | ``` |
29 | | -adb shell setprop security.perf_harden 0 |
| 58 | +// HWCPipe performs automated platform detection for CPU/GPU counters |
| 59 | +hwcpipe::HWCPipe h; |
| 60 | +
|
| 61 | +// Start HWCPipe once at the beginning of the profiling session |
| 62 | +h.run(); |
| 63 | +
|
| 64 | +while (main_loop) { |
| 65 | + // Call sample() to sample counters with the frequency you need |
| 66 | + auto measurements = h.sample(); |
| 67 | +
|
| 68 | + [...] |
| 69 | +} |
| 70 | +
|
| 71 | +// At the end of the profiling session, stop HWCPipe |
| 72 | +h.stop(); |
30 | 73 | ``` |
31 | 74 |
|
32 | | -#### Enabling a Counter: |
| 75 | +The `sample` function returns a `Measurements` struct, which can be accessed like this: |
| 76 | + |
| 77 | +``` |
| 78 | +// Check if CPU measurements are available |
| 79 | +if (measurements.cpu) |
| 80 | +{ |
| 81 | + // Look for a counter in the map |
| 82 | + const auto &counter = measurements.cpu->find(CpuCounter::Cycles); |
| 83 | + if (counter != measurements.cpu->end()) |
| 84 | + { |
| 85 | + // Get the data stored in the counter, casted to the type you need |
| 86 | + auto value = cpu_res->counter.get<float>(); |
| 87 | + } |
| 88 | +} |
| 89 | +``` |
33 | 90 |
|
34 | | -To enable a counter, create either a PMU or Mali counter and then call its start function. |
| 91 | +### Enabling counters |
| 92 | + |
| 93 | +The available counters are specified in the `CpuCounter` and `GpuCounter` enums (`cpu_profiler.h` and `gpu_profiler.h` respectively). |
| 94 | + |
| 95 | +Platforms will support a subset of these counters, which can be queried via: |
35 | 96 |
|
36 | 97 | ``` |
37 | | -Instrument instrument_ = PMUCounter(); |
38 | | -instrument_.start(); |
| 98 | +auto cpu_counters = h.cpu_profiler()->supported_counters(); |
| 99 | +auto gpu_counters = h.gpu_profiler()->supported_counters() |
39 | 100 | ``` |
40 | 101 |
|
41 | | -#### Reading a Counter: |
| 102 | +You can specify the counters to be enabled in the following ways: |
42 | 103 |
|
43 | | -To read a counter, first stop it and then call its measurements function to store results in the MeasurementsMap variable which can then be read from. |
| 104 | +``` |
| 105 | +// Enable a default set of counters |
| 106 | +auto h = hwcpipe::HWCPipe(); |
44 | 107 |
|
| 108 | +// Pass sets of CPU and GPU counters to be enabled |
| 109 | +auto h = hwcpipe::HWCPipe({CpuCounter::Cycles, CpuCounter::Instructions}, {GpuCounter::GpuCycles}); |
| 110 | +
|
| 111 | +// Pass a JSON string |
| 112 | +auto h = hwcpipe::HWCPipe(json); |
45 | 113 | ``` |
46 | | -instrument_.stop(); |
47 | | -MeasurementsMap measurements = instrument_.measurements(); |
| 114 | + |
| 115 | +The JSON string should be formatted like this: |
| 116 | + |
| 117 | +``` |
| 118 | +{ |
| 119 | + "cpu": ["Cycles", "Instructions"], |
| 120 | + "gpu": ["GpuCycles"] |
| 121 | +} |
48 | 122 | ``` |
49 | 123 |
|
| 124 | +Available counter names can be found in `cpu_counter_names` (`cpu_profiler.h`) and `gpu_counter_names` (`gpu_profiler.h`). |
| 125 | + |
| 126 | +For more information regarding Mali counters, see [Mali Performance Counters](https://community.arm.com/graphics/b/blog/posts/mali-bifrost-family-performance-counters). |
| 127 | + |
| 128 | +### Enabling profiling on Android |
| 129 | + |
| 130 | +In order for performance data to be displayed, profiling needs to be enabled on the device. |
| 131 | +Some devices may disable it by default. |
| 132 | + |
| 133 | +Profiling can be enabled via `adb`: |
| 134 | + |
| 135 | +``` |
| 136 | +adb shell setprop security.perf_harden 0 |
| 137 | +``` |
50 | 138 |
|
51 | | -## Counters |
| 139 | +## Adding support for a new platform |
52 | 140 |
|
53 | | -The counters are separated into two categories: PMU and Mali counters, the available counters are: |
| 141 | +If the counters provided in `CpuCounter` and `GpuCounter` are enough for the new platform, |
| 142 | +the process is simple: |
54 | 143 |
|
55 | | -#### PMU |
| 144 | +* Add an implementation of either `CpuProfiler` of `GpuProfiler` (you can use `PmuProfiler` and `MaliProfiler` as references). |
| 145 | +* Add your platform to the automated platform detection in `hwcpipe.cpp`. For consistency in platform detection, the constructor for your platform should throw if the platform is not available. |
| 146 | +* Add your platform to the build system. |
56 | 147 |
|
57 | | - - CPU cycles |
58 | | - - CPU instructions |
59 | | - - Cache miss ratio |
60 | | - - Branch miss ratio |
| 148 | +### Adding new counters |
61 | 149 |
|
62 | | -#### Mali |
| 150 | +If you need to add new counters to the existing ones, you should update the following variables: |
63 | 151 |
|
64 | | - - Timespan |
65 | | - - GPU cycles |
66 | | - - Fragment Jobs |
67 | | - - Vertex/compute jobs |
68 | | - - L2 cache read lookups |
69 | | - - L2 cache external reads |
70 | | - - L2 cache external read stalls |
71 | | - - L2 cache external read beats |
72 | | - - L2 cache write lookups |
73 | | - - L2 cache external writes |
74 | | - - L2 cache external write stalls |
75 | | - - L2 cache external write beats |
| 152 | +* Add the counter to the `CpuCounter`/`GpuCounter` enum. |
| 153 | +* Add the counter name to the `cpu_counter_names`/`gpu_counter_names` map (necessary for JSON initialization). |
| 154 | +* Add a description and the unit for your counter to the `cpu_counter_info`/`gpu_counter_info` map. |
76 | 155 |
|
77 | | -For more information regarding these counters, see [Mali Performance Counters](https://community.arm.com/graphics/b/blog/posts/mali-bifrost-family-performance-counters). |
| 156 | +The `CpuCounter` and `GpuCounter` enums are meant to be expanded. Platforms must not break if new counters are added. |
0 commit comments