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.2.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.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl (55.7 kB view details)

Uploaded PyPymacOS 11.0+ ARM64

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

Uploaded PyPymacOS 11.0+ ARM64

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

Uploaded CPython 3.13macOS 11.0+ ARM64

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

Uploaded CPython 3.12macOS 11.0+ ARM64

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

Uploaded CPython 3.11macOS 11.0+ ARM64

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

Uploaded CPython 3.10macOS 11.0+ ARM64

zeus_apple_silicon-1.0.2-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.2.tar.gz.

File metadata

  • Download URL: zeus-apple-silicon-1.0.2.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.2.tar.gz
Algorithm Hash digest
SHA256 4d0fbe129cc7e42afb1b9fd4b6929f1037ecbbd8748849a7cf02a776bd3d403a
MD5 f1aee852bac1ff571287436716d490b5
BLAKE2b-256 392d616b1aaf47367a0ff17f62db9f10bbf49ebd6dd25061593c78c0c0941d51

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for zeus_apple_silicon-1.0.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 a50c8c873a0adbbcbeeeff9981c506676f9203ffd986d8bb078657624f698c35
MD5 6d7e92664077723cfada3ceee69f74e4
BLAKE2b-256 9e31ebf89c60a705095c070545d68b21b3869edc83af62ac92e584f397acb33f

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for zeus_apple_silicon-1.0.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 c4b5beec5842a549303b54f1c278ae8e3e462fa74ad6526a161b3583ab72eccc
MD5 ef5330cb88eee3379066329d0c423390
BLAKE2b-256 fd44c1335a25b0b6c2d739439c4f895956a855d4522d9b0f5fd140570a597f49

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for zeus_apple_silicon-1.0.2-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 b858e0305e4e16f340bf2a5156f6289ab2ce1d58636d59e435f495a7fffd0663
MD5 8a3ff78115a77c5af9ff077847eaf856
BLAKE2b-256 fc42f7044afe4c0ac137ff7f3e55253acde4d6922626a8ed08213da2e2332ada

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for zeus_apple_silicon-1.0.2-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 6b48e917261adaf0ebcc39bdb5cabe30e7dd2ef6de8d910738f8bbc521c50870
MD5 a2e1d3e3c930fd723e5564a3a8915289
BLAKE2b-256 48c51bb1dbd710f66aa34457032c305cf5ae8e79772d840127e598bc0687583d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for zeus_apple_silicon-1.0.2-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 5078c2a09a443f49d68003e5b05207c9c3e52b79ec3dab10f865c3c97fbfb01a
MD5 02e0075eeaea8c341c4d88d05b409c9e
BLAKE2b-256 dbe5db99c3705f1d6238047b323d7b2ce99e0eb0ffabb6d77ed50087ae616d52

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for zeus_apple_silicon-1.0.2-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 1831247e70c7b0118d674cd0c7799019d68c83deff4278bcd228df17c6707235
MD5 8c7e6543403b538f80d3198623ce590c
BLAKE2b-256 9083cd2f51ac64fd5c0552aeba6889591cd057b1c76167e2abc96fa364f25c11

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for zeus_apple_silicon-1.0.2-cp39-cp39-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 a113d72ae30f2dad2a1946fb23e99812144ed4e22e007ab328d946c53ce24703
MD5 fb62a812a9ba2bcb6a1d64b4047978e0
BLAKE2b-256 468de593e2727281837ce32a850292bfa2e9e8d4d3dc094adef3f58535483247

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