codecarbon 2.3.0__tar.gz → 2.3.2__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 (108) hide show
  1. {codecarbon-2.3.0 → codecarbon-2.3.2}/LICENSE +3 -2
  2. {codecarbon-2.3.0/codecarbon.egg-info → codecarbon-2.3.2}/PKG-INFO +19 -3
  3. {codecarbon-2.3.0 → codecarbon-2.3.2}/README.md +2 -1
  4. codecarbon-2.3.2/codecarbon/_version.py +1 -0
  5. {codecarbon-2.3.0 → codecarbon-2.3.2}/codecarbon/core/cloud.py +0 -21
  6. {codecarbon-2.3.0 → codecarbon-2.3.2}/codecarbon/core/gpu.py +0 -22
  7. {codecarbon-2.3.0 → codecarbon-2.3.2}/codecarbon/core/util.py +15 -5
  8. {codecarbon-2.3.0 → codecarbon-2.3.2}/codecarbon/data/hardware/cpu_power.csv +2 -0
  9. {codecarbon-2.3.0 → codecarbon-2.3.2}/codecarbon/emissions_tracker.py +4 -3
  10. {codecarbon-2.3.0 → codecarbon-2.3.2}/codecarbon/external/hardware.py +45 -14
  11. {codecarbon-2.3.0 → codecarbon-2.3.2}/codecarbon/external/scheduler.py +5 -4
  12. {codecarbon-2.3.0 → codecarbon-2.3.2}/codecarbon/prometheus/metric_definitions.py +13 -3
  13. codecarbon-2.3.2/codecarbon/prometheus/prometheus.py +75 -0
  14. {codecarbon-2.3.0 → codecarbon-2.3.2}/codecarbon/viz/components.py +14 -9
  15. {codecarbon-2.3.0 → codecarbon-2.3.2/codecarbon.egg-info}/PKG-INFO +19 -3
  16. {codecarbon-2.3.0 → codecarbon-2.3.2}/setup.py +1 -1
  17. codecarbon-2.3.2/tests/test_ram.py +84 -0
  18. codecarbon-2.3.0/codecarbon/_version.py +0 -1
  19. codecarbon-2.3.0/codecarbon/prometheus/prometheus.py +0 -55
  20. codecarbon-2.3.0/tests/test_ram.py +0 -36
  21. {codecarbon-2.3.0 → codecarbon-2.3.2}/carbonserver/__init__.py +0 -0
  22. {codecarbon-2.3.0 → codecarbon-2.3.2}/carbonserver/carbonserver/__init__.py +0 -0
  23. {codecarbon-2.3.0 → codecarbon-2.3.2}/carbonserver/carbonserver/api/__init__.py +0 -0
  24. {codecarbon-2.3.0 → codecarbon-2.3.2}/carbonserver/carbonserver/api/dependencies.py +0 -0
  25. {codecarbon-2.3.0 → codecarbon-2.3.2}/carbonserver/carbonserver/api/domain/__init__.py +0 -0
  26. {codecarbon-2.3.0 → codecarbon-2.3.2}/carbonserver/carbonserver/api/domain/emissions.py +0 -0
  27. {codecarbon-2.3.0 → codecarbon-2.3.2}/carbonserver/carbonserver/api/domain/experiments.py +0 -0
  28. {codecarbon-2.3.0 → codecarbon-2.3.2}/carbonserver/carbonserver/api/domain/organizations.py +0 -0
  29. {codecarbon-2.3.0 → codecarbon-2.3.2}/carbonserver/carbonserver/api/domain/projects.py +0 -0
  30. {codecarbon-2.3.0 → codecarbon-2.3.2}/carbonserver/carbonserver/api/domain/runs.py +0 -0
  31. {codecarbon-2.3.0 → codecarbon-2.3.2}/carbonserver/carbonserver/api/domain/teams.py +0 -0
  32. {codecarbon-2.3.0 → codecarbon-2.3.2}/carbonserver/carbonserver/api/domain/users.py +0 -0
  33. {codecarbon-2.3.0 → codecarbon-2.3.2}/carbonserver/carbonserver/api/errors.py +0 -0
  34. {codecarbon-2.3.0 → codecarbon-2.3.2}/carbonserver/carbonserver/api/routers/__init__.py +0 -0
  35. {codecarbon-2.3.0 → codecarbon-2.3.2}/carbonserver/carbonserver/api/routers/authenticate.py +0 -0
  36. {codecarbon-2.3.0 → codecarbon-2.3.2}/carbonserver/carbonserver/api/routers/emissions.py +0 -0
  37. {codecarbon-2.3.0 → codecarbon-2.3.2}/carbonserver/carbonserver/api/routers/experiments.py +0 -0
  38. {codecarbon-2.3.0 → codecarbon-2.3.2}/carbonserver/carbonserver/api/routers/organizations.py +0 -0
  39. {codecarbon-2.3.0 → codecarbon-2.3.2}/carbonserver/carbonserver/api/routers/projects.py +0 -0
  40. {codecarbon-2.3.0 → codecarbon-2.3.2}/carbonserver/carbonserver/api/routers/runs.py +0 -0
  41. {codecarbon-2.3.0 → codecarbon-2.3.2}/carbonserver/carbonserver/api/routers/teams.py +0 -0
  42. {codecarbon-2.3.0 → codecarbon-2.3.2}/carbonserver/carbonserver/api/routers/users.py +0 -0
  43. {codecarbon-2.3.0 → codecarbon-2.3.2}/carbonserver/carbonserver/api/schemas.py +0 -0
  44. {codecarbon-2.3.0 → codecarbon-2.3.2}/carbonserver/carbonserver/config.py +0 -0
  45. {codecarbon-2.3.0 → codecarbon-2.3.2}/carbonserver/carbonserver/database/__init__.py +0 -0
  46. {codecarbon-2.3.0 → codecarbon-2.3.2}/carbonserver/carbonserver/database/database.py +0 -0
  47. {codecarbon-2.3.0 → codecarbon-2.3.2}/carbonserver/carbonserver/logger.py +0 -0
  48. {codecarbon-2.3.0 → codecarbon-2.3.2}/carbonserver/container.py +0 -0
  49. {codecarbon-2.3.0 → codecarbon-2.3.2}/carbonserver/main.py +0 -0
  50. {codecarbon-2.3.0 → codecarbon-2.3.2}/carbonserver/setup.py +0 -0
  51. {codecarbon-2.3.0 → codecarbon-2.3.2}/codecarbon/__init__.py +0 -0
  52. {codecarbon-2.3.0 → codecarbon-2.3.2}/codecarbon/cli/__init__.py +0 -0
  53. {codecarbon-2.3.0 → codecarbon-2.3.2}/codecarbon/cli/cli_utils.py +0 -0
  54. {codecarbon-2.3.0 → codecarbon-2.3.2}/codecarbon/cli/main.py +0 -0
  55. {codecarbon-2.3.0 → codecarbon-2.3.2}/codecarbon/core/__init__.py +0 -0
  56. {codecarbon-2.3.0 → codecarbon-2.3.2}/codecarbon/core/api_client.py +0 -0
  57. {codecarbon-2.3.0 → codecarbon-2.3.2}/codecarbon/core/co2_signal.py +0 -0
  58. {codecarbon-2.3.0 → codecarbon-2.3.2}/codecarbon/core/config.py +0 -0
  59. {codecarbon-2.3.0 → codecarbon-2.3.2}/codecarbon/core/cpu.py +0 -0
  60. {codecarbon-2.3.0 → codecarbon-2.3.2}/codecarbon/core/emissions.py +0 -0
  61. {codecarbon-2.3.0 → codecarbon-2.3.2}/codecarbon/core/measure.py +0 -0
  62. {codecarbon-2.3.0 → codecarbon-2.3.2}/codecarbon/core/rapl.py +0 -0
  63. {codecarbon-2.3.0 → codecarbon-2.3.2}/codecarbon/core/schemas.py +0 -0
  64. {codecarbon-2.3.0 → codecarbon-2.3.2}/codecarbon/core/units.py +0 -0
  65. {codecarbon-2.3.0 → codecarbon-2.3.2}/codecarbon/data/cloud/impact.csv +0 -0
  66. {codecarbon-2.3.0 → codecarbon-2.3.2}/codecarbon/data/private_infra/2016/canada_energy_mix.json +0 -0
  67. {codecarbon-2.3.0 → codecarbon-2.3.2}/codecarbon/data/private_infra/2016/usa_emissions.json +0 -0
  68. {codecarbon-2.3.0 → codecarbon-2.3.2}/codecarbon/data/private_infra/carbon_intensity_per_source.json +0 -0
  69. {codecarbon-2.3.0 → codecarbon-2.3.2}/codecarbon/data/private_infra/global_energy_mix.json +0 -0
  70. {codecarbon-2.3.0 → codecarbon-2.3.2}/codecarbon/external/__init__.py +0 -0
  71. {codecarbon-2.3.0 → codecarbon-2.3.2}/codecarbon/external/geography.py +0 -0
  72. {codecarbon-2.3.0 → codecarbon-2.3.2}/codecarbon/external/logger.py +0 -0
  73. {codecarbon-2.3.0 → codecarbon-2.3.2}/codecarbon/external/task.py +0 -0
  74. {codecarbon-2.3.0 → codecarbon-2.3.2}/codecarbon/input.py +0 -0
  75. {codecarbon-2.3.0 → codecarbon-2.3.2}/codecarbon/output.py +0 -0
  76. {codecarbon-2.3.0 → codecarbon-2.3.2}/codecarbon/prometheus/__init__.py +0 -0
  77. {codecarbon-2.3.0 → codecarbon-2.3.2}/codecarbon/viz/__init__.py +0 -0
  78. {codecarbon-2.3.0 → codecarbon-2.3.2}/codecarbon/viz/assets/__init__.py +0 -0
  79. {codecarbon-2.3.0 → codecarbon-2.3.2}/codecarbon/viz/assets/car_icon.png +0 -0
  80. {codecarbon-2.3.0 → codecarbon-2.3.2}/codecarbon/viz/assets/house_icon.png +0 -0
  81. {codecarbon-2.3.0 → codecarbon-2.3.2}/codecarbon/viz/assets/tv_icon.png +0 -0
  82. {codecarbon-2.3.0 → codecarbon-2.3.2}/codecarbon/viz/carbonboard.py +0 -0
  83. {codecarbon-2.3.0 → codecarbon-2.3.2}/codecarbon/viz/carbonboard_on_api.py +0 -0
  84. {codecarbon-2.3.0 → codecarbon-2.3.2}/codecarbon/viz/data.py +0 -0
  85. {codecarbon-2.3.0 → codecarbon-2.3.2}/codecarbon.egg-info/SOURCES.txt +0 -0
  86. {codecarbon-2.3.0 → codecarbon-2.3.2}/codecarbon.egg-info/dependency_links.txt +0 -0
  87. {codecarbon-2.3.0 → codecarbon-2.3.2}/codecarbon.egg-info/entry_points.txt +0 -0
  88. {codecarbon-2.3.0 → codecarbon-2.3.2}/codecarbon.egg-info/requires.txt +0 -0
  89. {codecarbon-2.3.0 → codecarbon-2.3.2}/codecarbon.egg-info/top_level.txt +0 -0
  90. {codecarbon-2.3.0 → codecarbon-2.3.2}/setup.cfg +0 -0
  91. {codecarbon-2.3.0 → codecarbon-2.3.2}/tests/test_api_call.py +0 -0
  92. {codecarbon-2.3.0 → codecarbon-2.3.2}/tests/test_cloud.py +0 -0
  93. {codecarbon-2.3.0 → codecarbon-2.3.2}/tests/test_co2_signal.py +0 -0
  94. {codecarbon-2.3.0 → codecarbon-2.3.2}/tests/test_config.py +0 -0
  95. {codecarbon-2.3.0 → codecarbon-2.3.2}/tests/test_core_util.py +0 -0
  96. {codecarbon-2.3.0 → codecarbon-2.3.2}/tests/test_cpu.py +0 -0
  97. {codecarbon-2.3.0 → codecarbon-2.3.2}/tests/test_emissions.py +0 -0
  98. {codecarbon-2.3.0 → codecarbon-2.3.2}/tests/test_emissions_tracker.py +0 -0
  99. {codecarbon-2.3.0 → codecarbon-2.3.2}/tests/test_emissions_tracker_constant.py +0 -0
  100. {codecarbon-2.3.0 → codecarbon-2.3.2}/tests/test_emissions_tracker_flush.py +0 -0
  101. {codecarbon-2.3.0 → codecarbon-2.3.2}/tests/test_energy.py +0 -0
  102. {codecarbon-2.3.0 → codecarbon-2.3.2}/tests/test_geography.py +0 -0
  103. {codecarbon-2.3.0 → codecarbon-2.3.2}/tests/test_gpu.py +0 -0
  104. {codecarbon-2.3.0 → codecarbon-2.3.2}/tests/test_logging_output.py +0 -0
  105. {codecarbon-2.3.0 → codecarbon-2.3.2}/tests/test_tracking_inference.py +0 -0
  106. {codecarbon-2.3.0 → codecarbon-2.3.2}/tests/test_viz_data.py +0 -0
  107. {codecarbon-2.3.0 → codecarbon-2.3.2}/tests/testdata.py +0 -0
  108. {codecarbon-2.3.0 → codecarbon-2.3.2}/tests/testutils.py +0 -0
