spikingjelly.activation_based.op_counter.spikesim.config 源代码

from __future__ import annotations

import math
from dataclasses import dataclass, replace

__all__ = ["SpikeSimEnergyConfig"]
_SPIKESIM_XBAR_ROW_DIVISOR = 8.0


[文档] @dataclass class SpikeSimEnergyConfig: r""" **API Language:** :ref:`中文 <SpikeSimEnergyConfig-cn>` | :ref:`English <SpikeSimEnergyConfig-en>` ---- .. _SpikeSimEnergyConfig-cn: * **中文** SpikeSim 事件驱动能耗估计器的运行时能耗配置。 默认系数有意与已发布的 ``ela_spikesim.py`` 能耗路径保持一致, 但计数逻辑已替换为基于运行时事件的分析。 ---- .. _SpikeSimEnergyConfig-en: * **English** Runtime energy configuration for the event-driven SpikeSim estimator. The default coefficients intentionally match the released ``ela_spikesim.py`` energy path, while the counting logic is replaced by runtime event analysis. """ xbar_size: int = 64 device: str = "rram" activity_mode: str = "dense" require_if_lif_neurons: bool = True tile_buffer_pj: float = 397.0 temp_buffer_pj: float = 0.2 sub_pj: float = 1.15e-6 adc_pj: float = 2.03084 htree_pj: float = 19.64 * 8.0 mux_pj: float = 0.094245 mem_fetch_pj: float = 4.64 neuron_pj: float = 1.274 * 4.0 rram_xbar_pj: float = 1.76423 sram_xbar_pj: float = 671.089
[文档] def copy(self) -> "SpikeSimEnergyConfig": r""" **API Language:** :ref:`中文 <SpikeSimEnergyConfig.copy-cn>` | :ref:`English <SpikeSimEnergyConfig.copy-en>` ---- .. _SpikeSimEnergyConfig.copy-cn: * **中文** 复制当前配置并返回新对象。 :return: 当前配置的副本 :rtype: :class:`SpikeSimEnergyConfig` ---- .. _SpikeSimEnergyConfig.copy-en: * **English** Return a copied config object. :return: a copy of the current config :rtype: :class:`SpikeSimEnergyConfig` """ return replace(self)
[文档] def validate(self) -> None: r""" **API Language:** :ref:`中文 <SpikeSimEnergyConfig.validate-cn>` | :ref:`English <SpikeSimEnergyConfig.validate-en>` ---- .. _SpikeSimEnergyConfig.validate-cn: * **中文** 校验配置是否合法; 不合法时抛出 ``ValueError``。 ---- .. _SpikeSimEnergyConfig.validate-en: * **English** Validate the config and raise ``ValueError`` on invalid values. """ if self.xbar_size <= 0: raise ValueError(f"xbar_size must be positive, got {self.xbar_size}.") if self.device not in ("rram", "sram"): raise ValueError(f"device must be 'rram' or 'sram', got {self.device}.") if self.activity_mode not in ("dense", "event"): raise ValueError( f"activity_mode must be 'dense' or 'event', got {self.activity_mode}." )
@property def xbar_array_energy_pj(self) -> float: if self.device == "rram": return self.rram_xbar_pj if self.device == "sram": return self.sram_xbar_pj raise ValueError(f"device must be 'rram' or 'sram', got {self.device}.") @property def patch_control_energy_pj(self) -> float: b = float(self.xbar_size) return ( self.htree_pj + self.mem_fetch_pj + self.tile_buffer_pj + (b / _SPIKESIM_XBAR_ROW_DIVISOR) * 16.0 * self.sub_pj + (b / _SPIKESIM_XBAR_ROW_DIVISOR) * self.temp_buffer_pj + (b / _SPIKESIM_XBAR_ROW_DIVISOR) * (b / _SPIKESIM_XBAR_ROW_DIVISOR) * (self.adc_pj + self.mux_pj) )
[文档] def pe_cycle_energy_for_kernel_pj(self, kernel_size: tuple[int, int]) -> float: if len(kernel_size) != 2: raise ValueError( f"kernel_size must be a tuple of length 2, got {kernel_size}." ) k_h, k_w = kernel_size if k_h <= 0 or k_w <= 0: raise ValueError( f"kernel_size dimensions must be positive, got ({k_h}, {k_w})." ) return ( self.patch_control_energy_pj + self.neuron_pj + (self.xbar_size / _SPIKESIM_XBAR_ROW_DIVISOR) * float(k_h) * float(k_w) * self.xbar_array_energy_pj )
[文档] def xbar_row_energy_pj(self, tile_channels: int) -> float: if tile_channels <= 0: raise ValueError(f"tile_channels must be positive, got {tile_channels}.") if self.xbar_size <= 0: raise ValueError(f"xbar_size must be positive, got {self.xbar_size}.") padded_ratio = math.ceil(tile_channels / self.xbar_size) padded_ratio = padded_ratio * self.xbar_size / float(tile_channels) # Keep the row-level basis aligned with the released SpikeSim dense # energy path, whose xbar contribution scales as (xbar_size / 8) * k^2. return (self.xbar_array_energy_pj / _SPIKESIM_XBAR_ROW_DIVISOR) * padded_ratio