Skip to content

[Version 3] feat(RAM): ✨ add psutil for RAM tracking #781

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 99 commits into
base: codecarbon_v3_rc
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
99 commits
Select commit Hold shift + click to select a range
3164f81
build on codecarbon_v3_rc
Dec 11, 2024
4a2b6ae
bump
Dec 11, 2024
35ef095
hatch run dev:bumpver update --set-version 3.0.0-rc0 --tag-num
Dec 11, 2024
311055e
build
Dec 11, 2024
20dc796
bump
Dec 11, 2024
015a67d
build
Dec 11, 2024
3128ea5
Add CPU load tracking
benoit-cty Jun 13, 2022
a34a47d
Add new CPU
benoit-cty Jun 14, 2022
984db97
Add mandatory country
benoit-cty Jun 14, 2022
db3bcdd
Fix RAPL fallback
benoit-cty Jun 14, 2022
a9021eb
debug RAPL
Nov 26, 2024
e6adb9b
Release Drafter
Dec 11, 2024
65ef805
refacto ResourceTracker
Dec 11, 2024
0abecc7
example
Dec 12, 2024
2d37eb4
Add CPU load
Jan 7, 2025
7954ebc
Add division to Power
Jan 7, 2025
4c0c871
Handle Pandas warning
Jan 7, 2025
7a360c1
CPU Load task support
Jan 7, 2025
96bef79
CPU load and RAPL comparison
Jan 7, 2025
80b075e
Better cpu load estimation
Jan 8, 2025
ed87a51
change version
Jan 10, 2025
771ec66
Fix test test_carbon_tracker_offline_region_error
Jan 10, 2025
f2612ba
RAPL path
Jan 10, 2025
83fb47d
Handle no Tapo
Jan 10, 2025
6f5bfbf
Debug config
Jan 10, 2025
1f39746
wip: test on Scaleway
Jan 10, 2025
b7c7eba
Add load per core
Jan 10, 2025
fa29257
Add E5-2620 v3
Jan 11, 2025
4c8a258
Add a TDP test
Jan 11, 2025
80536c0
Fix match for Intel(R) Xeon(R) CPU E5-2620 v3 @ 2.40GHz
Jan 11, 2025
78bdc2f
Fix psutil detection
Jan 11, 2025
4dbe2d1
Fix cpu 0
Jan 11, 2025
523bc56
Scaleway test results
Jan 12, 2025
5ab2617
TO REVERT : publish RC to Pypi
Jan 12, 2025
338cb96
Notes on E5-2620
Jan 12, 2025
70549dd
Add count_physical_cpus
Jan 14, 2025
9a53f58
Multiply TDP per physical CPU
Jan 14, 2025
658d3c1
Custom CPU load
Jan 14, 2025
47d1079
Find RAM domain
Jan 14, 2025
931b15a
Handle RAPL RAM
Jan 14, 2025
659c09f
Improve RAPL
Jan 14, 2025
2d5d50c
Do not read core
Jan 14, 2025
d1511e2
Docs
Jan 14, 2025
80c5911
CPU Fallback doc
Jan 17, 2025
af645bf
feat(RAM): :sparkles: add psutil for RAM tracking
LuisBlanche Feb 8, 2025
f4e48c7
Merge branch 'codecarbon_v3_rc' into use-ram-load
LuisBlanche Feb 15, 2025
9591940
black
LuisBlanche Feb 15, 2025
e26f343
test(RAM): :white_check_mark: fix tests
LuisBlanche Feb 15, 2025
c956f21
Add CPU load tracking
benoit-cty Jun 13, 2022
01e1d27
Add new CPU
benoit-cty Jun 14, 2022
2e2a013
Add mandatory country
benoit-cty Jun 14, 2022
4a867dc
Fix RAPL fallback
benoit-cty Jun 14, 2022
36f338c
debug RAPL
Nov 26, 2024
602de48
Release Drafter
Dec 11, 2024
5c3def8
refacto ResourceTracker
Dec 11, 2024
1ccf6b9
example
Dec 12, 2024
fee6837
Add CPU load
Jan 7, 2025
556b16b
Add division to Power
Jan 7, 2025
83dc626
Handle Pandas warning
Jan 7, 2025
0ba2fb9
CPU Load task support
Jan 7, 2025
4cbfe4e
CPU load and RAPL comparison
Jan 7, 2025
d07db89
Better cpu load estimation
Jan 8, 2025
463740c
change version
Jan 10, 2025
35d0040
Fix test test_carbon_tracker_offline_region_error
Jan 10, 2025
cb0e8df
RAPL path
Jan 10, 2025
53faaec
Handle no Tapo
Jan 10, 2025
8f78d5d
Debug config
Jan 10, 2025
ed52589
wip: test on Scaleway
Jan 10, 2025
c16e06f
Add load per core
Jan 10, 2025
0bb2cc8
Add E5-2620 v3
Jan 11, 2025
84eac1c
Add a TDP test
Jan 11, 2025
9664fb4
Fix match for Intel(R) Xeon(R) CPU E5-2620 v3 @ 2.40GHz
Jan 11, 2025
d23c919
Fix psutil detection
Jan 11, 2025
5ff761f
Fix cpu 0
Jan 11, 2025
27893f9
Scaleway test results
Jan 12, 2025
d5e122f
TO REVERT : publish RC to Pypi
Jan 12, 2025
fa12978
Notes on E5-2620
Jan 12, 2025
937bcf9
Add count_physical_cpus
Jan 14, 2025
1841fe3
Multiply TDP per physical CPU
Jan 14, 2025
98d70b8
Custom CPU load
Jan 14, 2025
316ef7e
Find RAM domain
Jan 14, 2025
2e05544
Handle RAPL RAM
Jan 14, 2025
d2e2b97
Improve RAPL
Jan 14, 2025
fed96ee
Do not read core
Jan 14, 2025
cddc72a
Docs
Jan 14, 2025
5674f13
CPU Fallback doc
Jan 17, 2025
5d5a09a
AMD CPU
Feb 3, 2025
a9d90e0
Add W per core for default
benoit-cty Feb 4, 2025
afff566
Data on CPU loads
Feb 14, 2025
e90ed10
fix circular import
Feb 15, 2025
57e5fa1
Default to 1 CPU
Feb 15, 2025
a07e44b
Fix case TDP is None
Feb 15, 2025
bf0dd10
bump
Feb 15, 2025
3bf3af6
docs
Feb 15, 2025
9674f05
Merge pull request #316 from mlco2/use-cpu-load
benoit-cty Feb 15, 2025
1c90c1b
feat(RAM): :sparkles: add psutil for RAM tracking
LuisBlanche Feb 8, 2025
a7cb4d1
black
LuisBlanche Feb 15, 2025
ad17eba
test(RAM): :white_check_mark: fix tests
LuisBlanche Feb 15, 2025
7509f70
Merge branch 'use-ram-load' of https://github.com/mlco2/codecarbon in…
LuisBlanche Apr 19, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 26 additions & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: build package & server
on:
pull_request:
push:
branches: [master]
branches: [master, codecarbon_v3_rc]

