xoscar 0.9.0__cp312-cp312-macosx_10_13_x86_64.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.
- xoscar/__init__.py +61 -0
- xoscar/_utils.cpython-312-darwin.so +0 -0
- xoscar/_utils.pxd +36 -0
- xoscar/_utils.pyx +246 -0
- xoscar/_version.py +693 -0
- xoscar/aio/__init__.py +16 -0
- xoscar/aio/base.py +86 -0
- xoscar/aio/file.py +59 -0
- xoscar/aio/lru.py +228 -0
- xoscar/aio/parallelism.py +39 -0
- xoscar/api.py +527 -0
- xoscar/backend.py +67 -0
- xoscar/backends/__init__.py +14 -0
- xoscar/backends/allocate_strategy.py +160 -0
- xoscar/backends/communication/__init__.py +30 -0
- xoscar/backends/communication/base.py +315 -0
- xoscar/backends/communication/core.py +69 -0
- xoscar/backends/communication/dummy.py +253 -0
- xoscar/backends/communication/errors.py +20 -0
- xoscar/backends/communication/socket.py +444 -0
- xoscar/backends/communication/ucx.py +538 -0
- xoscar/backends/communication/utils.py +97 -0
- xoscar/backends/config.py +157 -0
- xoscar/backends/context.py +437 -0
- xoscar/backends/core.py +352 -0
- xoscar/backends/indigen/__init__.py +16 -0
- xoscar/backends/indigen/__main__.py +19 -0
- xoscar/backends/indigen/backend.py +51 -0
- xoscar/backends/indigen/driver.py +26 -0
- xoscar/backends/indigen/fate_sharing.py +221 -0
- xoscar/backends/indigen/pool.py +515 -0
- xoscar/backends/indigen/shared_memory.py +548 -0
- xoscar/backends/message.cpython-312-darwin.so +0 -0
- xoscar/backends/message.pyi +255 -0
- xoscar/backends/message.pyx +646 -0
- xoscar/backends/pool.py +1630 -0
- xoscar/backends/router.py +285 -0
- xoscar/backends/test/__init__.py +16 -0
- xoscar/backends/test/backend.py +38 -0
- xoscar/backends/test/pool.py +233 -0
- xoscar/batch.py +256 -0
- xoscar/collective/__init__.py +27 -0
- xoscar/collective/backend/__init__.py +13 -0
- xoscar/collective/backend/nccl_backend.py +160 -0
- xoscar/collective/common.py +102 -0
- xoscar/collective/core.py +737 -0
- xoscar/collective/process_group.py +687 -0
- xoscar/collective/utils.py +41 -0
- xoscar/collective/xoscar_pygloo.cpython-312-darwin.so +0 -0
- xoscar/collective/xoscar_pygloo.pyi +239 -0
- xoscar/constants.py +23 -0
- xoscar/context.cpython-312-darwin.so +0 -0
- xoscar/context.pxd +21 -0
- xoscar/context.pyx +368 -0
- xoscar/core.cpython-312-darwin.so +0 -0
- xoscar/core.pxd +51 -0
- xoscar/core.pyx +664 -0
- xoscar/debug.py +188 -0
- xoscar/driver.py +42 -0
- xoscar/errors.py +63 -0
- xoscar/libcpp.pxd +31 -0
- xoscar/metrics/__init__.py +21 -0
- xoscar/metrics/api.py +288 -0
- xoscar/metrics/backends/__init__.py +13 -0
- xoscar/metrics/backends/console/__init__.py +13 -0
- xoscar/metrics/backends/console/console_metric.py +82 -0
- xoscar/metrics/backends/metric.py +149 -0
- xoscar/metrics/backends/prometheus/__init__.py +13 -0
- xoscar/metrics/backends/prometheus/prometheus_metric.py +70 -0
- xoscar/nvutils.py +717 -0
- xoscar/profiling.py +260 -0
- xoscar/serialization/__init__.py +20 -0
- xoscar/serialization/aio.py +141 -0
- xoscar/serialization/core.cpython-312-darwin.so +0 -0
- xoscar/serialization/core.pxd +28 -0
- xoscar/serialization/core.pyi +57 -0
- xoscar/serialization/core.pyx +944 -0
- xoscar/serialization/cuda.py +111 -0
- xoscar/serialization/exception.py +48 -0
- xoscar/serialization/mlx.py +67 -0
- xoscar/serialization/numpy.py +82 -0
- xoscar/serialization/pyfury.py +37 -0
- xoscar/serialization/scipy.py +72 -0
- xoscar/serialization/torch.py +180 -0
- xoscar/utils.py +522 -0
- xoscar/virtualenv/__init__.py +34 -0
- xoscar/virtualenv/core.py +268 -0
- xoscar/virtualenv/platform.py +56 -0
- xoscar/virtualenv/utils.py +100 -0
- xoscar/virtualenv/uv.py +321 -0
- xoscar-0.9.0.dist-info/METADATA +230 -0
- xoscar-0.9.0.dist-info/RECORD +94 -0
- xoscar-0.9.0.dist-info/WHEEL +6 -0
- xoscar-0.9.0.dist-info/top_level.txt +2 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Copyright 2022-2023 XProbe Inc.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
import os
|
|
15
|
+
|
|
16
|
+
import numpy as np
|
|
17
|
+
|
|
18
|
+
from ..utils import lazy_import
|
|
19
|
+
|
|
20
|
+
cupy = lazy_import("cupy")
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def convert_data_to_np_array(data):
|
|
24
|
+
if isinstance(data, np.ndarray):
|
|
25
|
+
return data
|
|
26
|
+
else:
|
|
27
|
+
return np.frombuffer(data, dtype="u1")
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def convert_data_to_cp_array(data):
|
|
31
|
+
if isinstance(data, cupy.ndarray):
|
|
32
|
+
return data
|
|
33
|
+
else:
|
|
34
|
+
return cupy.frombuffer(data, dtype="u1")
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def get_rank_address_via_env(env_key: str, err_message: str) -> str:
|
|
38
|
+
address = os.environ.get(env_key, None)
|
|
39
|
+
if address is None:
|
|
40
|
+
raise RuntimeError(err_message)
|
|
41
|
+
return address
|
|
Binary file
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
# Copyright 2022-2023 XProbe Inc.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
import datetime
|
|
16
|
+
from ctypes import c_void_p
|
|
17
|
+
from enum import IntEnum
|
|
18
|
+
from typing import Callable, List, Optional
|
|
19
|
+
|
|
20
|
+
import xoscar_pygloo
|
|
21
|
+
|
|
22
|
+
class ReduceOp(IntEnum):
|
|
23
|
+
SUM = 0
|
|
24
|
+
PRODUCT = 1
|
|
25
|
+
MIN = 2
|
|
26
|
+
MAX = 3
|
|
27
|
+
BAND = 4
|
|
28
|
+
BOR = 5
|
|
29
|
+
BXOR = 6
|
|
30
|
+
UNUSED = 7
|
|
31
|
+
|
|
32
|
+
class GlooDataType_t(IntEnum):
|
|
33
|
+
glooInt8 = 0
|
|
34
|
+
glooUint8 = 1
|
|
35
|
+
glooInt32 = 2
|
|
36
|
+
glooUint32 = 3
|
|
37
|
+
glooInt64 = 4
|
|
38
|
+
glooUint64 = 5
|
|
39
|
+
glooFloat16 = 6
|
|
40
|
+
glooFloat32 = 7
|
|
41
|
+
glooFloat64 = 8
|
|
42
|
+
|
|
43
|
+
class AllreduceAlgorithm(IntEnum):
|
|
44
|
+
UNSPECIFIED = 0
|
|
45
|
+
RING = 1
|
|
46
|
+
BCUBE = 2
|
|
47
|
+
|
|
48
|
+
def transport_tcp_available() -> bool: ...
|
|
49
|
+
def transport_uv_available() -> bool: ...
|
|
50
|
+
|
|
51
|
+
class Context:
|
|
52
|
+
rank: Optional[int] = None
|
|
53
|
+
size: Optional[int] = None
|
|
54
|
+
base: Optional[int] = 2
|
|
55
|
+
def getDevice(self) -> int: ...
|
|
56
|
+
def createUnboundBuffer(self, ptr: c_void_p, size: int): ...
|
|
57
|
+
def nextSlot(self, numToSkip: int) -> int: ...
|
|
58
|
+
def closeConnections(self) -> None: ...
|
|
59
|
+
def setTimeout(self, timeout: datetime.timedelta) -> None: ...
|
|
60
|
+
def getTimeout(self) -> datetime.timedelta: ...
|
|
61
|
+
|
|
62
|
+
def allreduce(
|
|
63
|
+
context: Optional[Context] = None,
|
|
64
|
+
sendbuf: Optional[int] = None,
|
|
65
|
+
recvbuf: Optional[int] = None,
|
|
66
|
+
size: Optional[int] = None,
|
|
67
|
+
datatype: Optional[GlooDataType_t] = None,
|
|
68
|
+
reduceop: Optional[ReduceOp] = ReduceOp.SUM,
|
|
69
|
+
algorithm: Optional[AllreduceAlgorithm] = AllreduceAlgorithm.RING,
|
|
70
|
+
tag: int = 0,
|
|
71
|
+
) -> None: ...
|
|
72
|
+
def allgather(
|
|
73
|
+
context: Optional[Context] = None,
|
|
74
|
+
sendbuf: Optional[int] = None,
|
|
75
|
+
recvbuf: Optional[int] = None,
|
|
76
|
+
size: Optional[int] = None,
|
|
77
|
+
datatype: Optional[GlooDataType_t] = None,
|
|
78
|
+
tag: Optional[int] = 0,
|
|
79
|
+
) -> None: ...
|
|
80
|
+
def all_to_all(
|
|
81
|
+
context: Optional[Context] = None,
|
|
82
|
+
sendbuf: Optional[int] = None,
|
|
83
|
+
recvbuf: Optional[int] = None,
|
|
84
|
+
size: Optional[int] = None,
|
|
85
|
+
datatype: Optional[GlooDataType_t] = None,
|
|
86
|
+
tag: Optional[int] = 0,
|
|
87
|
+
) -> None: ...
|
|
88
|
+
def allgatherv(
|
|
89
|
+
context: Optional[Context] = None,
|
|
90
|
+
sendbuf: Optional[int] = None,
|
|
91
|
+
recvbuf: Optional[int] = None,
|
|
92
|
+
size: Optional[int] = None,
|
|
93
|
+
datatype: Optional[GlooDataType_t] = None,
|
|
94
|
+
tag: Optional[int] = 0,
|
|
95
|
+
) -> None: ...
|
|
96
|
+
def reduce(
|
|
97
|
+
context: Optional[Context] = None,
|
|
98
|
+
sendbuf: Optional[int] = None,
|
|
99
|
+
recvbuf: Optional[int] = None,
|
|
100
|
+
size: Optional[int] = None,
|
|
101
|
+
datatype: Optional[GlooDataType_t] = None,
|
|
102
|
+
reduceop: Optional[ReduceOp] = ReduceOp.SUM,
|
|
103
|
+
root: Optional[int] = 0,
|
|
104
|
+
tag: Optional[int] = 0,
|
|
105
|
+
) -> None: ...
|
|
106
|
+
def scatter(
|
|
107
|
+
context: Optional[Context] = None,
|
|
108
|
+
sendbuf: Optional[int] = None,
|
|
109
|
+
recvbuf: Optional[int] = None,
|
|
110
|
+
size: Optional[int] = None,
|
|
111
|
+
datatype: Optional[GlooDataType_t] = None,
|
|
112
|
+
root: Optional[int] = 0,
|
|
113
|
+
tag: Optional[int] = 0,
|
|
114
|
+
) -> None: ...
|
|
115
|
+
def gather(
|
|
116
|
+
context: Optional[Context] = None,
|
|
117
|
+
sendbuf: Optional[int] = None,
|
|
118
|
+
recvbuf: Optional[int] = None,
|
|
119
|
+
size: Optional[int] = None,
|
|
120
|
+
datatype: Optional[GlooDataType_t] = None,
|
|
121
|
+
root: Optional[int] = 0,
|
|
122
|
+
tag: Optional[int] = 0,
|
|
123
|
+
) -> None: ...
|
|
124
|
+
def send(
|
|
125
|
+
context: Optional[Context] = None,
|
|
126
|
+
sendbuf: Optional[int] = None,
|
|
127
|
+
size: Optional[int] = None,
|
|
128
|
+
datatype: Optional[GlooDataType_t] = None,
|
|
129
|
+
peer: Optional[int] = None,
|
|
130
|
+
tag: Optional[int] = 0,
|
|
131
|
+
) -> None: ...
|
|
132
|
+
def recv(
|
|
133
|
+
context: Optional[Context] = None,
|
|
134
|
+
recvbuf: Optional[int] = None,
|
|
135
|
+
size: Optional[int] = None,
|
|
136
|
+
datatype: Optional[GlooDataType_t] = None,
|
|
137
|
+
peer: Optional[int] = None,
|
|
138
|
+
tag: Optional[int] = 0,
|
|
139
|
+
) -> None: ...
|
|
140
|
+
def broadcast(
|
|
141
|
+
context: Optional[Context] = None,
|
|
142
|
+
sendbuf: Optional[int] = None,
|
|
143
|
+
recvbuf: Optional[int] = None,
|
|
144
|
+
size: Optional[int] = None,
|
|
145
|
+
datatype: Optional[GlooDataType_t] = None,
|
|
146
|
+
root: Optional[int] = 0,
|
|
147
|
+
tag: Optional[int] = 0,
|
|
148
|
+
) -> None: ...
|
|
149
|
+
def reduce_scatter(
|
|
150
|
+
context: Optional[Context] = None,
|
|
151
|
+
sendbuf: Optional[int] = None,
|
|
152
|
+
recvbuf: Optional[int] = None,
|
|
153
|
+
size: Optional[int] = None,
|
|
154
|
+
recvElems: Optional[List[int]] = None,
|
|
155
|
+
datatype: Optional[GlooDataType_t] = None,
|
|
156
|
+
reduceop: Optional[ReduceOp] = ReduceOp.SUM,
|
|
157
|
+
) -> None: ...
|
|
158
|
+
def barrier(context: Optional[Context] = None, tag: Optional[int] = 0) -> None: ...
|
|
159
|
+
|
|
160
|
+
class rendezvous:
|
|
161
|
+
class Store:
|
|
162
|
+
def set(self, key: str, data: List[str]) -> None: ...
|
|
163
|
+
def get(self, key: str) -> str: ...
|
|
164
|
+
|
|
165
|
+
class TCPStoreOptions:
|
|
166
|
+
port: int
|
|
167
|
+
isServer: bool
|
|
168
|
+
numWorkers: Optional[int]
|
|
169
|
+
waitWorkers: bool
|
|
170
|
+
timeout: datetime.timedelta
|
|
171
|
+
multiTenant: bool
|
|
172
|
+
|
|
173
|
+
class TCPStore:
|
|
174
|
+
def __init__(
|
|
175
|
+
self,
|
|
176
|
+
host: str,
|
|
177
|
+
opts: rendezvous.TCPStoreOptions = rendezvous.TCPStoreOptions(),
|
|
178
|
+
): ...
|
|
179
|
+
def set(self, key: str, value: bytes): ...
|
|
180
|
+
def get(self, key: str) -> bytes: ...
|
|
181
|
+
def wait(self, keys: List[str]): ...
|
|
182
|
+
|
|
183
|
+
class FileStore(Store):
|
|
184
|
+
def __init__(self, path: str) -> None: ...
|
|
185
|
+
def set(self, key: str, data: List[str]) -> None: ...
|
|
186
|
+
def get(self, key: str) -> str: ...
|
|
187
|
+
|
|
188
|
+
class HashStore(Store):
|
|
189
|
+
def __init__(self) -> None: ...
|
|
190
|
+
def set(self, key: str, data: List[str]) -> None: ...
|
|
191
|
+
def get(self, key: str) -> str: ...
|
|
192
|
+
|
|
193
|
+
class PrefixStore(Store):
|
|
194
|
+
def __init__(self, prefix: str, store: rendezvous.Store) -> None: ...
|
|
195
|
+
def set(self, key: str, data: List[str]) -> None: ...
|
|
196
|
+
def get(self, key: str) -> str: ...
|
|
197
|
+
|
|
198
|
+
class CustomStore(Store):
|
|
199
|
+
def __init__(self, real_store_py_object: object) -> None: ...
|
|
200
|
+
def delKeys(self, keys: List[str]) -> None: ...
|
|
201
|
+
def set(self, key: str, data: List[str]) -> None: ...
|
|
202
|
+
def get(self, key: str) -> str: ...
|
|
203
|
+
|
|
204
|
+
class Context(xoscar_pygloo.Context):
|
|
205
|
+
def connectFullMesh(
|
|
206
|
+
self, store: rendezvous.Store, dev: transport.Device
|
|
207
|
+
) -> None: ...
|
|
208
|
+
|
|
209
|
+
class transport:
|
|
210
|
+
class uv:
|
|
211
|
+
pass
|
|
212
|
+
|
|
213
|
+
class tcp:
|
|
214
|
+
class Device(transport.Device):
|
|
215
|
+
def __init__(self, attr: transport.tcp.attr) -> None: ...
|
|
216
|
+
|
|
217
|
+
class Context(xoscar_pygloo.Context):
|
|
218
|
+
def __init__(
|
|
219
|
+
self, device: transport.tcp.Device, rank: int, size: int
|
|
220
|
+
) -> None: ...
|
|
221
|
+
|
|
222
|
+
class attr:
|
|
223
|
+
hostname: str
|
|
224
|
+
iface: str
|
|
225
|
+
ai_family: int
|
|
226
|
+
ai_socktype: int
|
|
227
|
+
ai_protocol: int
|
|
228
|
+
ai_addr: object
|
|
229
|
+
ai_addrlen: int
|
|
230
|
+
def __init__(self, string: Optional[str] = None) -> None: ...
|
|
231
|
+
|
|
232
|
+
def CreateDevice(self, src: transport.tcp.attr) -> transport.Device: ...
|
|
233
|
+
|
|
234
|
+
class Device:
|
|
235
|
+
def __str__(self) -> str: ...
|
|
236
|
+
def getPCIBusID(self) -> Callable[[], str]: ...
|
|
237
|
+
def getInterfaceSpeed(self) -> int: ...
|
|
238
|
+
def hasGPUDirect(self) -> bool: ...
|
|
239
|
+
def createContext(self, rank: int, size: int): ...
|
xoscar/constants.py
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Copyright 2022-2023 XProbe Inc.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
import os
|
|
16
|
+
from pathlib import Path
|
|
17
|
+
|
|
18
|
+
XOSCAR_TEMP_DIR = Path(os.getenv("XOSCAR_DIR", Path.home())) / ".xoscar"
|
|
19
|
+
|
|
20
|
+
# unix socket.
|
|
21
|
+
XOSCAR_UNIX_SOCKET_DIR = XOSCAR_TEMP_DIR / "socket"
|
|
22
|
+
|
|
23
|
+
XOSCAR_CONNECT_TIMEOUT = 8
|
|
Binary file
|
xoscar/context.pxd
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Copyright 2022-2023 XProbe Inc.
|
|
2
|
+
# derived from copyright 1999-2021 Alibaba Group Holding Ltd.
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
cdef class BaseActorContext:
|
|
18
|
+
cdef public str _address
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
cpdef get_context()
|
xoscar/context.pyx
ADDED
|
@@ -0,0 +1,368 @@
|
|
|
1
|
+
# Copyright 2022-2023 XProbe Inc.
|
|
2
|
+
# derived from copyright 1999-2021 Alibaba Group Holding Ltd.
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
from typing import Any, List, Optional, Union
|
|
16
|
+
from urllib.parse import urlparse
|
|
17
|
+
|
|
18
|
+
from ._utils cimport new_actor_id, new_random_id
|
|
19
|
+
from .core cimport ActorRef, BufferRef, FileObjectRef
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
cdef dict _backend_context_cls = dict()
|
|
23
|
+
|
|
24
|
+
cdef object _context = None
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
cdef class BaseActorContext:
|
|
28
|
+
# allocate strategy is for Indigen backend only
|
|
29
|
+
support_allocate_strategy = False
|
|
30
|
+
|
|
31
|
+
"""
|
|
32
|
+
Base class for actor context. Every backend need to implement
|
|
33
|
+
actor context for their own.
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
def __init__(self, address: str = None):
|
|
37
|
+
self._address = address
|
|
38
|
+
|
|
39
|
+
async def create_actor(
|
|
40
|
+
self,
|
|
41
|
+
object actor_cls,
|
|
42
|
+
*args,
|
|
43
|
+
object uid=None,
|
|
44
|
+
object address=None,
|
|
45
|
+
**kwargs,
|
|
46
|
+
):
|
|
47
|
+
"""
|
|
48
|
+
Stub method for creating an actor in current context.
|
|
49
|
+
|
|
50
|
+
Parameters
|
|
51
|
+
----------
|
|
52
|
+
actor_cls : Actor
|
|
53
|
+
Actor class
|
|
54
|
+
args : tuple
|
|
55
|
+
args to be passed into actor_cls.__init__
|
|
56
|
+
uid : identifier
|
|
57
|
+
Actor identifier
|
|
58
|
+
address : str
|
|
59
|
+
Address to locate the actor
|
|
60
|
+
kwargs : dict
|
|
61
|
+
kwargs to be passed into actor_cls.__init__
|
|
62
|
+
|
|
63
|
+
Returns
|
|
64
|
+
-------
|
|
65
|
+
ActorRef
|
|
66
|
+
|
|
67
|
+
"""
|
|
68
|
+
raise NotImplementedError
|
|
69
|
+
|
|
70
|
+
async def has_actor(self, ActorRef actor_ref):
|
|
71
|
+
"""
|
|
72
|
+
Check if actor exists in current context
|
|
73
|
+
|
|
74
|
+
Parameters
|
|
75
|
+
----------
|
|
76
|
+
actor_ref : ActorRef
|
|
77
|
+
Reference to an actor
|
|
78
|
+
|
|
79
|
+
Returns
|
|
80
|
+
-------
|
|
81
|
+
bool
|
|
82
|
+
"""
|
|
83
|
+
raise NotImplementedError
|
|
84
|
+
|
|
85
|
+
async def destroy_actor(self, ActorRef actor_ref):
|
|
86
|
+
"""
|
|
87
|
+
Destroy an actor by its reference
|
|
88
|
+
|
|
89
|
+
Parameters
|
|
90
|
+
----------
|
|
91
|
+
actor_ref : ActorRef
|
|
92
|
+
Reference to an actor
|
|
93
|
+
|
|
94
|
+
Returns
|
|
95
|
+
-------
|
|
96
|
+
bool
|
|
97
|
+
"""
|
|
98
|
+
raise NotImplementedError
|
|
99
|
+
|
|
100
|
+
async def kill_actor(self, ActorRef actor_ref):
|
|
101
|
+
"""
|
|
102
|
+
Force to kill an actor, take care this is a dangerous operation,
|
|
103
|
+
it may lead to the result that other actors are killed as well.
|
|
104
|
+
Hence, unless you are knowing what you are doing and know how
|
|
105
|
+
to recover possible effected actors, DO NOT USE this method!
|
|
106
|
+
|
|
107
|
+
Parameters
|
|
108
|
+
----------
|
|
109
|
+
actor_ref : ActorRef
|
|
110
|
+
Reference to an actor
|
|
111
|
+
|
|
112
|
+
Returns
|
|
113
|
+
-------
|
|
114
|
+
bool
|
|
115
|
+
"""
|
|
116
|
+
|
|
117
|
+
async def send(
|
|
118
|
+
self,
|
|
119
|
+
ActorRef actor_ref,
|
|
120
|
+
object message,
|
|
121
|
+
bint wait_response=True,
|
|
122
|
+
object profiling_context=None,
|
|
123
|
+
):
|
|
124
|
+
"""
|
|
125
|
+
Send a message to given actor by its reference
|
|
126
|
+
|
|
127
|
+
Parameters
|
|
128
|
+
----------
|
|
129
|
+
actor_ref : ActorRef
|
|
130
|
+
Reference to an actor
|
|
131
|
+
message : object
|
|
132
|
+
Message to send to an actor, need to comply to Actor.__on_receive__
|
|
133
|
+
wait_response : bool
|
|
134
|
+
Whether to wait for responses from the actor.
|
|
135
|
+
profiling_context: ProfilingContext
|
|
136
|
+
The profiling context.
|
|
137
|
+
|
|
138
|
+
Returns
|
|
139
|
+
-------
|
|
140
|
+
object
|
|
141
|
+
"""
|
|
142
|
+
raise NotImplementedError
|
|
143
|
+
|
|
144
|
+
async def actor_ref(self, *args, **kwargs):
|
|
145
|
+
"""
|
|
146
|
+
Create a reference to an actor
|
|
147
|
+
|
|
148
|
+
Returns
|
|
149
|
+
-------
|
|
150
|
+
ActorRef
|
|
151
|
+
"""
|
|
152
|
+
raise NotImplementedError
|
|
153
|
+
|
|
154
|
+
async def wait_actor_pool_recovered(self, str address, str main_address = None):
|
|
155
|
+
"""
|
|
156
|
+
Wait until an actor pool is recovered
|
|
157
|
+
|
|
158
|
+
Parameters
|
|
159
|
+
----------
|
|
160
|
+
address
|
|
161
|
+
address of the actor pool
|
|
162
|
+
main_address
|
|
163
|
+
address of the main pool
|
|
164
|
+
"""
|
|
165
|
+
raise NotImplementedError
|
|
166
|
+
|
|
167
|
+
async def get_pool_config(self, str address):
|
|
168
|
+
"""
|
|
169
|
+
Get config of actor pool with given address
|
|
170
|
+
|
|
171
|
+
Parameters
|
|
172
|
+
----------
|
|
173
|
+
address
|
|
174
|
+
address of the actor pool
|
|
175
|
+
|
|
176
|
+
Returns
|
|
177
|
+
-------
|
|
178
|
+
|
|
179
|
+
"""
|
|
180
|
+
raise NotImplementedError
|
|
181
|
+
|
|
182
|
+
def buffer_ref(self, str address, object buf) -> BufferRef:
|
|
183
|
+
"""
|
|
184
|
+
Create a reference to a buffer
|
|
185
|
+
|
|
186
|
+
Parameters
|
|
187
|
+
----------
|
|
188
|
+
address
|
|
189
|
+
address of the actor pool
|
|
190
|
+
buf
|
|
191
|
+
buffer object
|
|
192
|
+
|
|
193
|
+
Returns
|
|
194
|
+
-------
|
|
195
|
+
BufferRef
|
|
196
|
+
"""
|
|
197
|
+
return BufferRef.create(buf, address, new_random_id(32))
|
|
198
|
+
|
|
199
|
+
def file_object_ref(self, str address, object file_object) -> FileObjectRef:
|
|
200
|
+
"""
|
|
201
|
+
Create a reference to an aio file object
|
|
202
|
+
|
|
203
|
+
Parameters
|
|
204
|
+
----------
|
|
205
|
+
address
|
|
206
|
+
address of the actor pool
|
|
207
|
+
file_object
|
|
208
|
+
aio file object
|
|
209
|
+
|
|
210
|
+
Returns
|
|
211
|
+
-------
|
|
212
|
+
FileObjectRef
|
|
213
|
+
"""
|
|
214
|
+
return FileObjectRef.create(file_object, address, new_random_id(32))
|
|
215
|
+
|
|
216
|
+
async def copy_to_buffers(self, local_buffers: List, remote_buffer_refs: List[BufferRef], block_size: Optional[int] = None):
|
|
217
|
+
"""
|
|
218
|
+
Copy local buffers to remote buffers.
|
|
219
|
+
Parameters
|
|
220
|
+
----------
|
|
221
|
+
local_buffers
|
|
222
|
+
Local buffers.
|
|
223
|
+
remote_buffer_refs
|
|
224
|
+
Remote buffer refs
|
|
225
|
+
block_size
|
|
226
|
+
Transfer block size when non-ucx
|
|
227
|
+
"""
|
|
228
|
+
raise NotImplementedError
|
|
229
|
+
|
|
230
|
+
async def copy_to_fileobjs(self, local_fileobjs: list, remote_fileobj_refs: List[FileObjectRef], block_size: Optional[int] = None):
|
|
231
|
+
"""
|
|
232
|
+
Copy local file objs to remote file objs.
|
|
233
|
+
Parameters
|
|
234
|
+
----------
|
|
235
|
+
local_fileobjs
|
|
236
|
+
Local file objs.
|
|
237
|
+
remote_fileobj_refs
|
|
238
|
+
Remote file object refs
|
|
239
|
+
block_size
|
|
240
|
+
Transfer block size when non-ucx
|
|
241
|
+
"""
|
|
242
|
+
raise NotImplementedError
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
cdef class ClientActorContext(BaseActorContext):
|
|
246
|
+
"""
|
|
247
|
+
Default actor context. This context will keep references to other contexts
|
|
248
|
+
given their protocol scheme (i.e., `ray://xxx`).
|
|
249
|
+
"""
|
|
250
|
+
cdef dict _backend_contexts
|
|
251
|
+
|
|
252
|
+
def __init__(self, address: str = None):
|
|
253
|
+
BaseActorContext.__init__(self, address)
|
|
254
|
+
self._backend_contexts = dict()
|
|
255
|
+
|
|
256
|
+
cdef inline object _get_backend_context(self, object address):
|
|
257
|
+
if address is None:
|
|
258
|
+
raise ValueError('address has to be provided')
|
|
259
|
+
if '://' not in address:
|
|
260
|
+
scheme = None
|
|
261
|
+
else:
|
|
262
|
+
scheme = urlparse(address).scheme or None
|
|
263
|
+
try:
|
|
264
|
+
return self._backend_contexts[scheme]
|
|
265
|
+
except KeyError:
|
|
266
|
+
context = self._backend_contexts[scheme] = \
|
|
267
|
+
_backend_context_cls[scheme](address)
|
|
268
|
+
return context
|
|
269
|
+
|
|
270
|
+
def create_actor(
|
|
271
|
+
self,
|
|
272
|
+
object actor_cls,
|
|
273
|
+
*args,
|
|
274
|
+
object uid=None,
|
|
275
|
+
object address=None,
|
|
276
|
+
**kwargs,
|
|
277
|
+
):
|
|
278
|
+
context = self._get_backend_context(address)
|
|
279
|
+
uid = uid or new_actor_id()
|
|
280
|
+
return context.create_actor(actor_cls, *args, uid=uid, address=address, **kwargs)
|
|
281
|
+
|
|
282
|
+
def has_actor(self, ActorRef actor_ref):
|
|
283
|
+
context = self._get_backend_context(actor_ref.address)
|
|
284
|
+
return context.has_actor(actor_ref)
|
|
285
|
+
|
|
286
|
+
def destroy_actor(self, ActorRef actor_ref):
|
|
287
|
+
context = self._get_backend_context(actor_ref.address)
|
|
288
|
+
return context.destroy_actor(actor_ref)
|
|
289
|
+
|
|
290
|
+
def kill_actor(self, ActorRef actor_ref):
|
|
291
|
+
context = self._get_backend_context(actor_ref.address)
|
|
292
|
+
return context.kill_actor(actor_ref)
|
|
293
|
+
|
|
294
|
+
def actor_ref(self, *args, **kwargs):
|
|
295
|
+
from ._utils import create_actor_ref
|
|
296
|
+
|
|
297
|
+
actor_ref = create_actor_ref(*args, **kwargs)
|
|
298
|
+
context = self._get_backend_context(actor_ref.address)
|
|
299
|
+
return context.actor_ref(actor_ref)
|
|
300
|
+
|
|
301
|
+
def send(
|
|
302
|
+
self,
|
|
303
|
+
ActorRef actor_ref,
|
|
304
|
+
object message,
|
|
305
|
+
bint wait_response=True,
|
|
306
|
+
object profiling_context=None
|
|
307
|
+
):
|
|
308
|
+
context = self._get_backend_context(actor_ref.address)
|
|
309
|
+
return context.send(
|
|
310
|
+
actor_ref,
|
|
311
|
+
message,
|
|
312
|
+
wait_response=wait_response,
|
|
313
|
+
profiling_context=profiling_context,
|
|
314
|
+
)
|
|
315
|
+
|
|
316
|
+
def wait_actor_pool_recovered(self, str address, str main_address = None):
|
|
317
|
+
context = self._get_backend_context(address)
|
|
318
|
+
return context.wait_actor_pool_recovered(address, main_address)
|
|
319
|
+
|
|
320
|
+
def get_pool_config(self, str address):
|
|
321
|
+
context = self._get_backend_context(address)
|
|
322
|
+
return context.get_pool_config(address)
|
|
323
|
+
|
|
324
|
+
def buffer_ref(self, str address, buf: Any) -> BufferRef:
|
|
325
|
+
context = self._get_backend_context(address)
|
|
326
|
+
return context.buffer_ref(address, buf)
|
|
327
|
+
|
|
328
|
+
def file_object_ref(self, str address, object file_object) -> FileObjectRef:
|
|
329
|
+
context = self._get_backend_context(address)
|
|
330
|
+
return context.file_object_ref(address, file_object)
|
|
331
|
+
|
|
332
|
+
def copy_to(self, local_buffers_or_fileobjs: list, remote_refs: List[Union[BufferRef, FileObjectRef]], block_size: Optional[int] = None):
|
|
333
|
+
if len(local_buffers_or_fileobjs) == 0 or len(remote_refs) == 0:
|
|
334
|
+
raise ValueError("Nothing to transfer since the length of `local_buffers_or_fileobjs` or `remote_refs` is 0.")
|
|
335
|
+
assert (
|
|
336
|
+
len({ref.address for ref in remote_refs}) == 1
|
|
337
|
+
), "remote_refs for `copy_to` can support only 1 destination"
|
|
338
|
+
assert len(local_buffers_or_fileobjs) == len(remote_refs), (
|
|
339
|
+
f"Buffers or fileobjs from local and remote must have same size, "
|
|
340
|
+
f"local: {len(local_buffers_or_fileobjs)}, remote: {len(remote_refs)}"
|
|
341
|
+
)
|
|
342
|
+
if block_size is not None:
|
|
343
|
+
assert (
|
|
344
|
+
block_size > 0
|
|
345
|
+
), f"`block_size` option must be greater than 0, current value: {block_size}."
|
|
346
|
+
remote_ref = remote_refs[0]
|
|
347
|
+
address = remote_ref.address
|
|
348
|
+
context = self._get_backend_context(address)
|
|
349
|
+
if isinstance(remote_ref, BufferRef):
|
|
350
|
+
return context.copy_to_buffers(local_buffers_or_fileobjs, remote_refs, block_size)
|
|
351
|
+
else:
|
|
352
|
+
return context.copy_to_fileobjs(local_buffers_or_fileobjs, remote_refs, block_size)
|
|
353
|
+
|
|
354
|
+
|
|
355
|
+
def register_backend_context(scheme, cls):
|
|
356
|
+
assert issubclass(cls, BaseActorContext)
|
|
357
|
+
_backend_context_cls[scheme] = cls
|
|
358
|
+
|
|
359
|
+
|
|
360
|
+
cpdef get_context():
|
|
361
|
+
"""
|
|
362
|
+
Get an actor context. If not in an actor environment,
|
|
363
|
+
ClientActorContext will be used
|
|
364
|
+
"""
|
|
365
|
+
global _context
|
|
366
|
+
if _context is None:
|
|
367
|
+
_context = ClientActorContext()
|
|
368
|
+
return _context
|
|
Binary file
|