giul
giúl — Irish for joule. One ruler for "what did this answer cost in energy" across the FoxxeLabs fleet: Aigne, Tuiscint, Gléas.
Two rulers make a comparison an argument instead of evidence. This is one, and all three pin it.
pip install giul # no dependencies; imports fine with no GPU
pip install giul[nvml] # + nvidia-ml-py, for the energy counter
pip install giul[remote] # + httpx, for metering a remote node
What a joule means here
The number a request is charged is energy above idle:
joules = measured − idle_w × seconds
A request pays for the power it caused, not for the power the box burns
existing. idle_w is supplied by the caller, per node — giul never guesses
it, because a wrong idle floor silently rewrites every figure that node
reports.
Three rules
- Charged above idle. As above.
- No fabricated zeros. A window that measured ≤ 0 J above idle did not
measure a free request, it failed to measure one. It degrades to
estimated(with a hint) orunknown— never asampledzero. - Estimates are labelled as estimates. An estimate that reads as a measurement is exactly how an efficiency claim stops being evidence. A sampler that cannot be reached costs a measurement, never the request.
Use
from giul import Meter, Node
node = Node(name="iris", gpu_index=0, idle_w=38.0,
is_local=True, power_endpoint=None)
# async
async with Meter.for_node(node, joules_per_1k_hint=4100.0) as m:
await retrieve(); m.mark("retrieve")
await generate(); m.mark("generate")
e = m.result(tokens=412)
# e.joules, e.method, e.backend, e.stages == {"retrieve": Energy, "generate": Energy}
# sync
with Meter.for_node(node, sync=torch.cuda.synchronize).sync() as m:
...; m.mark("verify")
e = m.result(tokens=n)
mark(name) closes the current stage and opens the next. The total is always
computed over the whole window, never by summing stages, so a stage the
sampler was too slow to see cannot corrupt it.
The caller synchronises the GPU before the closing read. On the counter
backend the register only counts work the card has finished; pass
sync=torch.cuda.synchronize when the work is local. An HTTP upstream needs
nothing — the completion returning is the sync point.
Backends
Chosen at runtime in one place (Meter.for_node), needing no per-node
configuration. Support is probed once per card and cached.
backend |
when | how |
|---|---|---|
nvml_counter |
local card, pynvml present, counter answers |
nvmlDeviceGetTotalEnergyConsumption delta — a true measurement of a sub-second window |
smi_sampler |
local card, nvidia-smi on PATH |
integral of power.draw samples |
remote_agent |
node.power_endpoint set |
the same integral, sampled by giul-agent on that node |
none |
otherwise | estimated with a hint, else unknown |
method stays sampled / estimated / unknown. The counter is a
measurement, so it reports method="sampled"; the distinction lives in
backend.
Tools
giul-probe # what this host's cards support; counter vs sampler
giul-agent --port 9402 # expose a node's power draw; stdlib only, read-only
Bind giul-agent to the mesh address, not 0.0.0.0, unless the node is
otherwise firewalled.
Not in 0.1
CPU/RAPL, carbon, € cost, storing series, any UI.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file giul-0.1.0.tar.gz.
File metadata
- Download URL: giul-0.1.0.tar.gz
- Upload date:
- Size: 18.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3f31b454db0f895324b852220db52178d9ca544da67c1df3e1b1693677ed74f7
|
|
| MD5 |
16596fc81d7973ed893e17f3a66aad7e
|
|
| BLAKE2b-256 |
495b212a06273c46ea21e5f12834f1d1d29d088398f6c50fd0ef8af7525b91aa
|
File details
Details for the file giul-0.1.0-py3-none-any.whl.
File metadata
- Download URL: giul-0.1.0-py3-none-any.whl
- Upload date:
- Size: 15.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cda79b890b3a160d22104e6e1cd77070beaa1e1d01429eff66509b1c84efd2b9
|
|
| MD5 |
accb5753784bbb7c06aa4c56454bbe6a
|
|
| BLAKE2b-256 |
8135c6bc66d347d4dd4b26a693f0ba98580868f6db77bae884c080818f28cb44
|