codecarbon 3.0.7__tar.gz → 3.0.8__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.7 → codecarbon-3.0.8}/PKG-INFO +1 -1
- codecarbon-3.0.8/codecarbon/_version.py +1 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/codecarbon/core/units.py +16 -1
- {codecarbon-3.0.7 → codecarbon-3.0.8}/codecarbon/emissions_tracker.py +19 -3
- {codecarbon-3.0.7 → codecarbon-3.0.8}/codecarbon/external/task.py +1 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/codecarbon/output_methods/emissions_data.py +4 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/codecarbon.egg-info/PKG-INFO +1 -1
- {codecarbon-3.0.7 → codecarbon-3.0.8}/pyproject.toml +4 -1
- {codecarbon-3.0.7 → codecarbon-3.0.8}/tests/test_api_call.py +1 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/tests/test_emissions_tracker.py +56 -27
- codecarbon-3.0.7/codecarbon/_version.py +0 -1
- {codecarbon-3.0.7 → codecarbon-3.0.8}/LICENSE +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/README.md +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/codecarbon/__init__.py +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/codecarbon/cli/__init__.py +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/codecarbon/cli/cli_utils.py +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/codecarbon/cli/main.py +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/codecarbon/core/__init__.py +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/codecarbon/core/api_client.py +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/codecarbon/core/cloud.py +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/codecarbon/core/co2_signal.py +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/codecarbon/core/config.py +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/codecarbon/core/cpu.py +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/codecarbon/core/emissions.py +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/codecarbon/core/gpu.py +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/codecarbon/core/measure.py +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/codecarbon/core/powermetrics.py +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/codecarbon/core/rapl.py +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/codecarbon/core/resource_tracker.py +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/codecarbon/core/schemas.py +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/codecarbon/core/util.py +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/codecarbon/data/canada_provinces.geojson +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/codecarbon/data/cloud/impact.csv +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/codecarbon/data/hardware/cpu_dataset_builder/amd_cpu_scrapper.py +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/codecarbon/data/hardware/cpu_dataset_builder/intel_cpu_scrapper.py +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/codecarbon/data/hardware/cpu_dataset_builder/merge_scrapped_cpu_power.py +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/codecarbon/data/hardware/cpu_power.csv +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/codecarbon/data/private_infra/2016/usa_emissions.json +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/codecarbon/data/private_infra/2023/canada_energy_mix.json +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/codecarbon/data/private_infra/carbon_intensity_per_source.json +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/codecarbon/data/private_infra/global_energy_mix.json +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/codecarbon/external/__init__.py +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/codecarbon/external/geography.py +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/codecarbon/external/hardware.py +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/codecarbon/external/logger.py +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/codecarbon/external/ram.py +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/codecarbon/external/scheduler.py +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/codecarbon/input.py +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/codecarbon/lock.py +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/codecarbon/output.py +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/codecarbon/output_methods/__init__.py +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/codecarbon/output_methods/base_output.py +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/codecarbon/output_methods/file.py +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/codecarbon/output_methods/http.py +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/codecarbon/output_methods/logger.py +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/codecarbon/output_methods/metrics/__init__.py +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/codecarbon/output_methods/metrics/logfire.py +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/codecarbon/output_methods/metrics/metric_docs.py +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/codecarbon/output_methods/metrics/prometheus.py +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/codecarbon/viz/__init__.py +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/codecarbon/viz/assets/__init__.py +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/codecarbon/viz/carbonboard.py +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/codecarbon/viz/carbonboard_on_api.py +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/codecarbon/viz/components.py +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/codecarbon/viz/data.py +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/codecarbon/viz/units.py +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/codecarbon.egg-info/SOURCES.txt +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/codecarbon.egg-info/dependency_links.txt +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/codecarbon.egg-info/entry_points.txt +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/codecarbon.egg-info/requires.txt +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/codecarbon.egg-info/top_level.txt +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/setup.cfg +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/tests/test_cli.py +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/tests/test_cloud.py +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/tests/test_co2_signal.py +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/tests/test_config.py +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/tests/test_core_util.py +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/tests/test_cpu.py +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/tests/test_cpu_load.py +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/tests/test_custom_handler.py +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/tests/test_emissions.py +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/tests/test_emissions_tracker_constant.py +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/tests/test_emissions_tracker_flush.py +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/tests/test_energy.py +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/tests/test_geography.py +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/tests/test_gpu.py +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/tests/test_lock.py +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/tests/test_logging_output.py +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/tests/test_offline_emissions_tracker.py +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/tests/test_package_integrity.py +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/tests/test_powermetrics.py +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/tests/test_ram.py +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/tests/test_tracking_inference.py +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/tests/test_unsupported_gpu.py +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/tests/test_viz_data.py +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/tests/test_viz_units.py +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/tests/testdata.py +0 -0
- {codecarbon-3.0.7 → codecarbon-3.0.8}/tests/testutils.py +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "3.0.8"
|
|
@@ -90,7 +90,6 @@ class Energy:
|
|
|
90
90
|
return Energy(self.kWh + other.kWh)
|
|
91
91
|
|
|
92
92
|
def __mul__(self, factor: float) -> "Energy":
|
|
93
|
-
assert isinstance(factor, float)
|
|
94
93
|
assert isinstance(self.kWh, float)
|
|
95
94
|
result = Energy(self.kWh * factor)
|
|
96
95
|
return result
|
|
@@ -162,3 +161,19 @@ class Power:
|
|
|
162
161
|
|
|
163
162
|
def __floordiv__(self, divisor: float) -> "Power":
|
|
164
163
|
return Power(self.kW // divisor)
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
@dataclass
|
|
167
|
+
class Water:
|
|
168
|
+
"""
|
|
169
|
+
Measured in litres
|
|
170
|
+
"""
|
|
171
|
+
|
|
172
|
+
litres: float
|
|
173
|
+
|
|
174
|
+
@classmethod
|
|
175
|
+
def from_litres(cls, litres: float) -> "Water":
|
|
176
|
+
return cls(litres=litres)
|
|
177
|
+
|
|
178
|
+
def __add__(self, other: "Water") -> "Water":
|
|
179
|
+
return Water(self.litres + other.litres)
|
|
@@ -17,7 +17,7 @@ from codecarbon._version import __version__
|
|
|
17
17
|
from codecarbon.core.config import get_hierarchical_config
|
|
18
18
|
from codecarbon.core.emissions import Emissions
|
|
19
19
|
from codecarbon.core.resource_tracker import ResourceTracker
|
|
20
|
-
from codecarbon.core.units import Energy, Power, Time
|
|
20
|
+
from codecarbon.core.units import Energy, Power, Time, Water
|
|
21
21
|
from codecarbon.core.util import count_cpus, count_physical_cpus, suppress
|
|
22
22
|
from codecarbon.external.geography import CloudMetadata, GeoMetadata
|
|
23
23
|
from codecarbon.external.hardware import CPU, GPU, AppleSiliconChip
|
|
@@ -179,6 +179,7 @@ class BaseEmissionsTracker(ABC):
|
|
|
179
179
|
force_cpu_power: Optional[int] = _sentinel,
|
|
180
180
|
force_ram_power: Optional[int] = _sentinel,
|
|
181
181
|
pue: Optional[int] = _sentinel,
|
|
182
|
+
wue: Optional[bool] = _sentinel,
|
|
182
183
|
force_mode_cpu_load: Optional[bool] = _sentinel,
|
|
183
184
|
allow_multiple_runs: Optional[bool] = _sentinel,
|
|
184
185
|
):
|
|
@@ -238,6 +239,7 @@ class BaseEmissionsTracker(ABC):
|
|
|
238
239
|
:param pue: PUE (Power Usage Effectiveness) of the datacenter.
|
|
239
240
|
:param force_mode_cpu_load: Force the addition of a CPU in MODE_CPU_LOAD
|
|
240
241
|
:param allow_multiple_runs: Allow multiple instances of codecarbon running in parallel. Defaults to False.
|
|
242
|
+
:param wue: WUE (Water Usage Effectiveness) of the datacenter, L/kWh.
|
|
241
243
|
"""
|
|
242
244
|
|
|
243
245
|
# logger.info("base tracker init")
|
|
@@ -287,6 +289,7 @@ class BaseEmissionsTracker(ABC):
|
|
|
287
289
|
self._set_from_conf(force_cpu_power, "force_cpu_power", None, float)
|
|
288
290
|
self._set_from_conf(force_ram_power, "force_ram_power", None, float)
|
|
289
291
|
self._set_from_conf(pue, "pue", 1.0, float)
|
|
292
|
+
self._set_from_conf(wue, "wue", 0, float)
|
|
290
293
|
self._set_from_conf(force_mode_cpu_load, "force_mode_cpu_load", False, bool)
|
|
291
294
|
self._set_from_conf(
|
|
292
295
|
experiment_id, "experiment_id", "5b0fa12a-3dd7-45bb-9766-cc326314d9f1"
|
|
@@ -299,6 +302,7 @@ class BaseEmissionsTracker(ABC):
|
|
|
299
302
|
self._start_time: Optional[float] = None
|
|
300
303
|
self._last_measured_time: float = time.perf_counter()
|
|
301
304
|
self._total_energy: Energy = Energy.from_energy(kWh=0)
|
|
305
|
+
self._total_water: Water = Water.from_litres(litres=0)
|
|
302
306
|
self._total_cpu_energy: Energy = Energy.from_energy(kWh=0)
|
|
303
307
|
self._total_gpu_energy: Energy = Energy.from_energy(kWh=0)
|
|
304
308
|
self._total_ram_energy: Energy = Energy.from_energy(kWh=0)
|
|
@@ -703,6 +707,7 @@ class BaseEmissionsTracker(ABC):
|
|
|
703
707
|
gpu_energy=self._total_gpu_energy.kWh,
|
|
704
708
|
ram_energy=self._total_ram_energy.kWh,
|
|
705
709
|
energy_consumed=self._total_energy.kWh,
|
|
710
|
+
water_consumed=self._total_water.litres,
|
|
706
711
|
country_name=country_name,
|
|
707
712
|
country_iso_code=country_iso_code,
|
|
708
713
|
region=region,
|
|
@@ -721,6 +726,7 @@ class BaseEmissionsTracker(ABC):
|
|
|
721
726
|
ram_total_size=self._conf.get("ram_total_size"),
|
|
722
727
|
tracking_mode=self._conf.get("tracking_mode"),
|
|
723
728
|
pue=self._pue,
|
|
729
|
+
wue=self._wue,
|
|
724
730
|
)
|
|
725
731
|
logger.debug(total_emissions)
|
|
726
732
|
return total_emissions
|
|
@@ -778,7 +784,9 @@ class BaseEmissionsTracker(ABC):
|
|
|
778
784
|
) = hardware.measure_power_and_energy(last_duration=last_duration)
|
|
779
785
|
# Apply the PUE of the datacenter to the consumed energy
|
|
780
786
|
energy *= self._pue
|
|
787
|
+
water = Water.from_litres(litres=self._wue * energy.kWh)
|
|
781
788
|
self._total_energy += energy
|
|
789
|
+
self._total_water += water
|
|
782
790
|
if isinstance(hardware, CPU):
|
|
783
791
|
self._total_cpu_energy += energy
|
|
784
792
|
self._cpu_power = power
|
|
@@ -825,7 +833,7 @@ class BaseEmissionsTracker(ABC):
|
|
|
825
833
|
f"Done measure for {hardware.__class__.__name__} - measurement time: {h_time:,.4f} s - last call {last_duration:,.2f} s"
|
|
826
834
|
)
|
|
827
835
|
logger.info(
|
|
828
|
-
f"{self._total_energy.kWh:.6f} kWh of electricity used since the beginning."
|
|
836
|
+
f"{self._total_energy.kWh:.6f} kWh of electricity and {self._total_water.litres:.6f} L of water were used since the beginning."
|
|
829
837
|
)
|
|
830
838
|
|
|
831
839
|
def _measure_power_and_energy(self) -> None:
|
|
@@ -843,7 +851,11 @@ class BaseEmissionsTracker(ABC):
|
|
|
843
851
|
raise e
|
|
844
852
|
|
|
845
853
|
warning_duration = self._measure_power_secs * 3
|
|
846
|
-
if
|
|
854
|
+
if (
|
|
855
|
+
last_duration > warning_duration
|
|
856
|
+
and self._scheduler
|
|
857
|
+
and not self._scheduler._stopped
|
|
858
|
+
):
|
|
847
859
|
warn_msg = (
|
|
848
860
|
"Background scheduler didn't run for a long period"
|
|
849
861
|
+ " (%ds), results might be inaccurate"
|
|
@@ -1066,6 +1078,7 @@ def track_emissions(
|
|
|
1066
1078
|
force_cpu_power: Optional[int] = _sentinel,
|
|
1067
1079
|
force_ram_power: Optional[int] = _sentinel,
|
|
1068
1080
|
pue: Optional[int] = _sentinel,
|
|
1081
|
+
wue: Optional[float] = _sentinel,
|
|
1069
1082
|
allow_multiple_runs: Optional[bool] = _sentinel,
|
|
1070
1083
|
):
|
|
1071
1084
|
"""
|
|
@@ -1141,6 +1154,7 @@ def track_emissions(
|
|
|
1141
1154
|
:param force_cpu_power: cpu power to be used instead of automatic detection.
|
|
1142
1155
|
:param force_ram_power: ram power to be used instead of automatic detection.
|
|
1143
1156
|
:param pue: PUE (Power Usage Effectiveness) of the datacenter.
|
|
1157
|
+
:param wue: WUE (Water Usage Effectiveness) of the datacenter, L/kWh.
|
|
1144
1158
|
:param allow_multiple_runs: Prevent multiple instances of codecarbon running. Defaults to False.
|
|
1145
1159
|
|
|
1146
1160
|
:return: The decorated function
|
|
@@ -1181,6 +1195,7 @@ def track_emissions(
|
|
|
1181
1195
|
force_cpu_power=force_cpu_power,
|
|
1182
1196
|
force_ram_power=force_ram_power,
|
|
1183
1197
|
pue=pue,
|
|
1198
|
+
wue=wue,
|
|
1184
1199
|
allow_multiple_runs=allow_multiple_runs,
|
|
1185
1200
|
)
|
|
1186
1201
|
else:
|
|
@@ -1212,6 +1227,7 @@ def track_emissions(
|
|
|
1212
1227
|
force_cpu_power=force_cpu_power,
|
|
1213
1228
|
force_ram_power=force_ram_power,
|
|
1214
1229
|
pue=pue,
|
|
1230
|
+
wue=wue,
|
|
1215
1231
|
allow_multiple_runs=allow_multiple_runs,
|
|
1216
1232
|
)
|
|
1217
1233
|
tracker.start()
|
|
@@ -34,6 +34,7 @@ class Task:
|
|
|
34
34
|
gpu_energy=self.emissions_data.gpu_energy,
|
|
35
35
|
ram_energy=self.emissions_data.ram_energy,
|
|
36
36
|
energy_consumed=self.emissions_data.energy_consumed,
|
|
37
|
+
water_consumed=self.emissions_data.water_consumed,
|
|
37
38
|
country_name=self.emissions_data.country_name,
|
|
38
39
|
country_iso_code=self.emissions_data.country_iso_code,
|
|
39
40
|
region=self.emissions_data.region,
|
|
@@ -23,6 +23,7 @@ class EmissionsData:
|
|
|
23
23
|
gpu_energy: float
|
|
24
24
|
ram_energy: float
|
|
25
25
|
energy_consumed: float
|
|
26
|
+
water_consumed: float
|
|
26
27
|
country_name: str
|
|
27
28
|
country_iso_code: str
|
|
28
29
|
region: str
|
|
@@ -41,6 +42,7 @@ class EmissionsData:
|
|
|
41
42
|
tracking_mode: str
|
|
42
43
|
on_cloud: str = "N"
|
|
43
44
|
pue: float = 1
|
|
45
|
+
wue: float = 0
|
|
44
46
|
|
|
45
47
|
@property
|
|
46
48
|
def values(self) -> OrderedDict:
|
|
@@ -55,6 +57,7 @@ class EmissionsData:
|
|
|
55
57
|
self.gpu_energy -= previous_emission.gpu_energy
|
|
56
58
|
self.ram_energy -= previous_emission.ram_energy
|
|
57
59
|
self.energy_consumed -= previous_emission.energy_consumed
|
|
60
|
+
self.water_consumed -= previous_emission.water_consumed
|
|
58
61
|
if delta_duration > 0:
|
|
59
62
|
# emissions_rate in g/s : delta_emissions in kg.CO2 / delta_duration in s
|
|
60
63
|
self.emissions_rate = delta_emissions / delta_duration
|
|
@@ -81,6 +84,7 @@ class TaskEmissionsData:
|
|
|
81
84
|
gpu_energy: float
|
|
82
85
|
ram_energy: float
|
|
83
86
|
energy_consumed: float
|
|
87
|
+
water_consumed: float
|
|
84
88
|
country_name: str
|
|
85
89
|
country_iso_code: str
|
|
86
90
|
region: str
|
|
@@ -162,7 +162,7 @@ docs = "cd docs/edit && make docs"
|
|
|
162
162
|
carbonboard = "python codecarbon/viz/carbonboard.py"
|
|
163
163
|
|
|
164
164
|
[tool.bumpver]
|
|
165
|
-
current_version = "3.0.
|
|
165
|
+
current_version = "3.0.8"
|
|
166
166
|
version_pattern = "MAJOR.MINOR.PATCH[_TAGNUM]"
|
|
167
167
|
|
|
168
168
|
[tool.bumpver.file_patterns]
|
|
@@ -172,3 +172,6 @@ version_pattern = "MAJOR.MINOR.PATCH[_TAGNUM]"
|
|
|
172
172
|
"docs/edit/conf.py" = [
|
|
173
173
|
'^release = "{version}"$',
|
|
174
174
|
]
|
|
175
|
+
|
|
176
|
+
[tool.pytest.ini_options]
|
|
177
|
+
pythonpath = "."
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import os
|
|
2
2
|
import shutil
|
|
3
|
+
import sys
|
|
3
4
|
import tempfile
|
|
4
5
|
import time
|
|
5
6
|
import unittest
|
|
@@ -37,6 +38,16 @@ def heavy_computation(run_time_secs: float = 3):
|
|
|
37
38
|
empty_conf = "[codecarbon]"
|
|
38
39
|
|
|
39
40
|
|
|
41
|
+
if sys.platform == "darwin":
|
|
42
|
+
mock_platform_cli_setup = mock.patch(
|
|
43
|
+
"codecarbon.core.powermetrics.ApplePowermetrics._setup_cli"
|
|
44
|
+
)
|
|
45
|
+
else:
|
|
46
|
+
mock_platform_cli_setup = mock.patch(
|
|
47
|
+
"codecarbon.core.cpu.IntelPowerGadget._setup_cli"
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
|
|
40
51
|
@mock.patch("codecarbon.core.gpu.pynvml", fake_pynvml)
|
|
41
52
|
@mock.patch("codecarbon.core.gpu.is_gpu_details_available", return_value=True)
|
|
42
53
|
@mock.patch(
|
|
@@ -48,7 +59,7 @@ empty_conf = "[codecarbon]"
|
|
|
48
59
|
return_value=CloudMetadata(provider=None, region=None),
|
|
49
60
|
)
|
|
50
61
|
@mock.patch("codecarbon.core.cpu.IntelPowerGadget._log_values")
|
|
51
|
-
@
|
|
62
|
+
@mock_platform_cli_setup
|
|
52
63
|
class TestCarbonTracker(unittest.TestCase):
|
|
53
64
|
def setUp(self) -> None:
|
|
54
65
|
fake_pynvml.DETAILS = TWO_GPU_DETAILS_RESPONSE_HANDLES
|
|
@@ -73,7 +84,7 @@ class TestCarbonTracker(unittest.TestCase):
|
|
|
73
84
|
@responses.activate
|
|
74
85
|
def test_carbon_tracker_TWO_GPU_PRIVATE_INFRA_CANADA(
|
|
75
86
|
self,
|
|
76
|
-
|
|
87
|
+
mock_cli_setup,
|
|
77
88
|
mock_log_values,
|
|
78
89
|
mocked_get_gpu_details,
|
|
79
90
|
mocked_env_cloud_details,
|
|
@@ -89,7 +100,7 @@ class TestCarbonTracker(unittest.TestCase):
|
|
|
89
100
|
tracker = EmissionsTracker(measure_power_secs=1, save_to_file=False)
|
|
90
101
|
# WHEN
|
|
91
102
|
tracker.start()
|
|
92
|
-
heavy_computation()
|
|
103
|
+
heavy_computation(run_time_secs=5)
|
|
93
104
|
emissions = tracker.stop()
|
|
94
105
|
|
|
95
106
|
# THEN
|
|
@@ -108,7 +119,7 @@ class TestCarbonTracker(unittest.TestCase):
|
|
|
108
119
|
def test_carbon_tracker_timeout(
|
|
109
120
|
self,
|
|
110
121
|
mocked_requests_get,
|
|
111
|
-
|
|
122
|
+
mock_cli_setup,
|
|
112
123
|
mock_log_values,
|
|
113
124
|
mocked_get_gpu_details,
|
|
114
125
|
mocked_env_cloud_details,
|
|
@@ -135,7 +146,7 @@ class TestCarbonTracker(unittest.TestCase):
|
|
|
135
146
|
|
|
136
147
|
def test_graceful_start_failure(
|
|
137
148
|
self,
|
|
138
|
-
|
|
149
|
+
mock_cli_setup,
|
|
139
150
|
mock_log_values,
|
|
140
151
|
mocked_get_gpu_details,
|
|
141
152
|
mocked_env_cloud_details,
|
|
@@ -153,7 +164,7 @@ class TestCarbonTracker(unittest.TestCase):
|
|
|
153
164
|
|
|
154
165
|
def test_graceful_stop_failure(
|
|
155
166
|
self,
|
|
156
|
-
|
|
167
|
+
mock_cli_setup,
|
|
157
168
|
mock_log_values,
|
|
158
169
|
mocked_get_gpu_details,
|
|
159
170
|
mocked_env_cloud_details,
|
|
@@ -172,7 +183,7 @@ class TestCarbonTracker(unittest.TestCase):
|
|
|
172
183
|
@responses.activate
|
|
173
184
|
def test_decorator_ONLINE_NO_ARGS(
|
|
174
185
|
self,
|
|
175
|
-
|
|
186
|
+
mock_cli_setup,
|
|
176
187
|
mock_log_values,
|
|
177
188
|
mocked_get_gpu_details,
|
|
178
189
|
mocked_env_cloud_details,
|
|
@@ -199,7 +210,7 @@ class TestCarbonTracker(unittest.TestCase):
|
|
|
199
210
|
@responses.activate
|
|
200
211
|
def test_decorator_ONLINE_WITH_ARGS(
|
|
201
212
|
self,
|
|
202
|
-
|
|
213
|
+
mock_cli_setup,
|
|
203
214
|
mock_log_values,
|
|
204
215
|
mocked_get_gpu_details,
|
|
205
216
|
mocked_env_cloud_details,
|
|
@@ -225,7 +236,7 @@ class TestCarbonTracker(unittest.TestCase):
|
|
|
225
236
|
|
|
226
237
|
def test_decorator_OFFLINE_NO_COUNTRY(
|
|
227
238
|
self,
|
|
228
|
-
|
|
239
|
+
mock_cli_setup,
|
|
229
240
|
mock_log_values,
|
|
230
241
|
mocked_get_gpu_details,
|
|
231
242
|
mocked_env_cloud_details,
|
|
@@ -241,7 +252,7 @@ class TestCarbonTracker(unittest.TestCase):
|
|
|
241
252
|
|
|
242
253
|
def test_decorator_OFFLINE_WITH_LOC_ARGS(
|
|
243
254
|
self,
|
|
244
|
-
|
|
255
|
+
mock_cli_setup,
|
|
245
256
|
mock_log_values,
|
|
246
257
|
mocked_get_gpu_details,
|
|
247
258
|
mocked_env_cloud_details,
|
|
@@ -264,7 +275,7 @@ class TestCarbonTracker(unittest.TestCase):
|
|
|
264
275
|
|
|
265
276
|
def test_decorator_OFFLINE_WITH_CLOUD_ARGS(
|
|
266
277
|
self,
|
|
267
|
-
|
|
278
|
+
mock_cli_setup,
|
|
268
279
|
mock_log_values,
|
|
269
280
|
mocked_get_gpu_details,
|
|
270
281
|
mocked_env_cloud_details,
|
|
@@ -287,7 +298,7 @@ class TestCarbonTracker(unittest.TestCase):
|
|
|
287
298
|
|
|
288
299
|
def test_offline_tracker_country_name(
|
|
289
300
|
self,
|
|
290
|
-
|
|
301
|
+
mock_cli_setup,
|
|
291
302
|
mock_log_values,
|
|
292
303
|
mocked_get_gpu_details,
|
|
293
304
|
mocked_env_cloud_details,
|
|
@@ -309,7 +320,7 @@ class TestCarbonTracker(unittest.TestCase):
|
|
|
309
320
|
|
|
310
321
|
def test_offline_tracker_invalid_headers(
|
|
311
322
|
self,
|
|
312
|
-
|
|
323
|
+
mock_cli_setup,
|
|
313
324
|
mock_log_values,
|
|
314
325
|
mocked_get_gpu_details,
|
|
315
326
|
mocked_env_cloud_details,
|
|
@@ -341,7 +352,7 @@ class TestCarbonTracker(unittest.TestCase):
|
|
|
341
352
|
|
|
342
353
|
def test_offline_tracker_valid_headers(
|
|
343
354
|
self,
|
|
344
|
-
|
|
355
|
+
mock_cli_setup,
|
|
345
356
|
mock_log_values,
|
|
346
357
|
mocked_get_gpu_details,
|
|
347
358
|
mocked_env_cloud_details,
|
|
@@ -378,7 +389,7 @@ class TestCarbonTracker(unittest.TestCase):
|
|
|
378
389
|
@responses.activate
|
|
379
390
|
def test_carbon_tracker_online_context_manager_TWO_GPU_PRIVATE_INFRA_CANADA(
|
|
380
391
|
self,
|
|
381
|
-
|
|
392
|
+
mock_cli_setup,
|
|
382
393
|
mock_log_values,
|
|
383
394
|
mocked_get_gpu_details,
|
|
384
395
|
mocked_env_cloud_details,
|
|
@@ -394,7 +405,7 @@ class TestCarbonTracker(unittest.TestCase):
|
|
|
394
405
|
|
|
395
406
|
# WHEN
|
|
396
407
|
with EmissionsTracker(measure_power_secs=1, save_to_file=False) as tracker:
|
|
397
|
-
heavy_computation()
|
|
408
|
+
heavy_computation(run_time_secs=5)
|
|
398
409
|
|
|
399
410
|
# THEN
|
|
400
411
|
self.assertGreaterEqual(
|
|
@@ -408,17 +419,18 @@ class TestCarbonTracker(unittest.TestCase):
|
|
|
408
419
|
self.assertIsInstance(tracker.final_emissions, float)
|
|
409
420
|
self.assertAlmostEqual(tracker.final_emissions, 6.262572537957655e-05, places=2)
|
|
410
421
|
|
|
422
|
+
@mock.patch("codecarbon.external.ram.RAM.measure_power_and_energy")
|
|
423
|
+
@mock.patch("codecarbon.external.hardware.CPU.measure_power_and_energy")
|
|
411
424
|
@mock.patch(
|
|
412
|
-
"codecarbon.external.
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
"codecarbon.external.hardware.CPU.measure_power_and_energy"
|
|
416
|
-
) # Path for CPU is likely correct
|
|
425
|
+
"codecarbon.external.hardware.AppleSiliconChip.measure_power_and_energy",
|
|
426
|
+
autospec=True,
|
|
427
|
+
)
|
|
417
428
|
def test_task_energy_with_live_update_interference(
|
|
418
429
|
self,
|
|
430
|
+
mock_apple_silicon_measure,
|
|
419
431
|
mock_cpu_measure, # Method decorator (innermost)
|
|
420
432
|
mock_ram_measure, # Method decorator (outermost)
|
|
421
|
-
|
|
433
|
+
mock_cli_setup, # Class decorator (innermost)
|
|
422
434
|
mock_log_values, # Class decorator
|
|
423
435
|
mocked_env_cloud_details, # Class decorator
|
|
424
436
|
mocked_get_gpu_details, # Class decorator
|
|
@@ -428,6 +440,19 @@ class TestCarbonTracker(unittest.TestCase):
|
|
|
428
440
|
# Configure mocks to return specific, non-zero energy values
|
|
429
441
|
cpu_energy_val_task = 0.0001
|
|
430
442
|
ram_energy_val_task = 0.00005
|
|
443
|
+
|
|
444
|
+
# On a Mac, AppleSiliconChip.measure_power_and_energy is called for both CPUs and GPU
|
|
445
|
+
# so we need to check which it is before returning a value.
|
|
446
|
+
# We chose to return 0 for a GPU to be consistent when testing on Intel.
|
|
447
|
+
def apple_silicon_side_effect(hardware, *args, **kwargs):
|
|
448
|
+
if hardware.chip_part == "CPU":
|
|
449
|
+
return (
|
|
450
|
+
Power.from_watts(10),
|
|
451
|
+
Energy.from_energy(kWh=cpu_energy_val_task),
|
|
452
|
+
)
|
|
453
|
+
return (Power.from_watts(0), Energy.from_energy(kWh=0))
|
|
454
|
+
|
|
455
|
+
mock_apple_silicon_measure.side_effect = apple_silicon_side_effect
|
|
431
456
|
mock_cpu_measure.return_value = (
|
|
432
457
|
Power.from_watts(10),
|
|
433
458
|
Energy.from_energy(kWh=cpu_energy_val_task),
|
|
@@ -497,14 +522,18 @@ class TestCarbonTracker(unittest.TestCase):
|
|
|
497
522
|
)
|
|
498
523
|
|
|
499
524
|
# Verify mocks were called as expected
|
|
500
|
-
# They are called
|
|
501
|
-
|
|
525
|
+
# They are called from within _measure_power_and_energy inside stop_task.
|
|
526
|
+
# As noted above, mock_apple_silicon_measure is called twice on a Mac, once for CPU and once for GPU.
|
|
527
|
+
assert (
|
|
528
|
+
mock_cpu_measure.call_count == 1
|
|
529
|
+
or mock_apple_silicon_measure.call_count == 2
|
|
530
|
+
)
|
|
502
531
|
mock_ram_measure.assert_called_once()
|
|
503
532
|
|
|
504
533
|
@responses.activate
|
|
505
534
|
def test_carbon_tracker_offline_context_manager(
|
|
506
535
|
self,
|
|
507
|
-
|
|
536
|
+
mock_cli_setup,
|
|
508
537
|
mock_log_values,
|
|
509
538
|
mocked_get_gpu_details,
|
|
510
539
|
mocked_env_cloud_details,
|
|
@@ -525,7 +554,7 @@ class TestCarbonTracker(unittest.TestCase):
|
|
|
525
554
|
def test_scheduler_warning_suppressed_when_stopped(
|
|
526
555
|
self,
|
|
527
556
|
mock_logger,
|
|
528
|
-
|
|
557
|
+
mock_cli_setup,
|
|
529
558
|
mock_log_values,
|
|
530
559
|
mocked_get_gpu_details,
|
|
531
560
|
mocked_env_cloud_details,
|
|
@@ -567,7 +596,7 @@ class TestCarbonTracker(unittest.TestCase):
|
|
|
567
596
|
def test_scheduler_warning_shown_when_running(
|
|
568
597
|
self,
|
|
569
598
|
mock_logger,
|
|
570
|
-
|
|
599
|
+
mock_cli_setup,
|
|
571
600
|
mock_log_values,
|
|
572
601
|
mocked_get_gpu_details,
|
|
573
602
|
mocked_env_cloud_details,
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "3.0.7"
|
|
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
|
{codecarbon-3.0.7 → codecarbon-3.0.8}/codecarbon/data/private_infra/2023/canada_energy_mix.json
RENAMED
|
File without changes
|
{codecarbon-3.0.7 → codecarbon-3.0.8}/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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|