jobs:
python-test:
Expand Down Expand Up @@ -165,3 +165,28 @@ jobs:
- name: Check formatting with Prettier
working-directory: ./webapp
run: npx prettier . --check

TEMP_publish_release_candidate:
runs-on: ubuntu-latest
needs: [ python-test ]
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: 3.12
- name: Check versions
run: |
pip install -U pip requests
python3 .github/check_version.py
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install hatch==1.13.0 hatchling==1.25.0
- name: Build package
run: hatch build -c
- name: Publish package
uses: pypa/gh-action-pypi-publish@release/v1
with:
user: __token__
password: ${{ secrets.PYPI_TOKEN }}
2 changes: 1 addition & 1 deletion .github/workflows/package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: package

on:
push:
branches: [master]
branches: [master, codecarbon_v3_rc]

jobs:
build-package:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/pre-commit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: pre-commit
on:
pull_request:
push:
branches: [master]
branches: [master, codecarbon_v3_rc]

jobs:
pre-commit:
Expand Down
5 changes: 2 additions & 3 deletions .github/workflows/release-drafter.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,13 @@ name: Release Drafter
on:
push:
# branches to consider in the event; optional, defaults to all
branches:
- master
branches: [master, codecarbon_v3_rc]

jobs:
update_release_draft:
runs-on: ubuntu-latest
steps:
# Drafts your next Release notes as Pull Requests are merged into "master"
- uses: release-drafter/release-drafter@v5.7.0
- uses: release-drafter/release-drafter@v6
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
20 changes: 14 additions & 6 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -248,11 +248,15 @@ Here is the launch.json to be able to debug examples and tests:

```json
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [

{
"name": "Python: Current File",
"type": "python",
"type": "debugpy",
"request": "launch",
"program": "${file}",
"console": "integratedTerminal",
Expand All @@ -261,13 +265,17 @@ Here is the launch.json to be able to debug examples and tests:
},
{
"name": "PyTest: Current File",
"type": "python",
"type": "debugpy",
"request": "launch",
"module": "pytest",
"args": ["${file}"],
"args": [
"-s",
"${file}"
],
"console": "integratedTerminal",
"justMyCode": true,
"env": { "PYTHONPATH": "${workspaceRoot}" }
"env": { "PYTHONPATH": "${workspaceRoot}",
"CODECARBON_ALLOW_MULTIPLE_RUNS": "True" }
},
{
"name": "PyTest: codecarbon monitor",
Expand All @@ -279,7 +287,7 @@ Here is the launch.json to be able to debug examples and tests:
],
"console": "integratedTerminal",
"justMyCode": true,
"env": { "PYTHONPATH": "${workspaceRoot}" }
"env": { "PYTHONPATH": "${workspaceRoot}"}
}
]
}
Expand Down Expand Up @@ -350,7 +358,7 @@ to regenerate the html files.
### Release process

- Merge all PRs.
- Create a PR bumping the version with `hatch run dev:bumpver update --patch`.
- Create a PR bumping the version with `hatch run dev:bumpver update --patch`. For a release candidate, use `hatch run dev:bumpver update --set-version 3.0.0_rc1`.
- Run `hatch run python3 .github/check_version.py` to check version consistancy.
- Update the dependencies with `hatch-pip-compile --upgrade --all`.
- [Build Documentation](#documentation) if needed with `hatch run docs:build`.
Expand Down
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -172,3 +172,9 @@ Here is a sample for BibTeX:
# Contact 📝

Maintainers are [@vict0rsch](https://github.com/vict0rsch) [@benoit-cty](https://github.com/benoit-cty) and [@SaboniAmine](https://github.com/saboniamine). Codecarbon is developed by volunteers from [**Mila**](http://mila.quebec) and the [**DataForGoodFR**](https://twitter.com/dataforgood_fr) community alongside donated professional time of engineers at [**Comet.ml**](https://comet.ml) and [**BCG GAMMA**](https://www.bcg.com/en-nl/beyond-consulting/bcg-gamma/default).

## Star History

Comparison of the number of stars accumulated by the different Python CO2 emissions projects:
[![Star History Chart](https://api.star-history.com/svg?repos=mlco2/codecarbon,lfwa/carbontracker,sb-ai-lab/Eco2AI,fvaleye/tracarbon,Breakend/experiment-impact-tracker&type=Date)](https://star-history.com/#mlco2/codecarbon&lfwa/carbontracker&sb-ai-lab/Eco2AI&fvaleye/tracarbon&Breakend/experiment-impact-tracker&Date)

2 changes: 1 addition & 1 deletion codecarbon/_version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "2.8.2"
__version__ = "3.0.0_rc1"
4 changes: 2 additions & 2 deletions codecarbon/core/api_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -257,8 +257,8 @@ def _create_run(self, experiment_id):
gpu_count=self.conf.get("gpu_count"),
gpu_model=self.conf.get("gpu_model"),
# Reduce precision for Privacy
longitude=round(self.conf.get("longitude"), 1),
latitude=round(self.conf.get("latitude"), 1),
longitude=round(self.conf.get("longitude", 0), 1),
latitude=round(self.conf.get("latitude", 0), 1),
region=self.conf.get("region"),
provider=self.conf.get("provider"),
ram_total_size=self.conf.get("ram_total_size"),
Expand Down
50 changes: 45 additions & 5 deletions codecarbon/core/cpu.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@
"""

import os
import re
import shutil
import subprocess
import sys
from typing import Dict, Optional, Tuple

import pandas as pd
import psutil
from rapidfuzz import fuzz, process, utils

from codecarbon.core.rapl import RAPLFile
Expand All @@ -19,6 +21,9 @@
from codecarbon.external.logger import logger
from codecarbon.input import DataSource

# default W value per core for a CPU if no model is found in the ref csv
DEFAULT_POWER_PER_CORE = 4


def is_powergadget_available() -> bool:
"""
Expand Down Expand Up @@ -58,6 +63,21 @@ def is_rapl_available() -> bool:
return False


def is_psutil_available():
try:
nice = psutil.cpu_times().nice
if nice > 0.1:
return True
else:
return False
except Exception as e:
logger.debug(
"Not using the psutil interface, an exception occurred while instantiating "
+ f"psutil.cpu_percent : {e}",
)
return False


class IntelPowerGadget:
"""
A class to interface with Intel Power Gadget for monitoring CPU power consumption on Windows and (non-Apple Silicon) macOS.
Expand Down Expand Up @@ -237,7 +257,7 @@ class IntelRAPL:

"""

def __init__(self, rapl_dir="/sys/class/powercap/intel-rapl"):
def __init__(self, rapl_dir="/sys/class/powercap/intel-rapl/subsystem"):
self._lin_rapl_dir = rapl_dir
self._system = sys.platform.lower()
self._rapl_files = []
Expand Down Expand Up @@ -275,6 +295,8 @@ def _fetch_rapl_files(self) -> None:
with open(path) as f:
name = f.read().strip()
# Fake the name used by Power Gadget
# We ignore "core" in name as it seems to be included in "package" for Intel CPU.
# TODO: Use "dram" for memory power
if "package" in name:
name = f"Processor Energy Delta_{i}(kWh)"
i += 1
Expand All @@ -294,7 +316,7 @@ def _fetch_rapl_files(self) -> None:
logger.debug("We will read Intel RAPL files at %s", rapl_file)
except PermissionError as e:
raise PermissionError(
"Unable to read Intel RAPL files for CPU power, we will use a constant for your CPU power."
"PermissionError : Unable to read Intel RAPL files for CPU power, we will use a constant for your CPU power."
+ " Please view https://github.com/mlco2/codecarbon/issues/244"
+ " for workarounds : %s",
e,
Expand Down Expand Up @@ -332,8 +354,6 @@ def get_static_cpu_details(self) -> Dict:
"""
Return CPU details without computing them.
"""
logger.debug("get_static_cpu_details %s", self._cpu_details)

return self._cpu_details

def start(self) -> None:
Expand Down Expand Up @@ -426,6 +446,18 @@ def _get_matching_cpu(
start_cpu = model_raw.find(" CPU @ ")
if start_cpu > 0:
model_raw = model_raw[0:start_cpu]
model_raw = model_raw.replace(" CPU", "")
model_raw = re.sub(r" @\s*\d+\.\d+GHz", "", model_raw)
direct_match = process.extractOne(
model_raw,
cpu_df["Name"],
processor=lambda s: s.lower(),
scorer=fuzz.ratio,
score_cutoff=THRESHOLD_DIRECT,
)

if direct_match:
return direct_match[0]
indirect_matches = process.extract(
model_raw,
cpu_df["Name"],
Expand Down Expand Up @@ -467,10 +499,18 @@ def _main(self) -> Tuple[str, int]:
+ " Please contact us.",
cpu_model_detected,
)
if is_psutil_available():
# Count thread of the CPU
threads = psutil.cpu_count(logical=True)
estimated_tdp = threads * DEFAULT_POWER_PER_CORE
logger.warning(
f"We will use the default power consumption of {DEFAULT_POWER_PER_CORE} W per thread for your {threads} CPU, so {estimated_tdp}W."
)
return cpu_model_detected, estimated_tdp
return cpu_model_detected, None
logger.warning(
"We were unable to detect your CPU using the `cpuinfo` package."
+ " Resorting to a default power consumption of 85W."
+ " Resorting to a default power consumption."
)
return "Unknown", None

Expand Down
4 changes: 2 additions & 2 deletions codecarbon/core/emissions.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ def get_cloud_country_iso_code(self, cloud: CloudMetadata) -> str:
selected = df.loc[flags]
if not len(selected):
raise ValueError(
"Unable to find country name for "
"Unable to find country ISO Code for "
f"cloud_provider={cloud.provider}, "
f"cloud_region={cloud.region}"
)
Expand All @@ -105,7 +105,7 @@ def get_cloud_geo_region(self, cloud: CloudMetadata) -> str:
selected = df.loc[flags]
if not len(selected):
raise ValueError(
"Unable to find country name for "
"Unable to find State/City name for "
f"cloud_provider={cloud.provider}, "
f"cloud_region={cloud.region}"
)
Expand Down
Loading