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

Uploaded PyPymacOS 11.0+ ARM64

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

Uploaded PyPymacOS 11.0+ ARM64

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

Uploaded CPython 3.13macOS 11.0+ ARM64

zeus_apple_silicon-1.0.3-cp312-cp312-macosx_11_0_arm64.whl (57.3 kB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

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

Uploaded CPython 3.11macOS 11.0+ ARM64

zeus_apple_silicon-1.0.3-cp310-cp310-macosx_11_0_arm64.whl (58.4 kB view details)

Uploaded CPython 3.10macOS 11.0+ ARM64

zeus_apple_silicon-1.0.3-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.3.tar.gz.

File metadata

  • Download URL: zeus_apple_silicon-1.0.3.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.3.tar.gz
Algorithm Hash digest
SHA256 e8403b7be94ab1dc5b3f73dc5cfa6df4bc8691f9450785fbd30205ab1bc3da28
MD5 8e13d25f8c4b277cc3108fd29d5cfcb2
BLAKE2b-256 2d6645842c543030609350befee51e2b74c9b68731128523de2ea677c5f77a7d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for zeus_apple_silicon-1.0.3-pp310-pypy310_pp73-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 a197819b9d90378a23e775ddac38f350bb7fd75c6abb4b4cef389327880eae92
MD5 b7389500f77e18a648b625c2ec876c05
BLAKE2b-256 1986fb8ac5524f7ffdee650dc8879bda73f98aa958b0bf7531143e059dfbba57

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for zeus_apple_silicon-1.0.3-pp39-pypy39_pp73-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 a023ae12c1a0dea13d4c5df319c7cba91e7697eb49f7dad0f63cf9dd3a141276
MD5 8840e7f1b00c77b3e1b91b7c37759724
BLAKE2b-256 bf31a13195324bd267bb9243db16800abae2f2816d24509d46c50ce02217dc41

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for zeus_apple_silicon-1.0.3-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 e37bb824532db35ce96fc4444379813f5806ce6db6f2aeb919b28ce47b1ca863
MD5 b5ed03008bc6b51585fc29d5b7b1ac72
BLAKE2b-256 ffd1070e31241a8f4ba8da060463349ef386f0126a99bc432bebe7a33d63204a

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for zeus_apple_silicon-1.0.3-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 554715785e0b9bb020f9763919c28df725388f44d74d1bda0fb99c71df5c4ec3
MD5 964f99aaf00cce1d26c2653794422426
BLAKE2b-256 2629cdaf344d175ca142eb5167599a87af8eeea7ff27a8cf30bbdfc4d98eefb8

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for zeus_apple_silicon-1.0.3-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 a4afa2d15bfc909f23c1a894c3c80986f0e2560bd15a2c06068c913059298cbc
MD5 6ee37ce058fd70b6ff81994cf812d1a7
BLAKE2b-256 a21655cf93d627d9ef702aba16ee20f62781066618e4d48da6e406988b4bd745

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for zeus_apple_silicon-1.0.3-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 a0feb78fdd5f5d355725c9ac6e296f3fb6f8306136a6b9907961b06f9549d779
MD5 ef2e856698653d0d247bf1ad782716a1
BLAKE2b-256 ebd5fb0c403a587e092d94d37c88dc8497e56fff009424a1fef93d6ad992432e

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for zeus_apple_silicon-1.0.3-cp39-cp39-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 cb22f8ece3d998c47b3d50a18e8ea843820d155cf4224372637fa2f6c81b6876
MD5 84ddfd7a2824b841fc8c015e14341905
BLAKE2b-256 cdc90ea1fcde89f9e279f4f69fc18c6412270bfc6750ec0bc4a5f3807ae49ede

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