This page was generated from docs/devices/quick-xylo/xylo-audio-power.ipynb. Interactive online version: Binder badge

🐝🔌 Measuring power consumption on Xylo™Audio HDK

Note: In this tutorial Xylo™Audio refers to Xylo™Audio 2 and Xylo™Audio 3. In case differences occur we will explicitly name the correct HDK.

Note 2: This tutorial assume you have already build and mapped a network to Xylo™Audio. If this is not the case, please follow the tutorial at :ref:/devices/quick-xylo/xylo-audio-intro.ipynb

syns61201.XyloSamna and syns65302.XyloSamna (respectively for XyloAudio 2 and XyloAudio 3) provide an interface to real-time power measurements on the XyloAudio HDK. Current on several power nets on the chip can be sampled asynchronously while the device is in operation.

The evolve() method provides a power measurement interface while the device is in inference mode, and the XyloSamna module can also be used to measure idle power.

[ ]:
# Specify the xylo board you would like to use for this tutorial
# Available boards: XyloAudio2 and XyloAudio3
xylo_board_name = 'XyloAudio3'

# - Imports dependent on your HDK
# - XyloAudio 2
if xylo_board_name == 'XyloAudio2':
    import rockpool.devices.xylo.syns61201 as xa
    from rockpool.devices.xylo.syns61201 import xa2_devkit_utils as xa_utils
# - XyloAudio 3
elif xylo_board_name == 'XyloAudio3':
    import rockpool.devices.xylo.syns65302 as xa
    from rockpool.devices.xylo.syns65302 import xa3_devkit_utils as xa_utils

# Available boards: XyloAudio2 and XyloAudio3
xylo_board_name = 'XyloAudio3'


import numpy as np
[2]:
# - Find and connect to a XyloAudio HDK
from rockpool.devices.xylo import find_xylo_hdks
xylo_hdk_nodes, modules, versions = find_xylo_hdks()
print(xylo_hdk_nodes)

hdk = None

for version, xylo in zip(versions, xylo_hdk_nodes):
    if version == "syns61201":
        hdk = xylo
    # - For XyloAudio 3
    elif version == "syns65302":
        hdk = xylo

if hdk is None:
    assert False, 'This tutorial requires a connected XyloAudio HDK to demonstrate.'



The connected Xylo HDK contains a XyloAudio 3. Importing `rockpool.devices.xylo.syns65302`
[<samna.xyloAudio3.XyloAudio3TestBoard object at 0x7cd00f0de4b0>]

On instantiation, XyloSamna can specify a power sampling frequency. By default, power is measured at 5 Hz.

[3]:
# - Define the size of the network layers
Nin = 2
Nhidden = 4
Nout = 2
dt = 1e-3

# load config created in XyloAudio intro tutorial
%store -r config

# - For XyloAudio 2
if xylo_board_name == 'XyloAudio2':
    # - Set a low clock frequency for the XyloAudio 2 device
    xa_utils.set_xylo_core_clock_freq(hdk, 6.25)
    # - Use XyloSamna to deploy to the HDK
    modSamna = xa.XyloSamna(hdk, config, dt = 10e-3, power_frequency=20.)
# - For XyloAudio 3
elif xylo_board_name == 'XyloAudio3':
    import samna
    # - Set a low clock frequency for the XyloAudio 3 device
    xa_utils.set_xylo_core_clock_freq(hdk, 6.25)
    # - Use XyloSamna to deploy to the HDK
    modSamna = xa.XyloSamna(hdk, config, dt = 10e-3, power_frequency=20.)

print(modSamna)
WARNING:samna.xyloAudio3:Requested PDM clock frequency 195312 could not be achieved, used 194552.52918287937 instead
XyloSamna  with shape (2, 8, 2)
[4]:
# - Generate some Poisson input
T = 1000
f = 0.4
input_spikes = np.random.rand(T, Nin) < f

# - Evolve some input on the SNN core, and record power during inference
out, _, record_dict = modSamna(input_spikes, record_power = True)

