Skip to main content

A library for programmatic, in-code energy measurement on Apple Silicon.

Project description

In-Code Energy Measurement on Apple Silicon  ⚡

A lightweight, header-only C++ library for precisely measuring energy consumed by arbitrary code snippets on Apple Silicon processors.

Also available in Python, installable via pip.

This library is used to provide macOS support for Zeus, a framework for deep learning energy measurement and optimization.

Installation

Python

Install the package using pip:

pip install zeus-apple-silicon

Then, import the necessary components in your Python script:

from zeus_apple_silicon import AppleEnergyMonitor, AppleEnergyMetrics
# or: import zeus_apple_silicon

C++

  1. Copy/move the header file apple_energy.hpp (found in the apple_energy/ directory of the source repository) into your project.
  2. Include the header in your C++ files:
    #include "apple_energy.hpp"
    
  3. Link your executable against Apple's CoreFoundation framework and the IOReport library (part of IOKit); both dependencies are available by default on nearly all macOS devices. The library requires C++17.
    • Manual Compilation (g++/clang++) - add necessary flags to your compile command:
      g++ your_code.cpp -o your_executable -std=c++17 -framework CoreFoundation -lIOReport
      # or
      clang++ your_code.cpp -o your_executable -std=c++17 -framework CoreFoundation -lIOReport
      
    • CMake - add the following to your CMakeLists.txt file, where your_target_name is the name of your executable or library target:
      target_link_libraries(your_target_name PRIVATE
          "-framework CoreFoundation"
          IOReport
      )
      

Usage Overview

The library operates by defining measurement windows. You mark the beginning and end of a code section you want to measure.

  1. Start a measurement window: use AppleEnergyMonitor::begin_window(label) to indicate you want energy measurement to start at that line of code. Each window needs a string label passed in as an argument.
  2. The code being measured: The start of the window should be followed by the code you want to measure energy for.
  3. End & Retrieve Results: indicate where you want your measurement window to end by using AppleEnergyMonitor::end_window(label) with the same label you used to mark the window's start. The AppleEnergyMonitor::end_window(label) function returns an AppleEnergyMetrics object containing energy data collected during the window.

Note about Measurement Windows:

  • You can have multiple windows active simultaneously (i.e., they can overlap), as long as each uses a distinct label.
  • Non-overlapping windows can re-use names. I.e., once a window is ended with end_window, its label is free to be reused.
  • Attempting to start a window with a label still currently in use (i.e., end_window not yet called for that label) will raise an exception.
  • Calling end_window with a label that doesn't belong to any currently active window will raise an exception.

Note about Results of Measurements:

  • Results are reported via an AppleEnergyMetrics struct, but depending on your processor, some metrics may not be available (e.g., DRAM may not be available on older machines). In such cases, fields that could not be measured will be presented as: None in Python, and an empty std::optional object in C++.
  • A more detailed explanation of results is provided later in this readme.

Usage Examples

The API is identical in C++ and Python. For available fields of a result object, read this section of the readme.

C++ Example

#include "apple_energy.hpp"

int main() {
    // Create a monitor instance.
    AppleEnergyMonitor monitor;

    // --- Basic Measurement ---
    monitor.begin_window("task_1"); // Indicating the measurement window starts here.

    // Do some work...

    // End the window and get results.
    AppleEnergyMetrics result1 = monitor.end_window("task_1");


    // --- Overlapping Measurements ---
    monitor.begin_window("outer_task");

    monitor.begin_window("inner_task");
    AppleEnergyMetrics inner_result = monitor.end_window("inner_task");

    AppleEnergyMetrics outer_result = monitor.end_window("outer_task");


    // --- Reusing a Label ---
    monitor.begin_window("task_1"); // This is okay because previous "task_1" window ended.
    AppleEnergyMetrics result = monitor.end_window("task_1");
}

Python Example

from zeus_apple_silicon import AppleEnergyMonitor, AppleEnergyMetrics

# Create a monitor instance.
monitor = AppleEnergyMonitor()

# --- Basic Measurement ---
monitor.begin_window("task_1") # Indicating the measurement window starts here.

# Do some work...

# End the window and get results.
result1 = monitor.end_window("task_1")


