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.0.tar.gz (25.1 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.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl (55.7 kB view details)

Uploaded PyPymacOS 11.0+ ARM64

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

Uploaded PyPymacOS 11.0+ ARM64

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

Uploaded CPython 3.13macOS 11.0+ ARM64

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

Uploaded CPython 3.12macOS 11.0+ ARM64

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

Uploaded CPython 3.11macOS 11.0+ ARM64

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

Uploaded CPython 3.10macOS 11.0+ ARM64

zeus_apple_silicon-1.0.0-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.0.tar.gz.

File metadata

  • Download URL: zeus-apple-silicon-1.0.0.tar.gz
  • Upload date:
  • Size: 25.1 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.0.tar.gz
Algorithm Hash digest
SHA256 089847ddf7e39d09bb7e71b6ae304ee71e5190a865d99880b719d60573e52bea
MD5 b0c8dc7d9a7021daed98414e2481a03f
BLAKE2b-256 389c3033daddee9a9313f00b88e2a29aa2cd98860103a7ba599ba142f1feaf15

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for zeus_apple_silicon-1.0.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 3baca2c6f853c74692528297d51d399eb4456cd60bbc5d847d973539697f8a78
MD5 18c313f632bcb5e022d73515879fd69d
BLAKE2b-256 d718c0bb2d9d75b9dc0367f1058365f9c5880e68858b2091e0008f2eb0c16fb7

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for zeus_apple_silicon-1.0.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 893587ae2164b7c19d9983a25e5723055af6943df74b5bbf6bb7ea42978bb50d
MD5 4c25805b50093b52dbbce3c755ddc7dc
BLAKE2b-256 da0028c24b285f0a913fdfa7a548f8a40e79a0603828fb2b7cd923a8fb687c1f

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for zeus_apple_silicon-1.0.0-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 918fd80828c4f7cfd89638fd2efdf01ea2dc4cfd98f785efb03016cdc9076a27
MD5 7f26402148c77c5f33d1908836f0232c
BLAKE2b-256 2a83a6ac15cdc8c85b1ca96c437fc3367f036d97525f2c54170b64768fd4dc9a

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for zeus_apple_silicon-1.0.0-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 4dbaaa2c8ae3fd8487d65ce56bcbae8173cca8b7dfda4438c0ece14a31d74415
MD5 eb2efebb336fc1098b4e6d9601a4e2c7
BLAKE2b-256 3196237bdb0f5789e7a0ba745f9f4f54cd8ae27c5ea90b3f5a863b6a7071872d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for zeus_apple_silicon-1.0.0-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 76f4baeff2f1d3d1771c36474de5c18f8295d0a22b554450f7fab6fbb072a078
MD5 c8d659c6cef27075f8b1020351e1bccb
BLAKE2b-256 b0cd267e97c897dc6c516f874606518b3f3390f8ad7bfbc885b7e56ab4c1b0b5

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for zeus_apple_silicon-1.0.0-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 b521f8cab7f98752ced697debfcfbaa96b8adbd9d14e3013c09dcc331c50704d
MD5 f33ac29320899b58fac9bc57de050dfd
BLAKE2b-256 611e2cd9f2e0c41d2c7d6008acbb78cb7361d8bd8df7ede32659f9f8bb14f971

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for zeus_apple_silicon-1.0.0-cp39-cp39-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 1abd8975ef55f628255730af62c31089479d9cfc7daf73d23bc6ed1ffd48f8a9
MD5 b96b2bca002262d7e1cdb85bc9ec30f1
BLAKE2b-256 bd910ffc2062910fb7d13a024387e2acce2a0fbf26c628e2151d46aa3a563ff6

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