print(record_dict)
{'io_power': array([4.46644719e-05, 5.27330065e-05, 5.42548444e-05, 5.26624547e-05,
       5.22731397e-05, 5.24438111e-05, 5.15508297e-05, 5.20056725e-05,
       5.31936278e-05, 5.20105327e-05, 5.31826708e-05, 5.24881628e-05,
       5.22707500e-05, 5.29561894e-05, 5.17823424e-05, 5.23655495e-05,
       5.30992342e-05, 5.22785888e-05, 5.24720042e-05, 5.34786841e-05,
       5.24374957e-05, 5.29416290e-05, 5.25395594e-05, 5.25345340e-05,
       5.27847456e-05, 5.19925713e-05, 5.27561207e-05, 5.26861072e-05,
       5.25215358e-05, 5.23542377e-05, 5.24205504e-05, 5.20894094e-05,
       5.27775252e-05, 5.25651484e-05, 5.22221154e-05, 5.28711553e-05,
       5.25564873e-05, 5.21012408e-05, 5.30044813e-05, 5.28361825e-05,
       5.13447330e-05, 5.22164881e-05]), 'analog_power': array([1.17465585e-05, 1.19348250e-05, 1.23008853e-05, 1.15634605e-05,
       1.31435621e-05, 1.27060542e-05, 1.15766181e-05, 1.26167961e-05,
       1.23855745e-05, 1.26804249e-05, 1.25783420e-05, 1.18251313e-05,
       1.24061831e-05, 1.18949793e-05, 1.26562390e-05, 1.15477583e-05,
       1.25863335e-05, 1.19010734e-05, 1.22843344e-05, 1.17492459e-05,
       1.22880637e-05, 1.15174232e-05, 1.24418151e-05, 1.20264690e-05,
       1.22098524e-05, 1.27235501e-05, 1.21457320e-05, 1.19670520e-05,
       1.16380779e-05, 1.24937181e-05, 1.17544295e-05, 1.27169458e-05,
       1.25136790e-05, 1.23984491e-05, 1.19406408e-05, 1.31072229e-05,
       1.21830276e-05, 1.27201528e-05, 1.20502382e-05, 1.25654505e-05,
       1.15136281e-05, 1.19651731e-05]), 'digital_power': array([0.00078813, 0.00058126, 0.00058306, 0.00058354, 0.00058494,
       0.00058481, 0.00058357, 0.00058395, 0.00058351, 0.00058484,
       0.0005854 , 0.00058323, 0.0005837 , 0.00058436, 0.0005846 ,
       0.00058326, 0.00058377, 0.00058424, 0.00058334, 0.00058449,
       0.00058263, 0.00058453, 0.00058237, 0.00058415, 0.00058463,
       0.00058309, 0.00058493, 0.00058474, 0.00058511, 0.00058419,
       0.00058459, 0.00058431, 0.00058398, 0.00058536, 0.00058361,
       0.00058339, 0.00058352, 0.00058353, 0.00058478, 0.00058385,
       0.00058499, 0.00058398]), 'inf_duration': 2.0633151531219482}

For XyloAudio 2 power is sampled on four nets, and is returned in Watts.

‘io_power’ is the total I/O power of the device. ‘snn_core_power’ is the power consumption of the digital SNN core and control logic. ‘afe_core_power’ is the power of the analog audio front-end core. ‘afe_ldo_power’ is the power consumption of the internal low-drop-out voltage supply used by the AFE.

For XyloAudio 3 power is sampled on three nets, and is returned in Watts.

‘io_power’ is the total I/O power of the device. ‘analog_power’ is the power of the analog audio front-end core. ‘digital_power’ is the power consumption of the digital SNN core and control logic.

[5]:
# - Measure idle power (no evolution)
from time import sleep
import samna

# For XyloA3 power measurement is activated at the beginning of the evolve function and deactivated at the end
# to measure idle power, we need to activate power measurement explicitly
if xylo_board_name == 'XyloAudio3':
    modSamna._power_monitor.start_auto_power_measurement(20)

modSamna._power_buf.get_events()
sleep(5.)
power = modSamna._power_buf.get_events()

# - For XyloAudio 2
if xylo_board_name == 'XyloAudio2':
    power_idle = ([], [], [], [])
    for p in power:
        power_idle[p.channel].append(p.value)

    idle_power_per_channel = np.mean(np.stack(power_idle), axis = 1)

    channels = samna.xyloA2TestBoard.MeasurementChannels
    io_power = idle_power_per_channel[channels.Io]
    afe_core_power = idle_power_per_channel[channels.LogicAfe]
    afe_ldo_power = idle_power_per_channel[channels.IoAfe]
    snn_core_power = idle_power_per_channel[channels.Logic]

    print(f'XyloAudio 2\nAll IO:\t\t{io_power * 1e6:.1f} µW\nAFE core:\t{afe_core_power * 1e6:.1f} µW\nInternal LDO:\t{afe_ldo_power * 1e6:.1f} µW\nSNN core logic:\t{snn_core_power*1e6:.1f} µW')