# --- Overlapping Measurements ---
monitor.begin_window("outer_task")

monitor.begin_window("inner_task")
inner_result = monitor.end_window("inner_task")

outer_result = monitor.end_window("outer_task")


# --- Reusing a Label ---
monitor.begin_window("task_1") # This is okay because previous "task_1" ended.
result = monitor.end_window("task_1")

API Reference

Class: AppleEnergyMonitor

The main class for getting energy measurements.

  • AppleEnergyMonitor(): Constructor. Initializes the monitoring system.
  • begin_window(label: str): Starts a new measurement window identified by label.
  • end_window(label: str) -> AppleEnergyMetrics: Ends the measurement window identified by label and returns an object containing the results.
  • get_cumulative_energy() -> AppleEnergyMetrics: Returns cumulative energy consumed from an unspecified point fixed over the lifetime of the energy monitor (e.g., from bootup).

Struct/Class: AppleEnergyMetrics

This struct/class is how results get reported, containing metrics for various different SoC subsystems.

All energy values are reported in mJ.

Note: on some hardware configurations or macOS versions, certain metrics might not be available or reportable by the underlying system. In such cases, the corresponding attribute will be:

  • C++: An empty std::optional. You should check .has_value() before accessing .value().
  • Python: None. You should check for None before using the value.

Fields Reported in AppleEnergyMetrics:

  • CPU Related Metrics:

    • cpu_total_mj: std::optional<int64_t> (C++) / Optional[int] (Python)
      • Total energy consumed by all CPU related subsystems combined.
    • efficiency_cores_mj: std::optional<std::vector<int64_t>> (C++) / Optional[list[int]] (Python)
      • Energy consumed by each efficiency core individually. Returns a list where each element corresponds to an efficiency core.
    • performance_cores_mj: std::optional<std::vector<int64_t>> (C++) / Optional[list[int]] (Python)
      • Energy consumed by each performance core individually. Returns a list where each element corresponds to a performance core.
    • efficiency_core_manager_mj: std::optional<int64_t> (C++) / Optional[int] (Python)
      • Energy attributed to the efficiency core cluster's management logic.
    • performance_core_manager_mj: std::optional<int64_t> (C++) / Optional[int] (Python)
      • Energy attributed to the performance core cluster's management logic.
  • DRAM Metrics:

    • dram_mj: std::optional<int64_t> (C++) / Optional[int] (Python)
      • Energy consumed by DRAM.
  • GPU Related Metrics:

    • gpu_mj: std::optional<int64_t> (C++) / Optional[int] (Python)
      • Energy consumed by the on-chip GPU.
    • gpu_sram_mj: std::optional<int64_t> (C++) / Optional[int] (Python)
      • Energy consumed by the GPU's SRAM.
  • ANE Metrics:

    • ane_mj: std::optional<int64_t> (C++) / Optional[int] (Python)
      • Energy consumed by the Apple Neural Engine (ANE).

Source Code Directory Structure

  • apple_energy/: Contains the core C++ header library file (apple_energy.hpp).
  • bindings/: Contains nanobind bindings to create the Python package from the C++ library.
  • examples/: Contains sample usage and compilation examples (like the ones above).
  • scripts/: Utility scripts for development and CI.
  • tests/: Contains tests, which use mocked data.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

