... | ... | @@ -166,14 +166,58 @@ able to process their data in real-time, that is to say, they must be able to |
|
|
keep up with the associated sample rate at which they are operating. For a GNU
|
|
|
Radio flowgraph, this means all blocks in the flowgraph must be able to keep up
|
|
|
with the rate data are arriving on their input ports. This is obviously limited
|
|
|
by the overall processing power of the machine the application is running on. It
|
|
|
can be very helpful to know how much processing time each block in a flowgraph
|
|
|
is taking in order to look for bottlenecks, which can be done with
|
|
|
*performance counters*.
|
|
|
by the overall processing power of the machine on which the application is
|
|
|
running and the complexity of the flowgraph. It can be very helpful to know how
|
|
|
much processing time each block in a flowgraph is taking in order to look for
|
|
|
bottlenecks, which can be done using *performance counters*.
|
|
|
|
|
|
See the following GNU Radio usage page on performance counters:
|
|
|
- [Performance Counters](https://wiki.gnuradio.org/index.php?title=Performance_Counters)
|
|
|
|
|
|
To enable performance counters in your flowgraph, open the GNU Radio
|
|
|
configuration file in an editor (in this case Microsoft Visual Studio Code).
|
|
|
|
|
|
```
|
|
|
$ code ~/.gnuradio/config.conf
|
|
|
```
|
|
|
|
|
|
Look for the `[perfcounters]` section and ensure that `on` is set to `True`. Add this section to the configuration file if it is missing.
|
|
|
|
|
|
```
|
|
|
[perfcounters]
|
|
|
clock = thread
|
|
|
export = False
|
|
|
on = True
|
|
|
```
|
|
|
|
|
|
Performance counters will add overhead to your application, so you only want to
|
|
|
enable them when you are profiling.
|
|
|
|
|
|
The list of available performance counter functions can be found in `gr::block`
|
|
|
[class reference](https://www.gnuradio.org/doc/doxygen/classgr_1_1block.html).
|
|
|
We list some of the most useful counters in the following table.
|
|
|
|
|
|
| Class Method | Description |
|
|
|
| ---------------------- | ------------------------------------------|
|
|
|
| `pc_nproduced_avg()` | Gets average num items produced. |
|
|
|
| `pc_work_time_avg()` | Gets average clock cycles spent in work. |
|
|
|
| `pc_work_time_total()` | Gets total clock cycles spent in work. |
|
|
|
| `pc_throughput_avg()` | Gets average throughput. |
|
|
|
| `reset_perf_counters()` | Resets the performance counters. |
|
|
|
|
|
|
As an example, if you wished to know how efficiency your block was implemented,
|
|
|
you could look at the ratio of the average number of items produced to
|
|
|
average time spent producing those items.
|
|
|
|
|
|
```python
|
|
|
# Example of accessing performance counters in a Python block
|
|
|
work_time_avg = self.pc_work_time_avg()
|
|
|
nproduced_avg = self.pc_nproduced_avg()
|
|
|
nitems_per_cycle = nproduced_avg / work_time_avg
|
|
|
```
|
|
|
|
|
|
Here a larger `nitems_per_cycle` would be a more efficient block.
|
|
|
|
|
|
### VOLK
|
|
|
|
|
|
Hardware-based solutions have historically been the preferred way to implement
|
... | ... | |