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.
Files changed (121) hide show
  1. {codecarbon-3.2.3 → codecarbon-3.2.5}/PKG-INFO +18 -38
  2. {codecarbon-3.2.3 → codecarbon-3.2.5}/README.md +12 -8
  3. codecarbon-3.2.5/codecarbon/_version.py +1 -0
  4. {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/cli/main.py +8 -7
  5. {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/core/config.py +38 -1
  6. {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/core/cpu.py +2 -2
  7. {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/core/emissions.py +57 -1
  8. codecarbon-3.2.5/codecarbon/core/gpu.py +166 -0
  9. codecarbon-3.2.5/codecarbon/core/gpu_amd.py +272 -0
  10. codecarbon-3.2.5/codecarbon/core/gpu_device.py +116 -0
  11. codecarbon-3.2.5/codecarbon/core/gpu_nvidia.py +130 -0
  12. {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/core/measure.py +5 -1
  13. {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/core/resource_tracker.py +27 -15
  14. {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/core/util.py +15 -5
  15. codecarbon-3.2.5/codecarbon/data/private_infra/nordic_emissions.json +69 -0
  16. {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/emissions_tracker.py +76 -45
  17. {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/external/geography.py +25 -17
  18. {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/external/hardware.py +33 -9
  19. {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/external/logger.py +6 -3
  20. {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/input.py +14 -9
  21. {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/output_methods/file.py +4 -7
  22. codecarbon-3.2.5/codecarbon/viz/assets/__init__.py +0 -0
  23. {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon.egg-info/PKG-INFO +18 -38
  24. {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon.egg-info/SOURCES.txt +9 -0
  25. codecarbon-3.2.5/codecarbon.egg-info/requires.txt +33 -0
  26. {codecarbon-3.2.3 → codecarbon-3.2.5}/pyproject.toml +24 -72
  27. {codecarbon-3.2.3 → codecarbon-3.2.5}/tests/test_config.py +43 -0
  28. codecarbon-3.2.5/tests/test_core_util.py +137 -0
  29. {codecarbon-3.2.3 → codecarbon-3.2.5}/tests/test_cpu.py +193 -46
  30. {codecarbon-3.2.3 → codecarbon-3.2.5}/tests/test_emissions.py +103 -0
  31. {codecarbon-3.2.3 → codecarbon-3.2.5}/tests/test_emissions_tracker.py +23 -3
  32. {codecarbon-3.2.3 → codecarbon-3.2.5}/tests/test_emissions_tracker_constant.py +6 -4
  33. {codecarbon-3.2.3 → codecarbon-3.2.5}/tests/test_geography.py +16 -4
  34. codecarbon-3.2.5/tests/test_gpu.py +222 -0
  35. codecarbon-3.2.5/tests/test_gpu_amd.py +499 -0
  36. codecarbon-3.2.3/tests/test_gpu.py → codecarbon-3.2.5/tests/test_gpu_nvidia.py +62 -16
  37. codecarbon-3.2.5/tests/test_logger.py +59 -0
  38. {codecarbon-3.2.3 → codecarbon-3.2.5}/tests/test_package_integrity.py +10 -0
  39. codecarbon-3.2.5/tests/test_resource_tracker.py +43 -0
  40. {codecarbon-3.2.3 → codecarbon-3.2.5}/tests/testdata.py +6 -30
  41. codecarbon-3.2.3/codecarbon/_version.py +0 -1
  42. codecarbon-3.2.3/codecarbon/core/gpu.py +0 -309
  43. codecarbon-3.2.3/codecarbon.egg-info/requires.txt +0 -57
  44. codecarbon-3.2.3/tests/test_core_util.py +0 -44
  45. {codecarbon-3.2.3 → codecarbon-3.2.5}/LICENSE +0 -0
  46. {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/__init__.py +0 -0
  47. {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/cli/__init__.py +0 -0
  48. {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/cli/auth.py +0 -0
  49. {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/cli/cli_utils.py +0 -0
  50. {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/cli/monitor.py +0 -0
  51. {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/core/__init__.py +0 -0
  52. {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/core/api_client.py +0 -0
  53. {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/core/cloud.py +0 -0
  54. {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/core/electricitymaps_api.py +0 -0
  55. {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/core/powermetrics.py +0 -0
  56. {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/core/rapl.py +0 -0
  57. {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/core/schemas.py +0 -0
  58. {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/core/units.py +0 -0
  59. {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/data/canada_provinces.geojson +0 -0
  60. {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/data/cloud/impact.csv +0 -0
  61. {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/data/hardware/cpu_dataset_builder/amd_cpu_scrapper.py +0 -0
  62. {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/data/hardware/cpu_dataset_builder/intel_cpu_scrapper.py +0 -0
  63. {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/data/hardware/cpu_dataset_builder/merge_scrapped_cpu_power.py +0 -0
  64. {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/data/hardware/cpu_power.csv +0 -0
  65. {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/data/private_infra/2016/usa_emissions.json +0 -0
  66. {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/data/private_infra/2023/canada_energy_mix.json +0 -0
  67. {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/data/private_infra/carbon_intensity_per_source.json +0 -0
  68. {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/data/private_infra/global_energy_mix.json +0 -0
  69. {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/external/__init__.py +0 -0
  70. {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/external/ram.py +0 -0
  71. {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/external/scheduler.py +0 -0
  72. {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/external/task.py +0 -0
  73. {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/lock.py +0 -0
  74. {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/output.py +0 -0
  75. {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/output_methods/__init__.py +0 -0
  76. {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/output_methods/base_output.py +0 -0
  77. {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/output_methods/emissions_data.py +0 -0
  78. {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/output_methods/http.py +0 -0
  79. {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/output_methods/logger.py +0 -0
  80. {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/output_methods/metrics/__init__.py +0 -0
  81. {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/output_methods/metrics/logfire.py +0 -0
  82. {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/output_methods/metrics/metric_docs.py +0 -0
  83. {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/output_methods/metrics/prometheus.py +0 -0
  84. /codecarbon-3.2.3/codecarbon/viz/__init__.py → /codecarbon-3.2.5/codecarbon/py.typed +0 -0
  85. {codecarbon-3.2.3/codecarbon/viz/assets → codecarbon-3.2.5/codecarbon/viz}/__init__.py +0 -0
  86. {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/viz/assets/car_icon.png +0 -0
  87. {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/viz/assets/house_icon.png +0 -0
  88. {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/viz/assets/tv_icon.png +0 -0
  89. {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/viz/carbonboard.py +0 -0
  90. {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/viz/carbonboard_on_api.py +0 -0
  91. {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/viz/components.py +0 -0
  92. {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/viz/data.py +0 -0
  93. {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon/viz/units.py +0 -0
  94. {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon.egg-info/dependency_links.txt +0 -0
  95. {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon.egg-info/entry_points.txt +0 -0
  96. {codecarbon-3.2.3 → codecarbon-3.2.5}/codecarbon.egg-info/top_level.txt +0 -0
  97. {codecarbon-3.2.3 → codecarbon-3.2.5}/setup.cfg +0 -0
  98. {codecarbon-3.2.3 → codecarbon-3.2.5}/tests/test_api_call.py +0 -0
  99. {codecarbon-3.2.3 → codecarbon-3.2.5}/tests/test_cloud.py +0 -0
  100. {codecarbon-3.2.3 → codecarbon-3.2.5}/tests/test_cpu_load.py +0 -0
  101. {codecarbon-3.2.3 → codecarbon-3.2.5}/tests/test_custom_handler.py +0 -0
  102. {codecarbon-3.2.3 → codecarbon-3.2.5}/tests/test_electricitymaps_api.py +0 -0
  103. {codecarbon-3.2.3 → codecarbon-3.2.5}/tests/test_electricitymaps_backward_compatibility.py +0 -0
  104. {codecarbon-3.2.3 → codecarbon-3.2.5}/tests/test_electricitymaps_config_backward_compatibility.py +0 -0
  105. {codecarbon-3.2.3 → codecarbon-3.2.5}/tests/test_emissions_tracker_flush.py +0 -0
  106. {codecarbon-3.2.3 → codecarbon-3.2.5}/tests/test_energy.py +0 -0
  107. {codecarbon-3.2.3 → codecarbon-3.2.5}/tests/test_input.py +0 -0
  108. {codecarbon-3.2.3 → codecarbon-3.2.5}/tests/test_lock.py +0 -0
  109. {codecarbon-3.2.3 → codecarbon-3.2.5}/tests/test_logging_output.py +0 -0
  110. {codecarbon-3.2.3 → codecarbon-3.2.5}/tests/test_offline_emissions_tracker.py +0 -0
  111. {codecarbon-3.2.3 → codecarbon-3.2.5}/tests/test_powermetrics.py +0 -0
  112. {codecarbon-3.2.3 → codecarbon-3.2.5}/tests/test_ram.py +0 -0
  113. {codecarbon-3.2.3 → codecarbon-3.2.5}/tests/test_rapl_mmio_scanning.py +0 -0
  114. {codecarbon-3.2.3 → codecarbon-3.2.5}/tests/test_rapl_parameters.py +0 -0
  115. {codecarbon-3.2.3 → codecarbon-3.2.5}/tests/test_rapl_permissions.py +0 -0
  116. {codecarbon-3.2.3 → codecarbon-3.2.5}/tests/test_tracking_inference.py +0 -0
  117. {codecarbon-3.2.3 → codecarbon-3.2.5}/tests/test_unsupported_gpu.py +0 -0
  118. {codecarbon-3.2.3 → codecarbon-3.2.5}/tests/test_utilization_tracking.py +0 -0
  119. {codecarbon-3.2.3 → codecarbon-3.2.5}/tests/test_viz_data.py +0 -0
  120. {codecarbon-3.2.3 → codecarbon-3.2.5}/tests/test_viz_units.py +0 -0
  121. {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
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://mlco2.github.io/codecarbon/
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.8
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: api
47
- Requires-Dist: alembic<2.0.0; extra == "api"
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
- ![banner](docs/edit/images/banner.png)
49
+ ![banner](docs/images/banner.png)
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
- - [Installation 🔧](#installation-)
98
- - [Start to estimate your impact 📏](#start-to-estimate-your-impact-)
99
- - [Monitoring your whole machine](#monitoring-your-machine-)
100
- - [In your python code](#in-your-python-code-)
101
- - [Visualize](#visualize-)
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
- ![calculation Summary](docs/edit/images/calculation.png)
100
+ ![calculation Summary](docs/images/calculation.png)
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
- ![dashboard](docs/edit/images/dashboard.png)
183
+ ![dashboard](docs/images/dashboard.png)
204
184
 
205
185
 
206
186
  > Hope you enjoy your first steps monitoring your carbon computing impact!
@@ -1,4 +1,4 @@
1
- ![banner](docs/edit/images/banner.png)
1
+ ![banner](docs/images/banner.png)
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
- - [Installation 🔧](#installation-)
26
- - [Start to estimate your impact 📏](#start-to-estimate-your-impact-)
27
- - [Monitoring your whole machine](#monitoring-your-machine-)
28
- - [In your python code](#in-your-python-code-)
29
- - [Visualize](#visualize-)
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
- ![calculation Summary](docs/edit/images/calculation.png)
52
+ ![calculation Summary](docs/images/calculation.png)
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
- ![dashboard](docs/edit/images/dashboard.png)
135
+ ![dashboard](docs/images/dashboard.png)
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
- raise ValueError(
106
- f"Your configuration is invalid, please verify your configuration file at {path}. To start from scratch, run `codecarbon config` and overwrite your configuration file. (error: {e})"
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: country_iso_code is required for offline mode", file=sys.stderr
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 = psutil.cpu_count(logical=True)
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