Skip to content

Commit 9674f05

Browse files
authored
Merge pull request #316 from mlco2/use-cpu-load
[Version 3] Add CPU load tracking
2 parents 311055e + 3bf3af6 commit 9674f05

File tree

80 files changed

+7445
-136
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

80 files changed

+7445
-136
lines changed

.github/workflows/build.yml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,3 +165,28 @@ jobs:
165165
- name: Check formatting with Prettier
166166
working-directory: ./webapp
167167
run: npx prettier . --check
168+
169+
TEMP_publish_release_candidate:
170+
runs-on: ubuntu-latest
171+
needs: [ python-test ]
172+
steps:
173+
- uses: actions/checkout@v4
174+
- name: Set up Python
175+
uses: actions/setup-python@v5
176+
with:
177+
python-version: 3.12
178+
- name: Check versions
179+
run: |
180+
pip install -U pip requests
181+
python3 .github/check_version.py
182+
- name: Install dependencies
183+
run: |
184+
python -m pip install --upgrade pip
185+
pip install hatch==1.13.0 hatchling==1.25.0
186+
- name: Build package
187+
run: hatch build -c
188+
- name: Publish package
189+
uses: pypa/gh-action-pypi-publish@release/v1
190+
with:
191+
user: __token__
192+
password: ${{ secrets.PYPI_TOKEN }}

.github/workflows/release-drafter.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,6 @@ jobs:
1010
runs-on: ubuntu-latest
1111
steps:
1212
# Drafts your next Release notes as Pull Requests are merged into "master"
13-
- uses: release-drafter/release-drafter@v5.7.0
13+
- uses: release-drafter/release-drafter@v6
1414
env:
1515
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

CONTRIBUTING.md

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -248,11 +248,15 @@ Here is the launch.json to be able to debug examples and tests:
248248

249249
```json
250250
{
251+
// Use IntelliSense to learn about possible attributes.
252+
// Hover to view descriptions of existing attributes.
253+
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
251254
"version": "0.2.0",
252255
"configurations": [
256+
253257
{
254258
"name": "Python: Current File",
255-
"type": "python",
259+
"type": "debugpy",
256260
"request": "launch",
257261
"program": "${file}",
258262
"console": "integratedTerminal",
@@ -261,13 +265,17 @@ Here is the launch.json to be able to debug examples and tests:
261265
},
262266
{
263267
"name": "PyTest: Current File",
264-
"type": "python",
268+
"type": "debugpy",
265269
"request": "launch",
266270
"module": "pytest",
267-
"args": ["${file}"],
271+
"args": [
272+
"-s",
273+
"${file}"
274+
],
268275
"console": "integratedTerminal",
269276
"justMyCode": true,
270-
"env": { "PYTHONPATH": "${workspaceRoot}" }
277+
"env": { "PYTHONPATH": "${workspaceRoot}",
278+
"CODECARBON_ALLOW_MULTIPLE_RUNS": "True" }
271279
},
272280
{
273281
"name": "PyTest: codecarbon monitor",
@@ -279,7 +287,7 @@ Here is the launch.json to be able to debug examples and tests:
279287
],
280288
"console": "integratedTerminal",
281289
"justMyCode": true,
282-
"env": { "PYTHONPATH": "${workspaceRoot}" }
290+
"env": { "PYTHONPATH": "${workspaceRoot}"}
283291
}
284292
]
285293
}
@@ -350,7 +358,7 @@ to regenerate the html files.
350358
### Release process
351359

352360
- Merge all PRs.
353-
- Create a PR bumping the version with `hatch run dev:bumpver update --patch`.
361+
- 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`.
354362
- Run `hatch run python3 .github/check_version.py` to check version consistancy.
355363
- Update the dependencies with `hatch-pip-compile --upgrade --all`.
356364
- [Build Documentation](#documentation) if needed with `hatch run docs:build`.

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,3 +172,9 @@ Here is a sample for BibTeX:
172172
# Contact 📝
173173

174174
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).
175+
176+
## Star History
177+
178+
Comparison of the number of stars accumulated by the different Python CO2 emissions projects:
179+
[![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)
180+

codecarbon/_version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = "3.0.0-rc0"
1+
__version__ = "3.0.0_rc1"

codecarbon/core/api_client.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -257,8 +257,8 @@ def _create_run(self, experiment_id):
257257
gpu_count=self.conf.get("gpu_count"),
258258
gpu_model=self.conf.get("gpu_model"),
259259
# Reduce precision for Privacy
260-
longitude=round(self.conf.get("longitude"), 1),
261-
latitude=round(self.conf.get("latitude"), 1),
260+
longitude=round(self.conf.get("longitude", 0), 1),
261+
latitude=round(self.conf.get("latitude", 0), 1),
262262
region=self.conf.get("region"),
263263
provider=self.conf.get("provider"),
264264
ram_total_size=self.conf.get("ram_total_size"),

codecarbon/core/cpu.py

Lines changed: 45 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,14 @@
55
"""
66

77
import os
8+
import re
89
import shutil
910
import subprocess
1011
import sys
1112
from typing import Dict, Optional, Tuple
1213

1314
import pandas as pd
15+
import psutil
1416
from rapidfuzz import fuzz, process, utils
1517

1618
from codecarbon.core.rapl import RAPLFile
@@ -19,6 +21,9 @@
1921
from codecarbon.external.logger import logger
2022
from codecarbon.input import DataSource
2123

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

2328
def is_powergadget_available() -> bool:
2429
"""
@@ -58,6 +63,21 @@ def is_rapl_available() -> bool:
5863
return False
5964

6065

66+
def is_psutil_available():
67+
try:
68+
nice = psutil.cpu_times().nice
69+
if nice > 0.1:
70+
return True
71+
else:
72+
return False
73+
except Exception as e:
74+
logger.debug(
75+
"Not using the psutil interface, an exception occurred while instantiating "
76+
+ f"psutil.cpu_percent : {e}",
77+
)
78+
return False
79+
80+
6181
class IntelPowerGadget:
6282
"""
6383
A class to interface with Intel Power Gadget for monitoring CPU power consumption on Windows and (non-Apple Silicon) macOS.
@@ -237,7 +257,7 @@ class IntelRAPL:
237257
238258
"""
239259

240-
def __init__(self, rapl_dir="/sys/class/powercap/intel-rapl"):
260+
def __init__(self, rapl_dir="/sys/class/powercap/intel-rapl/subsystem"):
241261
self._lin_rapl_dir = rapl_dir
242262
self._system = sys.platform.lower()
243263
self._rapl_files = []
@@ -275,6 +295,8 @@ def _fetch_rapl_files(self) -> None:
275295
with open(path) as f:
276296
name = f.read().strip()
277297
# Fake the name used by Power Gadget
298+
# We ignore "core" in name as it seems to be included in "package" for Intel CPU.
299+
# TODO: Use "dram" for memory power
278300
if "package" in name:
279301
name = f"Processor Energy Delta_{i}(kWh)"
280302
i += 1
@@ -294,7 +316,7 @@ def _fetch_rapl_files(self) -> None:
294316
logger.debug("We will read Intel RAPL files at %s", rapl_file)
295317
except PermissionError as e:
296318
raise PermissionError(
297-
"Unable to read Intel RAPL files for CPU power, we will use a constant for your CPU power."
319+
"PermissionError : Unable to read Intel RAPL files for CPU power, we will use a constant for your CPU power."
298320
+ " Please view https://github.com/mlco2/codecarbon/issues/244"
299321
+ " for workarounds : %s",
300322
e,
@@ -332,8 +354,6 @@ def get_static_cpu_details(self) -> Dict:
332354
"""
333355
Return CPU details without computing them.
334356
"""
335-
logger.debug("get_static_cpu_details %s", self._cpu_details)
336-
337357
return self._cpu_details
338358

339359
def start(self) -> None:
@@ -426,6 +446,18 @@ def _get_matching_cpu(
426446
start_cpu = model_raw.find(" CPU @ ")
427447
if start_cpu > 0:
428448
model_raw = model_raw[0:start_cpu]
449+
model_raw = model_raw.replace(" CPU", "")
450+
model_raw = re.sub(r" @\s*\d+\.\d+GHz", "", model_raw)
451+
direct_match = process.extractOne(
452+
model_raw,
453+
cpu_df["Name"],
454+
processor=lambda s: s.lower(),
455+
scorer=fuzz.ratio,
456+
score_cutoff=THRESHOLD_DIRECT,
457+
)
458+
459+
if direct_match:
460+
return direct_match[0]
429461
indirect_matches = process.extract(
430462
model_raw,
431463
cpu_df["Name"],
@@ -467,10 +499,18 @@ def _main(self) -> Tuple[str, int]:
467499
+ " Please contact us.",
468500
cpu_model_detected,
469501
)
502+
if is_psutil_available():
503+
# Count thread of the CPU
504+
threads = psutil.cpu_count(logical=True)
505+
estimated_tdp = threads * DEFAULT_POWER_PER_CORE
506+
logger.warning(
507+
f"We will use the default power consumption of {DEFAULT_POWER_PER_CORE} W per thread for your {threads} CPU, so {estimated_tdp}W."
508+
)
509+
return cpu_model_detected, estimated_tdp
470510
return cpu_model_detected, None
471511
logger.warning(
472512
"We were unable to detect your CPU using the `cpuinfo` package."
473-
+ " Resorting to a default power consumption of 85W."
513+
+ " Resorting to a default power consumption."
474514
)
475515
return "Unknown", None
476516

codecarbon/core/emissions.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ def get_cloud_country_iso_code(self, cloud: CloudMetadata) -> str:
9090
selected = df.loc[flags]
9191
if not len(selected):
9292
raise ValueError(
93-
"Unable to find country name for "
93+
"Unable to find country ISO Code for "
9494
f"cloud_provider={cloud.provider}, "
9595
f"cloud_region={cloud.region}"
9696
)
@@ -105,7 +105,7 @@ def get_cloud_geo_region(self, cloud: CloudMetadata) -> str:
105105
selected = df.loc[flags]
106106
if not len(selected):
107107
raise ValueError(
108-
"Unable to find country name for "
108+
"Unable to find State/City name for "
109109
f"cloud_provider={cloud.provider}, "
110110
f"cloud_region={cloud.region}"
111111
)

0 commit comments

Comments
 (0)