codecarbon 3.2.7__tar.gz → 3.2.9__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {codecarbon-3.2.7 → codecarbon-3.2.9}/PKG-INFO +5 -4
- {codecarbon-3.2.7 → codecarbon-3.2.9}/README.md +2 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/codecarbon/__init__.py +7 -1
- codecarbon-3.2.9/codecarbon/_version.py +1 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/codecarbon/cli/auth.py +13 -6
- {codecarbon-3.2.7 → codecarbon-3.2.9}/codecarbon/cli/main.py +34 -8
- {codecarbon-3.2.7 → codecarbon-3.2.9}/codecarbon/cli/monitor.py +8 -6
- {codecarbon-3.2.7 → codecarbon-3.2.9}/codecarbon/core/api_client.py +7 -5
- {codecarbon-3.2.7 → codecarbon-3.2.9}/codecarbon/core/cpu.py +24 -10
- {codecarbon-3.2.7 → codecarbon-3.2.9}/codecarbon/core/emissions.py +30 -19
- {codecarbon-3.2.7 → codecarbon-3.2.9}/codecarbon/core/gpu.py +17 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/codecarbon/core/gpu_amd.py +7 -2
- {codecarbon-3.2.7 → codecarbon-3.2.9}/codecarbon/core/gpu_device.py +14 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/codecarbon/core/gpu_nvidia.py +6 -1
- codecarbon-3.2.9/codecarbon/core/hardware_cache.py +249 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/codecarbon/core/powermetrics.py +15 -2
- {codecarbon-3.2.7 → codecarbon-3.2.9}/codecarbon/core/resource_tracker.py +71 -25
- {codecarbon-3.2.7 → codecarbon-3.2.9}/codecarbon/core/schemas.py +4 -0
- codecarbon-3.2.9/codecarbon/core/telemetry_client.py +61 -0
- codecarbon-3.2.9/codecarbon/core/telemetry_schemas.py +156 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/codecarbon/core/util.py +2 -1
- {codecarbon-3.2.7 → codecarbon-3.2.9}/codecarbon/emissions_tracker.py +378 -219
- {codecarbon-3.2.7 → codecarbon-3.2.9}/codecarbon/external/hardware.py +21 -5
- {codecarbon-3.2.7 → codecarbon-3.2.9}/codecarbon/external/task.py +1 -1
- {codecarbon-3.2.7 → codecarbon-3.2.9}/codecarbon/input.py +29 -12
- {codecarbon-3.2.7 → codecarbon-3.2.9}/codecarbon/output.py +1 -1
- {codecarbon-3.2.7 → codecarbon-3.2.9}/codecarbon/output_methods/base_output.py +27 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/codecarbon/output_methods/file.py +15 -19
- {codecarbon-3.2.7 → codecarbon-3.2.9}/codecarbon/output_methods/http.py +13 -8
- {codecarbon-3.2.7 → codecarbon-3.2.9}/codecarbon.egg-info/PKG-INFO +5 -4
- {codecarbon-3.2.7 → codecarbon-3.2.9}/codecarbon.egg-info/SOURCES.txt +5 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/codecarbon.egg-info/requires.txt +2 -4
- {codecarbon-3.2.7 → codecarbon-3.2.9}/pyproject.toml +4 -7
- {codecarbon-3.2.7 → codecarbon-3.2.9}/tests/test_api_call.py +9 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/tests/test_config.py +4 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/tests/test_cpu.py +78 -9
- {codecarbon-3.2.7 → codecarbon-3.2.9}/tests/test_cpu_load.py +5 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/tests/test_custom_handler.py +4 -2
- {codecarbon-3.2.7 → codecarbon-3.2.9}/tests/test_emissions.py +72 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/tests/test_emissions_tracker.py +320 -10
- {codecarbon-3.2.7 → codecarbon-3.2.9}/tests/test_emissions_tracker_constant.py +10 -15
- {codecarbon-3.2.7 → codecarbon-3.2.9}/tests/test_gpu.py +7 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/tests/test_gpu_amd.py +73 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/tests/test_gpu_nvidia.py +35 -0
- codecarbon-3.2.9/tests/test_hardware_cache.py +288 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/tests/test_input.py +6 -3
- {codecarbon-3.2.7 → codecarbon-3.2.9}/tests/test_offline_emissions_tracker.py +11 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/tests/test_powermetrics.py +83 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/tests/test_resource_tracker.py +246 -2
- codecarbon-3.2.9/tests/test_telemetry_client.py +104 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/tests/testdata.py +7 -0
- codecarbon-3.2.7/codecarbon/_version.py +0 -1
- {codecarbon-3.2.7 → codecarbon-3.2.9}/LICENSE +0 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/codecarbon/cli/__init__.py +0 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/codecarbon/cli/cli_utils.py +0 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/codecarbon/core/__init__.py +0 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/codecarbon/core/cloud.py +0 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/codecarbon/core/config.py +0 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/codecarbon/core/electricitymaps_api.py +0 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/codecarbon/core/measure.py +0 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/codecarbon/core/rapl.py +0 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/codecarbon/core/units.py +0 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/codecarbon/data/canada_provinces.geojson +0 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/codecarbon/data/cloud/impact.csv +0 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/codecarbon/data/hardware/cpu_dataset_builder/amd_cpu_scrapper.py +0 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/codecarbon/data/hardware/cpu_dataset_builder/intel_cpu_scrapper.py +0 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/codecarbon/data/hardware/cpu_dataset_builder/merge_scrapped_cpu_power.py +0 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/codecarbon/data/hardware/cpu_power.csv +0 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/codecarbon/data/private_infra/2016/usa_emissions.json +0 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/codecarbon/data/private_infra/2023/canada_energy_mix.json +0 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/codecarbon/data/private_infra/carbon_intensity_per_source.json +0 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/codecarbon/data/private_infra/global_energy_mix.json +0 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/codecarbon/data/private_infra/nordic_emissions.json +0 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/codecarbon/external/__init__.py +0 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/codecarbon/external/geography.py +0 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/codecarbon/external/logger.py +0 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/codecarbon/external/ram.py +0 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/codecarbon/external/scheduler.py +0 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/codecarbon/lock.py +0 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/codecarbon/output_methods/__init__.py +0 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/codecarbon/output_methods/boamps/__init__.py +0 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/codecarbon/output_methods/boamps/mapper.py +0 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/codecarbon/output_methods/boamps/models.py +0 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/codecarbon/output_methods/boamps/output.py +0 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/codecarbon/output_methods/emissions_data.py +0 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/codecarbon/output_methods/logger.py +0 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/codecarbon/output_methods/metrics/__init__.py +0 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/codecarbon/output_methods/metrics/logfire.py +0 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/codecarbon/output_methods/metrics/metric_docs.py +0 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/codecarbon/output_methods/metrics/prometheus.py +0 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/codecarbon/py.typed +0 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/codecarbon/viz/__init__.py +0 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/codecarbon/viz/assets/__init__.py +0 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/codecarbon/viz/assets/car_icon.png +0 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/codecarbon/viz/assets/house_icon.png +0 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/codecarbon/viz/assets/tv_icon.png +0 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/codecarbon/viz/carbonboard.py +0 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/codecarbon/viz/carbonboard_on_api.py +0 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/codecarbon/viz/components.py +0 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/codecarbon/viz/data.py +0 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/codecarbon/viz/units.py +0 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/codecarbon.egg-info/dependency_links.txt +0 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/codecarbon.egg-info/entry_points.txt +0 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/codecarbon.egg-info/top_level.txt +0 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/setup.cfg +0 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/tests/test_boamps_output.py +0 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/tests/test_cloud.py +0 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/tests/test_core_util.py +0 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/tests/test_docs_examples.py +0 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/tests/test_electricitymaps_api.py +0 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/tests/test_electricitymaps_backward_compatibility.py +0 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/tests/test_electricitymaps_config_backward_compatibility.py +0 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/tests/test_emissions_tracker_flush.py +0 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/tests/test_energy.py +0 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/tests/test_geography.py +0 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/tests/test_lock.py +0 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/tests/test_logger.py +0 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/tests/test_logging_output.py +0 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/tests/test_package_integrity.py +0 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/tests/test_ram.py +0 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/tests/test_rapl_mmio_scanning.py +0 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/tests/test_rapl_parameters.py +0 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/tests/test_rapl_permissions.py +0 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/tests/test_tracking_inference.py +0 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/tests/test_unsupported_gpu.py +0 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/tests/test_utilization_tracking.py +0 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/tests/test_viz_data.py +0 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/tests/test_viz_units.py +0 -0
- {codecarbon-3.2.7 → codecarbon-3.2.9}/tests/testutils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: codecarbon
|
|
3
|
-
Version: 3.2.
|
|
3
|
+
Version: 3.2.9
|
|
4
4
|
Author: Mila, DataForGood, BCG GAMMA, Comet.ml, Haverford College
|
|
5
5
|
License-Expression: MIT
|
|
6
6
|
Project-URL: Homepage, https://codecarbon.io/
|
|
@@ -20,13 +20,14 @@ Description-Content-Type: text/markdown
|
|
|
20
20
|
License-File: LICENSE
|
|
21
21
|
Requires-Dist: arrow
|
|
22
22
|
Requires-Dist: authlib>=1.2.1
|
|
23
|
+
Requires-Dist: joserfc>=1.0.0
|
|
23
24
|
Requires-Dist: click
|
|
24
25
|
Requires-Dist: pandas>=2.3.3; python_version >= "3.14"
|
|
25
26
|
Requires-Dist: pandas; python_version < "3.14"
|
|
26
27
|
Requires-Dist: prometheus_client
|
|
27
28
|
Requires-Dist: psutil>=6.0.0
|
|
28
29
|
Requires-Dist: py-cpuinfo
|
|
29
|
-
Requires-Dist: pydantic
|
|
30
|
+
Requires-Dist: pydantic<3.0.0,>=2.0.0
|
|
30
31
|
Requires-Dist: nvidia-ml-py
|
|
31
32
|
Requires-Dist: rapidfuzz
|
|
32
33
|
Requires-Dist: requests
|
|
@@ -42,8 +43,6 @@ Provides-Extra: viz-legacy
|
|
|
42
43
|
Requires-Dist: dash; extra == "viz-legacy"
|
|
43
44
|
Requires-Dist: dash_bootstrap_components>1.0.0; extra == "viz-legacy"
|
|
44
45
|
Requires-Dist: fire; extra == "viz-legacy"
|
|
45
|
-
Provides-Extra: amdsmi
|
|
46
|
-
Requires-Dist: amdsmi>=6.0.0; extra == "amdsmi"
|
|
47
46
|
Dynamic: license-file
|
|
48
47
|
|
|
49
48
|