# - For XyloAudio 3
elif xylo_board_name == 'XyloAudio3':
    # deactivate power measurement
    modSamna._power_monitor.stop_auto_power_measurement()

    power_idle = ([], [], [])
    for p in power:
        power_idle[p.channel].append(p.value)

    channels = samna.xyloAudio3.MeasurementChannels
    idle_power_per_channel = np.mean(np.stack(power_idle), axis = 1)
    io_power = idle_power_per_channel[channels.Io]
    analog_power = idle_power_per_channel[channels.AnalogLogic]
    digital_power = idle_power_per_channel[channels.DigitalLogic]
    print(f'XyloAudio 3\nAll IO:\t\t{io_power * 1e6:.1f} µW\nAFE core:\t{analog_power * 1e6:.1f} µW\nSNN core logic:\t{digital_power*1e6:.1f} µW')

XyloAudio 3
All IO:         39.7 µW
AFE core:       12.2 µW
SNN core logic: 577.6 µW

About power measurement on XyloAudio 3

XyloAudio 3 power is sampled in three nets: * IO power measures the power necessary to communicate with the outside world. * Analog power measures the power of the analog frontend and ADC. * Digital power measures the power consumption of the digital logic (XyloAudio 3 internal digital power, excluding IO power)

The digital power consumption primarily depends on the clock speed, and the size of the network. The number of spikes generated per time step doesn’t matter that much on power consumption.

XyloAudio 3 digital microphone is fed by an external power source and is not included in the Xylo power measurements.

The internal block on Xylo that receives the PDM signal and does the signal processing (Digital Front End) is powered by the same power rail as the SNN core. Those blocks are included in the power measurement. And while all digital logic in XyloAudio 3 is powered with the same power supply, and thus the static power (without any clock) of the DFE and SNN core can’t be distinguished, it is possible to distinguish the dynamic powers between DFE and SNN Core, by: ** feeding PDM_CLK externally, also feeding meaningful PDM data, disabling main clock -> we will get the DFE dynamic power ** don’t activate PDM_IF, feeding spikes via SAER_I to SNN Core -> we will get the SNN core dynamic power

Also note that:

When XyloAudio 3 is powered on and no clocks are provided (disabling main clock as well via FPGA settings), the digital measured power is the total DFE + SNN Core static power (P0). When deploying a network and feeding spikes via the SAER_I interface and running SNN core in parallel, the measured digital power (P1) is P0 + dynamic SNN core power -> P1 - P0 = dynamic SNN core power. Note: P1 contains minor power from SAER_I processing, it is considered to be very small and can be ignored, also P1 is measured with SNN core in Accelerated mode. When deploying a network and activating digital microphone path as normal, the measured power (P2) at VDDHD is P0 + dynamic SNN core power + dynamic DFE power -> P2 - P1 = dynamic DFE power. Note: P2 is measured with SNN core in real-time mode.

Accelerated and real-time will differ in power consumption because accelerated mode will in most cases be in the active phase while real time mode will switch between active and idle.

Hints on reducing power consumption

Several points may be useful in reducing active power on XyloAudio.

Note: Accelerated time is not the most power-saving mode of XyloAudio 3. For instance, the same network above would have consumed around 350 µW of processing when ran in Real time mode.

  • Reducing the core clock frequency. The dev-kit utility function devices.xylo.syns61201.xa2_devkit_utils.set_xylo_core_clock_freq() can be used to set a lower core clock frequency than the default of 50 Mhz, lowering power consumption proportionally. Depending on your network size and complexity you can most likely reduce the clock frequency and still guarantee real-time operation.

  • Reducing network activity and network size. The SNN core within Xylo only works as hard as it needs to. Once all neuron states have been updated, the core performs no operations until the next network time-step. This conserves energy.

[7]:
if xylo_board_name == 'XyloAudio2':
    help(xa_utils.set_xylo_core_clock_freq)
elif xylo_board_name == 'XyloAudio3':
    help(xa_utils.set_xylo_core_clock_freq)

Help on function set_xylo_core_clock_freq in module rockpool.devices.xylo.syns65302.xa3_devkit_utils:

set_xylo_core_clock_freq(device: samna.xyloAudio3.XyloAudio3TestBoard, main_clock_frequency_MHz: float) -> None
    Set the internal core clock frequency used by Xylo

    Args:
        device (XyloAudio3HDK): A XyloAudio 3 device to configure
        main_clock_frequency_MHz (float): The main clock frequency of XyloAudio 3 in MHz

