Skip to content

Commit

Permalink
Merge pull request #355 from mlco2/feat/use_tracker_at_inference
Browse files Browse the repository at this point in the history
Add task-based tracking to enable inference emissions estimation
  • Loading branch information
benoit-cty committed Aug 3, 2023
2 parents 347a802 + 68f9216 commit 9f01ad2
Show file tree
Hide file tree
Showing 49 changed files with 1,253 additions and 193 deletions.
2 changes: 1 addition & 1 deletion .conda/meta.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{% set version = "2.2.7" %}
{% set version = "2.3.0" %}

package:
name: codecarbon
Expand Down
36 changes: 36 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,42 @@ To add a new feature to codecarbon, the following workflow is applied :
- Documenting the intent & the limits of a contribution in a dedicated issue or in the pull request helps the review
- Once automated tests pass, the PR is reviewed and merged by the repository maintainers

### Debug in VS Code

Here is the launch.json to be able to debug examples and tests:

```json
{
"version": "0.2.0",
"configurations": [
{
"name": "Python: Current File",
"type": "python",
"request": "launch",
"program": "${file}",
"console": "integratedTerminal",
"justMyCode": true,
"env": { "PYTHONPATH": "${workspaceRoot}" }
},
{
"name": "PyTest: Current File",
"type": "python",
"request": "launch",
"module": "pytest",
"args": [
"${file}"
],
"console": "integratedTerminal",
"justMyCode": true,
"env": { "PYTHONPATH": "${workspaceRoot}" }
}
]
}
```

Then run opened test with this button:

![vscode_debug](docs/edit/images/vscode_debug.png)

### <a name="local_deployement"></a> Local deployment

Expand Down
2 changes: 1 addition & 1 deletion codecarbon/_version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "2.2.7"
__version__ = "2.3.0"
1 change: 0 additions & 1 deletion codecarbon/core/cloud.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ def postprocess_gcp_cloud_metadata(cloud_metadata: Dict[str, Any]) -> Dict[str,


def get_env_cloud_details(timeout: int = 1) -> Optional[Any]:
# type: (int) -> Optional[Any]
"""
>>> get_env_cloud_details()
{'provider': 'AWS',
Expand Down
82 changes: 82 additions & 0 deletions codecarbon/core/measure.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
from time import time

from codecarbon.external.hardware import CPU, GPU, RAM
from codecarbon.external.logger import logger


class MeasurePowerEnergy:
"""
Measure power and energy consumption of a hardware component.
"""

_last_measured_time: int = 0
_hardware: list
_pue: float
_total_cpu_energy: float
_total_gpu_energy: float
_total_ram_energy: float
_total_energy: float
_cpu_power: float
_gpu_power: float
_ram_power: float

def __init__(self, hardware, pue):
"""
:param hardware: list of hardware components to measure
:param pue: Power Usage Effectiveness of the datacenter
"""
self._last_measured_time = time()
self._hardware = hardware
self._pue = pue
# TODO: Read initial energy values from hardware
self._total_cpu_energy = 0
self._total_gpu_energy = 0
self._total_ram_energy = 0
self._total_energy = 0
# Power cant't be read at init because we need time, so we set it to 0
self._cpu_power = 0
self._gpu_power = 0
self._ram_power = 0

def do_measure(self) -> None:
for hardware in self._hardware:
h_time = time.time()
# Compute last_duration again for more accuracy
last_duration = time.time() - self._last_measured_time
power, energy = hardware.measure_power_and_energy(
last_duration=last_duration
)
# Apply the PUE of the datacenter to the consumed energy
energy *= self._pue
self._total_energy += energy
if isinstance(hardware, CPU):
self._total_cpu_energy += energy
self._cpu_power = power
logger.info(
f"Energy consumed for all CPUs : {self._total_cpu_energy.kWh:.6f} kWh"
+ f". Total CPU Power : {self._cpu_power.W} W"
)
elif isinstance(hardware, GPU):
self._total_gpu_energy += energy
self._gpu_power = power
logger.info(
f"Energy consumed for all GPUs : {self._total_gpu_energy.kWh:.6f} kWh"
+ f". Total GPU Power : {self._gpu_power.W} W"
)
elif isinstance(hardware, RAM):
self._total_ram_energy += energy
self._ram_power = power
logger.info(
f"Energy consumed for RAM : {self._total_ram_energy.kWh:.6f} kWh"
+ f". RAM Power : {self._ram_power.W} W"
)
else:
logger.error(f"Unknown hardware type: {hardware} ({type(hardware)})")
h_time = time.time() - h_time
logger.debug(
f"{hardware.__class__.__name__} : {hardware.total_power().W:,.2f} "
+ f"W during {last_duration:,.2f} s [measurement time: {h_time:,.4f}]"
)
logger.info(
f"{self._total_energy.kWh:.6f} kWh of electricity used since the beginning."
)

0 comments on commit 9f01ad2

Please sign in to comment.