modal 0.73.7__py3-none-any.whl → 0.73.9__py3-none-any.whl
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.
- modal/_functions.py +3 -0
- modal/_runtime/container_io_manager.py +24 -0
- modal/_runtime/gpu_memory_snapshot.py +104 -0
- modal/app.py +4 -0
- modal/app.pyi +4 -0
- modal/client.pyi +2 -2
- modal/config.py +1 -0
- modal/functions.pyi +7 -6
- {modal-0.73.7.dist-info → modal-0.73.9.dist-info}/METADATA +1 -1
- {modal-0.73.7.dist-info → modal-0.73.9.dist-info}/RECORD +18 -17
- modal_proto/api.proto +3 -0
- modal_proto/api_pb2.py +542 -542
- modal_proto/api_pb2.pyi +9 -2
- modal_version/_version_generated.py +1 -1
- {modal-0.73.7.dist-info → modal-0.73.9.dist-info}/LICENSE +0 -0
- {modal-0.73.7.dist-info → modal-0.73.9.dist-info}/WHEEL +0 -0
- {modal-0.73.7.dist-info → modal-0.73.9.dist-info}/entry_points.txt +0 -0
- {modal-0.73.7.dist-info → modal-0.73.9.dist-info}/top_level.txt +0 -0
modal/_functions.py
CHANGED
@@ -476,6 +476,7 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
|
|
476
476
|
_experimental_buffer_containers: Optional[int] = None,
|
477
477
|
_experimental_proxy_ip: Optional[str] = None,
|
478
478
|
_experimental_custom_scaling_factor: Optional[float] = None,
|
479
|
+
_experimental_enable_gpu_snapshot: bool = False,
|
479
480
|
) -> "_Function":
|
480
481
|
"""mdmd:hidden"""
|
481
482
|
# Needed to avoid circular imports
|
@@ -824,6 +825,7 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
|
|
824
825
|
_experimental_buffer_containers=_experimental_buffer_containers or 0,
|
825
826
|
_experimental_proxy_ip=_experimental_proxy_ip,
|
826
827
|
_experimental_custom_scaling=_experimental_custom_scaling_factor is not None,
|
828
|
+
_experimental_enable_gpu_snapshot=_experimental_enable_gpu_snapshot,
|
827
829
|
)
|
828
830
|
|
829
831
|
if isinstance(gpu, list):
|
@@ -851,6 +853,7 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
|
|
851
853
|
_experimental_group_size=function_definition._experimental_group_size,
|
852
854
|
_experimental_buffer_containers=function_definition._experimental_buffer_containers,
|
853
855
|
_experimental_custom_scaling=function_definition._experimental_custom_scaling,
|
856
|
+
_experimental_enable_gpu_snapshot=_experimental_enable_gpu_snapshot,
|
854
857
|
_experimental_proxy_ip=function_definition._experimental_proxy_ip,
|
855
858
|
snapshot_debug=function_definition.snapshot_debug,
|
856
859
|
runtime_perf_record=function_definition.runtime_perf_record,
|
@@ -25,6 +25,7 @@ from grpclib import Status
|
|
25
25
|
from synchronicity.async_wrap import asynccontextmanager
|
26
26
|
|
27
27
|
import modal_proto.api_pb2
|
28
|
+
from modal._runtime import gpu_memory_snapshot
|
28
29
|
from modal._serialization import deserialize, serialize, serialize_data_format
|
29
30
|
from modal._traceback import extract_traceback, print_exception
|
30
31
|
from modal._utils.async_utils import TaskContext, asyncify, synchronize_api, synchronizer
|
@@ -877,6 +878,17 @@ class _ContainerIOManager:
|
|
877
878
|
if value != "":
|
878
879
|
config.override_locally(key, value)
|
879
880
|
|
881
|
+
# Restore GPU memory.
|
882
|
+
if self.function_def._experimental_enable_gpu_snapshot and self.function_def.resources.gpu_config.gpu_type:
|
883
|
+
logger.debug("GPU memory snapshot enabled. Attempting to restore GPU memory.")
|
884
|
+
gpu_process_state = gpu_memory_snapshot.get_state()
|
885
|
+
if gpu_process_state != gpu_memory_snapshot.CudaCheckpointState.CHECKPOINTED:
|
886
|
+
raise ValueError(
|
887
|
+
"Cannot restore GPU state if GPU isn't in a 'checkpointed' state. "
|
888
|
+
f"Current GPU state: {gpu_process_state}"
|
889
|
+
)
|
890
|
+
gpu_memory_snapshot.toggle()
|
891
|
+
|
880
892
|
# Restore input to default state.
|
881
893
|
self.current_input_id = None
|
882
894
|
self.current_inputs = {}
|
@@ -892,6 +904,18 @@ class _ContainerIOManager:
|
|
892
904
|
|
893
905
|
# Pause heartbeats since they keep the client connection open which causes the snapshotter to crash
|
894
906
|
async with self.heartbeat_condition:
|
907
|
+
# Snapshot GPU memory.
|
908
|
+
if self.function_def._experimental_enable_gpu_snapshot and self.function_def.resources.gpu_config.gpu_type:
|
909
|
+
logger.debug("GPU memory snapshot enabled. Attempting to snapshot GPU memory.")
|
910
|
+
gpu_process_state = gpu_memory_snapshot.get_state()
|
911
|
+
if gpu_process_state != gpu_memory_snapshot.CudaCheckpointState.RUNNING:
|
912
|
+
raise ValueError(
|
913
|
+
"Cannot snapshot GPU state if it isn't running. " f"Current GPU state: {gpu_process_state}"
|
914
|
+
)
|
915
|
+
|
916
|
+
gpu_memory_snapshot.toggle()
|
917
|
+
gpu_memory_snapshot.wait_for_state(gpu_memory_snapshot.CudaCheckpointState.CHECKPOINTED)
|
918
|
+
|
895
919
|
# Notify the heartbeat loop that the snapshot phase has begun in order to
|
896
920
|
# prevent it from sending heartbeat RPCs
|
897
921
|
self._waiting_for_memory_snapshot = True
|
@@ -0,0 +1,104 @@
|
|
1
|
+
# Copyright Modal Labs 2022
|
2
|
+
#
|
3
|
+
# This module provides a simple interface for creating GPU memory snapshots,
|
4
|
+
# provising a convenient interface to `cuda-checkpoint` [1]. This is intended
|
5
|
+
# to be used in conjunction with memory snapshots.
|
6
|
+
#
|
7
|
+
# [1] https://github.com/NVIDIA/cuda-checkpoint
|
8
|
+
|
9
|
+
import os
|
10
|
+
import subprocess
|
11
|
+
import time
|
12
|
+
from enum import Enum
|
13
|
+
|
14
|
+
from modal.config import config, logger
|
15
|
+
|
16
|
+
CUDA_CHECKPOINT_PATH: str = config.get("cuda_checkpoint_path")
|
17
|
+
|
18
|
+
|
19
|
+
class CudaCheckpointState(Enum):
|
20
|
+
"""State representation from the CUDA API: https://docs.nvidia.com/cuda/cuda-driver-api/group__CUDA__TYPES.html#group__CUDA__TYPES_1gc96cdda177a2b8c296144567cbea4f23"""
|
21
|
+
|
22
|
+
RUNNING = "running"
|
23
|
+
LOCKED = "locked"
|
24
|
+
CHECKPOINTED = "checkpointed"
|
25
|
+
FAILED = "failed"
|
26
|
+
|
27
|
+
|
28
|
+
class CudaCheckpointException(Exception):
|
29
|
+
pass
|
30
|
+
|
31
|
+
|
32
|
+
def toggle():
|
33
|
+
"""Toggle CUDA checkpoint state for current process, moving GPU memory to the
|
34
|
+
CPU and back depending on the current process state when called."""
|
35
|
+
pid = get_own_pid()
|
36
|
+
logger.debug(f"Toggling CUDA checkpoint state for PID {pid}")
|
37
|
+
|
38
|
+
try:
|
39
|
+
cuda_checkpoint_lock_timeout_ms = 5 * 1000
|
40
|
+
subprocess.run(
|
41
|
+
[
|
42
|
+
CUDA_CHECKPOINT_PATH,
|
43
|
+
"--toggle",
|
44
|
+
"--pid",
|
45
|
+
str(pid),
|
46
|
+
"--timeout",
|
47
|
+
str(cuda_checkpoint_lock_timeout_ms),
|
48
|
+
],
|
49
|
+
check=True,
|
50
|
+
capture_output=True,
|
51
|
+
text=True,
|
52
|
+
)
|
53
|
+
logger.debug("Successfully toggled CUDA checkpoint state")
|
54
|
+
|
55
|
+
except subprocess.CalledProcessError as e:
|
56
|
+
logger.debug(f"Failed to toggle CUDA checkpoint state: {e.stderr}")
|
57
|
+
raise CudaCheckpointException(e.stderr)
|
58
|
+
|
59
|
+
|
60
|
+
def get_state() -> CudaCheckpointState:
|
61
|
+
"""Get current CUDA checkpoint state for this process."""
|
62
|
+
pid = get_own_pid()
|
63
|
+
|
64
|
+
try:
|
65
|
+
result = subprocess.run(
|
66
|
+
[CUDA_CHECKPOINT_PATH, "--get-state", "--pid", str(pid)], check=True, capture_output=True, text=True
|
67
|
+
)
|
68
|
+
|
69
|
+
# Parse output to get state
|
70
|
+
state_str = result.stdout.strip().lower()
|
71
|
+
logger.debug(f"Raw state output: {state_str}")
|
72
|
+
return CudaCheckpointState(state_str)
|
73
|
+
|
74
|
+
except subprocess.CalledProcessError as e:
|
75
|
+
logger.debug(f"Failed to get CUDA checkpoint state: {e.stderr}")
|
76
|
+
raise CudaCheckpointException(e.stderr)
|
77
|
+
|
78
|
+
|
79
|
+
def wait_for_state(target_state: CudaCheckpointState, timeout_secs: float = 5.0):
|
80
|
+
"""Wait for CUDA checkpoint to reach a specific state."""
|
81
|
+
logger.debug(f"Waiting for CUDA checkpoint state {target_state.value}")
|
82
|
+
start_time = time.monotonic()
|
83
|
+
|
84
|
+
while True:
|
85
|
+
current_state = get_state()
|
86
|
+
|
87
|
+
if current_state == target_state:
|
88
|
+
logger.debug(f"Target state {target_state.value} reached")
|
89
|
+
|
90
|
+
if current_state == CudaCheckpointState.FAILED:
|
91
|
+
raise CudaCheckpointException(f"CUDA process state is {current_state}")
|
92
|
+
|
93
|
+
elapsed = time.monotonic() - start_time
|
94
|
+
if elapsed >= timeout_secs:
|
95
|
+
raise CudaCheckpointException(f"Timeout after {elapsed:.2f}s waiting for state {target_state.value}")
|
96
|
+
|
97
|
+
time.sleep(0.1)
|
98
|
+
|
99
|
+
|
100
|
+
def get_own_pid():
|
101
|
+
"""Returns the Process ID (PID) of the current Python process
|
102
|
+
using only the standard library.
|
103
|
+
"""
|
104
|
+
return os.getpid()
|
modal/app.py
CHANGED
@@ -617,6 +617,7 @@ class _App:
|
|
617
617
|
_experimental_buffer_containers: Optional[int] = None, # Number of additional, idle containers to keep around.
|
618
618
|
_experimental_proxy_ip: Optional[str] = None, # IP address of proxy
|
619
619
|
_experimental_custom_scaling_factor: Optional[float] = None, # Custom scaling factor
|
620
|
+
_experimental_enable_gpu_snapshot: bool = False, # Experimentally enable GPU memory snapshots.
|
620
621
|
) -> _FunctionDecoratorType:
|
621
622
|
"""Decorator to register a new Modal [Function](/docs/reference/modal.Function) with this App."""
|
622
623
|
if isinstance(_warn_parentheses_missing, _Image):
|
@@ -759,6 +760,7 @@ class _App:
|
|
759
760
|
i6pn_enabled=i6pn_enabled,
|
760
761
|
cluster_size=cluster_size, # Experimental: Clustered functions
|
761
762
|
include_source=include_source if include_source is not None else self._include_source_default,
|
763
|
+
_experimental_enable_gpu_snapshot=_experimental_enable_gpu_snapshot,
|
762
764
|
)
|
763
765
|
|
764
766
|
self._add_function(function, webhook_config is not None)
|
@@ -816,6 +818,7 @@ class _App:
|
|
816
818
|
_experimental_buffer_containers: Optional[int] = None, # Number of additional, idle containers to keep around.
|
817
819
|
_experimental_proxy_ip: Optional[str] = None, # IP address of proxy
|
818
820
|
_experimental_custom_scaling_factor: Optional[float] = None, # Custom scaling factor
|
821
|
+
_experimental_enable_gpu_snapshot: bool = False, # Experimentally enable GPU memory snapshots.
|
819
822
|
) -> Callable[[CLS_T], CLS_T]:
|
820
823
|
"""
|
821
824
|
Decorator to register a new Modal [Cls](/docs/reference/modal.Cls) with this App.
|
@@ -890,6 +893,7 @@ class _App:
|
|
890
893
|
_experimental_buffer_containers=_experimental_buffer_containers,
|
891
894
|
_experimental_proxy_ip=_experimental_proxy_ip,
|
892
895
|
_experimental_custom_scaling_factor=_experimental_custom_scaling_factor,
|
896
|
+
_experimental_enable_gpu_snapshot=_experimental_enable_gpu_snapshot,
|
893
897
|
)
|
894
898
|
|
895
899
|
self._add_function(cls_func, is_web_endpoint=False)
|
modal/app.pyi
CHANGED
@@ -197,6 +197,7 @@ class _App:
|
|
197
197
|
_experimental_buffer_containers: typing.Optional[int] = None,
|
198
198
|
_experimental_proxy_ip: typing.Optional[str] = None,
|
199
199
|
_experimental_custom_scaling_factor: typing.Optional[float] = None,
|
200
|
+
_experimental_enable_gpu_snapshot: bool = False,
|
200
201
|
) -> _FunctionDecoratorType: ...
|
201
202
|
@typing_extensions.dataclass_transform(
|
202
203
|
field_specifiers=(modal.cls.parameter,),
|
@@ -241,6 +242,7 @@ class _App:
|
|
241
242
|
_experimental_buffer_containers: typing.Optional[int] = None,
|
242
243
|
_experimental_proxy_ip: typing.Optional[str] = None,
|
243
244
|
_experimental_custom_scaling_factor: typing.Optional[float] = None,
|
245
|
+
_experimental_enable_gpu_snapshot: bool = False,
|
244
246
|
) -> collections.abc.Callable[[CLS_T], CLS_T]: ...
|
245
247
|
async def spawn_sandbox(
|
246
248
|
self,
|
@@ -431,6 +433,7 @@ class App:
|
|
431
433
|
_experimental_buffer_containers: typing.Optional[int] = None,
|
432
434
|
_experimental_proxy_ip: typing.Optional[str] = None,
|
433
435
|
_experimental_custom_scaling_factor: typing.Optional[float] = None,
|
436
|
+
_experimental_enable_gpu_snapshot: bool = False,
|
434
437
|
) -> _FunctionDecoratorType: ...
|
435
438
|
@typing_extensions.dataclass_transform(
|
436
439
|
field_specifiers=(modal.cls.parameter,),
|
@@ -475,6 +478,7 @@ class App:
|
|
475
478
|
_experimental_buffer_containers: typing.Optional[int] = None,
|
476
479
|
_experimental_proxy_ip: typing.Optional[str] = None,
|
477
480
|
_experimental_custom_scaling_factor: typing.Optional[float] = None,
|
481
|
+
_experimental_enable_gpu_snapshot: bool = False,
|
478
482
|
) -> collections.abc.Callable[[CLS_T], CLS_T]: ...
|
479
483
|
|
480
484
|
class __spawn_sandbox_spec(typing_extensions.Protocol[SUPERSELF]):
|
modal/client.pyi
CHANGED
@@ -27,7 +27,7 @@ class _Client:
|
|
27
27
|
_snapshotted: bool
|
28
28
|
|
29
29
|
def __init__(
|
30
|
-
self, server_url: str, client_type: int, credentials: typing.Optional[tuple[str, str]], version: str = "0.73.
|
30
|
+
self, server_url: str, client_type: int, credentials: typing.Optional[tuple[str, str]], version: str = "0.73.9"
|
31
31
|
): ...
|
32
32
|
def is_closed(self) -> bool: ...
|
33
33
|
@property
|
@@ -85,7 +85,7 @@ class Client:
|
|
85
85
|
_snapshotted: bool
|
86
86
|
|
87
87
|
def __init__(
|
88
|
-
self, server_url: str, client_type: int, credentials: typing.Optional[tuple[str, str]], version: str = "0.73.
|
88
|
+
self, server_url: str, client_type: int, credentials: typing.Optional[tuple[str, str]], version: str = "0.73.9"
|
89
89
|
): ...
|
90
90
|
def is_closed(self) -> bool: ...
|
91
91
|
@property
|
modal/config.py
CHANGED
@@ -223,6 +223,7 @@ _SETTINGS = {
|
|
223
223
|
"strict_parameters": _Setting(False, transform=_to_boolean), # For internal/experimental use
|
224
224
|
"snapshot_debug": _Setting(False, transform=_to_boolean),
|
225
225
|
"client_retries": _Setting(False, transform=_to_boolean), # For internal testing.
|
226
|
+
"cuda_checkpoint_path": _Setting("/__modal/.bin/cuda-checkpoint"), # Used for snapshotting GPU memory.
|
226
227
|
}
|
227
228
|
|
228
229
|
|
modal/functions.pyi
CHANGED
@@ -102,6 +102,7 @@ class Function(
|
|
102
102
|
_experimental_buffer_containers: typing.Optional[int] = None,
|
103
103
|
_experimental_proxy_ip: typing.Optional[str] = None,
|
104
104
|
_experimental_custom_scaling_factor: typing.Optional[float] = None,
|
105
|
+
_experimental_enable_gpu_snapshot: bool = False,
|
105
106
|
) -> Function: ...
|
106
107
|
def _bind_parameters(
|
107
108
|
self,
|
@@ -199,11 +200,11 @@ class Function(
|
|
199
200
|
|
200
201
|
_call_generator_nowait: ___call_generator_nowait_spec[typing_extensions.Self]
|
201
202
|
|
202
|
-
class __remote_spec(typing_extensions.Protocol[
|
203
|
+
class __remote_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER, SUPERSELF]):
|
203
204
|
def __call__(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> ReturnType_INNER: ...
|
204
205
|
async def aio(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> ReturnType_INNER: ...
|
205
206
|
|
206
|
-
remote: __remote_spec[modal._functions.
|
207
|
+
remote: __remote_spec[modal._functions.P, modal._functions.ReturnType, typing_extensions.Self]
|
207
208
|
|
208
209
|
class __remote_gen_spec(typing_extensions.Protocol[SUPERSELF]):
|
209
210
|
def __call__(self, *args, **kwargs) -> typing.Generator[typing.Any, None, None]: ...
|
@@ -218,19 +219,19 @@ class Function(
|
|
218
219
|
self, *args: modal._functions.P.args, **kwargs: modal._functions.P.kwargs
|
219
220
|
) -> modal._functions.OriginalReturnType: ...
|
220
221
|
|
221
|
-
class ___experimental_spawn_spec(typing_extensions.Protocol[
|
222
|
+
class ___experimental_spawn_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER, SUPERSELF]):
|
222
223
|
def __call__(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
|
223
224
|
async def aio(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
|
224
225
|
|
225
226
|
_experimental_spawn: ___experimental_spawn_spec[
|
226
|
-
modal._functions.
|
227
|
+
modal._functions.P, modal._functions.ReturnType, typing_extensions.Self
|
227
228
|
]
|
228
229
|
|
229
|
-
class __spawn_spec(typing_extensions.Protocol[
|
230
|
+
class __spawn_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER, SUPERSELF]):
|
230
231
|
def __call__(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
|
231
232
|
async def aio(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
|
232
233
|
|
233
|
-
spawn: __spawn_spec[modal._functions.
|
234
|
+
spawn: __spawn_spec[modal._functions.P, modal._functions.ReturnType, typing_extensions.Self]
|
234
235
|
|
235
236
|
def get_raw_f(self) -> collections.abc.Callable[..., typing.Any]: ...
|
236
237
|
|
@@ -3,7 +3,7 @@ modal/__main__.py,sha256=scYhGFqh8OJcVDo-VOxIT6CCwxOgzgflYWMnIZiMRqE,2871
|
|
3
3
|
modal/_clustered_functions.py,sha256=kTf-9YBXY88NutC1akI-gCbvf01RhMPCw-zoOI_YIUE,2700
|
4
4
|
modal/_clustered_functions.pyi,sha256=vllkegc99A0jrUOWa8mdlSbdp6uz36TsHhGxysAOpaQ,771
|
5
5
|
modal/_container_entrypoint.py,sha256=qahIuJvaMmWG85N5vNS1yuAQ9XZoo1ftzfatkos_q7I,29553
|
6
|
-
modal/_functions.py,sha256=
|
6
|
+
modal/_functions.py,sha256=XTcpMIlGqa3MPSTbnCwvbagTCeIHlnV4g8WlkGF5SOs,70352
|
7
7
|
modal/_ipython.py,sha256=TW1fkVOmZL3YYqdS2YlM1hqpf654Yf8ZyybHdBnlhSw,301
|
8
8
|
modal/_location.py,sha256=S3lSxIU3h9HkWpkJ3Pwo0pqjIOSB1fjeSgUsY3x7eec,1202
|
9
9
|
modal/_object.py,sha256=ItQcsMNkz9Y3kdTsvfNarbW-paJ2qabDyQ7njaqY0XI,11359
|
@@ -17,16 +17,16 @@ modal/_traceback.py,sha256=IZQzB3fVlUfMHOSyKUgw0H6qv4yHnpyq-XVCNZKfUdA,5023
|
|
17
17
|
modal/_tunnel.py,sha256=zTBxBiuH1O22tS1OliAJdIsSmaZS8PlnifS_6S5z-mk,6320
|
18
18
|
modal/_tunnel.pyi,sha256=JmmDYAy9F1FpgJ_hWx0xkom2nTOFQjn4mTPYlU3PFo4,1245
|
19
19
|
modal/_watcher.py,sha256=K6LYnlmSGQB4tWWI9JADv-tvSvQ1j522FwT71B51CX8,3584
|
20
|
-
modal/app.py,sha256=
|
21
|
-
modal/app.pyi,sha256=
|
20
|
+
modal/app.py,sha256=wRygVSrWH8iIqhDAAl2Ww_RAkz8MCJZ0Jt9qYZCF6SA,44626
|
21
|
+
modal/app.pyi,sha256=lxiuWzE_OLb3WHg-H7Pek9DGBuCUzZ55P594VhJL5LA,26113
|
22
22
|
modal/call_graph.py,sha256=1g2DGcMIJvRy-xKicuf63IVE98gJSnQsr8R_NVMptNc,2581
|
23
23
|
modal/client.py,sha256=8SQawr7P1PNUCq1UmJMUQXG2jIo4Nmdcs311XqrNLRE,15276
|
24
|
-
modal/client.pyi,sha256=
|
24
|
+
modal/client.pyi,sha256=UOfACeLizRMYzf2NDFzalr9sLhXAy447M3jSwPxPCbc,7591
|
25
25
|
modal/cloud_bucket_mount.py,sha256=YOe9nnvSr4ZbeCn587d7_VhE9IioZYRvF9VYQTQux08,5914
|
26
26
|
modal/cloud_bucket_mount.pyi,sha256=30T3K1a89l6wzmEJ_J9iWv9SknoGqaZDx59Xs-ZQcmk,1607
|
27
27
|
modal/cls.py,sha256=kNnZrBYVXOhgEXU0rDWk2Hr-bQRrsZkMKDgC-TD_6Bs,31063
|
28
28
|
modal/cls.pyi,sha256=gb6QNwfX3HSJfcZXPY36N9ywF7aBJTwwtoARnf3G1HQ,8877
|
29
|
-
modal/config.py,sha256=
|
29
|
+
modal/config.py,sha256=XT1W4Y9PVkbYMAXjJRshvQEPDhZmnfW_ZRMwl8XKoqA,11149
|
30
30
|
modal/container_process.py,sha256=WTqLn01dJPVkPpwR_0w_JH96ceN5mV4TGtiu1ZR2RRA,6108
|
31
31
|
modal/container_process.pyi,sha256=Hf0J5JyDdCCXBJSKx6gvkPOo0XrztCm78xzxamtzUjQ,2828
|
32
32
|
modal/dict.py,sha256=vc5lQVqzeDUCb4fRjnOlqYK2GmBb0fIhZmvB0xIBG0U,12921
|
@@ -40,7 +40,7 @@ modal/file_io.py,sha256=lcMs_E9Xfm0YX1t9U2wNIBPnqHRxmImqjLW1GHqVmyg,20945
|
|
40
40
|
modal/file_io.pyi,sha256=NTRft1tbPSWf9TlWVeZmTlgB5AZ_Zhu2srWIrWr7brk,9445
|
41
41
|
modal/file_pattern_matcher.py,sha256=1cZ4V2wSLiaXqAqStETSwp3bzDD6QZOt6pmmjk3Okz4,6505
|
42
42
|
modal/functions.py,sha256=kcNHvqeGBxPI7Cgd57NIBBghkfbeFJzXO44WW0jSmao,325
|
43
|
-
modal/functions.pyi,sha256=
|
43
|
+
modal/functions.pyi,sha256=QYZy3BCjA2y3UC217e3YG-omyG0E1Jx-Uc-sonsyQsE,14288
|
44
44
|
modal/gpu.py,sha256=2qZMNnoMrjU-5Bu7fx68pANUAKTtZq0EWEEeBA9OUVQ,7426
|
45
45
|
modal/image.py,sha256=Vjsi7wS9dEcoj-7m7_LmvbK5iqEuFz-SHKl2K-qWcew,90952
|
46
46
|
modal/image.pyi,sha256=A5mW2dBguEhmRo815Ax1rBIMXTCriu7PqLMHoUPsez8,26372
|
@@ -83,8 +83,9 @@ modal/volume.py,sha256=JAWeDvoAG95tMBv-fYIERyHsJPS_X_xGpxRRmYtb6j0,30096
|
|
83
83
|
modal/volume.pyi,sha256=kTsXarphjZILXci84LQy7EyC84eXUs5-7D62IM5q3eE,12491
|
84
84
|
modal/_runtime/__init__.py,sha256=MIEP8jhXUeGq_eCjYFcqN5b1bxBM4fdk0VESpjWR0fc,28
|
85
85
|
modal/_runtime/asgi.py,sha256=c4hmaMW1pLo-cm7ouriJjieuFm4ZF6D2LMy0638sfOs,22139
|
86
|
-
modal/_runtime/container_io_manager.py,sha256=
|
86
|
+
modal/_runtime/container_io_manager.py,sha256=L6qv-Mo3mN3ttR5GX-G36cUhH_oz8wdP5WG0HT5FFzg,44619
|
87
87
|
modal/_runtime/execution_context.py,sha256=E6ofm6j1POXGPxS841X3V7JU6NheVb8OkQc7JpLq4Kg,2712
|
88
|
+
modal/_runtime/gpu_memory_snapshot.py,sha256=vV6igsqN9CxOoH91kUkuaZQ32QfX5wdoXIS-6MIYX2Y,3315
|
88
89
|
modal/_runtime/telemetry.py,sha256=T1RoAGyjBDr1swiM6pPsGRSITm7LI5FDK18oNXxY08U,5163
|
89
90
|
modal/_runtime/user_code_imports.py,sha256=zl_Mq9dsrVF62x3w-iNK1YAhZKYAXeFaGpd4G7AySTc,14746
|
90
91
|
modal/_utils/__init__.py,sha256=waLjl5c6IPDhSsdWAm9Bji4e2PVxamYABKAze6CHVXY,28
|
@@ -153,10 +154,10 @@ modal_global_objects/mounts/__init__.py,sha256=MIEP8jhXUeGq_eCjYFcqN5b1bxBM4fdk0
|
|
153
154
|
modal_global_objects/mounts/modal_client_package.py,sha256=W0E_yShsRojPzWm6LtIQqNVolapdnrZkm2hVEQuZK_4,767
|
154
155
|
modal_global_objects/mounts/python_standalone.py,sha256=EsC-hdPtiAPOwgW9emHN6muNUkrJwR8dYxroVArxHxM,1841
|
155
156
|
modal_proto/__init__.py,sha256=MIEP8jhXUeGq_eCjYFcqN5b1bxBM4fdk0VESpjWR0fc,28
|
156
|
-
modal_proto/api.proto,sha256=
|
157
|
+
modal_proto/api.proto,sha256=_RV_hQIWR_CmanZcjieKll-P9P5qVsRDDS7TtGWL4AU,85264
|
157
158
|
modal_proto/api_grpc.py,sha256=FYGqDegM_w_qxdtlxum8k31mDibKoMvmNxv_p9cKdKs,109056
|
158
|
-
modal_proto/api_pb2.py,sha256=
|
159
|
-
modal_proto/api_pb2.pyi,sha256=
|
159
|
+
modal_proto/api_pb2.py,sha256=7hj3Dqmv3Xb6nEzLVMt-zai1EGqUT5uAU5nbGjnk85A,311104
|
160
|
+
modal_proto/api_pb2.pyi,sha256=ScYf3xdzV3TQZZR-uPusjrEHoHIxKCRPseS7e8Ee_EI,415384
|
160
161
|
modal_proto/api_pb2_grpc.py,sha256=DNp0Et5i_Ey4dKx_1o1LRtYhyWYyT0NzTcAY4EcHn-c,235765
|
161
162
|
modal_proto/api_pb2_grpc.pyi,sha256=RI6tWC3L8EIN4-izFSEGPPJl5Ta0lXPNuHUJaWAr35s,54892
|
162
163
|
modal_proto/modal_api_grpc.py,sha256=UG8WJU81afrWPwItWB4Ag64E9EpyREMpBbAVGVEYJiM,14550
|
@@ -170,10 +171,10 @@ modal_proto/options_pb2_grpc.pyi,sha256=CImmhxHsYnF09iENPoe8S4J-n93jtgUYD2JPAc0y
|
|
170
171
|
modal_proto/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
171
172
|
modal_version/__init__.py,sha256=wiJQ53c-OMs0Xf1UeXOxQ7FwlV1VzIjnX6o-pRYZ_Pk,470
|
172
173
|
modal_version/__main__.py,sha256=2FO0yYQQwDTh6udt1h-cBnGd1c4ZyHnHSI4BksxzVac,105
|
173
|
-
modal_version/_version_generated.py,sha256=
|
174
|
-
modal-0.73.
|
175
|
-
modal-0.73.
|
176
|
-
modal-0.73.
|
177
|
-
modal-0.73.
|
178
|
-
modal-0.73.
|
179
|
-
modal-0.73.
|
174
|
+
modal_version/_version_generated.py,sha256=RgDn253uA_DeV6d6P40AOPpDJqMMVupp6gXgLMcak24,148
|
175
|
+
modal-0.73.9.dist-info/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
|
176
|
+
modal-0.73.9.dist-info/METADATA,sha256=BYeidDOAvKaxgE_yMfAun3xjsRB6Q0jGKR8fcs9a0jU,2329
|
177
|
+
modal-0.73.9.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
|
178
|
+
modal-0.73.9.dist-info/entry_points.txt,sha256=An-wYgeEUnm6xzrAP9_NTSTSciYvvEWsMZILtYrvpAI,46
|
179
|
+
modal-0.73.9.dist-info/top_level.txt,sha256=1nvYbOSIKcmU50fNrpnQnrrOpj269ei3LzgB6j9xGqg,64
|
180
|
+
modal-0.73.9.dist-info/RECORD,,
|
modal_proto/api.proto
CHANGED
@@ -1263,6 +1263,8 @@ message Function {
|
|
1263
1263
|
bool _experimental_custom_scaling = 76;
|
1264
1264
|
|
1265
1265
|
string cloud_provider_str = 77; // Supersedes cloud_provider
|
1266
|
+
|
1267
|
+
bool _experimental_enable_gpu_snapshot = 78; // Experimental support for GPU snapshotting
|
1266
1268
|
}
|
1267
1269
|
|
1268
1270
|
message FunctionAsyncInvokeRequest {
|
@@ -1376,6 +1378,7 @@ message FunctionData {
|
|
1376
1378
|
uint32 _experimental_group_size = 19;
|
1377
1379
|
uint32 _experimental_buffer_containers = 22;
|
1378
1380
|
bool _experimental_custom_scaling = 23;
|
1381
|
+
bool _experimental_enable_gpu_snapshot = 30;
|
1379
1382
|
string worker_id = 7; // for internal debugging use only
|
1380
1383
|
|
1381
1384
|
uint32 timeout_secs = 8;
|