Estimate the required master clock frequency for real-time operation

Rockpool includes a model of the cycles required to operate the Xylo SNN inference core, in cycles_model(). Xylo is an efficient device, which skips computation whenever possible. As a result, the computational requirements and power consumption vary dynamically with network activity, and with network configuration.

By default cycles_model() estimates a worst-case scenario, which can inform the master clock frequency that guarantees real-time operation for your network. It can also take into account real network activity to estimate a usual computational load.

The function est_clock_freq() will return the master clock frequency that guarantees real-time operation, for a given Xylo configuration.

[8]:
if xylo_board_name == 'XyloAudio2':
    from rockpool.devices.xylo.syns61201 import cycles_model, est_clock_freq
elif xylo_board_name == 'XyloAudio3':
    from rockpool.devices.xylo.syns65302 import cycles_model, est_clock_freq
help(cycles_model)
Help on function cycles_model in module rockpool.devices.xylo.syns63300.power_cycles_model:

cycles_model(config: Union[samna.xyloImu.configuration.XyloConfiguration, samna.xyloAudio3.configuration.XyloConfiguration], input_sp: Union[float, numpy.ndarray, torch.Tensor, array] = 1.0, hidden_sp: Union[float, numpy.ndarray, torch.Tensor, array] = 1.0, output_sp: Union[float, numpy.ndarray, torch.Tensor, array] = 1.0) -> float
    Calculate the average number of cycles required for a given network architecture

    This function contains a model which estimates the number of master clock cycles required for the Xylo SNN SYNS61202 and SYNS65302 inference cores to compute one time-step for a given chip configuration in ``config``. Use :py:func:`~.devices.xylo.syns61201.config_from_specification` to obtain a chip configuration, along with :py:meth:`.Module.as_graph` and :py:func:`~.devices.xylo.syns61201.mapper`, as described in the deployment tutorials for Xylo.

    By default the model provides a "worst-case" estimation, assuming that every neuron and every input channel fire on each time-step. If desired, real input rasters and real hidden and output spike rasters can be provided for analysis. Alternative spiking probabilities can also be provided as floats ``0..1``.

    Note that when estimating spiking probablility, only boolean values are relevant --- either a spike or no spike per time step per channel. Multiple events per bin cost the same as a single event.

    Args:
        config (Union[XyloIMUConfig, XyloA3Config]): A Xylo configuration for which to calculate the cycle requirements
        input_sp (FloatVector): Either a floating-point number 0..1, specifying the average input firing rate, or an actual input spike raster to use in evaluation. Default: `1.0`; estimate a worst-case scenario
        hidden_sp (FloatVector): Either a floating-point number 0..1, specifying the average hidden neuron firing rate, or an actual hidden spike raster to use in evaluation. Default: `1.0`; estimate a worst-case scenario
        output_sp (FloatVector): Either a floating-point number 0..1, specifying the average output neuron firing rate, or an actual output spike raster to use in evaluation. Default: `1.0`; estimate a worst-case scenario

    Returns:
        float: The average number of master clock cycles required for this configuration, for the Xylo SNN core to compute one network `dt`

[9]:
help(est_clock_freq)
Help on function est_clock_freq in module rockpool.devices.xylo.syns63300.power_cycles_model:

est_clock_freq(config: Union[samna.xyloImu.configuration.XyloConfiguration, samna.xyloAudio3.configuration.XyloConfiguration], dt: float, margin: float = 0.2)
    Estimate the required master clock frequency, to run a network in real-time.

    This function will perform a worst-case analysis, assuming that every input channel, every hidden neuron and every output neuron fire an event on each `dt`.
    An additional margin is included (Default: 20%), to guarantee that the model will run in real time at the suggested master clock frequency.
    Note: The clock frequency is returned in Hz.

    Args:
        config (Union[XyloIMUConfig, XyloA3Config]):  A Xylo configuration for which to estimate the required clock frequency
        dt (float): The required network `dt`, in seconds
        margin (float): The additional overhead safety margin to add to the estimation, as a fraction. Default: `0.2` (20%)

[10]:
print(f"This network requires {cycles_model(config)} master clock cycles per network time-step.")
print(f"This network requires a master clock of {est_clock_freq(config, dt) / 1e6:.2f} MHz for real-time operation.")
This network requires 562.0 master clock cycles per network time-step.
This network requires a master clock of 0.67 MHz for real-time operation.
[ ]: