codecarbon 3.2.3__tar.gz → 3.2.5__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {codecarbon-3.2.3 → codecarbon-3.2.5}/PKG-INFO +18 -38
- {codecarbon-3.2.3 → codecarbon-3.2.5}/README.md +12 -8
- codecarbon-3.2.5/codecarbon/_version.py +1 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/cli/main.py +8 -7
- {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/core/config.py +38 -1
- {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/core/cpu.py +2 -2
- {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/core/emissions.py +57 -1
- codecarbon-3.2.5/codecarbon/core/gpu.py +166 -0
- codecarbon-3.2.5/codecarbon/core/gpu_amd.py +272 -0
- codecarbon-3.2.5/codecarbon/core/gpu_device.py +116 -0
- codecarbon-3.2.5/codecarbon/core/gpu_nvidia.py +130 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/core/measure.py +5 -1
- {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/core/resource_tracker.py +27 -15
- {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/core/util.py +15 -5
- codecarbon-3.2.5/codecarbon/data/private_infra/nordic_emissions.json +69 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/emissions_tracker.py +76 -45
- {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/external/geography.py +25 -17
- {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/external/hardware.py +33 -9
- {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/external/logger.py +6 -3
- {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/input.py +14 -9
- {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/output_methods/file.py +4 -7
- codecarbon-3.2.5/codecarbon/viz/assets/__init__.py +0 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon.egg-info/PKG-INFO +18 -38
- {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon.egg-info/SOURCES.txt +9 -0
- codecarbon-3.2.5/codecarbon.egg-info/requires.txt +33 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/pyproject.toml +24 -72
- {codecarbon-3.2.3 → codecarbon-3.2.5}/tests/test_config.py +43 -0
- codecarbon-3.2.5/tests/test_core_util.py +137 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/tests/test_cpu.py +193 -46
- {codecarbon-3.2.3 → codecarbon-3.2.5}/tests/test_emissions.py +103 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/tests/test_emissions_tracker.py +23 -3
- {codecarbon-3.2.3 → codecarbon-3.2.5}/tests/test_emissions_tracker_constant.py +6 -4
- {codecarbon-3.2.3 → codecarbon-3.2.5}/tests/test_geography.py +16 -4
- codecarbon-3.2.5/tests/test_gpu.py +222 -0
- codecarbon-3.2.5/tests/test_gpu_amd.py +499 -0
- codecarbon-3.2.3/tests/test_gpu.py → codecarbon-3.2.5/tests/test_gpu_nvidia.py +62 -16
- codecarbon-3.2.5/tests/test_logger.py +59 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/tests/test_package_integrity.py +10 -0
- codecarbon-3.2.5/tests/test_resource_tracker.py +43 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/tests/testdata.py +6 -30
- codecarbon-3.2.3/codecarbon/_version.py +0 -1
- codecarbon-3.2.3/codecarbon/core/gpu.py +0 -309
- codecarbon-3.2.3/codecarbon.egg-info/requires.txt +0 -57
- codecarbon-3.2.3/tests/test_core_util.py +0 -44
- {codecarbon-3.2.3 → codecarbon-3.2.5}/LICENSE +0 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/__init__.py +0 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/cli/__init__.py +0 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/cli/auth.py +0 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/cli/cli_utils.py +0 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/cli/monitor.py +0 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/core/__init__.py +0 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/core/api_client.py +0 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/core/cloud.py +0 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/core/electricitymaps_api.py +0 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/core/powermetrics.py +0 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/core/rapl.py +0 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/core/schemas.py +0 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/core/units.py +0 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/data/canada_provinces.geojson +0 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/data/cloud/impact.csv +0 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/data/hardware/cpu_dataset_builder/amd_cpu_scrapper.py +0 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/data/hardware/cpu_dataset_builder/intel_cpu_scrapper.py +0 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/data/hardware/cpu_dataset_builder/merge_scrapped_cpu_power.py +0 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/data/hardware/cpu_power.csv +0 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/data/private_infra/2016/usa_emissions.json +0 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/data/private_infra/2023/canada_energy_mix.json +0 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/data/private_infra/carbon_intensity_per_source.json +0 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/data/private_infra/global_energy_mix.json +0 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/external/__init__.py +0 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/external/ram.py +0 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/external/scheduler.py +0 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/external/task.py +0 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/lock.py +0 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/output.py +0 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/output_methods/__init__.py +0 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/output_methods/base_output.py +0 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/output_methods/emissions_data.py +0 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/output_methods/http.py +0 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/output_methods/logger.py +0 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/output_methods/metrics/__init__.py +0 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/output_methods/metrics/logfire.py +0 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/output_methods/metrics/metric_docs.py +0 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/output_methods/metrics/prometheus.py +0 -0
- /codecarbon-3.2.3/codecarbon/viz/__init__.py → /codecarbon-3.2.5/codecarbon/py.typed +0 -0
- {codecarbon-3.2.3/codecarbon/viz/assets → codecarbon-3.2.5/codecarbon/viz}/__init__.py +0 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/viz/assets/car_icon.png +0 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/viz/assets/house_icon.png +0 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/viz/assets/tv_icon.png +0 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/viz/carbonboard.py +0 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/viz/carbonboard_on_api.py +0 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/viz/components.py +0 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/viz/data.py +0 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/viz/units.py +0 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon.egg-info/dependency_links.txt +0 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon.egg-info/entry_points.txt +0 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon.egg-info/top_level.txt +0 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/setup.cfg +0 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/tests/test_api_call.py +0 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/tests/test_cloud.py +0 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/tests/test_cpu_load.py +0 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/tests/test_custom_handler.py +0 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/tests/test_electricitymaps_api.py +0 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/tests/test_electricitymaps_backward_compatibility.py +0 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/tests/test_electricitymaps_config_backward_compatibility.py +0 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/tests/test_emissions_tracker_flush.py +0 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/tests/test_energy.py +0 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/tests/test_input.py +0 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/tests/test_lock.py +0 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/tests/test_logging_output.py +0 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/tests/test_offline_emissions_tracker.py +0 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/tests/test_powermetrics.py +0 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/tests/test_ram.py +0 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/tests/test_rapl_mmio_scanning.py +0 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/tests/test_rapl_parameters.py +0 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/tests/test_rapl_permissions.py +0 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/tests/test_tracking_inference.py +0 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/tests/test_unsupported_gpu.py +0 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/tests/test_utilization_tracking.py +0 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/tests/test_viz_data.py +0 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/tests/test_viz_units.py +0 -0
- {codecarbon-3.2.3 → codecarbon-3.2.5}/tests/testutils.py +0 -0
|
@@ -1,23 +1,21 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: codecarbon
|
|
3
|
-
Version: 3.2.
|
|
3
|
+
Version: 3.2.5
|
|
4
4
|
Author: Mila, DataForGood, BCG GAMMA, Comet.ml, Haverford College
|
|
5
5
|
License-Expression: MIT
|
|
6
6
|
Project-URL: Homepage, https://codecarbon.io/
|
|
7
7
|
Project-URL: Repository, https://github.com/mlco2/codecarbon
|
|
8
8
|
Project-URL: Dashboard, http://dashboard.codecarbon.io/
|
|
9
|
-
Project-URL: Documentation, https://
|
|
9
|
+
Project-URL: Documentation, https://docs.codecarbon.io/
|
|
10
10
|
Project-URL: Issues, https://github.com/mlco2/codecarbon/issues
|
|
11
11
|
Project-URL: Changelog, https://github.com/mlco2/codecarbon/releases
|
|
12
12
|
Classifier: Natural Language :: English
|
|
13
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
14
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
15
13
|
Classifier: Programming Language :: Python :: 3.10
|
|
16
14
|
Classifier: Programming Language :: Python :: 3.11
|
|
17
15
|
Classifier: Programming Language :: Python :: 3.12
|
|
18
16
|
Classifier: Programming Language :: Python :: 3.13
|
|
19
17
|
Classifier: Programming Language :: Python :: 3.14
|
|
20
|
-
Requires-Python: >=3.
|
|
18
|
+
Requires-Python: >=3.10
|
|
21
19
|
Description-Content-Type: text/markdown
|
|
22
20
|
License-File: LICENSE
|
|
23
21
|
Requires-Dist: arrow
|
|
@@ -35,6 +33,7 @@ Requires-Dist: requests
|
|
|
35
33
|
Requires-Dist: questionary
|
|
36
34
|
Requires-Dist: rich
|
|
37
35
|
Requires-Dist: typer
|
|
36
|
+
Requires-Dist: pycountry
|
|
38
37
|
Provides-Extra: carbonboard
|
|
39
38
|
Requires-Dist: dash; extra == "carbonboard"
|
|
40
39
|
Requires-Dist: dash_bootstrap_components>1.0.0; extra == "carbonboard"
|
|
@@ -43,34 +42,11 @@ Provides-Extra: viz-legacy
|
|
|
43
42
|
Requires-Dist: dash; extra == "viz-legacy"
|
|
44
43
|
Requires-Dist: dash_bootstrap_components>1.0.0; extra == "viz-legacy"
|
|
45
44
|
Requires-Dist: fire; extra == "viz-legacy"
|
|
46
|
-
Provides-Extra:
|
|
47
|
-
Requires-Dist:
|
|
48
|
-
Requires-Dist: authlib>=1.2.1; extra == "api"
|
|
49
|
-
Requires-Dist: bcrypt<5.0.0; extra == "api"
|
|
50
|
-
Requires-Dist: python-dateutil<3.0.0; extra == "api"
|
|
51
|
-
Requires-Dist: dependency-injector<5.0.0; extra == "api"
|
|
52
|
-
Requires-Dist: fastapi<1.0.0; extra == "api"
|
|
53
|
-
Requires-Dist: fief-client[fastapi]; extra == "api"
|
|
54
|
-
Requires-Dist: httpx; extra == "api"
|
|
55
|
-
Requires-Dist: itsdangerous; extra == "api"
|
|
56
|
-
Requires-Dist: pydantic[email]<2.0.0; extra == "api"
|
|
57
|
-
Requires-Dist: psycopg2-binary<3.0.0; extra == "api"
|
|
58
|
-
Requires-Dist: requests<3.0.0; extra == "api"
|
|
59
|
-
Requires-Dist: sqlalchemy<2.0.0; extra == "api"
|
|
60
|
-
Requires-Dist: uvicorn[standard]<1.0.0; extra == "api"
|
|
61
|
-
Requires-Dist: fastapi-pagination<1.0.0; extra == "api"
|
|
62
|
-
Requires-Dist: pytest; extra == "api"
|
|
63
|
-
Requires-Dist: mock; extra == "api"
|
|
64
|
-
Requires-Dist: responses; extra == "api"
|
|
65
|
-
Requires-Dist: fastapi-oidc; python_version >= "3.10" and extra == "api"
|
|
66
|
-
Requires-Dist: numpy; extra == "api"
|
|
67
|
-
Requires-Dist: psutil; extra == "api"
|
|
68
|
-
Requires-Dist: requests-mock; extra == "api"
|
|
69
|
-
Requires-Dist: rapidfuzz; extra == "api"
|
|
70
|
-
Requires-Dist: PyJWT; extra == "api"
|
|
45
|
+
Provides-Extra: amdsmi
|
|
46
|
+
Requires-Dist: amdsmi>=6.0.0; extra == "amdsmi"
|
|
71
47
|
Dynamic: license-file
|
|
72
48
|
|
|
73
|
-

|
|
74
50
|
|
|
75
51
|
Estimate and track carbon emissions from your computer, quantify and analyze their impact.
|
|
76
52
|
|
|
@@ -94,14 +70,18 @@ CodeCarbon websites:
|
|
|
94
70
|
|
|
95
71
|
- [About CodeCarbon 💡](#about-codecarbon-)
|
|
96
72
|
- [Quickstart 🚀](#quickstart-)
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
73
|
+
- [Installation 🔧](#installation-)
|
|
74
|
+
- [Start to estimate your impact 📏](#start-to-estimate-your-impact-)
|
|
75
|
+
- [Without using the online dashboard](#without-using-the-online-dashboard)
|
|
76
|
+
- [With the online dashboard](#with-the-online-dashboard)
|
|
77
|
+
- [Monitoring your machine 💻](#monitoring-your-machine-)
|
|
78
|
+
- [Detecting your hardware 🔍](#detecting-your-hardware-)
|
|
79
|
+
- [In your Python code 🐍](#in-your-python-code-)
|
|
80
|
+
- [Visualize 📊](#visualize-)
|
|
102
81
|
- [Contributing 🤝](#contributing-)
|
|
103
82
|
- [How To Cite 📝](#how-to-cite-)
|
|
104
83
|
- [Contact 📝](#contact-)
|
|
84
|
+
- [Star History](#star-history)
|
|
105
85
|
|
|
106
86
|
# About CodeCarbon 💡
|
|
107
87
|
|
|
@@ -117,7 +97,7 @@ At **CodeCarbon**, we believe, along with Niels Bohr, that "Nothing exists until
|
|
|
117
97
|
|
|
118
98
|
We created a Python package that estimates your hardware electricity power consumption (GPU + CPU + RAM) and we apply to it the carbon intensity of the region where the computing is done.
|
|
119
99
|
|
|
120
|
-

|
|
121
101
|
|
|
122
102
|
We explain more about this calculation in the [**Methodology**](https://mlco2.github.io/codecarbon/methodology.html#) section of the documentation.
|
|
123
103
|
|
|
@@ -200,7 +180,7 @@ There is other ways to use **codecarbon** package, please refer to the documenta
|
|
|
200
180
|
## Visualize 📊
|
|
201
181
|
|
|
202
182
|
You can now visualize your experiment emissions on the [dashboard](https://dashboard.codecarbon.io/).
|
|
203
|
-

|
|
204
184
|
|
|
205
185
|
|
|
206
186
|
> Hope you enjoy your first steps monitoring your carbon computing impact!
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-

|
|
2
2
|
|
|
3
3
|
Estimate and track carbon emissions from your computer, quantify and analyze their impact.
|
|
4
4
|
|
|
@@ -22,14 +22,18 @@ CodeCarbon websites:
|
|
|
22
22
|
|
|
23
23
|
- [About CodeCarbon 💡](#about-codecarbon-)
|
|
24
24
|
- [Quickstart 🚀](#quickstart-)
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
25
|
+
- [Installation 🔧](#installation-)
|
|
26
|
+
- [Start to estimate your impact 📏](#start-to-estimate-your-impact-)
|
|
27
|
+
- [Without using the online dashboard](#without-using-the-online-dashboard)
|
|
28
|
+
- [With the online dashboard](#with-the-online-dashboard)
|
|
29
|
+
- [Monitoring your machine 💻](#monitoring-your-machine-)
|
|
30
|
+
- [Detecting your hardware 🔍](#detecting-your-hardware-)
|
|
31
|
+
- [In your Python code 🐍](#in-your-python-code-)
|
|
32
|
+
- [Visualize 📊](#visualize-)
|
|
30
33
|
- [Contributing 🤝](#contributing-)
|
|
31
34
|
- [How To Cite 📝](#how-to-cite-)
|
|
32
35
|
- [Contact 📝](#contact-)
|
|
36
|
+
- [Star History](#star-history)
|
|
33
37
|
|
|
34
38
|
# About CodeCarbon 💡
|
|
35
39
|
|
|
@@ -45,7 +49,7 @@ At **CodeCarbon**, we believe, along with Niels Bohr, that "Nothing exists until
|
|
|
45
49
|
|
|
46
50
|
We created a Python package that estimates your hardware electricity power consumption (GPU + CPU + RAM) and we apply to it the carbon intensity of the region where the computing is done.
|
|
47
51
|
|
|
48
|
-

|
|
49
53
|
|
|
50
54
|
We explain more about this calculation in the [**Methodology**](https://mlco2.github.io/codecarbon/methodology.html#) section of the documentation.
|
|
51
55
|
|
|
@@ -128,7 +132,7 @@ There is other ways to use **codecarbon** package, please refer to the documenta
|
|
|
128
132
|
## Visualize 📊
|
|
129
133
|
|
|
130
134
|
You can now visualize your experiment emissions on the [dashboard](https://dashboard.codecarbon.io/).
|
|
131
|
-

|
|
132
136
|
|
|
133
137
|
|
|
134
138
|
> Hope you enjoy your first steps monitoring your carbon computing impact!
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "3.2.5"
|
|
@@ -69,13 +69,13 @@ def version(
|
|
|
69
69
|
|
|
70
70
|
def show_config(path: Path = Path("./.codecarbon.config")) -> None:
|
|
71
71
|
d = get_config(path)
|
|
72
|
-
api_endpoint = get_api_endpoint(path)
|
|
73
|
-
api = ApiClient(endpoint_url=api_endpoint)
|
|
74
|
-
api.set_access_token(get_access_token())
|
|
75
72
|
print("Current configuration : \n")
|
|
76
73
|
print("Config file content : ")
|
|
77
74
|
print(d)
|
|
78
75
|
try:
|
|
76
|
+
api_endpoint = get_api_endpoint(path)
|
|
77
|
+
api = ApiClient(endpoint_url=api_endpoint)
|
|
78
|
+
api.set_access_token(get_access_token())
|
|
79
79
|
if "organization_id" not in d:
|
|
80
80
|
print(
|
|
81
81
|
"No organization_id in config, follow setup instruction to complete your configuration file!",
|
|
@@ -102,8 +102,8 @@ def show_config(path: Path = Path("./.codecarbon.config")) -> None:
|
|
|
102
102
|
print("\nOrganization :")
|
|
103
103
|
print(org)
|
|
104
104
|
except Exception as e:
|
|
105
|
-
|
|
106
|
-
f"
|
|
105
|
+
print(
|
|
106
|
+
f"[yellow]Could not validate remote configuration details[/yellow]. You can continue with local configuration setup. (error: {e})"
|
|
107
107
|
)
|
|
108
108
|
|
|
109
109
|
|
|
@@ -345,7 +345,8 @@ def monitor(
|
|
|
345
345
|
if offline:
|
|
346
346
|
if not country_iso_code:
|
|
347
347
|
print(
|
|
348
|
-
"ERROR:
|
|
348
|
+
"ERROR: Country ISO code is required for offline mode. Add it to your configuration or provide it via the command line: `--country-iso-code FRA`",
|
|
349
|
+
file=sys.stderr,
|
|
349
350
|
)
|
|
350
351
|
raise typer.Exit(1)
|
|
351
352
|
|
|
@@ -358,7 +359,7 @@ def monitor(
|
|
|
358
359
|
experiment_id = get_existing_local_exp_id()
|
|
359
360
|
if api and experiment_id is None:
|
|
360
361
|
print(
|
|
361
|
-
"ERROR: No experiment id, call 'codecarbon config' first.",
|
|
362
|
+
"ERROR: No experiment id, call 'codecarbon config' first. Or run in offline mode with `--offline --country-iso-code FRA` flag if you don't want to connect to the API.",
|
|
362
363
|
file=sys.stderr,
|
|
363
364
|
)
|
|
364
365
|
raise typer.Exit(1)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import configparser
|
|
2
2
|
import os
|
|
3
3
|
from pathlib import Path
|
|
4
|
-
from typing import List, Union
|
|
4
|
+
from typing import List, Optional, Union
|
|
5
5
|
|
|
6
6
|
from codecarbon.external.logger import logger
|
|
7
7
|
|
|
@@ -73,6 +73,43 @@ def parse_gpu_ids(gpu_ids: Union[str, List[int]]) -> List[str]:
|
|
|
73
73
|
)
|
|
74
74
|
|
|
75
75
|
|
|
76
|
+
def normalize_gpu_ids(
|
|
77
|
+
gpu_ids: Optional[Union[str, List[Union[int, str]]]],
|
|
78
|
+
) -> Optional[List[Union[int, str]]]:
|
|
79
|
+
"""
|
|
80
|
+
Normalize GPU IDs from config/user input into a list of ids consumable by hardware
|
|
81
|
+
resolution code.
|
|
82
|
+
|
|
83
|
+
Supports:
|
|
84
|
+
- comma-separated string values (sanitized via parse_gpu_ids)
|
|
85
|
+
- lists containing ints and/or strings
|
|
86
|
+
"""
|
|
87
|
+
if gpu_ids is None:
|
|
88
|
+
return None
|
|
89
|
+
|
|
90
|
+
if isinstance(gpu_ids, str):
|
|
91
|
+
return parse_gpu_ids(gpu_ids)
|
|
92
|
+
|
|
93
|
+
if isinstance(gpu_ids, list):
|
|
94
|
+
normalized_gpu_ids: List[Union[int, str]] = []
|
|
95
|
+
for gpu_id in gpu_ids:
|
|
96
|
+
if isinstance(gpu_id, int):
|
|
97
|
+
normalized_gpu_ids.append(gpu_id)
|
|
98
|
+
elif isinstance(gpu_id, str):
|
|
99
|
+
normalized_gpu_ids.extend(parse_gpu_ids(gpu_id))
|
|
100
|
+
else:
|
|
101
|
+
logger.warning(
|
|
102
|
+
"Ignoring invalid gpu_id entry of type %s; expected int or str.",
|
|
103
|
+
type(gpu_id).__name__,
|
|
104
|
+
)
|
|
105
|
+
return normalized_gpu_ids
|
|
106
|
+
|
|
107
|
+
logger.warning(
|
|
108
|
+
"Invalid gpu_ids format. Expected a string or a list of ints/strings."
|
|
109
|
+
)
|
|
110
|
+
return None
|
|
111
|
+
|
|
112
|
+
|
|
76
113
|
def get_hierarchical_config():
|
|
77
114
|
"""
|
|
78
115
|
Get the user-defined codecarbon configuration ConfigParser dictionnary
|
|
@@ -17,7 +17,7 @@ from rapidfuzz import fuzz, process, utils
|
|
|
17
17
|
|
|
18
18
|
from codecarbon.core.rapl import RAPLFile
|
|
19
19
|
from codecarbon.core.units import Time
|
|
20
|
-
from codecarbon.core.util import detect_cpu_model
|
|
20
|
+
from codecarbon.core.util import count_cpus, detect_cpu_model
|
|
21
21
|
from codecarbon.external.logger import logger
|
|
22
22
|
from codecarbon.input import DataSource
|
|
23
23
|
|
|
@@ -1001,7 +1001,7 @@ class TDP:
|
|
|
1001
1001
|
)
|
|
1002
1002
|
if is_psutil_available():
|
|
1003
1003
|
# Count thread of the CPU
|
|
1004
|
-
threads =
|
|
1004
|
+
threads = count_cpus()
|
|
1005
1005
|
estimated_tdp = threads * DEFAULT_POWER_PER_CORE
|
|
1006
1006
|
logger.warning(
|
|
1007
1007
|
f"We will use the default power consumption of {DEFAULT_POWER_PER_CORE} W per thread for your {threads} CPU, so {estimated_tdp}W."
|
|
@@ -156,7 +156,7 @@ class Emissions:
|
|
|
156
156
|
)
|
|
157
157
|
|
|
158
158
|
compute_with_regional_data: bool = (geo.region is not None) and (
|
|
159
|
-
geo.country_iso_code.upper() in ["USA", "CAN"]
|
|
159
|
+
geo.country_iso_code.upper() in ["USA", "CAN", "SWE", "NOR", "FIN"]
|
|
160
160
|
)
|
|
161
161
|
|
|
162
162
|
if compute_with_regional_data:
|
|
@@ -170,16 +170,72 @@ class Emissions:
|
|
|
170
170
|
)
|
|
171
171
|
return self.get_country_emissions(energy, geo)
|
|
172
172
|
|
|
173
|
+
def _try_get_nordic_region_emissions(
|
|
174
|
+
self, energy: Energy, geo: GeoMetadata
|
|
175
|
+
) -> Optional[float]:
|
|
176
|
+
nordic_regions = {
|
|
177
|
+
"SE1",
|
|
178
|
+
"SE2",
|
|
179
|
+
"SE3",
|
|
180
|
+
"SE4",
|
|
181
|
+
"NO1",
|
|
182
|
+
"NO2",
|
|
183
|
+
"NO3",
|
|
184
|
+
"NO4",
|
|
185
|
+
"NO5",
|
|
186
|
+
"FI",
|
|
187
|
+
}
|
|
188
|
+
if geo.region is None:
|
|
189
|
+
return None
|
|
190
|
+
|
|
191
|
+
region_upper = geo.region.upper()
|
|
192
|
+
if region_upper not in nordic_regions:
|
|
193
|
+
return None
|
|
194
|
+
|
|
195
|
+
try:
|
|
196
|
+
nordic_data = self._data_source.get_nordic_country_energy_mix_data()
|
|
197
|
+
region_data = nordic_data["data"].get(region_upper)
|
|
198
|
+
if region_data:
|
|
199
|
+
emission_factor_g = region_data["emission_factor"]
|
|
200
|
+
emission_factor_kg = emission_factor_g / 1000
|
|
201
|
+
emissions = emission_factor_kg * energy.kWh
|
|
202
|
+
logger.debug(
|
|
203
|
+
f"Nordic region {geo.region}: Retrieved emissions using static factor "
|
|
204
|
+
+ f"{emission_factor_g} gCO2eq/kWh: {emissions * 1000} g CO2eq"
|
|
205
|
+
)
|
|
206
|
+
return emissions
|
|
207
|
+
except Exception as e:
|
|
208
|
+
logger.warning(
|
|
209
|
+
f"Error loading Nordic emissions data for {geo.region}: {e}. "
|
|
210
|
+
+ "Falling back to default emission calculation."
|
|
211
|
+
)
|
|
212
|
+
return None
|
|
213
|
+
|
|
173
214
|
def get_region_emissions(self, energy: Energy, geo: GeoMetadata) -> float:
|
|
174
215
|
"""
|
|
175
216
|
Computes emissions for a region on private infra.
|
|
176
217
|
Given an quantity of power consumed, use regional data
|
|
177
218
|
on emissions per unit power consumed or the mix of energy sources.
|
|
178
219
|
https://github.com/responsibleproblemsolving/energy-usage#calculating-co2-emissions
|
|
220
|
+
|
|
221
|
+
get_private_infra_emissions
|
|
222
|
+
├─ Electricity Maps API (si token)
|
|
223
|
+
├─ get_region_emissions (USA/CAN/SWE/NOR/FIN)
|
|
224
|
+
│ └─ _try_get_nordic_region_emissions (pour SWE/NOR/FIN)
|
|
225
|
+
│ └─ country_emissions_data (pour USA)
|
|
226
|
+
│ └─ country_energy_mix_data (pour CAN)
|
|
227
|
+
└─ get_country_emissions (fallback)
|
|
228
|
+
|
|
179
229
|
:param energy: Mean power consumption of the process (kWh)
|
|
180
230
|
:param geo: Country and region metadata.
|
|
181
231
|
:return: CO2 emissions in kg
|
|
182
232
|
"""
|
|
233
|
+
# Handle Nordic regions (Sweden, Norway, Finland electricity bidding zones)
|
|
234
|
+
nordic_emissions = self._try_get_nordic_region_emissions(energy, geo)
|
|
235
|
+
if nordic_emissions is not None:
|
|
236
|
+
return nordic_emissions
|
|
237
|
+
|
|
238
|
+
# Handle USA and Canada regional data
|
|
183
239
|
try:
|
|
184
240
|
country_emissions_data = self._data_source.get_country_emissions_data(
|
|
185
241
|
geo.country_iso_code.lower()
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
from typing import List
|
|
2
|
+
|
|
3
|
+
from codecarbon.core import gpu_amd, gpu_nvidia
|
|
4
|
+
from codecarbon.core.gpu_device import GPUDevice
|
|
5
|
+
from codecarbon.core.units import Time
|
|
6
|
+
from codecarbon.external.logger import logger
|
|
7
|
+
|
|
8
|
+
AMDSMI_AVAILABLE = gpu_amd.AMDSMI_AVAILABLE
|
|
9
|
+
PYNVML_AVAILABLE = gpu_nvidia.PYNVML_AVAILABLE
|
|
10
|
+
|
|
11
|
+
AMDGPUDevice = gpu_amd.AMDGPUDevice
|
|
12
|
+
NvidiaGPUDevice = gpu_nvidia.NvidiaGPUDevice
|
|
13
|
+
is_rocm_system = gpu_amd.is_rocm_system
|
|
14
|
+
is_nvidia_system = gpu_nvidia.is_nvidia_system
|
|
15
|
+
|
|
16
|
+
# Backward-compatible module attributes
|
|
17
|
+
amdsmi = gpu_amd.amdsmi
|
|
18
|
+
pynvml = gpu_nvidia.pynvml
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class AllGPUDevices:
|
|
22
|
+
device_count: int
|
|
23
|
+
devices: List[GPUDevice]
|
|
24
|
+
|
|
25
|
+
def __init__(self) -> None:
|
|
26
|
+
gpu_details_available = is_gpu_details_available()
|
|
27
|
+
if gpu_details_available:
|
|
28
|
+
logger.debug("GPU available. Starting setup")
|
|
29
|
+
else:
|
|
30
|
+
logger.error("There is no GPU available")
|
|
31
|
+
self.devices = []
|
|
32
|
+
|
|
33
|
+
if PYNVML_AVAILABLE:
|
|
34
|
+
logger.debug("PyNVML available. Starting setup")
|
|
35
|
+
gpu_nvidia.pynvml.nvmlInit()
|
|
36
|
+
nvidia_devices_count = gpu_nvidia.pynvml.nvmlDeviceGetCount()
|
|
37
|
+
for i in range(nvidia_devices_count):
|
|
38
|
+
handle = gpu_nvidia.pynvml.nvmlDeviceGetHandleByIndex(i)
|
|
39
|
+
nvidia_gpu_device = NvidiaGPUDevice(handle=handle, gpu_index=i)
|
|
40
|
+
self.devices.append(nvidia_gpu_device)
|
|
41
|
+
|
|
42
|
+
if AMDSMI_AVAILABLE:
|
|
43
|
+
logger.debug("AMDSMI available. Starting setup")
|
|
44
|
+
try:
|
|
45
|
+
gpu_amd.amdsmi.amdsmi_init()
|
|
46
|
+
amd_devices_handles = gpu_amd.amdsmi.amdsmi_get_processor_handles()
|
|
47
|
+
if len(amd_devices_handles) == 0:
|
|
48
|
+
logger.warning(
|
|
49
|
+
"No AMD GPUs found on machine with amdsmi_get_processor_handles() !"
|
|
50
|
+
)
|
|
51
|
+
else:
|
|
52
|
+
for i, handle in enumerate(amd_devices_handles):
|
|
53
|
+
# Try to get the actual device index from BDF (Bus/Device/Function)
|
|
54
|
+
# If this fails, fall back to enumeration index
|
|
55
|
+
try:
|
|
56
|
+
bdf_info = gpu_amd.amdsmi.amdsmi_get_gpu_device_bdf(handle)
|
|
57
|
+
# BDF typically contains domain, bus, device, function
|
|
58
|
+
# The device portion often corresponds to the GPU index
|
|
59
|
+
# For now, we'll use the enumeration index but log the BDF
|
|
60
|
+
logger.debug(
|
|
61
|
+
f"Found AMD GPU device with handle {handle}, enum_index {i}, BDF {bdf_info}: {gpu_amd.amdsmi.amdsmi_get_gpu_device_uuid(handle)}"
|
|
62
|
+
)
|
|
63
|
+
# Use enumerate index for now - this will be the index in the filtered list
|
|
64
|
+
gpu_index = i
|
|
65
|
+
except Exception:
|
|
66
|
+
logger.debug(
|
|
67
|
+
f"Found AMD GPU device with handle {handle} and index {i} : {gpu_amd.amdsmi.amdsmi_get_gpu_device_uuid(handle)}"
|
|
68
|
+
)
|
|
69
|
+
gpu_index = i
|
|
70
|
+
|
|
71
|
+
amd_gpu_device = AMDGPUDevice(
|
|
72
|
+
handle=handle, gpu_index=gpu_index
|
|
73
|
+
)
|
|
74
|
+
self.devices.append(amd_gpu_device)
|
|
75
|
+
except gpu_amd.amdsmi.AmdSmiException as e:
|
|
76
|
+
logger.warning(f"Failed to initialize AMDSMI: {e}", exc_info=True)
|
|
77
|
+
self.device_count = len(self.devices)
|
|
78
|
+
|
|
79
|
+
def start(self) -> None:
|
|
80
|
+
for device in self.devices:
|
|
81
|
+
if hasattr(device, "start"):
|
|
82
|
+
device.start()
|
|
83
|
+
|
|
84
|
+
def get_gpu_static_info(self) -> List:
|
|
85
|
+
"""Get all GPUs static information.
|
|
86
|
+
>>> get_gpu_static_info()
|
|
87
|
+
[
|
|
88
|
+
{
|
|
89
|
+
"name": "Tesla V100-SXM2-16GB",
|
|
90
|
+
"uuid": "GPU-4e817856-1fb8-192a-7ab7-0e0e4476c184",
|
|
91
|
+
"total_memory": 16945512448,
|
|
92
|
+
"power_limit": 300000,
|
|
93
|
+
"gpu_index": 0,
|
|
94
|
+
}
|
|
95
|
+
]
|
|
96
|
+
"""
|
|
97
|
+
try:
|
|
98
|
+
devices_static_info = []
|
|
99
|
+
for i in range(self.device_count):
|
|
100
|
+
gpu_device = self.devices[i]
|
|
101
|
+
devices_static_info.append(gpu_device.get_static_details())
|
|
102
|
+
return devices_static_info
|
|
103
|
+
|
|
104
|
+
except Exception:
|
|
105
|
+
logger.warning("Failed to retrieve gpu static info", exc_info=True)
|
|
106
|
+
return []
|
|
107
|
+
|
|
108
|
+
def get_gpu_details(self) -> List:
|
|
109
|
+
"""Get all GPUs instantaneous metrics
|
|
110
|
+
>>> get_gpu_details()
|
|
111
|
+
[
|
|
112
|
+
{
|
|
113
|
+
"name": "Tesla V100-SXM2-16GB",
|
|
114
|
+
"uuid": "GPU-4e817856-1fb8-192a-7ab7-0e0e4476c184",
|
|
115
|
+
"free_memory": 16945381376,
|
|
116
|
+
"total_memory": 16945512448,
|
|
117
|
+
"used_memory": 131072,
|
|
118
|
+
"temperature": 28,
|
|
119
|
+
"total_energy_consumption":2000,
|
|
120
|
+
"power_usage": 42159,
|
|
121
|
+
"power_limit": 300000,
|
|
122
|
+
"gpu_utilization": 0,
|
|
123
|
+
"compute_mode": 0,
|
|
124
|
+
"compute_processes": [],
|
|
125
|
+
"graphics_processes": [],
|
|
126
|
+
}
|
|
127
|
+
]
|
|
128
|
+
"""
|
|
129
|
+
try:
|
|
130
|
+
devices_info = []
|
|
131
|
+
for i in range(self.device_count):
|
|
132
|
+
gpu_device = self.devices[i]
|
|
133
|
+
devices_info.append(gpu_device.get_gpu_details())
|
|
134
|
+
return devices_info
|
|
135
|
+
|
|
136
|
+
except Exception:
|
|
137
|
+
logger.warning("Failed to retrieve gpu information", exc_info=True)
|
|
138
|
+
return []
|
|
139
|
+
|
|
140
|
+
def get_delta(self, last_duration: Time) -> List:
|
|
141
|
+
"""Get difference since last time this function was called
|
|
142
|
+
>>> get_delta()
|
|
143
|
+
[
|
|
144
|
+
{
|
|
145
|
+
"name": "Tesla V100-SXM2-16GB",
|
|
146
|
+
"uuid": "GPU-4e817856-1fb8-192a-7ab7-0e0e4476c184",
|
|
147
|
+
"delta_energy_consumption":2000,
|
|
148
|
+
"power_usage": 42159,
|
|
149
|
+
}
|
|
150
|
+
]
|
|
151
|
+
"""
|
|
152
|
+
try:
|
|
153
|
+
devices_info = []
|
|
154
|
+
for i in range(self.device_count):
|
|
155
|
+
gpu_device = self.devices[i]
|
|
156
|
+
devices_info.append(gpu_device.delta(last_duration))
|
|
157
|
+
return devices_info
|
|
158
|
+
|
|
159
|
+
except Exception:
|
|
160
|
+
logger.warning("Failed to retrieve gpu information", exc_info=True)
|
|
161
|
+
return []
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
def is_gpu_details_available() -> bool:
|
|
165
|
+
"""Returns True if the GPU details are available."""
|
|
166
|
+
return PYNVML_AVAILABLE or AMDSMI_AVAILABLE
|