@@ -1,6 +1,7 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) [year] [fullname]
3
+ Copyright (c) 2019 Mila, BCG Gamma, CometML, Haverford College
4
+ Copyright (c) 2023 Code Carbon NGO
4
5
 
5
6
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
7
  of this software and associated documentation files (the "Software"), to deal
@@ -18,4 +19,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
19
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
20
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
21
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
22
+ SOFTWARE.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: codecarbon
3
- Version: 2.3.0
3
+ Version: 2.3.2
4
4
  Author: Mila, DataForGood, BCG GAMMA, Comet.ml, Haverford College
5
5
  Classifier: Natural Language :: English
6
6
  Classifier: Programming Language :: Python :: 3.7
@@ -11,9 +11,24 @@ Classifier: Programming Language :: Python :: 3.11
11
11
  Classifier: License :: OSI Approved :: MIT License
12
12
  Requires-Python: >=3.7
13
13
  Description-Content-Type: text/markdown
14
+ License-File: LICENSE
15
+ Requires-Dist: arrow
16
+ Requires-Dist: pandas
17
+ Requires-Dist: pynvml
18
+ Requires-Dist: requests
19
+ Requires-Dist: psutil
20
+ Requires-Dist: py-cpuinfo
21
+ Requires-Dist: fuzzywuzzy
22
+ Requires-Dist: click
23
+ Requires-Dist: prometheus_client
14
24
  Provides-Extra: viz