|
|
@@ -124,6 +123,8 @@ Configuration precedence and examples: [configuration guide](https://docs.codeca
|
|
|
124
123
|
|
|
125
124
|
We created a Python package that estimates your hardware electricity power consumption (GPU + CPU + RAM) and we apply to it the carbon intensity of the region where the computing is done.
|
|
126
125
|
|
|
126
|
+
CodeCarbon focuses on the main compute components it can measure or estimate directly: CPU, GPU, and RAM. It does not separately model disk I/O, network transfers, displays, cooling, or other peripherals because those sources are usually much smaller for local code-level experiments and are not exposed through the same low-overhead measurement interfaces.
|
|
127
|
+
|
|
127
128
|

|
|
128
129
|
|
|
129
130
|
We explain more about this calculation in the [**Methodology**](https://docs.codecarbon.io/latest/explanation/methodology/) section of the documentation.
|
|
@@ -76,6 +76,8 @@ Configuration precedence and examples: [configuration guide](https://docs.codeca
|
|
|
76
76
|
|
|
77
77
|
We created a Python package that estimates your hardware electricity power consumption (GPU + CPU + RAM) and we apply to it the carbon intensity of the region where the computing is done.
|
|
78
78
|
|
|
79
|
+
CodeCarbon focuses on the main compute components it can measure or estimate directly: CPU, GPU, and RAM. It does not separately model disk I/O, network transfers, displays, cooling, or other peripherals because those sources are usually much smaller for local code-level experiments and are not exposed through the same low-overhead measurement interfaces.
|
|
80
|
+
|
|
79
81
|

|
|
80
82
|
|
|
81
83
|
We explain more about this calculation in the [**Methodology**](https://docs.codecarbon.io/latest/explanation/methodology/) section of the documentation.
|
|
@@ -8,6 +8,12 @@ from .emissions_tracker import (
|
|
|
8
8
|
OfflineEmissionsTracker,
|
|
9
9
|
track_emissions,
|
|
10
10
|
)
|
|
11
|
+
from .output_methods.base_output import OutputMethod
|
|
11
12
|
|
|
12
|
-
__all__ = [
|
|
13
|
+
__all__ = [
|
|
14
|
+
"EmissionsTracker",
|
|
15
|
+
"OfflineEmissionsTracker",
|
|
16
|
+
"OutputMethod",
|
|
17
|
+
"track_emissions",
|
|
18
|
+
]
|
|
13
19
|
__app_name__ = "codecarbon"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "3.2.9"
|
|
@@ -6,6 +6,7 @@ PKCE), credential storage, JWKS validation, and transparent refresh.
|
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
8
|
import json
|
|
9
|
+
import logging
|
|
9
10
|
import os
|
|
10
11
|
import webbrowser
|
|
11
12
|
from http.server import BaseHTTPRequestHandler, HTTPServer
|
|
@@ -15,9 +16,9 @@ from urllib.parse import parse_qs, urlparse
|
|
|
15
16
|
import requests
|
|
16
17
|
from authlib.common.security import generate_token
|
|
17
18
|
from authlib.integrations.requests_client import OAuth2Session
|
|
18
|
-
from authlib.jose import JsonWebKey
|
|
19
|
-
from authlib.jose import jwt as jose_jwt
|
|
20
19
|
from authlib.oauth2.rfc7636 import create_s256_code_challenge
|
|
20
|
+
from joserfc import jwt as jose_jwt
|
|
21
|
+
from joserfc.jwk import KeySet
|
|
21
22
|
|
|
22
23
|
AUTH_CLIENT_ID = os.environ.get(
|
|
23
24
|
"AUTH_CLIENT_ID",
|
|
@@ -31,6 +32,7 @@ AUTH_SERVER_WELL_KNOWN = os.environ.get(
|
|
|
31
32
|
_REDIRECT_PORT = 8090
|
|
32
33
|
_REDIRECT_URI = f"http://localhost:{_REDIRECT_PORT}/callback"
|
|
33
34
|
_CREDENTIALS_FILE = Path("./credentials.json")
|
|
35
|
+
logger = logging.getLogger(__name__)
|
|
34
36
|
|
|
35
37
|
|
|
36
38
|
# ── OAuth callback server ───────────────────────────────────────────
|
|
@@ -108,11 +110,16 @@ def _validate_access_token(access_token: str) -> bool:
|
|
|
108
110
|
discovery = _discover_endpoints()
|
|
109
111
|
jwks_resp = requests.get(discovery["jwks_uri"])
|
|
110
112
|
jwks_resp.raise_for_status()
|
|
111
|
-
keyset =
|
|
112
|
-
|
|
113
|
-
|
|
113
|
+
keyset = KeySet.import_key_set(jwks_resp.json())
|
|
114
|
+
token = jose_jwt.decode(access_token, keyset)
|
|
115
|
+
jose_jwt.JWTClaimsRegistry().validate(token.claims)
|
|
114
116
|
return True
|
|
115
|
-
except requests.RequestException:
|
|
117
|
+
except requests.RequestException as exc:
|
|
118
|
+
logger.warning(
|
|
119
|
+
"Skipping local access token validation because the auth server is "
|
|
120
|
+
"unreachable; the API will validate the token. Error: %s",
|
|
121
|
+
exc,
|
|
122
|
+
)
|
|
116
123
|
return True # Can't reach auth server — let the API handle it
|
|
117
124
|
except Exception:
|
|
118
125
|
return False
|
|
@@ -5,15 +5,12 @@ import time
|
|
|
5
5
|
from pathlib import Path
|
|
6
6
|
from typing import Optional
|
|
7
7
|
|
|
8
|
-
import questionary
|
|
9
|
-
import requests
|
|
10
8
|
import typer
|
|
11
9
|
from rich import print
|
|
12
10
|
from rich.prompt import Confirm
|
|
13
11
|
from typing_extensions import Annotated
|
|
14
12
|
|
|
15
13
|
from codecarbon import __app_name__, __version__
|
|
16
|
-
from codecarbon.cli.auth import authorize, get_access_token
|
|
17
14
|
from codecarbon.cli.cli_utils import (
|
|
18
15
|
create_new_config_file,
|
|
19
16
|
get_api_endpoint,
|
|
@@ -21,10 +18,6 @@ from codecarbon.cli.cli_utils import (
|
|
|
21
18
|
get_existing_exp_id,
|
|
22
19
|
overwrite_local_config,
|
|
23
20
|
)
|
|
24
|
-
from codecarbon.cli.monitor import run_and_monitor
|
|
25
|
-
from codecarbon.core.api_client import ApiClient, get_datetime_with_timezone
|
|
26
|
-
from codecarbon.core.schemas import ExperimentCreate, OrganizationCreate, ProjectCreate
|
|
27
|
-
from codecarbon.emissions_tracker import EmissionsTracker, OfflineEmissionsTracker
|
|
28
21
|
|
|
29
22
|
API_URL = os.environ.get("API_URL", "https://dashboard.codecarbon.io/api")
|
|
30
23
|
|
|
@@ -68,6 +61,9 @@ def version(
|
|
|
68
61
|
|
|
69
62
|
|
|
70
63
|
def show_config(path: Path = Path("./.codecarbon.config")) -> None:
|
|
64
|
+
from codecarbon.cli.auth import get_access_token
|
|
65
|
+
from codecarbon.core.api_client import ApiClient
|
|
66
|
+
|
|
71
67
|
d = get_config(path)
|
|
72
68
|
print("Current configuration : \n")
|
|
73
69
|
print("Config file content : ")
|
|
@@ -114,6 +110,9 @@ def api_get():
|
|
|
114
110
|
"""
|
|
115
111
|
ex: test-api
|
|
116
112
|
"""
|
|
113
|
+
from codecarbon.cli.auth import get_access_token
|
|
114
|
+
from codecarbon.core.api_client import ApiClient
|
|
115
|
+
|
|
117
116
|
api_endpoint = get_api_endpoint()
|
|
118
117
|
api = ApiClient(endpoint_url=api_endpoint)
|
|
119
118
|
api.set_access_token(get_access_token())
|
|
@@ -123,6 +122,9 @@ def api_get():
|
|
|
123
122
|
|
|
124
123
|
@codecarbon.command("login", short_help="Login to CodeCarbon")
|
|
125
124
|
def login():
|
|
125
|
+
from codecarbon.cli.auth import authorize, get_access_token
|
|
126
|
+
from codecarbon.core.api_client import ApiClient
|
|
127
|
+
|
|
126
128
|
authorize()
|
|
127
129
|
api_endpoint = get_api_endpoint()
|
|
128
130
|
api = ApiClient(endpoint_url=api_endpoint)
|
|
@@ -132,6 +134,10 @@ def login():
|
|
|
132
134
|
|
|
133
135
|
|
|
134
136
|
def get_api_key(project_id: str):
|
|
137
|
+
import requests
|
|
138
|
+
|
|
139
|
+
from codecarbon.cli.auth import get_access_token
|
|
140
|
+
|
|
135
141
|
api_endpoint = get_api_endpoint()
|
|
136
142
|
api_endpoint = api_endpoint.rstrip("/")
|
|
137
143
|
req = requests.post(
|
|
@@ -161,6 +167,13 @@ def config():
|
|
|
161
167
|
"""
|
|
162
168
|
Initialize CodeCarbon, this will prompt you for configuration of Organisation/Team/Project/Experiment.
|
|
163
169
|
"""
|
|
170
|
+
from codecarbon.cli.auth import get_access_token
|
|
171
|
+
from codecarbon.core.api_client import ApiClient, get_datetime_with_timezone
|
|
172
|
+
from codecarbon.core.schemas import (
|
|
173
|
+
ExperimentCreate,
|
|
174
|
+
OrganizationCreate,
|
|
175
|
+
ProjectCreate,
|
|
176
|
+
)
|
|
164
177
|
|
|
165
178
|
print("Welcome to CodeCarbon configuration wizard")
|
|
166
179
|
home = Path.home()
|
|
@@ -342,6 +355,10 @@ def monitor(
|
|
|
342
355
|
str,
|
|
343
356
|
typer.Option(help="Region/province for offline mode"),
|
|
344
357
|
] = None,
|
|
358
|
+
log_level: Annotated[
|
|
359
|
+
str,
|
|
360
|
+
typer.Option(help="Log level (critical, error, warning, info, debug)"),
|
|
361
|
+
] = "error",
|
|
345
362
|
):
|
|
346
363
|
"""Monitor your machine's carbon emissions."""
|
|
347
364
|
|
|
@@ -349,6 +366,7 @@ def monitor(
|
|
|
349
366
|
tracker_args = {
|
|
350
367
|
"measure_power_secs": measure_power_secs,
|
|
351
368
|
"api_call_interval": api_call_interval,
|
|
369
|
+
"log_level": log_level,
|
|
352
370
|
}
|
|
353
371
|
# Set up the tracker arguments based on mode (offline vs online) and validate required args for each mode
|
|
354
372
|
if offline:
|
|
@@ -375,9 +393,13 @@ def monitor(
|
|
|
375
393
|
|
|
376
394
|
tracker_args = {**tracker_args, "save_to_api": api}
|
|
377
395
|
|
|
396
|
+
from codecarbon.emissions_tracker import EmissionsTracker, OfflineEmissionsTracker
|
|
397
|
+
|
|
378
398
|
# If extra args are provided (e.g. `codecarbon monitor -- my_script.py`), delegate to `run_and_monitor`
|
|
379
399
|
if getattr(ctx, "args", None):
|
|
380
|
-
|
|
400
|
+
from codecarbon.cli.monitor import run_and_monitor
|
|
401
|
+
|
|
402
|
+
return run_and_monitor(ctx, offline=offline, **tracker_args)
|
|
381
403
|
|
|
382
404
|
# Instantiate the tracker
|
|
383
405
|
if offline:
|
|
@@ -417,6 +439,8 @@ def detect():
|
|
|
417
439
|
"""
|
|
418
440
|
Detects hardware and prints information without running any measurements.
|
|
419
441
|
"""
|
|
442
|
+
from codecarbon.emissions_tracker import EmissionsTracker
|
|
443
|
+
|
|
420
444
|
print("Detecting hardware...")
|
|
421
445
|
tracker = EmissionsTracker(save_to_file=False)
|
|
422
446
|
hardware_info = tracker.get_detected_hardware()
|
|
@@ -438,6 +462,8 @@ def detect():
|
|
|
438
462
|
|
|
439
463
|
|
|
440
464
|
def questionary_prompt(prompt, list_options, default):
|
|
465
|
+
import questionary
|
|
466
|
+
|
|
441
467
|
value = questionary.select(
|
|
442
468
|
prompt,
|
|
443
469
|
list_options,
|
|
@@ -8,8 +8,6 @@ import typer
|
|
|
8
8
|
from rich import print
|
|
9
9
|
from typing_extensions import Annotated
|
|
10
10
|
|
|
11
|
-
from codecarbon.emissions_tracker import EmissionsTracker
|
|
12
|
-
|
|
13
11
|
|
|
14
12
|
def run_and_monitor(
|
|
15
13
|
ctx: typer.Context,
|
|
@@ -17,6 +15,7 @@ def run_and_monitor(
|
|
|
17
15
|
str,
|
|
18
16
|
typer.Option(help="Log level (critical, error, warning, info, debug)"),
|
|
19
17
|
] = "error",
|
|
18
|
+
offline: bool = False,
|
|
20
19
|
**tracker_args,
|
|
21
20
|
):
|
|
22
21
|
"""
|
|
@@ -49,12 +48,15 @@ def run_and_monitor(
|
|
|
49
48
|
directory. The file path is shown in the final report.
|
|
50
49
|
"""
|
|
51
50
|
# Suppress all CodeCarbon logs during execution
|
|
51
|
+
from codecarbon.emissions_tracker import EmissionsTracker, OfflineEmissionsTracker
|
|
52
52
|
from codecarbon.external.logger import set_logger_level
|
|
53
53
|
|
|
54
54
|
set_logger_level(log_level)
|
|
55
55
|
|
|
56
|
-
# Get the command from remaining args
|
|
57
|
-
command = ctx
|
|
56
|
+
# Get the command from remaining args (strip nested subcommand / `--` leftovers)
|
|
57
|
+
command = list(getattr(ctx, "args", None) or [])
|
|
58
|
+
while command and command[0] in ("monitor", "--"):
|
|
59
|
+
command.pop(0)
|
|
58
60
|
|
|
59
61
|
if not command:
|
|
60
62
|
print(
|
|
@@ -63,8 +65,8 @@ def run_and_monitor(
|
|
|
63
65
|
)
|
|
64
66
|
raise typer.Exit(1)
|
|
65
67
|
|
|
66
|
-
|
|
67
|
-
tracker =
|
|
68
|
+
tracker_cls = OfflineEmissionsTracker if offline else EmissionsTracker
|
|
69
|
+
tracker = tracker_cls(
|
|
68
70
|
log_level=log_level,
|
|
69
71
|
save_to_logger=False,
|
|
70
72
|
tracking_mode="process",
|
|
@@ -10,7 +10,6 @@ import dataclasses
|
|
|
10
10
|
import json
|
|
11
11
|
from datetime import timedelta, tzinfo
|
|
12
12
|
|
|
13
|
-
import arrow
|
|
14
13
|
import requests
|
|
15
14
|
|
|
16
15
|
from codecarbon.core.schemas import (
|
|
@@ -22,12 +21,11 @@ from codecarbon.core.schemas import (
|
|
|
22
21
|
)
|
|
23
22
|
from codecarbon.external.logger import logger
|
|
24
23
|
|
|
25
|
-
# from codecarbon.output import EmissionsData
|
|
26
|
-
|
|
27
24
|
|
|
28
25
|
def get_datetime_with_timezone():
|
|
29
|
-
|
|
30
|
-
|
|
26
|
+
import arrow
|
|
27
|
+
|
|
28
|
+
return str(arrow.now().isoformat())
|
|
31
29
|
|
|
32
30
|
|
|
33
31
|
class ApiClient: # (AsyncClient)
|
|
@@ -227,6 +225,10 @@ class ApiClient: # (AsyncClient)
|
|
|
227
225
|
gpu_energy=carbon_emission["gpu_energy"],
|
|
228
226
|
ram_energy=carbon_emission["ram_energy"],
|
|
229
227
|
energy_consumed=carbon_emission["energy_consumed"],
|
|
228
|
+
cpu_utilization_percent=carbon_emission.get("cpu_utilization_percent"),
|
|
229
|
+
gpu_utilization_percent=carbon_emission.get("gpu_utilization_percent"),
|
|
230
|
+
ram_utilization_percent=carbon_emission.get("ram_utilization_percent"),
|
|
231
|
+
wue=carbon_emission.get("wue", 0),
|
|
230
232
|
)
|
|
231
233
|
try:
|
|
232
234
|
payload = dataclasses.asdict(emission)
|
|
@@ -4,14 +4,16 @@ using Intel Power Gadget
|
|
|
4
4
|
https://software.intel.com/content/www/us/en/develop/articles/intel-power-gadget.html
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
7
9
|
import os
|
|
8
10
|
import re
|
|
9
11
|
import shutil
|
|
10
12
|
import subprocess
|
|
11
13
|
import sys
|
|
12
|
-
from
|
|
14
|
+
from functools import lru_cache
|
|
15
|
+
from typing import TYPE_CHECKING, Dict, Optional, Tuple
|
|
13
16
|
|
|
14
|
-
import pandas as pd
|
|
15
17
|
import psutil
|
|
16
18
|
from rapidfuzz import fuzz, process, utils
|
|
17
19
|
|
|
@@ -19,12 +21,15 @@ from codecarbon.core.rapl import RAPLFile
|
|
|
19
21
|
from codecarbon.core.units import Time
|
|
20
22
|
from codecarbon.core.util import count_cpus, detect_cpu_model
|
|
21
23
|
from codecarbon.external.logger import logger
|
|
22
|
-
|
|
24
|
+
|
|
25
|
+
if TYPE_CHECKING:
|
|
26
|
+
import pandas as pd
|
|
23
27
|
|
|
24
28
|
# default W value per core for a CPU if no model is found in the ref csv
|
|
25
29
|
DEFAULT_POWER_PER_CORE = 4
|
|
26
30
|
|
|
27
31
|
|
|
32
|
+
@lru_cache(maxsize=1)
|
|
28
33
|
def is_powergadget_available() -> bool:
|
|
29
34
|
"""
|
|
30
35
|
Checks if Intel Power Gadget is available on the system.
|
|
@@ -44,6 +49,10 @@ def is_powergadget_available() -> bool:
|
|
|
44
49
|
return False
|
|
45
50
|
|
|
46
51
|
|
|
52
|
+
def clear_powergadget_cache() -> None:
|
|
53
|
+
is_powergadget_available.cache_clear()
|
|
54
|
+
|
|
55
|
+
|
|
47
56
|
def _get_candidate_bases(rapl_dir: str) -> list:
|
|
48
57
|
"""Get list of directories to scan for RAPL files."""
|
|
49
58
|
default_rapl_dir = "/sys/class/powercap/intel-rapl/subsystem"
|
|
@@ -217,19 +226,19 @@ def is_psutil_available():
|
|
|
217
226
|
return True
|
|
218
227
|
else:
|
|
219
228
|
logger.debug(
|
|
220
|
-
f"is_psutil_available(): psutil.cpu_times().nice is too small: {nice}"
|
|
229
|
+
f"is_psutil_available(): psutil.cpu_times().nice is too small: {nice}; "
|
|
230
|
+
"using fallback check."
|
|
221
231
|
)
|
|
222
|
-
return False
|
|
223
232
|
|
|
224
233
|
else:
|
|
225
|
-
# Fallback: check if psutil works by calling cpu_percent
|
|
226
234
|
logger.debug(
|
|
227
235
|
"is_psutil_available(): no 'nice' attribute, using fallback check."
|
|
228
236
|
)
|
|
229
237
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
238
|
+
# Fallback: check if psutil CPU utilization is usable. This covers
|
|
239
|
+
# platforms like Windows and macOS where cpu_times().nice is absent or 0.
|
|
240
|
+
psutil.cpu_percent(interval=0.0, percpu=False)
|
|
241
|
+
return True
|
|
233
242
|
|
|
234
243
|
except Exception as e:
|
|
235
244
|
logger.debug(
|
|
@@ -366,6 +375,8 @@ class IntelPowerGadget:
|
|
|
366
375
|
self._log_values()
|
|
367
376
|
cpu_details = {}
|
|
368
377
|
try:
|
|
378
|
+
import pandas as pd
|
|
379
|
+
|
|
369
380
|
cpu_data = pd.read_csv(self._log_file_path).dropna()
|
|
370
381
|
for col_name in cpu_data.columns:
|
|
371
382
|
if col_name in ["System Time", "Elapsed Time (sec)", "RDTSC"]:
|
|
@@ -828,7 +839,8 @@ class IntelRAPL:
|
|
|
828
839
|
"""
|
|
829
840
|
cpu_details = {}
|
|
830
841
|
try:
|
|
831
|
-
|
|
842
|
+
for rapl_file in self._rapl_files:
|
|
843
|
+
rapl_file.delta(duration)
|
|
832
844
|
|
|
833
845
|
for rapl_file in self._rapl_files:
|
|
834
846
|
logger.debug(rapl_file)
|
|
@@ -891,6 +903,8 @@ class TDP:
|
|
|
891
903
|
return float(cpu_power_df[cpu_power_df["Name"] == match]["TDP"].values[0])
|
|
892
904
|
|
|
893
905
|
def _get_cpu_power_from_registry(self, cpu_model_raw: str) -> Optional[int]:
|
|
906
|
+
from codecarbon.input import DataSource
|
|
907
|
+
|
|
894
908
|
cpu_power_df = DataSource().get_cpu_power_data()
|
|
895
909
|
cpu_matching = self._get_matching_cpu(cpu_model_raw, cpu_power_df)
|
|
896
910
|
if cpu_matching:
|
|
@@ -6,9 +6,7 @@ https://github.com/mlco2/impact
|
|
|
6
6
|
https://github.com/responsibleproblemsolving/energy-usage
|
|
7
7
|
"""
|
|
8
8
|
|
|
9
|
-
from typing import Dict, Optional
|
|
10
|
-
|
|
11
|
-
import pandas as pd
|
|
9
|
+
from typing import TYPE_CHECKING, Dict, Optional
|
|
12
10
|
|
|
13
11
|
from codecarbon.core import electricitymaps_api
|
|
14
12
|
from codecarbon.core.units import EmissionsPerKWh, Energy
|
|
@@ -16,6 +14,15 @@ from codecarbon.external.geography import CloudMetadata, GeoMetadata
|
|
|
16
14
|
from codecarbon.external.logger import logger
|
|
17
15
|
from codecarbon.input import DataSource, DataSourceException
|
|
18
16
|
|
|
17
|
+
if TYPE_CHECKING:
|
|
18
|
+
import pandas as pd
|
|
19
|
+
|
|
20
|
+
_NORDIC_REGIONS_BY_COUNTRY = {
|
|
21
|
+
"SWE": {"SE1", "SE2", "SE3", "SE4"},
|
|
22
|
+
"NOR": {"NO1", "NO2", "NO3", "NO4", "NO5"},
|
|
23
|
+
"FIN": {"FI"},
|
|
24
|
+
}
|
|
25
|
+
|
|
19
26
|
|
|
20
27
|
class Emissions:
|
|
21
28
|
def __init__(
|
|
@@ -169,8 +176,11 @@ class Emissions:
|
|
|
169
176
|
+ " >>> Using CodeCarbon's data."
|
|
170
177
|
)
|
|
171
178
|
|
|
179
|
+
country_iso_code = (
|
|
180
|
+
geo.country_iso_code.upper() if geo.country_iso_code is not None else None
|
|
181
|
+
)
|
|
172
182
|
compute_with_regional_data: bool = (geo.region is not None) and (
|
|
173
|
-
|
|
183
|
+
country_iso_code in ["USA", "CAN"] or self._is_supported_nordic_region(geo)
|
|
174
184
|
)
|
|
175
185
|
|
|
176
186
|
if compute_with_regional_data:
|
|
@@ -187,24 +197,10 @@ class Emissions:
|
|
|
187
197
|
def _try_get_nordic_region_emissions(
|
|
188
198
|
self, energy: Energy, geo: GeoMetadata
|
|
189
199
|
) -> Optional[float]:
|
|
190
|
-
|
|
191
|
-
"SE1",
|
|
192
|
-
"SE2",
|
|
193
|
-
"SE3",
|
|
194
|
-
"SE4",
|
|
195
|
-
"NO1",
|
|
196
|
-
"NO2",
|
|
197
|
-
"NO3",
|
|
198
|
-
"NO4",
|
|
199
|
-
"NO5",
|
|
200
|
-
"FI",
|
|
201
|
-
}
|
|
202
|
-
if geo.region is None:
|
|
200
|
+
if not self._is_supported_nordic_region(geo):
|
|
203
201
|
return None
|
|
204
202
|
|
|
205
203
|
region_upper = geo.region.upper()
|
|
206
|
-
if region_upper not in nordic_regions:
|
|
207
|
-
return None
|
|
208
204
|
|
|
209
205
|
try:
|
|
210
206
|
nordic_data = self._data_source.get_nordic_country_energy_mix_data()
|
|
@@ -225,6 +221,16 @@ class Emissions:
|
|
|
225
221
|
)
|
|
226
222
|
return None
|
|
227
223
|
|
|
224
|
+
@staticmethod
|
|
225
|
+
def _is_supported_nordic_region(geo: GeoMetadata) -> bool:
|
|
226
|
+
if geo.country_iso_code is None or geo.region is None:
|
|
227
|
+
return False
|
|
228
|
+
|
|
229
|
+
country_regions = _NORDIC_REGIONS_BY_COUNTRY.get(
|
|
230
|
+
geo.country_iso_code.upper(), set()
|
|
231
|
+
)
|
|
232
|
+
return geo.region.upper() in country_regions
|
|
233
|
+
|
|
228
234
|
def get_region_emissions(self, energy: Energy, geo: GeoMetadata) -> float:
|
|
229
235
|
"""
|
|
230
236
|
Computes emissions for a region on private infra.
|
|
@@ -248,6 +254,11 @@ class Emissions:
|
|
|
248
254
|
nordic_emissions = self._try_get_nordic_region_emissions(energy, geo)
|
|
249
255
|
if nordic_emissions is not None:
|
|
250
256
|
return nordic_emissions
|
|
257
|
+
if (
|
|
258
|
+
geo.country_iso_code is not None
|
|
259
|
+
and geo.country_iso_code.upper() in _NORDIC_REGIONS_BY_COUNTRY
|
|
260
|
+
):
|
|
261
|
+
return self.get_country_emissions(energy, geo)
|
|
251
262
|
|
|
252
263
|
# Handle USA and Canada regional data
|
|
253
264
|
try:
|
|
@@ -137,6 +137,23 @@ class AllGPUDevices:
|
|
|
137
137
|
logger.warning("Failed to retrieve gpu information", exc_info=True)
|
|
138
138
|
return []
|
|
139
139
|
|
|
140
|
+
def get_gpu_utilization_list(self) -> List:
|
|
141
|
+
"""Lightweight alternative to :meth:`get_gpu_details` for the 1s
|
|
142
|
+
monitoring hot path. Returns only ``gpu_index`` and
|
|
143
|
+
``gpu_utilization`` per device, skipping heavyweight queries
|
|
144
|
+
(memory, temperature, compute mode, process lists).
|
|
145
|
+
|
|
146
|
+
>>> get_gpu_utilization_list()
|
|
147
|
+
[
|
|
148
|
+
{"gpu_index": 0, "gpu_utilization": 0},
|
|
149
|
+
]
|
|
150
|
+
"""
|
|
151
|
+
try:
|
|
152
|
+
return [d.get_gpu_utilization_lightweight() for d in self.devices]
|
|
153
|
+
except Exception:
|
|
154
|
+
logger.warning("Failed to retrieve gpu utilization", exc_info=True)
|
|
155
|
+
return []
|
|
156
|
+
|
|
140
157
|
def get_delta(self, last_duration: Time) -> List:
|
|
141
158
|
"""Get difference since last time this function was called
|
|
142
159
|
>>> get_delta()
|
|
@@ -1,21 +1,26 @@
|
|
|
1
1
|
import subprocess
|
|
2
2
|
from collections import namedtuple
|
|
3
|
+
from functools import lru_cache
|
|
3
4
|
from typing import Callable
|
|
4
5
|
|
|
5
6
|
from codecarbon.core.gpu_device import GPUDevice
|
|
6
7
|
from codecarbon.external.logger import logger
|
|
7
8
|
|
|
8
9
|
|
|
10
|
+
@lru_cache(maxsize=1)
|
|
9
11
|
def is_rocm_system():
|
|
10
12
|
"""Returns True if the system has an rocm-smi interface."""
|
|
11
13
|
try:
|
|
12
|
-
# Check if rocm-smi is available
|
|
13
14
|
subprocess.check_output(["rocm-smi", "--help"])
|
|
14
15
|
return True
|
|
15
16
|
except (subprocess.CalledProcessError, OSError):
|
|
16
17
|
return False
|
|
17
18
|
|
|
18
19
|
|
|
20
|
+
def clear_rocm_system_cache() -> None:
|
|
21
|
+
is_rocm_system.cache_clear()
|
|
22
|
+
|
|
23
|
+
|
|
19
24
|
try:
|
|
20
25
|
import amdsmi
|
|
21
26
|
|
|
@@ -28,7 +33,7 @@ except ImportError:
|
|
|
28
33
|
"Please install amdsmi to get GPU metrics."
|
|
29
34
|
)
|
|
30
35
|
AMDSMI_AVAILABLE = False
|
|
31
|
-
except AttributeError as e:
|
|
36
|
+
except (AttributeError, OSError, KeyError) as e:
|
|
32
37
|
amdsmi = None
|
|
33
38
|
# In some environments, amdsmi may be present but not properly configured, leading to AttributeError when importing
|
|
34
39
|
logger.warning(
|
|
@@ -101,6 +101,20 @@ class GPUDevice:
|
|
|
101
101
|
}
|
|
102
102
|
return device_details
|
|
103
103
|
|
|
104
|
+
def get_gpu_utilization_lightweight(self) -> Dict[str, Any]:
|
|
105
|
+
"""
|
|
106
|
+
Lightweight alternative to :meth:`get_gpu_details` for the hot path
|
|
107
|
+
(``_monitor_power`` which runs every 1s).
|
|
108
|
+
|
|
109
|
+
Only queries the GPU utilization — avoids heavyweight calls like
|
|
110
|
+
memory info, temperature, compute mode, and process lists which are
|
|
111
|
+
not consumed by the tracker's monitoring loop.
|
|
112
|
+
"""
|
|
113
|
+
return {
|
|
114
|
+
"gpu_index": self.gpu_index,
|
|
115
|
+
"gpu_utilization": self._get_gpu_utilization(),
|
|
116
|
+
}
|
|
117
|
+
|
|
104
118
|
def _to_utf8(self, str_or_bytes) -> Any:
|
|
105
119
|
if hasattr(str_or_bytes, "decode"):
|
|
106
120
|
return str_or_bytes.decode("utf-8", errors="replace")
|
|
@@ -1,21 +1,26 @@
|
|
|
1
1
|
import subprocess
|
|
2
2
|
from dataclasses import dataclass
|
|
3
|
+
from functools import lru_cache
|
|
3
4
|
from typing import Any, Union
|
|
4
5
|
|
|
5
6
|
from codecarbon.core.gpu_device import GPUDevice
|
|
6
7
|
from codecarbon.external.logger import logger
|
|
7
8
|
|
|
8
9
|
|
|
10
|
+
@lru_cache(maxsize=1)
|
|
9
11
|
def is_nvidia_system():
|
|
10
12
|
"""Returns True if the system has an nvidia-smi interface."""
|
|
11
13
|
try:
|
|
12
|
-
# Check if nvidia-smi is available
|
|
13
14
|
subprocess.check_output(["nvidia-smi", "--help"])
|
|
14
15
|
return True
|
|
15
16
|
except Exception:
|
|
16
17
|
return False
|
|
17
18
|
|
|
18
19
|
|
|
20
|
+
def clear_nvidia_system_cache() -> None:
|
|
21
|
+
is_nvidia_system.cache_clear()
|
|
22
|
+
|
|
23
|
+
|
|
19
24
|
try:
|
|
20
25
|
import pynvml
|
|
21
26
|
|