zeus-apple-silicon-1.0.1.tar.gz (25.7 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

zeus_apple_silicon-1.0.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl (55.7 kB view details)

Uploaded PyPymacOS 11.0+ ARM64

zeus_apple_silicon-1.0.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl (55.7 kB view details)

Uploaded PyPymacOS 11.0+ ARM64

zeus_apple_silicon-1.0.1-cp313-cp313-macosx_11_0_arm64.whl (57.1 kB view details)

Uploaded CPython 3.13macOS 11.0+ ARM64

zeus_apple_silicon-1.0.1-cp312-cp312-macosx_11_0_arm64.whl (57.2 kB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

zeus_apple_silicon-1.0.1-cp311-cp311-macosx_11_0_arm64.whl (58.2 kB view details)

Uploaded CPython 3.11macOS 11.0+ ARM64

zeus_apple_silicon-1.0.1-cp310-cp310-macosx_11_0_arm64.whl (58.3 kB view details)

Uploaded CPython 3.10macOS 11.0+ ARM64

zeus_apple_silicon-1.0.1-cp39-cp39-macosx_11_0_arm64.whl (58.6 kB view details)

Uploaded CPython 3.9macOS 11.0+ ARM64

File details

Details for the file zeus-apple-silicon-1.0.1.tar.gz.

File metadata

  • Download URL: zeus-apple-silicon-1.0.1.tar.gz
  • Upload date:
  • Size: 25.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.9

File hashes

Hashes for zeus-apple-silicon-1.0.1.tar.gz
Algorithm Hash digest
SHA256 e4fe98b53a5065b50abcbc761d4317bba2ba5d8cfb81f513f764a74898098253
MD5 8ea634b0b138d0c4aa05d93012d80531
BLAKE2b-256 07afa7b2b311c4d36c5f2d8b63cc7a3ce0310720e7a8c3029aaa263027692eb8

See more details on using hashes here.

File details

Details for the file zeus_apple_silicon-1.0.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for zeus_apple_silicon-1.0.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 1c9eb7f75d08e3caad1d08851fc0596c792c95256d25975b3ddbe9b29a2b1b65
MD5 94515c4e14e9c02d6ab0a909d7e18a11
BLAKE2b-256 3327b817a5a22d588e9a1c90ee91724aaa4ff5409a18fd5e36aba1e878cdfbe8

See more details on using hashes here.

File details

Details for the file zeus_apple_silicon-1.0.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for zeus_apple_silicon-1.0.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 5ea0267cbd8983344eacc17b8acfd2362031b5be8c64b28140d8aaf38c515d1c
MD5 c1e6f66f8fb9b3682295fee89c6f1e19
BLAKE2b-256 dd27e4c7c512ce5f13539a5048808c0d870f12431e837546c1f8f4a37e1dfa74

See more details on using hashes here.

File details

Details for the file zeus_apple_silicon-1.0.1-cp313-cp313-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for zeus_apple_silicon-1.0.1-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 030c5ab47dd514b3ea20b2c01312423a82574feb6749e2c7d054292eb28c3f9b
MD5 7530879b162ad6c23102473dfd6faa01
BLAKE2b-256 d599f530c0c568bd85270dbfeebca0ada31d60c59c5fd28a4f66105e1cf63965

See more details on using hashes here.

File details

Details for the file zeus_apple_silicon-1.0.1-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for zeus_apple_silicon-1.0.1-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 918503c62f603ae3a28413fbfd733ef7f0073d19b3a10cfa320350c07238b4c5
MD5 536adc0e5cc704856bd3c945856da3d8
BLAKE2b-256 d0500ad2ef3c5df0668b709d4031e951bd4109310c0e41087eb6cbb9021feeab

See more details on using hashes here.

File details

Details for the file zeus_apple_silicon-1.0.1-cp311-cp311-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for zeus_apple_silicon-1.0.1-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 7abc39422f345df96608df37b7634606c3121d963922ee7029d9d3bf76808830
MD5 90778291d12028b55e22c29bcb134993
BLAKE2b-256 c0c9e12df4a7694d34f96092f28055bb59e6e9a3bb7c8161e6238b2288826986

See more details on using hashes here.

File details

Details for the file zeus_apple_silicon-1.0.1-cp310-cp310-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for zeus_apple_silicon-1.0.1-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 fe09961f10365c0329b01bc549e8ebaadba014879ade2236de029519f470786b
MD5 e4edcee13ee519718d4843d869b9ed95
BLAKE2b-256 08cf363b92060695b4afe89fb0c3c867b57dbd5d45f31216b83ab6a9a2667bf2

See more details on using hashes here.

File details

Details for the file zeus_apple_silicon-1.0.1-cp39-cp39-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for zeus_apple_silicon-1.0.1-cp39-cp39-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 531646bba9d4a62e5f24d03595f596e519f18ddea17a6164348f2ad5d4d4e1bd
MD5 7c8b4a7422b6d241d37266593a23f3e8
BLAKE2b-256 45cd1f2d34160a409dd45140714f07b199bba3025c72a6326f5b12a5b23cc616

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page