25
+ Requires-Dist: dash; extra == "viz"
26
+ Requires-Dist: dash_bootstrap_components<1.0.0; extra == "viz"
27
+ Requires-Dist: fire; extra == "viz"
15
28
  Provides-Extra: dashboard
16
- License-File: LICENSE
29
+ Requires-Dist: dash>=2.2.0; extra == "dashboard"
30
+ Requires-Dist: plotly>=5.6.0; extra == "dashboard"
31
+ Requires-Dist: dash_bootstrap_components; extra == "dashboard"
17
32
 
18
33
  ![banner](docs/edit/images/banner.png)
19
34
 
@@ -26,6 +41,7 @@ Estimate and track carbon emissions from your computer, quantify and analyze the
26
41
  [![](https://anaconda.org/conda-forge/codecarbon/badges/version.svg)](https://anaconda.org/conda-forge/codecarbon)
27
42
  [![](https://img.shields.io/pypi/v/codecarbon?color=024758)](https://pypi.org/project/codecarbon/)
28
43
  [![DOI](https://zenodo.org/badge/263364731.svg)](https://zenodo.org/badge/latestdoi/263364731)
44
+ [![Downloads](https://static.pepy.tech/badge/codecarbon/month)](https://pepy.tech/project/codecarbon)
29
45
 
30
46
 
31
47
  - [About CodeCarbon 💡](#about-codecarbon-)
@@ -73,7 +89,7 @@ pip install codecarbon
73
89
  ```python
74
90
  conda install -c conda-forge codecarbon
75
91
  ```
76
- To see more installation options please refer to the documentation : [**Installation**](https://mlco2.github.io/codecarbon/installation.html#)
92
+ To see more installation options please refer to the documentation: [**Installation**](https://mlco2.github.io/codecarbon/installation.html#)
77
93
 
78
94
  ## Start to estimate your impact 📏
79
95
 
@@ -9,6 +9,7 @@ Estimate and track carbon emissions from your computer, quantify and analyze the
9
9
  [![](https://anaconda.org/conda-forge/codecarbon/badges/version.svg)](https://anaconda.org/conda-forge/codecarbon)
10
10
  [![](https://img.shields.io/pypi/v/codecarbon?color=024758)](https://pypi.org/project/codecarbon/)
11
11
  [![DOI](https://zenodo.org/badge/263364731.svg)](https://zenodo.org/badge/latestdoi/263364731)
12
+ [![Downloads](https://static.pepy.tech/badge/codecarbon/month)](https://pepy.tech/project/codecarbon)
12
13
 
13
14
 
14
15
  - [About CodeCarbon 💡](#about-codecarbon-)
@@ -56,7 +57,7 @@ pip install codecarbon
56
57
  ```python
57
58
  conda install -c conda-forge codecarbon
58
59
  ```
59
- To see more installation options please refer to the documentation : [**Installation**](https://mlco2.github.io/codecarbon/installation.html#)
60
+ To see more installation options please refer to the documentation: [**Installation**](https://mlco2.github.io/codecarbon/installation.html#)
60
61
 
61
62
  ## Start to estimate your impact 📏
62
63
 
@@ -0,0 +1 @@
1
+ __version__ = "2.3.2"
@@ -1,24 +1,3 @@
1
- # -*- coding: utf-8 -*-
2
-
3
- # Copyright (C) 2020 [COMET-ML]
4
- #
5
- # Permission is hereby granted, free of charge, to any person obtaining a copy of this
6
- # software and associated documentation files (the "Software"), to deal in the Software
7
- # without restriction, including without limitation the rights to use, copy, modify,
8
- # merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
9
- # permit persons to whom the Software is furnished to do so, subject to the following
10
- # conditions:
11
- #
12
- # The above copyright notice and this permission notice shall be included in all copies
13
- # or substantial portions of the Software.
14
- #
15
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
16
- # INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
17
- # PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
18
- # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
19
- # CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
20
- # OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
-
22
1
  from typing import Any, Dict, Optional
23
2
 
24
3
  import requests
@@ -1,25 +1,3 @@
1
- # -*- coding: utf-8 -*-
2
-
3
- # Copyright (C) 2020 [COMET-ML]
4
- #
5
- # Permission is hereby granted, free of charge, to any person obtaining a copy of this
6
- # software and associated documentation files (the "Software"), to deal in the Software
7
- # without restriction, including without limitation the rights to use, copy, modify,
8
- # merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
9
- # permit persons to whom the Software is furnished to do so, subject to the following
10
- # conditions:
11
- #
12
- # The above copyright notice and this permission notice shall be included in all copies
13
- # or substantial portions of the Software.
14
- #
15
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
16
- # INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
17
- # PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
18
- # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
19
- # CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
20
- # OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
-
22
-
23
1
  from dataclasses import dataclass, field
24
2
 
25
3
  import pynvml
@@ -11,6 +11,11 @@ import psutil
11
11
 
12
12
  from codecarbon.external.logger import logger
13
13
 
14
+ SLURM_JOB_ID = os.environ.get(
15
+ "SLURM_JOB_ID", # default
16
+ os.environ.get("SLURM_JOBID"), # deprecated but may still be used
17
+ )
18
+
14
19
 
15
20
  @contextmanager
16
21
  def suppress(*exceptions):
@@ -75,16 +80,20 @@ def detect_cpu_model() -> str:
75
80
 
76
81
 
77
82
  def count_cpus() -> int:
78
- if os.environ.get("SLURM_JOB_ID") is None:
83
+ if SLURM_JOB_ID is None:
79
84
  return psutil.cpu_count()
80
85
 
81
86
  try:
87
+ logger.debug(
88
+ "SLURM environment detected for job {SLURM_JOB_ID}, running"
89
+ + " `scontrol show job $SLURM_JOB_ID` to count SLURM-available cpus."
90
+ )
82
91
  scontrol = subprocess.check_output(
83
- ["scontrol show job $SLURM_JOBID"], shell=True
92
+ [f"scontrol show job {SLURM_JOB_ID}"], shell=True
84
93
  ).decode()
85
94
  except subprocess.CalledProcessError:
86
95
  logger.warning(
87
- "Error running `scontrol show job $SLURM_JOBID` "
96
+ "Error running `scontrol show job $SLURM_JOB_ID` "
88
97
  + "to count SLURM-available cpus. Using the machine's cpu count."
89
98
  )
90
99
  return psutil.cpu_count()
@@ -93,17 +102,18 @@ def count_cpus() -> int:
93
102
 
94
103
  if len(num_cpus_matches) == 0:
95
104
  logger.warning(
96
- "Could not find NumCPUs= after running `scontrol show job $SLURM_JOBID` "
105
+ "Could not find NumCPUs= after running `scontrol show job $SLURM_JOB_ID` "
97
106
  + "to count SLURM-available cpus. Using the machine's cpu count."
98
107
  )
99
108
  return psutil.cpu_count()
100
109
 
101
110
  if len(num_cpus_matches) > 1:
102
111
  logger.warning(
103
- "Unexpected output after running `scontrol show job $SLURM_JOBID` "
112
+ "Unexpected output after running `scontrol show job $SLURM_JOB_ID` "
104
113
  + "to count SLURM-available cpus. Using the machine's cpu count."
105
114
  )
106
115
  return psutil.cpu_count()
107
116
 
108
117
  num_cpus = num_cpus_matches[0].replace("NumCPUs=", "")
118
+ logger.debug(f"Detected {num_cpus} cpus available on SLURM.")
109
119
  return int(num_cpus)
@@ -1991,8 +1991,10 @@ Intel Xeon E3-1285 v4,95
1991
1991
  Intel Xeon E3-1285 v6,79
1992
1992
  Intel Xeon E3-1290,95
1993
1993
  Intel Xeon E3-1290 v2,87
1994
+ Intel Xeon E5-1603 v3,140
1994
1995
  Intel Xeon E5-1620 v2,130
1995
1996
  Intel Xeon E5-1650 v2,130
1997
+ Intel Xeon E5-1650 v4,140
1996
1998
  Intel Xeon E5-1660 v2,130
1997
1999
  Intel Xeon E5-2403 v2,80
1998
2000
  Intel Xeon E5-2407 v2,80
@@ -433,7 +433,8 @@ class BaseEmissionsTracker(ABC):
433
433
  :return: None
434
434
  """
435
435
  # Stop scheduler as we do not want it to interfere with the task measurement
436
- self._scheduler.stop()
436
+ if self._scheduler:
437
+ self._scheduler.stop()
437
438
 
438
439
  if self._active_task:
439
440
  logger.info("A task is already under measure")
@@ -457,11 +458,11 @@ class BaseEmissionsTracker(ABC):
457
458
  )
458
459
  self._active_task = task_name
459
460
 
460
- def stop_task(self, task_name: str = None) -> float:
461
+ def stop_task(self, task_name: str = None) -> EmissionsData:
461
462
  """
462
463
  Stop tracking a dedicated execution task. Delta energy is computed by task, to isolate its contribution to total
463
464
  emissions.
464
- :return: None
465
+ :return: EmissionsData
465
466
  """
466
467
  task_name = task_name if task_name else self._active_task
467
468
  self._measure_power_and_energy()
@@ -1,8 +1,6 @@
1
1
  """
2
2
  Encapsulates external dependencies to retrieve hardware metadata
3
3
  """
4
-
5
- import os
6
4
  import re
7
5
  import subprocess
8
6
  from abc import ABC, abstractmethod
@@ -14,7 +12,7 @@ import psutil
14
12
  from codecarbon.core.cpu import IntelPowerGadget, IntelRAPL
15
13
  from codecarbon.core.gpu import AllGPUDevices
16
14
  from codecarbon.core.units import Energy, Power, Time
17
- from codecarbon.core.util import detect_cpu_model
15
+ from codecarbon.core.util import SLURM_JOB_ID, detect_cpu_model
18
16
  from codecarbon.external.logger import logger
19
17
 
20
18
  # default W value for a CPU if no model is found in the ref csv
@@ -46,7 +44,7 @@ class BaseHardware(ABC):
46
44
  )
47
45
  return power, energy
48
46
 
49
- def start(self) -> None:
47
+ def start(self) -> None: # noqa B027
50
48
  pass
51
49
 
52
50
 
@@ -168,7 +166,7 @@ class CPU(BaseHardware):
168
166
 
169
167
  power = 0
170
168
  for metric, value in all_cpu_details.items():
171
- # "^Processor Power_\d+\(Watt\)$" for Inter Power Gadget
169
+ # "^Processor Power_\d+\(Watt\)$" for Intel Power Gadget
172
170
  if re.match(r"^Processor Power", metric):
173
171
  power += value
174
172
  logger.debug(f"_get_power_from_cpus - MATCH {metric} : {value}")
@@ -238,6 +236,7 @@ class RAM(BaseHardware):
238
236
  # 3 watts of power for every 8GB of DDR3 or DDR4 memory
239
237
  # https://www.crucial.com/support/articles-faq-memory/how-much-power-does-memory-use
240
238
  power_per_GB = 3 / 8 # W/GB
239
+ memory_size = None
241
240
 
242
241
  def __init__(
243
242
  self,
@@ -273,13 +272,29 @@ class RAM(BaseHardware):
273
272
 
274
273
  def _read_slurm_scontrol(self):
275
274
  try:
276
- return subprocess.check_output(
277
- ["scontrol show job $SLURM_JOBID"], shell=True
278
- ).decode()
275
+ logger.debug(
276
+ "SLURM environment detected, running `scontrol show job $SLURM_JOB_ID`..."
277
+ )
278
+ return (
279
+ subprocess.check_output(
280
+ [f"scontrol show job {SLURM_JOB_ID}"], shell=True
281
+ )
282
+ .decode()
283
+ .strip()
284
+ )
279
285
  except subprocess.CalledProcessError:
280
286
  return
281
287
 
282
288
  def _parse_scontrol_memory_GB(self, mem):
289
+ """
290
+ Parse the memory string (B) returned by scontrol to a float (GB)
291
+
292
+ Args:
293
+ mem (str): Memory string (B) as `[amount][unit]` (e.g. `128G`)
294
+
295
+ Returns:
296
+ float: Memory (GB)
297
+ """
283
298
  nb = int(mem[:-1])
284
299
  unit = mem[-1]
285
300
  if unit == "T":
@@ -292,16 +307,16 @@ class RAM(BaseHardware):
292
307
  return nb / (1000**2)
293
308
 
294
309
  def _parse_scontrol(self, scontrol_str):
295
- mem_matches = re.findall(r"mem=\d+[A-Z]", scontrol_str)
310
+ mem_matches = re.findall(r"AllocTRES=.*?,mem=(\d+[A-Z])", scontrol_str)
296
311
  if len(mem_matches) == 0:
297
312
  logger.warning(
298
- "Could not find mem= after running `scontrol show job $SLURM_JOBID` "
313
+ "Could not find mem= after running `scontrol show job $SLURM_JOB_ID` "
299
314
  + "to count SLURM-available RAM. Using the machine's total RAM."
300
315
  )
301
316
  return psutil.virtual_memory().total / B_TO_GB
302
317
  if len(mem_matches) > 1:
303
318
  logger.warning(
304
- "Unexpected output after running `scontrol show job $SLURM_JOBID` "
319
+ "Unexpected output after running `scontrol show job $SLURM_JOB_ID` "
305
320
  + "to count SLURM-available RAM. Using the machine's total RAM."
306
321
  )
307
322
  return psutil.virtual_memory().total / B_TO_GB
@@ -310,17 +325,27 @@ class RAM(BaseHardware):
310
325
 
311
326
  @property
312
327
  def slurm_memory_GB(self):
328
+ """
329
+ Property to compute the SLURM-available RAM in GigaBytes.
330
+
331
+ Returns:
332
+ float: Memory allocated to the job (GB)
333
+ """
334
+ # Prevent calling scontrol at each mesure
335
+ if self.memory_size:
336
+ return self.memory_size
313
337
  scontrol_str = self._read_slurm_scontrol()
314
338
  if scontrol_str is None:
315
339
  logger.warning(
316
- "Error running `scontrol show job $SLURM_JOBID` "
340
+ "Error running `scontrol show job $SLURM_JOB_ID` "
317
341
  + "to retrieve SLURM-available RAM."
318
342
  + "Using the machine's total RAM."
319
343
  )
320
344
  return psutil.virtual_memory().total / B_TO_GB
321
345
  mem = self._parse_scontrol(scontrol_str)
322
346
  if isinstance(mem, str):
323
- return self._parse_scontrol_memory_GB(mem)
347
+ mem = self._parse_scontrol_memory_GB(mem)
348
+ self.memory_size = mem
324
349
  return mem
325
350
 
326
351
  @property
@@ -338,9 +363,15 @@ class RAM(BaseHardware):
338
363
 
339
364
  @property
340
365
  def machine_memory_GB(self):
366
+ """
367
+ Property to compute the machine's total memory in bytes.
368
+
369
+ Returns:
370
+ float: Total RAM (GB)
371
+ """
341
372
  return (
342
373
  self.slurm_memory_GB
343
- if os.environ.get("SLURM_JOB_ID")
374
+ if SLURM_JOB_ID
344
375
  else psutil.virtual_memory().total / B_TO_GB
345
376
  )
346
377
 
@@ -45,7 +45,8 @@ class PeriodicScheduler:
45
45
  """
46
46
  Stop the scheduler.
47
47
  """
48
- self._lock.acquire()
49
- self._stopped = True
50
- self._timer.cancel()
51
- self._lock.release()
48
+ if not self._stopped:
49
+ self._lock.acquire()
50
+ self._stopped = True
51
+ self._timer.cancel()
52
+ self._lock.release()
@@ -32,50 +32,60 @@ labelnames = [
32
32
  duration_gauge = Gauge(
33
33
  "codecarbon_duration",
34
34
  "Duration from last measure (s)",
35
+ ["project_name"],
35
36
  registry=registry,
36
37
  )
37
38
  emissions_gauge = Gauge(
38
39
  "codecarbon_emissions",
39
40
  "Emissions as CO₂-equivalents [CO₂eq] (kg)",
41
+ ["project_name"],
40
42
  registry=registry,
41
43
  )
42
44
  emissions_rate_gauge = Gauge(
43
45
  "codecarbon_emissions_rate",
44
46
  "Emissions divided per duration (Kg/s)",
47
+ ["project_name"],
45
48
  registry=registry,
46
49
  )
47
50
  cpu_power_gauge = Gauge(
48
51
  "codecarbon_cpu_power",
49
52
  "CPU power (W)",
53
+ ["project_name"],
50
54
  registry=registry,
51
55
  )
52
56
  gpu_power_gauge = Gauge(
53
57
  "codecarbon_gpu_power",
54
58
  "GPU power (W)",
59
+ ["project_name"],
55
60
  registry=registry,
56
61
  )
57
62
  ram_power_gauge = Gauge(
58
63
  "codecarbon_ram_power",
59
64
  "RAM power (W)",
65
+ ["project_name"],
60
66
  registry=registry,
61
67
  )
62
68
  cpu_energy_gauge = Gauge(
63
69
  "codecarbon_cpu_energy",
64
- "Energy used per CPU (kW)",
70
+ "Energy used per CPU (kWh)",
71
+ ["project_name"],
65
72
  registry=registry,
66
73
  )
67
74
  gpu_energy_gauge = Gauge(
68
75
  "codecarbon_gpu_energy",
69
- "Energy used per GPU (kW)",
76
+ "Energy used per GPU (kWh)",
77
+ ["project_name"],
70
78
  registry=registry,
71
79
  )
72
80
  ram_energy_gauge = Gauge(
73
81
  "codecarbon_ram_energy",
74
- "Energy used per RAM (kW)",
82
+ "Energy used per RAM (kWh)",
83
+ ["project_name"],
75
84
  registry=registry,
76
85
  )
77
86
  energy_consumed_gauge = Gauge(
78
87
  "codecarbon_energy_consumed",
79
88
  "Sum of cpu_energy, gpu_energy and ram_energy (kW)",
89
+ ["project_name"],
80
90
  registry=registry,
81
91
  )
@@ -0,0 +1,75 @@
1
+ import os
2
+
3
+ from prometheus_client import push_to_gateway
4
+ from prometheus_client.exposition import basic_auth_handler
5
+
6
+ from codecarbon.prometheus.metric_definitions import (
7
+ cpu_energy_gauge,
8
+ cpu_power_gauge,
9
+ duration_gauge,
10
+ emissions_gauge,
11
+ emissions_rate_gauge,
12
+ energy_consumed_gauge,
13
+ gpu_energy_gauge,
14
+ gpu_power_gauge,
15
+ ram_energy_gauge,
16
+ ram_power_gauge,
17
+ registry,
18
+ )
19
+
20
+
21
+ class Prometheus:
22
+ def __init__(self, prometheus_url):
23
+ self.prometheus_url = prometheus_url
24
+
25
+ def _auth_handler(self, url, method, timeout, headers, data):
26
+ username = os.getenv("PROMETHEUS_USERNAME")
27
+ password = os.getenv("PROMETHEUS_PASSWORD")
28
+ return basic_auth_handler(
29
+ url, method, timeout, headers, data, username, password
30
+ )
31
+
32
+ def add_emission(self, carbon_emission: dict):
33
+ """
34
+ Send emissions data to push gateway
35
+ """
36
+
37
+ # Save the values of the metrics to the local registry
38
+ duration_gauge.labels(carbon_emission["project_name"]).set(
39
+ int(carbon_emission["duration"])
40
+ )
41
+ emissions_gauge.labels(carbon_emission["project_name"]).set(
42
+ carbon_emission["emissions"]
43
+ )
44
+ emissions_rate_gauge.labels(carbon_emission["project_name"]).set(
45
+ carbon_emission["emissions_rate"]
46
+ )
47
+ cpu_power_gauge.labels(carbon_emission["project_name"]).set(
48
+ carbon_emission["cpu_power"]
49
+ )
50
+ gpu_power_gauge.labels(carbon_emission["project_name"]).set(
51
+ carbon_emission["gpu_power"]
52
+ )
53
+ ram_power_gauge.labels(carbon_emission["project_name"]).set(
54
+ carbon_emission["ram_power"]
55
+ )
56
+ cpu_energy_gauge.labels(carbon_emission["project_name"]).set(
57
+ carbon_emission["cpu_energy"]
58
+ )
59
+ gpu_energy_gauge.labels(carbon_emission["project_name"]).set(
60
+ carbon_emission["gpu_energy"]
61
+ )
62
+ ram_energy_gauge.labels(carbon_emission["project_name"]).set(
63
+ carbon_emission["ram_energy"]
64
+ )
65
+ energy_consumed_gauge.labels(carbon_emission["project_name"]).set(
66
+ carbon_emission["energy_consumed"]
67
+ )
68
+
69
+ # Send the new metric values
70
+ push_to_gateway(
71
+ self.prometheus_url,
72
+ job="codecarbon",
73
+ registry=registry,
74
+ handler=self._auth_handler,
75
+ )
@@ -29,15 +29,20 @@ class Components:
29
29
 
30
30
  @staticmethod
31
31
  def get_header():
32
- return dbc.Jumbotron(
33
- [
34
- html.H1("Carbon Footprint", style={"textAlign": "center"}),
35
- html.P(
36
- "Measure Compute Emissions",
37
- style={"textAlign": "center", "paddingLeft": "0.5%"},
38
- className="lead",
39
- ),
40
- ]
32
+ return html.Div(
33
+ dbc.Container(
34
+ [
35
+ html.H1("Carbon Footprint", style={"textAlign": "center"}),
36
+ html.P(
37
+ "Measure Compute Emissions",
38
+ style={"textAlign": "center", "paddingLeft": "0.5%"},
39
+ className="lead",
40
+ ),
41
+ ],
42
+ fluid=True,
43
+ className="py-3",
44
+ ),
45
+ className="p-3 mb-5 bg-light rounded-5",
41
46
  )
42
47
 
43
48
  @staticmethod
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: codecarbon
3
- Version: 2.3.0
3
+ Version: 2.3.2
4
4
  Author: Mila, DataForGood, BCG GAMMA, Comet.ml, Haverford College
5
5
  Classifier: Natural Language :: English
6
6
  Classifier: Programming Language :: Python :: 3.7
@@ -11,9 +11,24 @@ Classifier: Programming Language :: Python :: 3.11
11
11
  Classifier: License :: OSI Approved :: MIT License
12
12
  Requires-Python: >=3.7
13
13
  Description-Content-Type: text/markdown
14
+ License-File: LICENSE
15
+ Requires-Dist: arrow
16
+ Requires-Dist: pandas
17
+ Requires-Dist: pynvml
18
+ Requires-Dist: requests
19
+ Requires-Dist: psutil
20
+ Requires-Dist: py-cpuinfo
21
+ Requires-Dist: fuzzywuzzy
22
+ Requires-Dist: click
23
+ Requires-Dist: prometheus_client
14
24
  Provides-Extra: viz
25
+ Requires-Dist: dash; extra == "viz"
26
+ Requires-Dist: dash_bootstrap_components<1.0.0; extra == "viz"
27
+ Requires-Dist: fire; extra == "viz"
15
28
  Provides-Extra: dashboard
16
- License-File: LICENSE
29
+ Requires-Dist: dash>=2.2.0; extra == "dashboard"
30
+ Requires-Dist: plotly>=5.6.0; extra == "dashboard"
31
+ Requires-Dist: dash_bootstrap_components; extra == "dashboard"
17
32
 
18
33
  ![banner](docs/edit/images/banner.png)
19
34
 
@@ -26,6 +41,7 @@ Estimate and track carbon emissions from your computer, quantify and analyze the
26
41
  [![](https://anaconda.org/conda-forge/codecarbon/badges/version.svg)](https://anaconda.org/conda-forge/codecarbon)
27
42
  [![](https://img.shields.io/pypi/v/codecarbon?color=024758)](https://pypi.org/project/codecarbon/)
28
43
  [![DOI](https://zenodo.org/badge/263364731.svg)](https://zenodo.org/badge/latestdoi/263364731)
44
+ [![Downloads](https://static.pepy.tech/badge/codecarbon/month)](https://pepy.tech/project/codecarbon)
29
45
 
30
46
 
31
47
  - [About CodeCarbon 💡](#about-codecarbon-)
@@ -73,7 +89,7 @@ pip install codecarbon
73
89
  ```python
74
90
  conda install -c conda-forge codecarbon
75
91
  ```
76
- To see more installation options please refer to the documentation : [**Installation**](https://mlco2.github.io/codecarbon/installation.html#)
92
+ To see more installation options please refer to the documentation: [**Installation**](https://mlco2.github.io/codecarbon/installation.html#)
77
93
 
78
94
  ## Start to estimate your impact 📏
79
95
 
@@ -20,7 +20,7 @@ TEST_DEPENDENCIES = ["mock", "pytest", "responses", "tox", "numpy", "requests-mo
20
20
 
21
21
  setuptools.setup(
22
22
  name="codecarbon",
23
- version="2.3.0",
23
+ version="2.3.2",
24
24
  author="Mila, DataForGood, BCG GAMMA, Comet.ml, Haverford College",
25
25
  long_description=long_description,
26
26
  long_description_content_type="text/markdown",
@@ -0,0 +1,84 @@
1
+ import unittest
2
+ from textwrap import dedent
3
+
4
+ import numpy as np
5
+
6
+ from codecarbon.external.hardware import RAM
7
+
8
+ # TODO: need help: test multiprocess case
9
+
10
+
11
+ class TestRAM(unittest.TestCase):
12
+ def test_ram_diff(self):
13
+ ram = RAM(tracking_mode="process")
14
+
15
+ for array_size in [
16
+ # (10, 10), # too small to be noticed
17
+ # (100, 100), # too small to be noticed
18
+ (1000, 1000), # ref for atol
19
+ (10, 1000, 1000),
20
+ (20, 1000, 1000),
21
+ (100, 1000, 1000),
22
+ (200, 1000, 1000),
23
+ (1000, 1000, 1000),
24
+ (2000, 1000, 1000),
25
+ ]:
26
+ with self.subTest(array_size=array_size):
27
+ ref_W = ram.total_power().W
28
+ array = np.ones(array_size, dtype=np.int8)
29
+ new_W = ram.total_power().W
30
+ n_gb = array.nbytes / (1024**3)
31
+ n_gb_W = (new_W - ref_W) / ram.power_per_GB
32
+ is_close = np.isclose(n_gb, n_gb_W, atol=1e-3)
33
+ self.assertTrue(
34
+ is_close,
35
+ msg=f"{array_size}, {n_gb}, {n_gb_W}, {is_close}",
36
+ )
37
+ del array
38
+
39
+ def test_ram_slurm(self):
40
+ scontrol_str = dedent(
41
+ """\
42
+ scontrol show job $SLURM_JOB_ID
43
+ JobId=XXXX JobName=gpu-jupyterhub
44
+ UserId=XXXX GroupId=XXXX MCS_label=N/A
45
+ Priority=255342 Nice=0 Account=puk@v100 QOS=qos_gpu-t3
46
+ JobState=RUNNING Reason=None Dependency=(null)
47
+ Requeue=1 Restarts=0 BatchFlag=1 Reboot=0 ExitCode=0:0
48
+ RunTime=00:33:42 TimeLimit=08:00:00 TimeMin=N/A
49
+ SubmitTime=2023-10-23T10:45:25 EligibleTime=2023-10-23T10:45:25
50
+ AccrueTime=2023-10-23T10:45:25
51
+ StartTime=2023-10-23T10:45:35 EndTime=2023-10-23T18:45:35 Deadline=N/A
52
+ SuspendTime=None SecsPreSuspend=0 LastSchedEval=2023-10-23T10:45:35 Scheduler=Main
53
+ Partition=gpu_p13 AllocNode:Sid=idrsrv12-ib0:500994
54
+ ReqNodeList=(null) ExcNodeList=(null)
55
+ NodeList=r13i5n0
56
+ BatchHost=r13i5n0
57
+ NumNodes=1 NumCPUs=64 NumTasks=1 CPUs/Task=32 ReqB:S:C:T=0:0:*:1
58
+ ReqTRES=cpu=32,mem=128G,node=1,billing=40,gres/gpu=4
59
+ AllocTRES=cpu=64,mem=128G,node=1,billing=40,gres/gpu=4
60
+ Socks/Node=* NtasksPerN:B:S:C=0:0:*:* CoreSpec=*
61
+ MinCPUsNode=32 MinMemoryCPU=4G MinTmpDiskNode=0
62
+ Features=v100-16g DelayBoot=00:00:00
63
+ OverSubscribe=OK Contiguous=0 Licenses=(null) Network=(null)
64
+ Command=(null)
65
+ WorkDir=/linkhome/rech/gendxh01/uei48xr
66
+ StdErr=/linkhome/rech/gendxh01/uei48xr/jupyterhub_slurm.err
67
+ StdIn=/dev/null
68
+ StdOut=/linkhome/rech/gendxh01/uei48xr/jupyterhub_slurm.out
69
+ Power=
70
+ TresPerNode=gres:gpu:4
71
+ """
72
+ )
73
+ ram = RAM(tracking_mode="slurm")
74
+ ram_size = ram._parse_scontrol(scontrol_str)
75
+ self.assertEqual(ram_size, "128G")
76
+ scontrol_str = dedent(
77
+ """\
78
+ ReqTRES=cpu=32,mem=134G,node=1,billing=40,gres/gpu=4
79
+ AllocTRES=cpu=64,mem=42K,node=1,billing=40,gres/gpu=4
80
+ """
81
+ )
82
+ ram = RAM(tracking_mode="slurm")
83
+ ram_size = ram._parse_scontrol(scontrol_str)
84
+ self.assertEqual(ram_size, "42K")
@@ -1 +0,0 @@
1
- __version__ = "2.3.0"
@@ -1,55 +0,0 @@
1
- import os
2
-
3
- from prometheus_client import push_to_gateway
4
- from prometheus_client.exposition import basic_auth_handler
5
-
6
- from codecarbon.prometheus.metric_definitions import (
7
- cpu_energy_gauge,
8
- cpu_power_gauge,
9
- duration_gauge,
10
- emissions_gauge,
11
- emissions_rate_gauge,
12
- energy_consumed_gauge,
13
- gpu_energy_gauge,
14
- gpu_power_gauge,
15
- ram_energy_gauge,
16
- ram_power_gauge,
17
- registry,
18
- )
19
-
20
-
21
- class Prometheus:
22
- def __init__(self, prometheus_url):
23
- self.prometheus_url = prometheus_url
24
-
25
- def _auth_handler(self, url, method, timeout, headers, data):
26
- username = os.getenv("PROMETHEUS_USERNAME")
27
- password = os.getenv("PROMETHEUS_PASSWORD")
28
- return basic_auth_handler(
29
- url, method, timeout, headers, data, username, password
30
- )
31
-
32
- def add_emission(self, carbon_emission: dict):
33
- """
34
- Send emissions data to push gateway
35
- """
36
-
37
- # Save the values of the metrics to the local registry
38
- duration_gauge.set(int(carbon_emission["duration"]))
39
- emissions_gauge.set(carbon_emission["emissions"])
40
- emissions_rate_gauge.set(carbon_emission["emissions_rate"])
41
- cpu_power_gauge.set(carbon_emission["cpu_power"])
42
- gpu_power_gauge.set(carbon_emission["gpu_power"])
43
- ram_power_gauge.set(carbon_emission["ram_power"])
44
- cpu_energy_gauge.set(carbon_emission["cpu_energy"])
45
- gpu_energy_gauge.set(carbon_emission["gpu_energy"])
46
- ram_energy_gauge.set(carbon_emission["ram_energy"])
47
- energy_consumed_gauge.set(carbon_emission["energy_consumed"])
48
-
49
- # Send the new metric values
50
- push_to_gateway(
51
- self.prometheus_url,
52
- job="codecarbon",
53
- registry=registry,
54
- handler=self._auth_handler,
55
- )
@@ -1,36 +0,0 @@
1
- import unittest
2
-
3
- import numpy as np
4
-
5
- from codecarbon.external.hardware import RAM
6
-
7
- # TODO: need help: test multiprocess case
8
-
9
-
10
- class TestRAM(unittest.TestCase):
11
- def test_ram_diff(self):
12
- ram = RAM(tracking_mode="process")
13
-
14
- for array_size in [
15
- # (10, 10), # too small to be noticed
16
- # (100, 100), # too small to be noticed
17
- (1000, 1000), # ref for atol
18
- (10, 1000, 1000),
19
- (20, 1000, 1000),
20
- (100, 1000, 1000),
21
- (200, 1000, 1000),
22
- (1000, 1000, 1000),
23
- (2000, 1000, 1000),
24
- ]:
25
- with self.subTest(array_size=array_size):
26
- ref_W = ram.total_power().W
27
- array = np.ones(array_size, dtype=np.int8)
28
- new_W = ram.total_power().W
29
- n_gb = array.nbytes / (1024**3)
30
- n_gb_W = (new_W - ref_W) / ram.power_per_GB
31
- is_close = np.isclose(n_gb, n_gb_W, atol=1e-3)
32
- self.assertTrue(
33
- is_close,
34
- msg=f"{array_size}, {n_gb}, {n_gb_W}, {is_close}",
35
- )
36
- del array
File without changes
File without changes
File without changes
File without changes