codecarbon 3.0.4__tar.gz → 3.0.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.0.4 → codecarbon-3.0.5}/PKG-INFO +1 -1
- codecarbon-3.0.5/codecarbon/_version.py +1 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/codecarbon/core/config.py +21 -12
- {codecarbon-3.0.4 → codecarbon-3.0.5}/codecarbon/core/resource_tracker.py +3 -10
- {codecarbon-3.0.4 → codecarbon-3.0.5}/codecarbon/data/hardware/cpu_power.csv +2 -0
- codecarbon-3.0.5/codecarbon/data/private_infra/2023/canada_energy_mix.json +171 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/codecarbon/emissions_tracker.py +1 -1
- {codecarbon-3.0.4 → codecarbon-3.0.5}/codecarbon/external/hardware.py +34 -16
- {codecarbon-3.0.4 → codecarbon-3.0.5}/codecarbon/input.py +1 -1
- {codecarbon-3.0.4 → codecarbon-3.0.5}/codecarbon/output_methods/file.py +6 -2
- {codecarbon-3.0.4 → codecarbon-3.0.5}/codecarbon.egg-info/PKG-INFO +1 -1
- {codecarbon-3.0.4 → codecarbon-3.0.5}/codecarbon.egg-info/SOURCES.txt +1 -1
- {codecarbon-3.0.4 → codecarbon-3.0.5}/pyproject.toml +2 -2
- {codecarbon-3.0.4 → codecarbon-3.0.5}/tests/test_config.py +14 -14
- {codecarbon-3.0.4 → codecarbon-3.0.5}/tests/test_cpu_load.py +4 -2
- {codecarbon-3.0.4 → codecarbon-3.0.5}/tests/test_emissions.py +4 -1
- {codecarbon-3.0.4 → codecarbon-3.0.5}/tests/test_emissions_tracker.py +88 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/tests/test_gpu.py +33 -6
- {codecarbon-3.0.4 → codecarbon-3.0.5}/tests/test_unsupported_gpu.py +5 -0
- codecarbon-3.0.4/codecarbon/_version.py +0 -1
- codecarbon-3.0.4/codecarbon/data/private_infra/2016/canada_energy_mix.json +0 -171
- {codecarbon-3.0.4 → codecarbon-3.0.5}/LICENSE +0 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/README.md +0 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/codecarbon/__init__.py +0 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/codecarbon/cli/__init__.py +0 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/codecarbon/cli/cli_utils.py +0 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/codecarbon/cli/main.py +0 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/codecarbon/core/__init__.py +0 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/codecarbon/core/api_client.py +0 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/codecarbon/core/cloud.py +0 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/codecarbon/core/co2_signal.py +0 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/codecarbon/core/cpu.py +0 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/codecarbon/core/emissions.py +0 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/codecarbon/core/gpu.py +0 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/codecarbon/core/measure.py +0 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/codecarbon/core/powermetrics.py +0 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/codecarbon/core/rapl.py +0 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/codecarbon/core/schemas.py +0 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/codecarbon/core/units.py +0 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/codecarbon/core/util.py +0 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/codecarbon/data/canada_provinces.geojson +0 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/codecarbon/data/cloud/impact.csv +0 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/codecarbon/data/hardware/cpu_dataset_builder/amd_cpu_scrapper.py +0 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/codecarbon/data/hardware/cpu_dataset_builder/intel_cpu_scrapper.py +0 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/codecarbon/data/hardware/cpu_dataset_builder/merge_scrapped_cpu_power.py +0 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/codecarbon/data/private_infra/2016/usa_emissions.json +0 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/codecarbon/data/private_infra/carbon_intensity_per_source.json +0 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/codecarbon/data/private_infra/global_energy_mix.json +0 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/codecarbon/external/__init__.py +0 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/codecarbon/external/geography.py +0 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/codecarbon/external/logger.py +0 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/codecarbon/external/ram.py +0 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/codecarbon/external/scheduler.py +0 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/codecarbon/external/task.py +0 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/codecarbon/lock.py +0 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/codecarbon/output.py +0 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/codecarbon/output_methods/__init__.py +0 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/codecarbon/output_methods/base_output.py +0 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/codecarbon/output_methods/emissions_data.py +0 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/codecarbon/output_methods/http.py +0 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/codecarbon/output_methods/logger.py +0 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/codecarbon/output_methods/metrics/__init__.py +0 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/codecarbon/output_methods/metrics/logfire.py +0 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/codecarbon/output_methods/metrics/metric_docs.py +0 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/codecarbon/output_methods/metrics/prometheus.py +0 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/codecarbon/viz/__init__.py +0 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/codecarbon/viz/assets/__init__.py +0 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/codecarbon/viz/carbonboard.py +0 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/codecarbon/viz/carbonboard_on_api.py +0 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/codecarbon/viz/components.py +0 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/codecarbon/viz/data.py +0 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/codecarbon/viz/units.py +0 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/codecarbon.egg-info/dependency_links.txt +0 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/codecarbon.egg-info/entry_points.txt +0 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/codecarbon.egg-info/requires.txt +0 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/codecarbon.egg-info/top_level.txt +0 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/setup.cfg +0 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/tests/test_api_call.py +0 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/tests/test_cli.py +0 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/tests/test_cloud.py +0 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/tests/test_co2_signal.py +0 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/tests/test_core_util.py +0 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/tests/test_cpu.py +0 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/tests/test_custom_handler.py +0 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/tests/test_emissions_tracker_constant.py +0 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/tests/test_emissions_tracker_flush.py +0 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/tests/test_energy.py +0 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/tests/test_geography.py +0 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/tests/test_lock.py +0 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/tests/test_logging_output.py +0 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/tests/test_offline_emissions_tracker.py +0 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/tests/test_package_integrity.py +0 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/tests/test_powermetrics.py +0 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/tests/test_ram.py +0 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/tests/test_tracking_inference.py +0 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/tests/test_viz_data.py +0 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/tests/test_viz_units.py +0 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/tests/testdata.py +0 -0
- {codecarbon-3.0.4 → codecarbon-3.0.5}/tests/testutils.py +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "3.0.5"
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import configparser
|
|
2
2
|
import os
|
|
3
3
|
from pathlib import Path
|
|
4
|
-
from typing import List
|
|
4
|
+
from typing import List, Union
|
|
5
5
|
|
|
6
6
|
from codecarbon.external.logger import logger
|
|
7
7
|
|
|
@@ -44,24 +44,33 @@ def parse_env_config() -> dict:
|
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
|
|
47
|
-
def parse_gpu_ids(
|
|
47
|
+
def parse_gpu_ids(gpu_ids: Union[str, List[int]]) -> List[str]:
|
|
48
48
|
"""
|
|
49
|
-
Transforms the potential gpu_ids
|
|
49
|
+
Transforms the potential gpu_ids into a list of string id values.
|
|
50
|
+
|
|
50
51
|
|
|
51
52
|
Args:
|
|
52
|
-
|
|
53
|
-
which is read as a string and should be parsed into a list of ints
|
|
53
|
+
gpu_ids: The config file or environment variable value for `gpu_ids`
|
|
54
54
|
|
|
55
55
|
Returns:
|
|
56
|
-
list[
|
|
56
|
+
list[str]: The list of GPU ids available.
|
|
57
57
|
Potentially empty.
|
|
58
58
|
"""
|
|
59
|
-
if
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
59
|
+
if isinstance(gpu_ids, str):
|
|
60
|
+
# Allow '-' in id strings since UUIDs may include them.
|
|
61
|
+
gpu_ids = "".join(c for c in gpu_ids if (c.isalnum() or c in ("-", ",")))
|
|
62
|
+
str_ids = [gpu_id for gpu_id in gpu_ids.split(",") if gpu_id]
|
|
63
|
+
return str_ids
|
|
64
|
+
|
|
65
|
+
elif isinstance(gpu_ids, list) and all(
|
|
66
|
+
isinstance(gpu_id, int) for gpu_id in gpu_ids
|
|
67
|
+
):
|
|
68
|
+
return list(map(str, gpu_ids))
|
|
69
|
+
|
|
70
|
+
else:
|
|
71
|
+
logger.warning(
|
|
72
|
+
"Invalid gpu_ids format. Expected a string or a list of ints/strings."
|
|
73
|
+
)
|
|
65
74
|
|
|
66
75
|
|
|
67
76
|
def get_hierarchical_config():
|
|
@@ -183,18 +183,11 @@ class ResourceTracker:
|
|
|
183
183
|
def set_GPU_tracking(self):
|
|
184
184
|
logger.info("[setup] GPU Tracking...")
|
|
185
185
|
if self.tracker._gpu_ids:
|
|
186
|
-
|
|
187
|
-
if
|
|
188
|
-
isinstance(self.tracker._gpu_ids, list)
|
|
189
|
-
and all(isinstance(gpu_id, int) for gpu_id in self.tracker._gpu_ids)
|
|
190
|
-
):
|
|
191
|
-
self.tracker._gpu_ids: List[int] = parse_gpu_ids(self.tracker._gpu_ids)
|
|
186
|
+
self.tracker._gpu_ids = parse_gpu_ids(self.tracker._gpu_ids)
|
|
187
|
+
if self.tracker._gpu_ids:
|
|
192
188
|
self.tracker._conf["gpu_ids"] = self.tracker._gpu_ids
|
|
193
189
|
self.tracker._conf["gpu_count"] = len(self.tracker._gpu_ids)
|
|
194
|
-
|
|
195
|
-
logger.warning(
|
|
196
|
-
"Invalid gpu_ids format. Expected a string or a list of ints."
|
|
197
|
-
)
|
|
190
|
+
|
|
198
191
|
if gpu.is_gpu_details_available():
|
|
199
192
|
logger.info("Tracking Nvidia GPU via pynvml")
|
|
200
193
|
gpu_devices = GPU.from_utils(self.tracker._gpu_ids)
|
|
@@ -1538,6 +1538,7 @@ AMD Turion X2 Ultra ZM-88,35
|
|
|
1538
1538
|
AMD X940,45.0
|
|
1539
1539
|
AMD Z-01,6
|
|
1540
1540
|
AMD Z-60,5
|
|
1541
|
+
ARMv8 Processor rev 0 (v8l),30
|
|
1541
1542
|
Apple M1,10
|
|
1542
1543
|
Athlon 5150 APU,25
|
|
1543
1544
|
Athlon 5350 APU,25
|
|
@@ -3111,6 +3112,7 @@ Intel Core i9-11900K,125.0
|
|
|
3111
3112
|
Intel Core i9-11900KF,125.0
|
|
3112
3113
|
Intel Core i9-11900T,35.0
|
|
3113
3114
|
Intel Core i9-13900E,65.0
|
|
3115
|
+
Intel Core i9-13900K,125.0
|
|
3114
3116
|
Intel Core i9-13900TE,35.0
|
|
3115
3117
|
Intel Core i9-14900HX,55.0
|
|
3116
3118
|
Intel Core i9-7900X,140
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
{
|
|
2
|
+
"british columbia": {
|
|
3
|
+
"naturalGas": 2.8,
|
|
4
|
+
"nuclear": 0.0,
|
|
5
|
+
"petroleum": 0.1,
|
|
6
|
+
"biomass": 6.7,
|
|
7
|
+
"coal": 0.0,
|
|
8
|
+
"other": 0.0,
|
|
9
|
+
"solar": 0.6,
|
|
10
|
+
"tidal": 0.0,
|
|
11
|
+
"total": 99.9,
|
|
12
|
+
"wind": 2.9,
|
|
13
|
+
"hydro": 86.8
|
|
14
|
+
},
|
|
15
|
+
"newfoundland and labrador": {
|
|
16
|
+
"naturalGas": 0.2,
|
|
17
|
+
"nuclear": 0.0,
|
|
18
|
+
"petroleum": 0.4,
|
|
19
|
+
"biomass": 0.0,
|
|
20
|
+
"coal": 0.0,
|
|
21
|
+
"other": 0.0,
|
|
22
|
+
"solar": 0.0,
|
|
23
|
+
"tidal": 0.0,
|
|
24
|
+
"total": 100.0,
|
|
25
|
+
"wind": 0.4,
|
|
26
|
+
"hydro": 99.0
|
|
27
|
+
},
|
|
28
|
+
"saskatchewan": {
|
|
29
|
+
"naturalGas": 50.7,
|
|
30
|
+
"nuclear": 0.0,
|
|
31
|
+
"petroleum": 0.0,
|
|
32
|
+
"biomass": 1.2,
|
|
33
|
+
"coal": 27.9,
|
|
34
|
+
"other": 0.0,
|
|
35
|
+
"solar": 0.6,
|
|
36
|
+
"tidal": 0.0,
|
|
37
|
+
"total": 100.0,
|
|
38
|
+
"wind": 3.0,
|
|
39
|
+
"hydro": 16.6
|
|
40
|
+
},
|
|
41
|
+
"prince edward island": {
|
|
42
|
+
"naturalGas": 0.0,
|
|
43
|
+
"nuclear": 0.0,
|
|
44
|
+
"petroleum": 2.2,
|
|
45
|
+
"biomass": 0.6,
|
|
46
|
+
"coal": 0.0,
|
|
47
|
+
"other": 0.0,
|
|
48
|
+
"solar": 0.1,
|
|
49
|
+
"tidal": 0.0,
|
|
50
|
+
"total": 100.2,
|
|
51
|
+
"wind": 97.3,
|
|
52
|
+
"hydro": 0.0
|
|
53
|
+
},
|
|
54
|
+
"ontario": {
|
|
55
|
+
"naturalGas": 8.6,
|
|
56
|
+
"nuclear": 50.1,
|
|
57
|
+
"petroleum": 0.1,
|
|
58
|
+
"biomass": 1.0,
|
|
59
|
+
"coal": 0.0,
|
|
60
|
+
"other": 0.0,
|
|
61
|
+
"solar": 5.2,
|
|
62
|
+
"tidal": 0.0,
|
|
63
|
+
"total": 100.1,
|
|
64
|
+
"wind": 11.7,
|
|
65
|
+
"hydro": 23.4
|
|
66
|
+
},
|
|
67
|
+
"nova scotia": {
|
|
68
|
+
"naturalGas": 13.9,
|
|
69
|
+
"nuclear": 0.0,
|
|
70
|
+
"petroleum": 0.0,
|
|
71
|
+
"biomass": 3.5,
|
|
72
|
+
"coal": 47.5,
|
|
73
|
+
"other": 0.0,
|
|
74
|
+
"solar": 0.02,
|
|
75
|
+
"tidal": 0,
|
|
76
|
+
"total": 100.02,
|
|
77
|
+
"wind": 24.2,
|
|
78
|
+
"hydro": 10.9
|
|
79
|
+
},
|
|
80
|
+
"quebec": {
|
|
81
|
+
"naturalGas": 0.2,
|
|
82
|
+
"nuclear": 0.0,
|
|
83
|
+
"petroleum": 0.3,
|
|
84
|
+
"biomass": 0.7,
|
|
85
|
+
"coal": 0.0,
|
|
86
|
+
"other": 0.0,
|
|
87
|
+
"solar": 0.01,
|
|
88
|
+
"tidal": 0.0,
|
|
89
|
+
"total": 100.01,
|
|
90
|
+
"wind": 6.7,
|
|
91
|
+
"hydro": 92.1
|
|
92
|
+
},
|
|
93
|
+
"alberta": {
|
|
94
|
+
"naturalGas": 73.5,
|
|
95
|
+
"nuclear": 0.0,
|
|
96
|
+
"petroleum": 0.02,
|
|
97
|
+
"biomass": 2.0,
|
|
98
|
+
"coal": 8.0,
|
|
99
|
+
"other": 0.0,
|
|
100
|
+
"solar": 3.2,
|
|
101
|
+
"tidal": 0.0,
|
|
102
|
+
"total": 99.82,
|
|
103
|
+
"wind": 11.3,
|
|
104
|
+
"hydro": 1.8
|
|
105
|
+
},
|
|
106
|
+
"manitoba": {
|
|
107
|
+
"naturalGas": 0.6,
|
|
108
|
+
"nuclear": 0.0,
|
|
109
|
+
"petroleum": 0.1,
|
|
110
|
+
"biomass": 0.2,
|
|
111
|
+
"coal": 0.0,
|
|
112
|
+
"other": 0.0,
|
|
113
|
+
"solar": 0.1,
|
|
114
|
+
"tidal": 0.0,
|
|
115
|
+
"total": 100.1,
|
|
116
|
+
"wind": 1.7,
|
|
117
|
+
"hydro": 97.4
|
|
118
|
+
},
|
|
119
|
+
"northwest territories": {
|
|
120
|
+
"naturalGas": 7.3,
|
|
121
|
+
"nuclear": 0.0,
|
|
122
|
+
"petroleum": 10.5,
|
|
123
|
+
"biomass": 0.0,
|
|
124
|
+
"coal": 0.0,
|
|
125
|
+
"other": 0.0,
|
|
126
|
+
"solar": 0.9,
|
|
127
|
+
"tidal": 0.0,
|
|
128
|
+
"total": 100.0,
|
|
129
|
+
"wind": 7.1,
|
|
130
|
+
"hydro": 74.2
|
|
131
|
+
},
|
|
132
|
+
"new brunswick": {
|
|
133
|
+
"naturalGas": 16.6,
|
|
134
|
+
"nuclear": 39.9,
|
|
135
|
+
"petroleum": 0.3,
|
|
136
|
+
"biomass": 1.3,
|
|
137
|
+
"coal": 12.1,
|
|
138
|
+
"other": 0.0,
|
|
139
|
+
"solar": 0.0,
|
|
140
|
+
"tidal": 0.0,
|
|
141
|
+
"total": 99.9,
|
|
142
|
+
"wind": 8.7,
|
|
143
|
+
"hydro": 21.0
|
|
144
|
+
},
|
|
145
|
+
"nunavut": {
|
|
146
|
+
"naturalGas": 0.0,
|
|
147
|
+
"nuclear": 0.0,
|
|
148
|
+
"petroleum": 99.8,
|
|
149
|
+
"biomass": 0.0,
|
|
150
|
+
"coal": 0.0,
|
|
151
|
+
"other": 0.0,
|
|
152
|
+
"solar": 0.2,
|
|
153
|
+
"tidal": 0.0,
|
|
154
|
+
"total": 100.0,
|
|
155
|
+
"wind": 0.0,
|
|
156
|
+
"hydro": 0.0
|
|
157
|
+
},
|
|
158
|
+
"yukon": {
|
|
159
|
+
"naturalGas": 20.2,
|
|
160
|
+
"nuclear": 0.0,
|
|
161
|
+
"petroleum": 15.0,
|
|
162
|
+
"biomass": 0.5,
|
|
163
|
+
"coal": 0.0,
|
|
164
|
+
"other": 0.0,
|
|
165
|
+
"solar": 0.1,
|
|
166
|
+
"tidal": 0.0,
|
|
167
|
+
"total": 100.1,
|
|
168
|
+
"wind": 0.2,
|
|
169
|
+
"hydro": 64.1
|
|
170
|
+
}
|
|
171
|
+
}
|
|
@@ -843,7 +843,7 @@ class BaseEmissionsTracker(ABC):
|
|
|
843
843
|
raise e
|
|
844
844
|
|
|
845
845
|
warning_duration = self._measure_power_secs * 3
|
|
846
|
-
if last_duration > warning_duration:
|
|
846
|
+
if last_duration > warning_duration and not self._scheduler._stopped:
|
|
847
847
|
warn_msg = (
|
|
848
848
|
"Background scheduler didn't run for a long period"
|
|
849
849
|
+ " (%ds), results might be inaccurate"
|
|
@@ -102,25 +102,43 @@ class GPU(BaseHardware):
|
|
|
102
102
|
Get the Ids of the GPUs that we will monitor
|
|
103
103
|
:return: list of ids
|
|
104
104
|
"""
|
|
105
|
-
gpu_ids = []
|
|
106
105
|
if self.gpu_ids is not None:
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
for gpu_id in
|
|
114
|
-
|
|
115
|
-
|
|
106
|
+
uuids_to_ids = {
|
|
107
|
+
gpu.get("uuid"): gpu.get("gpu_index")
|
|
108
|
+
for gpu in self.devices.get_gpu_static_info()
|
|
109
|
+
}
|
|
110
|
+
monitored_gpu_ids = []
|
|
111
|
+
|
|
112
|
+
for gpu_id in self.gpu_ids:
|
|
113
|
+
found_gpu_id = False
|
|
114
|
+
# Does it look like an index into the number of GPUs on the system?
|
|
115
|
+
if isinstance(gpu_id, int) or gpu_id.isdigit():
|
|
116
|
+
gpu_id = int(gpu_id)
|
|
117
|
+
if 0 <= gpu_id < self.num_gpus:
|
|
118
|
+
monitored_gpu_ids.append(gpu_id)
|
|
119
|
+
found_gpu_id = True
|
|
120
|
+
# Does it match a prefix of any UUID on the system after stripping any 'MIG-'
|
|
121
|
+
# id prefix per https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#cuda-environment-variables ?
|
|
116
122
|
else:
|
|
117
|
-
|
|
118
|
-
|
|
123
|
+
stripped_gpu_id_str = gpu_id.lstrip("MIG-")
|
|
124
|
+
for uuid, id in uuids_to_ids.items():
|
|
125
|
+
if uuid.startswith(stripped_gpu_id_str):
|
|
126
|
+
logger.debug(
|
|
127
|
+
f"Matching GPU ID {stripped_gpu_id_str} (originally {gpu_id}) against {uuid} for GPU index {id}"
|
|
128
|
+
)
|
|
129
|
+
monitored_gpu_ids.append(id)
|
|
130
|
+
found_gpu_id = True
|
|
131
|
+
break
|
|
132
|
+
if not found_gpu_id:
|
|
133
|
+
logger.warning(
|
|
134
|
+
f"GPU with ID '{gpu_id}' not found or invalid. It will be ignored."
|
|
119
135
|
)
|
|
120
|
-
|
|
136
|
+
|
|
137
|
+
monitored_gpu_ids = sorted(list(set(monitored_gpu_ids)))
|
|
138
|
+
self.gpu_ids = monitored_gpu_ids
|
|
139
|
+
return monitored_gpu_ids
|
|
121
140
|
else:
|
|
122
|
-
|
|
123
|
-
return gpu_ids
|
|
141
|
+
return list(range(self.num_gpus))
|
|
124
142
|
|
|
125
143
|
def total_power(self) -> Power:
|
|
126
144
|
return self._total_power
|
|
@@ -135,7 +153,7 @@ class GPU(BaseHardware):
|
|
|
135
153
|
new_gpu_ids = gpus._get_gpu_ids()
|
|
136
154
|
if len(new_gpu_ids) < gpus.num_gpus:
|
|
137
155
|
logger.warning(
|
|
138
|
-
f"You have {gpus.num_gpus} GPUs but we will monitor only {len(
|
|
156
|
+
f"You have {gpus.num_gpus} GPUs but we will monitor only {len(new_gpu_ids)} ({new_gpu_ids}) of them. Check your configuration."
|
|
139
157
|
)
|
|
140
158
|
return cls(gpu_ids=new_gpu_ids)
|
|
141
159
|
|
|
@@ -24,7 +24,7 @@ class DataSource:
|
|
|
24
24
|
"geo_js_url": "https://get.geojs.io/v1/ip/geo.json",
|
|
25
25
|
"cloud_emissions_path": "data/cloud/impact.csv",
|
|
26
26
|
"usa_emissions_data_path": "data/private_infra/2016/usa_emissions.json",
|
|
27
|
-
"can_energy_mix_data_path": "data/private_infra/
|
|
27
|
+
"can_energy_mix_data_path": "data/private_infra/2023/canada_energy_mix.json", # noqa: E501
|
|
28
28
|
"global_energy_mix_data_path": "data/private_infra/global_energy_mix.json", # noqa: E501
|
|
29
29
|
"carbon_intensity_per_source_path": "data/private_infra/carbon_intensity_per_source.json",
|
|
30
30
|
"cpu_power_path": "data/hardware/cpu_power.csv",
|
|
@@ -36,7 +36,11 @@ class FileOutput(BaseOutput):
|
|
|
36
36
|
def has_valid_headers(self, data: EmissionsData):
|
|
37
37
|
with open(self.save_file_path) as csv_file:
|
|
38
38
|
csv_reader = csv.DictReader(csv_file)
|
|
39
|
-
|
|
39
|
+
csv_entries_list = list(csv_reader)
|
|
40
|
+
if len(csv_entries_list) == 0:
|
|
41
|
+
# No entries
|
|
42
|
+
return True
|
|
43
|
+
dict_from_csv = dict(csv_entries_list[0])
|
|
40
44
|
list_of_column_names = list(dict_from_csv.keys())
|
|
41
45
|
return list(data.values.keys()) == list_of_column_names
|
|
42
46
|
|
|
@@ -48,7 +52,7 @@ class FileOutput(BaseOutput):
|
|
|
48
52
|
"""
|
|
49
53
|
file_exists: bool = os.path.isfile(self.save_file_path)
|
|
50
54
|
if file_exists and not self.has_valid_headers(total):
|
|
51
|
-
logger.warning("The CSV format
|
|
55
|
+
logger.warning("The CSV format has changed, backing up old emission file.")
|
|
52
56
|
backup(self.save_file_path)
|
|
53
57
|
file_exists = False
|
|
54
58
|
new_df = pd.DataFrame.from_records([dict(total.values)])
|
|
@@ -39,8 +39,8 @@ codecarbon/data/hardware/cpu_dataset_builder/intel_cpu_scrapper.py
|
|
|
39
39
|
codecarbon/data/hardware/cpu_dataset_builder/merge_scrapped_cpu_power.py
|
|
40
40
|
codecarbon/data/private_infra/carbon_intensity_per_source.json
|
|
41
41
|
codecarbon/data/private_infra/global_energy_mix.json
|
|
42
|
-
codecarbon/data/private_infra/2016/canada_energy_mix.json
|
|
43
42
|
codecarbon/data/private_infra/2016/usa_emissions.json
|
|
43
|
+
codecarbon/data/private_infra/2023/canada_energy_mix.json
|
|
44
44
|
codecarbon/external/__init__.py
|
|
45
45
|
codecarbon/external/geography.py
|
|
46
46
|
codecarbon/external/hardware.py
|
|
@@ -61,7 +61,7 @@ codecarbon = [
|
|
|
61
61
|
"data/private_infra/global_energy_mix.json",
|
|
62
62
|
"data/private_infra/carbon_intensity_per_source.json",
|
|
63
63
|
"data/private_infra/2016/usa_emissions.json",
|
|
64
|
-
"data/private_infra/
|
|
64
|
+
"data/private_infra/2023/canada_energy_mix.json",
|
|
65
65
|
]
|
|
66
66
|
|
|
67
67
|
[project.urls]
|
|
@@ -160,7 +160,7 @@ docs = "cd docs/edit && make docs"
|
|
|
160
160
|
carbonboard = "python codecarbon/viz/carbonboard.py"
|
|
161
161
|
|
|
162
162
|
[tool.bumpver]
|
|
163
|
-
current_version = "3.0.
|
|
163
|
+
current_version = "3.0.5"
|
|
164
164
|
version_pattern = "MAJOR.MINOR.PATCH[_TAGNUM]"
|
|
165
165
|
|
|
166
166
|
[tool.bumpver.file_patterns]
|
|
@@ -32,16 +32,16 @@ class TestConfig(unittest.TestCase):
|
|
|
32
32
|
|
|
33
33
|
def test_parse_gpu_ids(self):
|
|
34
34
|
for ids, target in [
|
|
35
|
-
("0,1,2", [0, 1, 2]),
|
|
36
|
-
("[0, 1, 2", [0, 1, 2]),
|
|
37
|
-
("(0, 1, 2)", [0, 1, 2]),
|
|
38
|
-
("[1]", [1]),
|
|
39
|
-
("1", [1]),
|
|
40
|
-
("0", [0]),
|
|
35
|
+
("0,1,2", ["0", "1", "2"]),
|
|
36
|
+
("[0, 1, 2", ["0", "1", "2"]),
|
|
37
|
+
("(0, 1, 2)", ["0", "1", "2"]),
|
|
38
|
+
("[1]", ["1"]),
|
|
39
|
+
("1", ["1"]),
|
|
40
|
+
("0", ["0"]),
|
|
41
|
+
("MIG-f1e", ["MIG-f1e"]),
|
|
41
42
|
("", []),
|
|
42
43
|
([], []),
|
|
43
|
-
([1, 2, 3], [1, 2, 3]),
|
|
44
|
-
(1, 1),
|
|
44
|
+
([1, 2, 3], ["1", "2", "3"]),
|
|
45
45
|
]:
|
|
46
46
|
self.assertEqual(parse_gpu_ids(ids), target)
|
|
47
47
|
|
|
@@ -101,6 +101,7 @@ class TestConfig(unittest.TestCase):
|
|
|
101
101
|
"USER": "useless key",
|
|
102
102
|
"CODECARBON_ENV_OVERWRITE": "SUCCESS:overwritten",
|
|
103
103
|
"CODECARBON_ENV_NEW_KEY": "cool value",
|
|
104
|
+
"CODECARBON_ALLOW_MULTIPLE_RUNS": "True",
|
|
104
105
|
},
|
|
105
106
|
)
|
|
106
107
|
def test_read_confs_and_parse_envs(self):
|
|
@@ -145,9 +146,8 @@ class TestConfig(unittest.TestCase):
|
|
|
145
146
|
"builtins.open", new_callable=get_custom_mock_open(global_conf, local_conf)
|
|
146
147
|
):
|
|
147
148
|
conf = dict(get_hierarchical_config())
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
} # allow_multiple_runs is a default value
|
|
149
|
+
# allow_multiple_runs is set in pytest.ini and not mocked, so it's visible here.
|
|
150
|
+
target = {"allow_multiple_runs": "True"}
|
|
151
151
|
self.assertDictEqual(conf, target)
|
|
152
152
|
|
|
153
153
|
@mock.patch.dict(
|
|
@@ -190,7 +190,7 @@ class TestConfig(unittest.TestCase):
|
|
|
190
190
|
self.assertEqual(tracker._force_ram_power, 50.5)
|
|
191
191
|
self.assertEqual(tracker._output_dir, "/success/overwritten")
|
|
192
192
|
self.assertEqual(tracker._emissions_endpoint, "http://testhost:2000")
|
|
193
|
-
self.assertEqual(tracker._gpu_ids, [0, 1])
|
|
193
|
+
self.assertEqual(tracker._gpu_ids, ["0", "1"])
|
|
194
194
|
self.assertEqual(tracker._co2_signal_api_token, "signal-token")
|
|
195
195
|
self.assertEqual(tracker._project_name, "test-project")
|
|
196
196
|
self.assertTrue(tracker._save_to_file)
|
|
@@ -206,7 +206,7 @@ class TestConfig(unittest.TestCase):
|
|
|
206
206
|
tracker = EmissionsTracker(
|
|
207
207
|
project_name="test-project", allow_multiple_runs=True
|
|
208
208
|
)
|
|
209
|
-
self.assertEqual(tracker._gpu_ids, [2, 3])
|
|
209
|
+
self.assertEqual(tracker._gpu_ids, ["2", "3"])
|
|
210
210
|
|
|
211
211
|
@mock.patch.dict(
|
|
212
212
|
os.environ,
|
|
@@ -220,7 +220,7 @@ class TestConfig(unittest.TestCase):
|
|
|
220
220
|
tracker = EmissionsTracker(
|
|
221
221
|
project_name="test-project", allow_multiple_runs=True
|
|
222
222
|
)
|
|
223
|
-
self.assertEqual(tracker._gpu_ids, [99])
|
|
223
|
+
self.assertEqual(tracker._gpu_ids, ["99"])
|
|
224
224
|
gpu_count = 0
|
|
225
225
|
for hardware in tracker._hardware:
|
|
226
226
|
if isinstance(hardware, GPU):
|
|
@@ -4,7 +4,7 @@ from unittest import mock
|
|
|
4
4
|
|
|
5
5
|
from codecarbon.core.units import Power
|
|
6
6
|
from codecarbon.emissions_tracker import OfflineEmissionsTracker
|
|
7
|
-
from codecarbon.external.hardware import CPU, MODE_CPU_LOAD
|
|
7
|
+
from codecarbon.external.hardware import CPU, MODE_CPU_LOAD, AppleSiliconChip
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
@mock.patch("codecarbon.core.cpu.is_psutil_available", return_value=True)
|
|
@@ -57,7 +57,9 @@ class TestCPULoad(unittest.TestCase):
|
|
|
57
57
|
):
|
|
58
58
|
tracker = OfflineEmissionsTracker(country_iso_code="FRA")
|
|
59
59
|
for hardware in tracker._hardware:
|
|
60
|
-
if
|
|
60
|
+
if (
|
|
61
|
+
isinstance(hardware, CPU) and hardware._mode == MODE_CPU_LOAD
|
|
62
|
+
) or isinstance(hardware, AppleSiliconChip):
|
|
61
63
|
break
|
|
62
64
|
else:
|
|
63
65
|
raise Exception("No CPU load !!!")
|
|
@@ -154,10 +154,13 @@ class TestEmissions(unittest.TestCase):
|
|
|
154
154
|
country_iso_code="CAN", country_name="Canada", region="ontario"
|
|
155
155
|
),
|
|
156
156
|
)
|
|
157
|
+
manually_computed_emissions = (
|
|
158
|
+
3 * (0.995725971 * 0.0 + 0.8166885263 * 0.1 + 0.7438415916 * 8.6) / 100.1
|
|
159
|
+
)
|
|
157
160
|
|
|
158
161
|
# THEN
|
|
159
162
|
assert isinstance(emissions, float)
|
|
160
|
-
self.assertAlmostEqual(emissions,
|
|
163
|
+
self.assertAlmostEqual(emissions, manually_computed_emissions, places=2)
|
|
161
164
|
|
|
162
165
|
def test_get_emissions_PRIVATE_INFRA_unknown_country(self):
|
|
163
166
|
"""
|
|
@@ -520,3 +520,91 @@ class TestCarbonTracker(unittest.TestCase):
|
|
|
520
520
|
self.assertEqual("United States", emissions_df["country_name"].values[0])
|
|
521
521
|
self.assertEqual("USA", emissions_df["country_iso_code"].values[0])
|
|
522
522
|
self.assertIsInstance(tracker.final_emissions, float)
|
|
523
|
+
|
|
524
|
+
@mock.patch("codecarbon.emissions_tracker.logger")
|
|
525
|
+
def test_scheduler_warning_suppressed_when_stopped(
|
|
526
|
+
self,
|
|
527
|
+
mock_logger,
|
|
528
|
+
mock_setup_intel_cli,
|
|
529
|
+
mock_log_values,
|
|
530
|
+
mocked_get_gpu_details,
|
|
531
|
+
mocked_env_cloud_details,
|
|
532
|
+
mocked_is_gpu_details_available,
|
|
533
|
+
):
|
|
534
|
+
"""Test that scheduler warning is suppressed when scheduler is stopped."""
|
|
535
|
+
with EmissionsTracker(
|
|
536
|
+
output_dir=self.temp_path,
|
|
537
|
+
measure_power_secs=1, # Short interval for testing
|
|
538
|
+
) as tracker:
|
|
539
|
+
# Stop the scheduler to simulate task mode or manual stopping
|
|
540
|
+
tracker._scheduler.stop()
|
|
541
|
+
|
|
542
|
+
# Artificially set last measured time to simulate long delay
|
|
543
|
+
import time
|
|
544
|
+
|
|
545
|
+
tracker._last_measured_time = time.perf_counter() - 10 # 10 seconds ago
|
|
546
|
+
|
|
547
|
+
# Reset mock to clear any previous warning calls
|
|
548
|
+
mock_logger.warning.reset_mock()
|
|
549
|
+
|
|
550
|
+
# Call _measure_power_and_energy directly - this would normally trigger warning
|
|
551
|
+
tracker._measure_power_and_energy()
|
|
552
|
+
|
|
553
|
+
# Verify that if warning was called, it wasn't the scheduler warning
|
|
554
|
+
if mock_logger.warning.called:
|
|
555
|
+
for call in mock_logger.warning.call_args_list:
|
|
556
|
+
args, kwargs = call
|
|
557
|
+
if (
|
|
558
|
+
args
|
|
559
|
+
and "Background scheduler didn't run for a long period"
|
|
560
|
+
in str(args[0])
|
|
561
|
+
):
|
|
562
|
+
self.fail(
|
|
563
|
+
"Scheduler warning was called when it should have been suppressed"
|
|
564
|
+
)
|
|
565
|
+
|
|
566
|
+
@mock.patch("codecarbon.emissions_tracker.logger")
|
|
567
|
+
def test_scheduler_warning_shown_when_running(
|
|
568
|
+
self,
|
|
569
|
+
mock_logger,
|
|
570
|
+
mock_setup_intel_cli,
|
|
571
|
+
mock_log_values,
|
|
572
|
+
mocked_get_gpu_details,
|
|
573
|
+
mocked_env_cloud_details,
|
|
574
|
+
mocked_is_gpu_details_available,
|
|
575
|
+
):
|
|
576
|
+
"""Test that scheduler warning is shown when scheduler is running but delayed."""
|
|
577
|
+
with EmissionsTracker(
|
|
578
|
+
output_dir=self.temp_path,
|
|
579
|
+
measure_power_secs=1, # Short interval for testing
|
|
580
|
+
) as tracker:
|
|
581
|
+
# Ensure scheduler is running (default state)
|
|
582
|
+
self.assertFalse(tracker._scheduler._stopped)
|
|
583
|
+
|
|
584
|
+
# Artificially set last measured time to simulate long delay
|
|
585
|
+
import time
|
|
586
|
+
|
|
587
|
+
tracker._last_measured_time = time.perf_counter() - 10 # 10 seconds ago
|
|
588
|
+
|
|
589
|
+
# Reset mock to clear any previous warning calls
|
|
590
|
+
mock_logger.warning.reset_mock()
|
|
591
|
+
|
|
592
|
+
# Call _measure_power_and_energy directly - this should trigger warning
|
|
593
|
+
tracker._measure_power_and_energy()
|
|
594
|
+
|
|
595
|
+
# Verify warning was logged since scheduler should be running
|
|
596
|
+
scheduler_warning_found = False
|
|
597
|
+
if mock_logger.warning.called:
|
|
598
|
+
for call in mock_logger.warning.call_args_list:
|
|
599
|
+
args, kwargs = call
|
|
600
|
+
if (
|
|
601
|
+
args
|
|
602
|
+
and "Background scheduler didn't run for a long period"
|
|
603
|
+
in str(args[0])
|
|
604
|
+
):
|
|
605
|
+
scheduler_warning_found = True
|
|
606
|
+
break
|
|
607
|
+
|
|
608
|
+
self.assertTrue(
|
|
609
|
+
scheduler_warning_found, "Expected scheduler warning was not found"
|
|
610
|
+
)
|
|
@@ -50,7 +50,7 @@ class FakeGPUEnv:
|
|
|
50
50
|
self.DETAILS = {
|
|
51
51
|
"handle_0": {
|
|
52
52
|
"name": b"GeForce GTX 1080",
|
|
53
|
-
"uuid": b"uuid
|
|
53
|
+
"uuid": b"uuid-1",
|
|
54
54
|
"memory": real_pynvml.c_nvmlMemory_t(1024, 100, 924),
|
|
55
55
|
"temperature": 75,
|
|
56
56
|
"power_usage": 26,
|
|
@@ -66,7 +66,7 @@ class FakeGPUEnv:
|
|
|
66
66
|
},
|
|
67
67
|
"handle_1": {
|
|
68
68
|
"name": b"GeForce GTX 1080",
|
|
69
|
-
"uuid": b"uuid
|
|
69
|
+
"uuid": b"uuid-2",
|
|
70
70
|
"memory": real_pynvml.c_nvmlMemory_t(1024, 200, 824),
|
|
71
71
|
"temperature": 79,
|
|
72
72
|
"power_usage": 29,
|
|
@@ -84,7 +84,7 @@ class FakeGPUEnv:
|
|
|
84
84
|
self.expected = [
|
|
85
85
|
{
|
|
86
86
|
"name": "GeForce GTX 1080",
|
|
87
|
-
"uuid": "uuid
|
|
87
|
+
"uuid": "uuid-1",
|
|
88
88
|
"total_memory": 1024,
|
|
89
89
|
"free_memory": 100,
|
|
90
90
|
"used_memory": 924,
|
|
@@ -102,7 +102,7 @@ class FakeGPUEnv:
|
|
|
102
102
|
},
|
|
103
103
|
{
|
|
104
104
|
"name": "GeForce GTX 1080",
|
|
105
|
-
"uuid": "uuid
|
|
105
|
+
"uuid": "uuid-2",
|
|
106
106
|
"total_memory": 1024,
|
|
107
107
|
"free_memory": 200,
|
|
108
108
|
"used_memory": 824,
|
|
@@ -146,14 +146,14 @@ class TestGpu(FakeGPUEnv):
|
|
|
146
146
|
expected = [
|
|
147
147
|
{
|
|
148
148
|
"name": "GeForce GTX 1080",
|
|
149
|
-
"uuid": "uuid
|
|
149
|
+
"uuid": "uuid-1",
|
|
150
150
|
"total_memory": 1024,
|
|
151
151
|
"power_limit": 149,
|
|
152
152
|
"gpu_index": 0,
|
|
153
153
|
},
|
|
154
154
|
{
|
|
155
155
|
"name": "GeForce GTX 1080",
|
|
156
|
-
"uuid": "uuid
|
|
156
|
+
"uuid": "uuid-2",
|
|
157
157
|
"total_memory": 1024,
|
|
158
158
|
"power_limit": 149,
|
|
159
159
|
"gpu_index": 1,
|
|
@@ -311,6 +311,33 @@ class TestGpu(FakeGPUEnv):
|
|
|
311
311
|
expected_power = gpu2_power
|
|
312
312
|
tc.assertAlmostEqual(expected_power.kW, gpu.total_power().kW)
|
|
313
313
|
|
|
314
|
+
def test_get_gpu_ids(self):
|
|
315
|
+
"""
|
|
316
|
+
Check parsing of gpu_ids in various forms.
|
|
317
|
+
"""
|
|
318
|
+
# Prepare
|
|
319
|
+
from codecarbon.external.hardware import GPU
|
|
320
|
+
|
|
321
|
+
for test_ids, expected_ids in [
|
|
322
|
+
([0, 1], [0, 1]),
|
|
323
|
+
([0, 1, 2], [0, 1]),
|
|
324
|
+
([2], []),
|
|
325
|
+
(["0", "1"], [0, 1]),
|
|
326
|
+
# Only two GPUS in the system, so ignore the third (index 2)
|
|
327
|
+
(["0", "1", "2"], [0, 1]),
|
|
328
|
+
(["2"], []),
|
|
329
|
+
# Check UUID-to-index mapping
|
|
330
|
+
(["uuid-1"], [0]),
|
|
331
|
+
(["uuid-1", "uuid-2"], [0, 1]),
|
|
332
|
+
(["uuid-3"], []),
|
|
333
|
+
# Check UUID-to-index mapping when we need to strip the prefix
|
|
334
|
+
(["MIG-uuid-1"], [0]),
|
|
335
|
+
(["MIG-uuid-3"], []),
|
|
336
|
+
]:
|
|
337
|
+
gpu = GPU(test_ids)
|
|
338
|
+
result = gpu._get_gpu_ids()
|
|
339
|
+
assert result == expected_ids
|
|
340
|
+
|
|
314
341
|
|
|
315
342
|
class TestGpuNotAvailable:
|
|
316
343
|
def setup_method(self):
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import os
|
|
2
|
+
import sys
|
|
2
3
|
import unittest
|
|
3
4
|
from unittest.mock import MagicMock, patch
|
|
4
5
|
|
|
@@ -18,6 +19,10 @@ class TestUnsupportedGPU(unittest.TestCase):
|
|
|
18
19
|
if os.path.exists(self.output_csv):
|
|
19
20
|
os.remove(self.output_csv)
|
|
20
21
|
|
|
22
|
+
# If we run this on macOS, NVMLError_NotSupported has no effect
|
|
23
|
+
# and we end up with non-zero values for GPU energy and power because
|
|
24
|
+
# we use the non-NVML code-path in hardware.AppleSiliconChip().
|
|
25
|
+
@unittest.skipIf(sys.platform == "darwin", "NVML not available on macOS")
|
|
21
26
|
@patch("codecarbon.core.gpu.pynvml")
|
|
22
27
|
def test_emissions_tracker_unsupported_gpu(self, mock_pynvml):
|
|
23
28
|
mock_pynvml.NVMLError_NotSupported = self.NVMLError_NotSupported
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "3.0.4"
|
|
@@ -1,171 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"british columbia": {
|
|
3
|
-
"naturalGas": 1.1,
|
|
4
|
-
"nuclear": 0.0,
|
|
5
|
-
"petroleum": 0.7,
|
|
6
|
-
"biomass": 6.4,
|
|
7
|
-
"coal": 0.0,
|
|
8
|
-
"other": 0.0,
|
|
9
|
-
"solar": 0.0,
|
|
10
|
-
"tidal": 0.0,
|
|
11
|
-
"total": 100,
|
|
12
|
-
"wind": 1.3,
|
|
13
|
-
"hydro": 90.5
|
|
14
|
-
},
|
|
15
|
-
"newfoundland and labrador": {
|
|
16
|
-
"naturalGas": 0.7,
|
|
17
|
-
"nuclear": 0.0,
|
|
18
|
-
"petroleum": 4.8,
|
|
19
|
-
"biomass": 0.3,
|
|
20
|
-
"coal": 0.0,
|
|
21
|
-
"other": 0.0,
|
|
22
|
-
"solar": 0.0,
|
|
23
|
-
"tidal": 0.0,
|
|
24
|
-
"total": 100,
|
|
25
|
-
"wind": 0.5,
|
|
26
|
-
"hydro": 93.7
|
|
27
|
-
},
|
|
28
|
-
"saskatchewan": {
|
|
29
|
-
"naturalGas": 35.7,
|
|
30
|
-
"nuclear": 0.0,
|
|
31
|
-
"petroleum": 0.0,
|
|
32
|
-
"biomass": 0.0,
|
|
33
|
-
"coal": 46.6,
|
|
34
|
-
"other": 0.0,
|
|
35
|
-
"solar": 0.1,
|
|
36
|
-
"tidal": 0.0,
|
|
37
|
-
"total": 99.9,
|
|
38
|
-
"wind": 3.8,
|
|
39
|
-
"hydro": 13.7
|
|
40
|
-
},
|
|
41
|
-
"prince edward island": {
|
|
42
|
-
"naturalGas": 0.0,
|
|
43
|
-
"nuclear": 0.0,
|
|
44
|
-
"petroleum": 1.1,
|
|
45
|
-
"biomass": 0.7,
|
|
46
|
-
"coal": 0.0,
|
|
47
|
-
"other": 0.0,
|
|
48
|
-
"solar": 0.3,
|
|
49
|
-
"tidal": 0.0,
|
|
50
|
-
"total": 100,
|
|
51
|
-
"wind": 97.9,
|
|
52
|
-
"hydro": 0.0
|
|
53
|
-
},
|
|
54
|
-
"ontario": {
|
|
55
|
-
"naturalGas": 5.2,
|
|
56
|
-
"nuclear": 58.6,
|
|
57
|
-
"petroleum": 0.1,
|
|
58
|
-
"biomass": 1.3,
|
|
59
|
-
"coal": 0.0,
|
|
60
|
-
"other": 0.0,
|
|
61
|
-
"solar": 2.2,
|
|
62
|
-
"tidal": 0.0,
|
|
63
|
-
"total": 100,
|
|
64
|
-
"wind": 6.7,
|
|
65
|
-
"hydro": 25.9
|
|
66
|
-
},
|
|
67
|
-
"nova scotia": {
|
|
68
|
-
"naturalGas": 14.3,
|
|
69
|
-
"nuclear": 0.0,
|
|
70
|
-
"petroleum": 12.2,
|
|
71
|
-
"biomass": 4.9,
|
|
72
|
-
"coal": 47.9,
|
|
73
|
-
"other": 0.0,
|
|
74
|
-
"solar": 0.03,
|
|
75
|
-
"tidal": 0.2,
|
|
76
|
-
"total": 100.13,
|
|
77
|
-
"wind": 11.8,
|
|
78
|
-
"hydro": 8.8
|
|
79
|
-
},
|
|
80
|
-
"quebec": {
|
|
81
|
-
"naturalGas": 0.1,
|
|
82
|
-
"nuclear": 0.0,
|
|
83
|
-
"petroleum": 0.2,
|
|
84
|
-
"biomass": 0.8,
|
|
85
|
-
"coal": 0.0,
|
|
86
|
-
"other": 0.0,
|
|
87
|
-
"solar": 0.0,
|
|
88
|
-
"tidal": 0.0,
|
|
89
|
-
"total": 100,
|
|
90
|
-
"wind": 3.9,
|
|
91
|
-
"hydro": 95.0
|
|
92
|
-
},
|
|
93
|
-
"alberta": {
|
|
94
|
-
"naturalGas": 42.2,
|
|
95
|
-
"nuclear": 0.0,
|
|
96
|
-
"petroleum": 2.6,
|
|
97
|
-
"biomass": 2.2,
|
|
98
|
-
"coal": 44.9,
|
|
99
|
-
"other": 0.2,
|
|
100
|
-
"solar": 0.1,
|
|
101
|
-
"tidal": 0.0,
|
|
102
|
-
"total": 100.1,
|
|
103
|
-
"wind": 5.4,
|
|
104
|
-
"hydro": 2.5
|
|
105
|
-
},
|
|
106
|
-
"manitoba": {
|
|
107
|
-
"naturalGas": 0.0,
|
|
108
|
-
"nuclear": 0.0,
|
|
109
|
-
"petroleum": 0.2,
|
|
110
|
-
"biomass": 0.1,
|
|
111
|
-
"coal": 0.1,
|
|
112
|
-
"other": 0.0,
|
|
113
|
-
"solar": 0.0,
|
|
114
|
-
"tidal": 0.0,
|
|
115
|
-
"total": 99.9,
|
|
116
|
-
"wind": 2.7,
|
|
117
|
-
"hydro": 96.8
|
|
118
|
-
},
|
|
119
|
-
"northwest territories": {
|
|
120
|
-
"naturalGas": 4.0,
|
|
121
|
-
"nuclear": 0.0,
|
|
122
|
-
"petroleum": 55.3,
|
|
123
|
-
"biomass": 0.0,
|
|
124
|
-
"coal": 0.0,
|
|
125
|
-
"other": 0.0,
|
|
126
|
-
"solar": 0.2,
|
|
127
|
-
"tidal": 0.0,
|
|
128
|
-
"total": 100,
|
|
129
|
-
"wind": 2.0,
|
|
130
|
-
"hydro": 38.5
|
|
131
|
-
},
|
|
132
|
-
"new brunswick": {
|
|
133
|
-
"naturalGas": 9.9,
|
|
134
|
-
"nuclear": 36.1,
|
|
135
|
-
"petroleum": 7.6,
|
|
136
|
-
"biomass": 4.2,
|
|
137
|
-
"coal": 15.8,
|
|
138
|
-
"other": 0.0,
|
|
139
|
-
"solar": 0.0,
|
|
140
|
-
"tidal": 0.0,
|
|
141
|
-
"total": 99.8,
|
|
142
|
-
"wind": 6.6,
|
|
143
|
-
"hydro": 19.6
|
|
144
|
-
},
|
|
145
|
-
"nunavut": {
|
|
146
|
-
"naturalGas": 0.0,
|
|
147
|
-
"nuclear": 0.0,
|
|
148
|
-
"petroleum": 100.0,
|
|
149
|
-
"biomass": 0.0,
|
|
150
|
-
"coal": 0.0,
|
|
151
|
-
"other": 0.0,
|
|
152
|
-
"solar": 0.0,
|
|
153
|
-
"tidal": 0.0,
|
|
154
|
-
"total": 100,
|
|
155
|
-
"wind": 0.0,
|
|
156
|
-
"hydro": 0.0
|
|
157
|
-
},
|
|
158
|
-
"yukon": {
|
|
159
|
-
"naturalGas": 2.0,
|
|
160
|
-
"nuclear": 0.0,
|
|
161
|
-
"petroleum": 5.5,
|
|
162
|
-
"biomass": 0.0,
|
|
163
|
-
"coal": 0.0,
|
|
164
|
-
"other": 0.0,
|
|
165
|
-
"solar": 0.3,
|
|
166
|
-
"tidal": 0.0,
|
|
167
|
-
"total": 100,
|
|
168
|
-
"wind": 0.0,
|
|
169
|
-
"hydro": 92.2
|
|
170
|
-
}
|
|
171
|
-
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{codecarbon-3.0.4 → codecarbon-3.0.5}/codecarbon/data/private_infra/carbon_intensity_per_source.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|