xoscar 0.4.5__cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl → 0.5.0__cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.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.
Potentially problematic release.
This version of xoscar might be problematic. Click here for more details.
- xoscar/_utils.cpython-39-aarch64-linux-gnu.so +0 -0
- xoscar/_utils.pyx +6 -2
- xoscar/backends/communication/__init__.py +1 -1
- xoscar/backends/communication/socket.py +10 -2
- xoscar/backends/config.py +12 -0
- xoscar/backends/context.py +41 -8
- xoscar/backends/core.py +31 -5
- xoscar/backends/indigen/pool.py +16 -0
- xoscar/backends/message.cpython-39-aarch64-linux-gnu.so +0 -0
- xoscar/backends/message.pyx +56 -9
- xoscar/backends/pool.py +30 -3
- xoscar/backends/router.py +86 -8
- xoscar/context.cpython-39-aarch64-linux-gnu.so +0 -0
- xoscar/core.cpython-39-aarch64-linux-gnu.so +0 -0
- xoscar/core.pxd +1 -0
- xoscar/core.pyx +11 -5
- xoscar/serialization/__init__.py +2 -2
- xoscar/serialization/core.cpython-39-aarch64-linux-gnu.so +0 -0
- xoscar/serialization/mlx.py +63 -0
- {xoscar-0.4.5.dist-info → xoscar-0.5.0.dist-info}/METADATA +1 -1
- {xoscar-0.4.5.dist-info → xoscar-0.5.0.dist-info}/RECORD +58 -57
- {xoscar-0.4.5.dist-info → xoscar-0.5.0.dist-info}/WHEEL +0 -0
- {xoscar-0.4.5.dist-info → xoscar-0.5.0.dist-info}/top_level.txt +0 -0
|
Binary file
|
xoscar/_utils.pyx
CHANGED
|
@@ -208,28 +208,32 @@ def create_actor_ref(*args, **kwargs):
|
|
|
208
208
|
|
|
209
209
|
address = to_str(kwargs.pop('address', None))
|
|
210
210
|
uid = kwargs.pop('uid', None)
|
|
211
|
+
proxy_addresses = kwargs.pop("proxy_addresses", None)
|
|
211
212
|
|
|
212
213
|
if kwargs:
|
|
213
214
|
raise ValueError('Only `address` or `uid` keywords are supported')
|
|
214
215
|
|
|
215
|
-
if len(args)
|
|
216
|
+
if 2 <= len(args) <= 3:
|
|
216
217
|
if address:
|
|
217
218
|
raise ValueError('address has been specified')
|
|
218
219
|
address = to_str(args[0])
|
|
219
220
|
uid = args[1]
|
|
221
|
+
if len(args) == 3:
|
|
222
|
+
proxy_addresses = args[2]
|
|
220
223
|
elif len(args) == 1:
|
|
221
224
|
tp0 = type(args[0])
|
|
222
225
|
if tp0 is ActorRef or tp0 is LocalActorRef:
|
|
223
226
|
existing_ref = <ActorRef>(args[0])
|
|
224
227
|
uid = existing_ref.uid
|
|
225
228
|
address = to_str(address or existing_ref.address)
|
|
229
|
+
proxy_addresses = existing_ref.proxy_addresses
|
|
226
230
|
else:
|
|
227
231
|
uid = args[0]
|
|
228
232
|
|
|
229
233
|
if uid is None:
|
|
230
234
|
raise ValueError('Actor uid should be provided')
|
|
231
235
|
|
|
232
|
-
return ActorRef(address, uid)
|
|
236
|
+
return ActorRef(address, uid, proxy_addresses=proxy_addresses)
|
|
233
237
|
|
|
234
238
|
|
|
235
239
|
cdef class Timer:
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
# See the License for the specific language governing permissions and
|
|
14
14
|
# limitations under the License.
|
|
15
15
|
|
|
16
|
-
from .base import Channel, Client, Server
|
|
16
|
+
from .base import Channel, ChannelType, Client, Server
|
|
17
17
|
from .core import gen_local_address, get_client_type, get_server_type
|
|
18
18
|
from .dummy import DummyChannel, DummyClient, DummyServer
|
|
19
19
|
from .socket import (
|
|
@@ -315,7 +315,11 @@ class SocketClient(Client):
|
|
|
315
315
|
except asyncio.TimeoutError:
|
|
316
316
|
raise ConnectionError("connect timeout")
|
|
317
317
|
channel = SocketChannel(
|
|
318
|
-
reader,
|
|
318
|
+
reader,
|
|
319
|
+
writer,
|
|
320
|
+
local_address=local_address,
|
|
321
|
+
dest_address=dest_address,
|
|
322
|
+
channel_type=ChannelType.remote,
|
|
319
323
|
)
|
|
320
324
|
return SocketClient(local_address, dest_address, channel)
|
|
321
325
|
|
|
@@ -431,6 +435,10 @@ class UnixSocketClient(Client):
|
|
|
431
435
|
"Cannot connect unix socket due to file not exists"
|
|
432
436
|
)
|
|
433
437
|
channel = SocketChannel(
|
|
434
|
-
reader,
|
|
438
|
+
reader,
|
|
439
|
+
writer,
|
|
440
|
+
local_address=local_address,
|
|
441
|
+
dest_address=dest_address,
|
|
442
|
+
channel_type=ChannelType.ipc,
|
|
435
443
|
)
|
|
436
444
|
return UnixSocketClient(local_address, dest_address, channel)
|
xoscar/backends/config.py
CHANGED
|
@@ -33,6 +33,8 @@ class ActorPoolConfig:
|
|
|
33
33
|
self._conf["metrics"] = dict()
|
|
34
34
|
if "comm" not in self._conf:
|
|
35
35
|
self._conf["comm"] = dict()
|
|
36
|
+
if "proxy" not in self._conf:
|
|
37
|
+
self._conf["proxy"] = dict()
|
|
36
38
|
|
|
37
39
|
@property
|
|
38
40
|
def n_pool(self):
|
|
@@ -143,3 +145,13 @@ class ActorPoolConfig:
|
|
|
143
145
|
|
|
144
146
|
def get_comm_config(self) -> dict:
|
|
145
147
|
return self._conf["comm"]
|
|
148
|
+
|
|
149
|
+
def get_proxy_config(self) -> dict:
|
|
150
|
+
return self._conf["proxy"]
|
|
151
|
+
|
|
152
|
+
def add_proxy_config(self, proxy_config: dict[str, str] | None):
|
|
153
|
+
if proxy_config:
|
|
154
|
+
self._conf["proxy"].update(proxy_config)
|
|
155
|
+
|
|
156
|
+
def remove_proxy(self, from_addr: str):
|
|
157
|
+
del self._conf["proxy"][from_addr]
|
xoscar/backends/context.py
CHANGED
|
@@ -72,15 +72,24 @@ class IndigenActorContext(BaseActorContext):
|
|
|
72
72
|
self._caller.cancel_tasks()
|
|
73
73
|
|
|
74
74
|
async def _call(
|
|
75
|
-
self,
|
|
75
|
+
self,
|
|
76
|
+
address: str,
|
|
77
|
+
message: _MessageBase,
|
|
78
|
+
wait: bool = True,
|
|
79
|
+
proxy_addresses: list[str] | None = None,
|
|
76
80
|
) -> Union[ResultMessage, ErrorMessage, asyncio.Future]:
|
|
77
81
|
return await self._caller.call(
|
|
78
|
-
Router.get_instance_or_empty(),
|
|
82
|
+
Router.get_instance_or_empty(),
|
|
83
|
+
address,
|
|
84
|
+
message,
|
|
85
|
+
wait=wait,
|
|
86
|
+
proxy_addresses=proxy_addresses,
|
|
79
87
|
)
|
|
80
88
|
|
|
81
89
|
async def _call_with_client(
|
|
82
90
|
self, client: Client, message: _MessageBase, wait: bool = True
|
|
83
91
|
) -> Union[ResultMessage, ErrorMessage, asyncio.Future]:
|
|
92
|
+
# NOTE: used by copyto, cannot support proxy
|
|
84
93
|
return await self._caller.call_with_client(client, message, wait)
|
|
85
94
|
|
|
86
95
|
async def _call_send_buffers(
|
|
@@ -146,7 +155,12 @@ class IndigenActorContext(BaseActorContext):
|
|
|
146
155
|
message = HasActorMessage(
|
|
147
156
|
new_message_id(), actor_ref, protocol=DEFAULT_PROTOCOL
|
|
148
157
|
)
|
|
149
|
-
future = await self._call(
|
|
158
|
+
future = await self._call(
|
|
159
|
+
actor_ref.address,
|
|
160
|
+
message,
|
|
161
|
+
wait=False,
|
|
162
|
+
proxy_addresses=actor_ref.proxy_addresses,
|
|
163
|
+
)
|
|
150
164
|
result = await self._wait(future, actor_ref.address, message) # type: ignore
|
|
151
165
|
return self._process_result_message(result)
|
|
152
166
|
|
|
@@ -154,7 +168,12 @@ class IndigenActorContext(BaseActorContext):
|
|
|
154
168
|
message = DestroyActorMessage(
|
|
155
169
|
new_message_id(), actor_ref, protocol=DEFAULT_PROTOCOL
|
|
156
170
|
)
|
|
157
|
-
future = await self._call(
|
|
171
|
+
future = await self._call(
|
|
172
|
+
actor_ref.address,
|
|
173
|
+
message,
|
|
174
|
+
wait=False,
|
|
175
|
+
proxy_addresses=actor_ref.proxy_addresses,
|
|
176
|
+
)
|
|
158
177
|
result = await self._wait(future, actor_ref.address, message) # type: ignore
|
|
159
178
|
return self._process_result_message(result)
|
|
160
179
|
|
|
@@ -168,7 +187,7 @@ class IndigenActorContext(BaseActorContext):
|
|
|
168
187
|
protocol=DEFAULT_PROTOCOL,
|
|
169
188
|
)
|
|
170
189
|
main_address = self._process_result_message(
|
|
171
|
-
await self._call(actor_ref.address, control_message) # type: ignore
|
|
190
|
+
await self._call(actor_ref.address, control_message, proxy_addresses=actor_ref.proxy_addresses) # type: ignore
|
|
172
191
|
)
|
|
173
192
|
real_actor_ref = await self.actor_ref(actor_ref)
|
|
174
193
|
if real_actor_ref.address == main_address:
|
|
@@ -182,7 +201,9 @@ class IndigenActorContext(BaseActorContext):
|
|
|
182
201
|
protocol=DEFAULT_PROTOCOL,
|
|
183
202
|
)
|
|
184
203
|
# stop server
|
|
185
|
-
result = await self._call(
|
|
204
|
+
result = await self._call(
|
|
205
|
+
main_address, stop_message, proxy_addresses=actor_ref.proxy_addresses
|
|
206
|
+
)
|
|
186
207
|
return self._process_result_message(result) # type: ignore
|
|
187
208
|
|
|
188
209
|
async def actor_ref(self, *args, **kwargs):
|
|
@@ -194,7 +215,12 @@ class IndigenActorContext(BaseActorContext):
|
|
|
194
215
|
message = ActorRefMessage(
|
|
195
216
|
new_message_id(), actor_ref, protocol=DEFAULT_PROTOCOL
|
|
196
217
|
)
|
|
197
|
-
future = await self._call(
|
|
218
|
+
future = await self._call(
|
|
219
|
+
actor_ref.address,
|
|
220
|
+
message,
|
|
221
|
+
wait=False,
|
|
222
|
+
proxy_addresses=actor_ref.proxy_addresses,
|
|
223
|
+
)
|
|
198
224
|
result = await self._wait(future, actor_ref.address, message)
|
|
199
225
|
res = self._process_result_message(result)
|
|
200
226
|
if res.address != connect_addr:
|
|
@@ -225,7 +251,12 @@ class IndigenActorContext(BaseActorContext):
|
|
|
225
251
|
actor_ref.address,
|
|
226
252
|
):
|
|
227
253
|
detect_cycle_send(send_message, wait_response)
|
|
228
|
-
future = await self._call(
|
|
254
|
+
future = await self._call(
|
|
255
|
+
actor_ref.address,
|
|
256
|
+
send_message,
|
|
257
|
+
wait=False,
|
|
258
|
+
proxy_addresses=actor_ref.proxy_addresses,
|
|
259
|
+
)
|
|
229
260
|
if wait_response:
|
|
230
261
|
result = await self._wait(future, actor_ref.address, send_message) # type: ignore
|
|
231
262
|
return self._process_result_message(result)
|
|
@@ -315,6 +346,8 @@ class IndigenActorContext(BaseActorContext):
|
|
|
315
346
|
async def _get_client(self, address: str) -> Client:
|
|
316
347
|
router = Router.get_instance()
|
|
317
348
|
assert router is not None, "`copy_to` can only be used inside pools"
|
|
349
|
+
if router.get_proxy(address):
|
|
350
|
+
raise RuntimeError("Cannot run `copy_to` when enabling proxy")
|
|
318
351
|
return await self._get_copy_to_client(router, address)
|
|
319
352
|
|
|
320
353
|
async def copy_to_buffers(
|
xoscar/backends/core.py
CHANGED
|
@@ -26,8 +26,15 @@ from typing import Type, Union
|
|
|
26
26
|
from .._utils import Timer
|
|
27
27
|
from ..errors import ServerClosed
|
|
28
28
|
from ..profiling import get_profiling_data
|
|
29
|
-
from .communication import Client, UCXClient
|
|
30
|
-
from .message import
|
|
29
|
+
from .communication import ChannelType, Client, UCXClient
|
|
30
|
+
from .message import (
|
|
31
|
+
DeserializeMessageFailed,
|
|
32
|
+
ErrorMessage,
|
|
33
|
+
ForwardMessage,
|
|
34
|
+
MessageType,
|
|
35
|
+
ResultMessage,
|
|
36
|
+
_MessageBase,
|
|
37
|
+
)
|
|
31
38
|
from .router import Router
|
|
32
39
|
|
|
33
40
|
ResultMessageType = Union[ResultMessage, ErrorMessage]
|
|
@@ -67,8 +74,15 @@ class ActorCallerThreadLocal:
|
|
|
67
74
|
self._listen_client(client)
|
|
68
75
|
return client
|
|
69
76
|
|
|
70
|
-
async def get_client(
|
|
71
|
-
|
|
77
|
+
async def get_client(
|
|
78
|
+
self,
|
|
79
|
+
router: Router,
|
|
80
|
+
dest_address: str,
|
|
81
|
+
proxy_addresses: list[str] | None = None,
|
|
82
|
+
) -> Client:
|
|
83
|
+
client = await router.get_client(
|
|
84
|
+
dest_address, from_who=self, proxy_addresses=proxy_addresses
|
|
85
|
+
)
|
|
72
86
|
self._listen_client(client)
|
|
73
87
|
return client
|
|
74
88
|
|
|
@@ -191,8 +205,20 @@ class ActorCallerThreadLocal:
|
|
|
191
205
|
dest_address: str,
|
|
192
206
|
message: _MessageBase,
|
|
193
207
|
wait: bool = True,
|
|
208
|
+
proxy_addresses: list[str] | None = None,
|
|
194
209
|
) -> ResultMessage | ErrorMessage | asyncio.Future:
|
|
195
|
-
client = await self.get_client(
|
|
210
|
+
client = await self.get_client(
|
|
211
|
+
router, dest_address, proxy_addresses=proxy_addresses
|
|
212
|
+
)
|
|
213
|
+
if (
|
|
214
|
+
client.channel_type == ChannelType.remote
|
|
215
|
+
and client.dest_address != dest_address
|
|
216
|
+
and message.message_type != MessageType.control
|
|
217
|
+
):
|
|
218
|
+
# wrap message with forward message
|
|
219
|
+
message = ForwardMessage(
|
|
220
|
+
message_id=message.message_id, address=dest_address, raw_message=message
|
|
221
|
+
)
|
|
196
222
|
return await self.call_with_client(client, message, wait)
|
|
197
223
|
|
|
198
224
|
async def stop(self):
|
xoscar/backends/indigen/pool.py
CHANGED
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
from __future__ import annotations
|
|
17
17
|
|
|
18
18
|
import asyncio
|
|
19
|
+
import atexit
|
|
19
20
|
import concurrent.futures as futures
|
|
20
21
|
import configparser
|
|
21
22
|
import contextlib
|
|
@@ -29,6 +30,7 @@ import sys
|
|
|
29
30
|
import threading
|
|
30
31
|
import uuid
|
|
31
32
|
from dataclasses import dataclass
|
|
33
|
+
from multiprocessing import util
|
|
32
34
|
from types import TracebackType
|
|
33
35
|
from typing import List, Optional
|
|
34
36
|
|
|
@@ -79,6 +81,19 @@ logger = logging.getLogger(__name__)
|
|
|
79
81
|
_init_main_suspended_local = threading.local()
|
|
80
82
|
|
|
81
83
|
|
|
84
|
+
def _terminate_children():
|
|
85
|
+
for c in multiprocessing.active_children():
|
|
86
|
+
try:
|
|
87
|
+
c.terminate()
|
|
88
|
+
except Exception:
|
|
89
|
+
pass
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
if util:
|
|
93
|
+
# Import multiprocessing.util to register _exit_function at exit.
|
|
94
|
+
atexit.register(_terminate_children)
|
|
95
|
+
|
|
96
|
+
|
|
82
97
|
def _patch_spawn_get_preparation_data():
|
|
83
98
|
try:
|
|
84
99
|
from multiprocessing import spawn as mp_spawn
|
|
@@ -309,6 +324,7 @@ class MainActorPool(MainActorPoolBase):
|
|
|
309
324
|
raise
|
|
310
325
|
finally:
|
|
311
326
|
status_queue.put(process_status)
|
|
327
|
+
status_queue.cancel_join_thread()
|
|
312
328
|
await pool.join()
|
|
313
329
|
|
|
314
330
|
async def append_sub_pool(
|
|
Binary file
|
xoscar/backends/message.pyx
CHANGED
|
@@ -47,6 +47,7 @@ class MessageType(Enum):
|
|
|
47
47
|
cancel = 9
|
|
48
48
|
copy_to_buffers = 10
|
|
49
49
|
copy_to_fileobjs = 11
|
|
50
|
+
forward = 12
|
|
50
51
|
|
|
51
52
|
|
|
52
53
|
class ControlMessageType(Enum):
|
|
@@ -350,13 +351,14 @@ cdef class DestroyActorMessage(_MessageBase):
|
|
|
350
351
|
cdef _MessageSerialItem serial(self):
|
|
351
352
|
cdef _MessageSerialItem item = _MessageBase.serial(self)
|
|
352
353
|
item.serialized += (
|
|
353
|
-
self.actor_ref.address, self.actor_ref.uid,
|
|
354
|
+
self.actor_ref.address, self.actor_ref.uid,
|
|
355
|
+
self.actor_ref.proxy_addresses, self.from_main
|
|
354
356
|
)
|
|
355
357
|
return item
|
|
356
358
|
|
|
357
359
|
cdef deserial_members(self, tuple serialized, list subs):
|
|
358
360
|
_MessageBase.deserial_members(self, serialized, subs)
|
|
359
|
-
self.actor_ref = ActorRef(serialized[-3], serialized[-2])
|
|
361
|
+
self.actor_ref = ActorRef(serialized[-4], serialized[-3], serialized[-2])
|
|
360
362
|
self.from_main = serialized[-1]
|
|
361
363
|
|
|
362
364
|
|
|
@@ -381,13 +383,13 @@ cdef class HasActorMessage(_MessageBase):
|
|
|
381
383
|
cdef _MessageSerialItem serial(self):
|
|
382
384
|
cdef _MessageSerialItem item = _MessageBase.serial(self)
|
|
383
385
|
item.serialized += (
|
|
384
|
-
self.actor_ref.address, self.actor_ref.uid
|
|
386
|
+
self.actor_ref.address, self.actor_ref.uid, self.actor_ref.proxy_addresses
|
|
385
387
|
)
|
|
386
388
|
return item
|
|
387
389
|
|
|
388
390
|
cdef deserial_members(self, tuple serialized, list subs):
|
|
389
391
|
_MessageBase.deserial_members(self, serialized, subs)
|
|
390
|
-
self.actor_ref = ActorRef(serialized[-2], serialized[-1])
|
|
392
|
+
self.actor_ref = ActorRef(serialized[-3], serialized[-2], serialized[-1])
|
|
391
393
|
|
|
392
394
|
|
|
393
395
|
cdef class ActorRefMessage(_MessageBase):
|
|
@@ -411,13 +413,13 @@ cdef class ActorRefMessage(_MessageBase):
|
|
|
411
413
|
cdef _MessageSerialItem serial(self):
|
|
412
414
|
cdef _MessageSerialItem item = _MessageBase.serial(self)
|
|
413
415
|
item.serialized += (
|
|
414
|
-
self.actor_ref.address, self.actor_ref.uid
|
|
416
|
+
self.actor_ref.address, self.actor_ref.uid, self.actor_ref.proxy_addresses
|
|
415
417
|
)
|
|
416
418
|
return item
|
|
417
419
|
|
|
418
420
|
cdef deserial_members(self, tuple serialized, list subs):
|
|
419
421
|
_MessageBase.deserial_members(self, serialized, subs)
|
|
420
|
-
self.actor_ref = ActorRef(serialized[-2], serialized[-1])
|
|
422
|
+
self.actor_ref = ActorRef(serialized[-3], serialized[-2], serialized[-1])
|
|
421
423
|
|
|
422
424
|
|
|
423
425
|
cdef class SendMessage(_MessageBase):
|
|
@@ -449,14 +451,14 @@ cdef class SendMessage(_MessageBase):
|
|
|
449
451
|
cdef _MessageSerialItem serial(self):
|
|
450
452
|
cdef _MessageSerialItem item = _MessageBase.serial(self)
|
|
451
453
|
item.serialized += (
|
|
452
|
-
self.actor_ref.address, self.actor_ref.uid
|
|
454
|
+
self.actor_ref.address, self.actor_ref.uid, self.actor_ref.proxy_addresses
|
|
453
455
|
)
|
|
454
456
|
item.subs = [self.content]
|
|
455
457
|
return item
|
|
456
458
|
|
|
457
459
|
cdef deserial_members(self, tuple serialized, list subs):
|
|
458
460
|
_MessageBase.deserial_members(self, serialized, subs)
|
|
459
|
-
self.actor_ref = ActorRef(serialized[-2], serialized[-1])
|
|
461
|
+
self.actor_ref = ActorRef(serialized[-3], serialized[-2], serialized[-1])
|
|
460
462
|
self.content = subs[0]
|
|
461
463
|
|
|
462
464
|
|
|
@@ -533,6 +535,50 @@ cdef class CopyToFileObjectsMessage(CopyToBuffersMessage):
|
|
|
533
535
|
message_type = MessageType.copy_to_fileobjs
|
|
534
536
|
|
|
535
537
|
|
|
538
|
+
cdef class ForwardMessage(_MessageBase):
|
|
539
|
+
message_type = MessageType.forward
|
|
540
|
+
|
|
541
|
+
cdef:
|
|
542
|
+
public str address
|
|
543
|
+
public _MessageBase raw_message
|
|
544
|
+
|
|
545
|
+
def __init__(
|
|
546
|
+
self,
|
|
547
|
+
bytes message_id = None,
|
|
548
|
+
str address = None,
|
|
549
|
+
_MessageBase raw_message = None,
|
|
550
|
+
int protocol = DEFAULT_PROTOCOL,
|
|
551
|
+
list message_trace = None,
|
|
552
|
+
):
|
|
553
|
+
_MessageBase.__init__(
|
|
554
|
+
self,
|
|
555
|
+
message_id,
|
|
556
|
+
protocol=protocol,
|
|
557
|
+
message_trace=message_trace
|
|
558
|
+
)
|
|
559
|
+
self.address = address
|
|
560
|
+
self.raw_message = raw_message
|
|
561
|
+
|
|
562
|
+
cdef _MessageSerialItem serial(self):
|
|
563
|
+
cdef _MessageSerialItem item = _MessageBase.serial(self)
|
|
564
|
+
cdef _MessageSerialItem raw_message_serialized = self.raw_message.serial()
|
|
565
|
+
item.serialized += (self.address,)
|
|
566
|
+
item.serialized += raw_message_serialized.serialized
|
|
567
|
+
item.subs += raw_message_serialized.subs
|
|
568
|
+
return item
|
|
569
|
+
|
|
570
|
+
cdef deserial_members(self, tuple serialized, list subs):
|
|
571
|
+
# 5 is magic number that means serialized for _MessageBase
|
|
572
|
+
base_serialized = serialized[:5]
|
|
573
|
+
_MessageBase.deserial_members(self, base_serialized, [])
|
|
574
|
+
self.address = serialized[5]
|
|
575
|
+
# process raw message
|
|
576
|
+
tp = _message_type_to_message_cls[serialized[6]]
|
|
577
|
+
cdef _MessageBase raw_message = <_MessageBase>(tp())
|
|
578
|
+
raw_message.deserial_members(serialized[6:], subs)
|
|
579
|
+
self.raw_message = raw_message
|
|
580
|
+
|
|
581
|
+
|
|
536
582
|
cdef dict _message_type_to_message_cls = {
|
|
537
583
|
MessageType.control.value: ControlMessage,
|
|
538
584
|
MessageType.result.value: ResultMessage,
|
|
@@ -545,7 +591,8 @@ cdef dict _message_type_to_message_cls = {
|
|
|
545
591
|
MessageType.tell.value: TellMessage,
|
|
546
592
|
MessageType.cancel.value: CancelMessage,
|
|
547
593
|
MessageType.copy_to_buffers.value: CopyToBuffersMessage,
|
|
548
|
-
MessageType.copy_to_fileobjs.value: CopyToFileObjectsMessage
|
|
594
|
+
MessageType.copy_to_fileobjs.value: CopyToFileObjectsMessage,
|
|
595
|
+
MessageType.forward.value: ForwardMessage,
|
|
549
596
|
}
|
|
550
597
|
|
|
551
598
|
|
xoscar/backends/pool.py
CHANGED
|
@@ -62,6 +62,7 @@ from .message import (
|
|
|
62
62
|
CreateActorMessage,
|
|
63
63
|
DestroyActorMessage,
|
|
64
64
|
ErrorMessage,
|
|
65
|
+
ForwardMessage,
|
|
65
66
|
HasActorMessage,
|
|
66
67
|
MessageType,
|
|
67
68
|
ResultMessage,
|
|
@@ -123,6 +124,7 @@ def _register_message_handler(pool_type: Type["AbstractActorPool"]):
|
|
|
123
124
|
(MessageType.send, pool_type.send),
|
|
124
125
|
(MessageType.tell, pool_type.tell),
|
|
125
126
|
(MessageType.cancel, pool_type.cancel),
|
|
127
|
+
(MessageType.forward, pool_type.forward),
|
|
126
128
|
(MessageType.control, pool_type.handle_control_command),
|
|
127
129
|
(MessageType.copy_to_buffers, pool_type.handle_copy_to_buffers_message),
|
|
128
130
|
(MessageType.copy_to_fileobjs, pool_type.handle_copy_to_fileobjs_message),
|
|
@@ -311,6 +313,22 @@ class AbstractActorPool(ABC):
|
|
|
311
313
|
result or error message
|
|
312
314
|
"""
|
|
313
315
|
|
|
316
|
+
async def forward(self, message: ForwardMessage) -> ResultMessageType:
|
|
317
|
+
"""
|
|
318
|
+
Forward message
|
|
319
|
+
|
|
320
|
+
Parameters
|
|
321
|
+
----------
|
|
322
|
+
message: ForwardMessage
|
|
323
|
+
Forward message.
|
|
324
|
+
|
|
325
|
+
Returns
|
|
326
|
+
-------
|
|
327
|
+
result_message
|
|
328
|
+
result or error message
|
|
329
|
+
"""
|
|
330
|
+
return await self.call(message.address, message.raw_message)
|
|
331
|
+
|
|
314
332
|
def _sync_pool_config(self, actor_pool_config: ActorPoolConfig):
|
|
315
333
|
self._config = actor_pool_config
|
|
316
334
|
# remove router from global one
|
|
@@ -377,7 +395,7 @@ class AbstractActorPool(ABC):
|
|
|
377
395
|
try:
|
|
378
396
|
await channel.send(result)
|
|
379
397
|
except (ChannelClosed, ConnectionResetError):
|
|
380
|
-
if not self._stopped.is_set():
|
|
398
|
+
if not self._stopped.is_set() and not channel.closed:
|
|
381
399
|
raise
|
|
382
400
|
except Exception as ex:
|
|
383
401
|
logger.exception(
|
|
@@ -443,6 +461,7 @@ class AbstractActorPool(ABC):
|
|
|
443
461
|
gen_local_address(process_index),
|
|
444
462
|
actor_pool_config.external_to_internal_address_map,
|
|
445
463
|
comm_config=actor_pool_config.get_comm_config(),
|
|
464
|
+
proxy_config=actor_pool_config.get_proxy_config(),
|
|
446
465
|
)
|
|
447
466
|
kw["env"] = curr_pool_config["env"]
|
|
448
467
|
|
|
@@ -605,7 +624,8 @@ class ActorPoolBase(AbstractActorPool, metaclass=ABCMeta):
|
|
|
605
624
|
self._actors[actor_id] = actor
|
|
606
625
|
await self._run_coro(message.message_id, actor.__post_create__())
|
|
607
626
|
|
|
608
|
-
|
|
627
|
+
proxies = self._router.get_proxies(address)
|
|
628
|
+
result = ActorRef(address, actor_id, proxy_addresses=proxies)
|
|
609
629
|
# ensemble result message
|
|
610
630
|
processor.result = ResultMessage(
|
|
611
631
|
message.message_id, result, protocol=message.protocol
|
|
@@ -647,9 +667,10 @@ class ActorPoolBase(AbstractActorPool, metaclass=ABCMeta):
|
|
|
647
667
|
actor_id = message.actor_ref.uid
|
|
648
668
|
if actor_id not in self._actors:
|
|
649
669
|
raise ActorNotExist(f"Actor {actor_id} does not exist")
|
|
670
|
+
proxies = self._router.get_proxies(self.external_address)
|
|
650
671
|
result = ResultMessage(
|
|
651
672
|
message.message_id,
|
|
652
|
-
ActorRef(self.external_address, actor_id),
|
|
673
|
+
ActorRef(self.external_address, actor_id, proxy_addresses=proxies),
|
|
653
674
|
protocol=message.protocol,
|
|
654
675
|
)
|
|
655
676
|
processor.result = result
|
|
@@ -762,6 +783,7 @@ class ActorPoolBase(AbstractActorPool, metaclass=ABCMeta):
|
|
|
762
783
|
gen_local_address(process_index),
|
|
763
784
|
actor_pool_config.external_to_internal_address_map,
|
|
764
785
|
comm_config=actor_pool_config.get_comm_config(),
|
|
786
|
+
proxy_config=actor_pool_config.get_proxy_config(),
|
|
765
787
|
)
|
|
766
788
|
|
|
767
789
|
@classmethod
|
|
@@ -1155,6 +1177,7 @@ class MainActorPoolBase(ActorPoolBase):
|
|
|
1155
1177
|
actor_ref = message.actor_ref
|
|
1156
1178
|
actor_ref.uid = to_binary(actor_ref.uid)
|
|
1157
1179
|
if actor_ref.address == self.external_address and actor_ref.uid in self._actors:
|
|
1180
|
+
actor_ref.proxy_addresses = self._router.get_proxies(actor_ref.address)
|
|
1158
1181
|
return ResultMessage(
|
|
1159
1182
|
message.message_id, actor_ref, protocol=message.protocol
|
|
1160
1183
|
)
|
|
@@ -1163,6 +1186,7 @@ class MainActorPoolBase(ActorPoolBase):
|
|
|
1163
1186
|
for address, item in self._allocated_actors.items():
|
|
1164
1187
|
ref = create_actor_ref(address, actor_ref.uid)
|
|
1165
1188
|
if ref in item:
|
|
1189
|
+
ref.proxy_addresses = self._router.get_proxies(ref.address)
|
|
1166
1190
|
return ResultMessage(message.message_id, ref, protocol=message.protocol)
|
|
1167
1191
|
|
|
1168
1192
|
with _ErrorProcessor(
|
|
@@ -1503,6 +1527,7 @@ async def create_actor_pool(
|
|
|
1503
1527
|
suspend_sigint: bool | None = None,
|
|
1504
1528
|
use_uvloop: str | bool = "auto",
|
|
1505
1529
|
logging_conf: dict | None = None,
|
|
1530
|
+
proxy_conf: dict | None = None,
|
|
1506
1531
|
on_process_down: Callable[[MainActorPoolType, str], None] | None = None,
|
|
1507
1532
|
on_process_recover: Callable[[MainActorPoolType, str], None] | None = None,
|
|
1508
1533
|
extra_conf: dict | None = None,
|
|
@@ -1549,6 +1574,8 @@ async def create_actor_pool(
|
|
|
1549
1574
|
)
|
|
1550
1575
|
actor_pool_config = ActorPoolConfig()
|
|
1551
1576
|
actor_pool_config.add_metric_configs(kwargs.get("metrics", {}))
|
|
1577
|
+
# add proxy config
|
|
1578
|
+
actor_pool_config.add_proxy_config(proxy_conf)
|
|
1552
1579
|
# add main config
|
|
1553
1580
|
process_index_gen = pool_cls.process_index_gen(address)
|
|
1554
1581
|
main_process_index = next(process_index_gen)
|
xoscar/backends/router.py
CHANGED
|
@@ -17,10 +17,15 @@ from __future__ import annotations
|
|
|
17
17
|
|
|
18
18
|
import asyncio
|
|
19
19
|
import threading
|
|
20
|
-
from typing import Any,
|
|
20
|
+
from typing import Any, Optional, Type, Union
|
|
21
21
|
|
|
22
22
|
from .communication import Client, get_client_type
|
|
23
23
|
|
|
24
|
+
_CACHE_KEY_TYPE = Union[
|
|
25
|
+
tuple[str, Any, Optional[Type[Client]]],
|
|
26
|
+
tuple[str, Any, Optional[Type[Client]], Optional[tuple[str, ...]]],
|
|
27
|
+
]
|
|
28
|
+
|
|
24
29
|
|
|
25
30
|
class Router:
|
|
26
31
|
"""
|
|
@@ -32,6 +37,7 @@ class Router:
|
|
|
32
37
|
"_local_mapping",
|
|
33
38
|
"_mapping",
|
|
34
39
|
"_comm_config",
|
|
40
|
+
"_proxy_config",
|
|
35
41
|
"_cache_local",
|
|
36
42
|
)
|
|
37
43
|
|
|
@@ -56,6 +62,7 @@ class Router:
|
|
|
56
62
|
local_address: str | None,
|
|
57
63
|
mapping: dict[str, str] | None = None,
|
|
58
64
|
comm_config: dict | None = None,
|
|
65
|
+
proxy_config: dict | None = None,
|
|
59
66
|
):
|
|
60
67
|
self._curr_external_addresses = external_addresses
|
|
61
68
|
self._local_mapping = dict()
|
|
@@ -65,10 +72,11 @@ class Router:
|
|
|
65
72
|
mapping = dict()
|
|
66
73
|
self._mapping = mapping
|
|
67
74
|
self._comm_config = comm_config or dict()
|
|
75
|
+
self._proxy_config = proxy_config or dict()
|
|
68
76
|
self._cache_local = threading.local()
|
|
69
77
|
|
|
70
78
|
@property
|
|
71
|
-
def _cache(self) -> dict[
|
|
79
|
+
def _cache(self) -> dict[_CACHE_KEY_TYPE, Client]:
|
|
72
80
|
try:
|
|
73
81
|
return self._cache_local.cache
|
|
74
82
|
except AttributeError:
|
|
@@ -92,6 +100,7 @@ class Router:
|
|
|
92
100
|
self._local_mapping.update(router._local_mapping)
|
|
93
101
|
self._mapping.update(router._mapping)
|
|
94
102
|
self._comm_config.update(router._comm_config)
|
|
103
|
+
self._proxy_config.update(router._proxy_config)
|
|
95
104
|
self._cache_local = threading.local()
|
|
96
105
|
|
|
97
106
|
def remove_router(self, router: "Router"):
|
|
@@ -124,14 +133,23 @@ class Router:
|
|
|
124
133
|
external_address: str,
|
|
125
134
|
from_who: Any = None,
|
|
126
135
|
cached: bool = True,
|
|
136
|
+
proxy_addresses: list[str] | None = None,
|
|
127
137
|
**kw,
|
|
128
138
|
) -> Client:
|
|
129
139
|
async with self._lock:
|
|
130
|
-
|
|
131
|
-
|
|
140
|
+
proxy_addrs: tuple[str, ...] | None = (
|
|
141
|
+
tuple(proxy_addresses) if proxy_addresses else None
|
|
142
|
+
)
|
|
143
|
+
if (
|
|
144
|
+
cached
|
|
145
|
+
and (external_address, from_who, None, proxy_addrs) in self._cache
|
|
146
|
+
):
|
|
147
|
+
cached_client = self._cache[
|
|
148
|
+
external_address, from_who, None, proxy_addrs
|
|
149
|
+
]
|
|
132
150
|
if cached_client.closed:
|
|
133
151
|
# closed before, ignore it
|
|
134
|
-
del self._cache[external_address, from_who, None]
|
|
152
|
+
del self._cache[external_address, from_who, None, proxy_addrs]
|
|
135
153
|
else:
|
|
136
154
|
return cached_client
|
|
137
155
|
|
|
@@ -139,10 +157,22 @@ class Router:
|
|
|
139
157
|
if address is None:
|
|
140
158
|
# no inner address, just use external address
|
|
141
159
|
address = external_address
|
|
160
|
+
# check if proxy address exists
|
|
161
|
+
proxy_address = proxy_addresses[-1] if proxy_addresses else None
|
|
162
|
+
if proxy_address is None:
|
|
163
|
+
proxy_address = self.get_proxy(address)
|
|
164
|
+
if proxy_address and proxy_address != self.external_address:
|
|
165
|
+
address = proxy_address
|
|
166
|
+
else:
|
|
167
|
+
if new_proxy_address := self.get_proxy(proxy_address):
|
|
168
|
+
address = new_proxy_address
|
|
169
|
+
else:
|
|
170
|
+
address = proxy_address
|
|
171
|
+
|
|
142
172
|
client_type: Type[Client] = get_client_type(address)
|
|
143
173
|
client = await self._create_client(client_type, address, **kw)
|
|
144
174
|
if cached:
|
|
145
|
-
self._cache[external_address, from_who, None] = client
|
|
175
|
+
self._cache[external_address, from_who, None, proxy_addrs] = client
|
|
146
176
|
return client
|
|
147
177
|
|
|
148
178
|
async def _create_client(
|
|
@@ -158,7 +188,7 @@ class Router:
|
|
|
158
188
|
|
|
159
189
|
def _get_client_type_to_addresses(
|
|
160
190
|
self, external_address: str
|
|
161
|
-
) ->
|
|
191
|
+
) -> dict[Type[Client], str]:
|
|
162
192
|
client_type_to_addresses = dict()
|
|
163
193
|
client_type_to_addresses[get_client_type(external_address)] = external_address
|
|
164
194
|
if external_address in self._curr_external_addresses: # pragma: no cover
|
|
@@ -173,7 +203,7 @@ class Router:
|
|
|
173
203
|
client_type_to_addresses[client_type] = addr # type: ignore
|
|
174
204
|
return client_type_to_addresses
|
|
175
205
|
|
|
176
|
-
def get_all_client_types(self, external_address: str) ->
|
|
206
|
+
def get_all_client_types(self, external_address: str) -> list[Type[Client]]:
|
|
177
207
|
return list(self._get_client_type_to_addresses(external_address))
|
|
178
208
|
|
|
179
209
|
async def get_client_via_type(
|
|
@@ -205,3 +235,51 @@ class Router:
|
|
|
205
235
|
if cached:
|
|
206
236
|
self._cache[external_address, from_who, client_type] = client
|
|
207
237
|
return client
|
|
238
|
+
|
|
239
|
+
def get_proxy(self, from_addr: str) -> str | None:
|
|
240
|
+
"""
|
|
241
|
+
Get proxy address that sent to.
|
|
242
|
+
|
|
243
|
+
Some patterns can be supported:
|
|
244
|
+
|
|
245
|
+
1. Direct address mapping, e.g. mapping 127.0.0.1:12345 -> 127.0.0.1:12346
|
|
246
|
+
The message will be sent to 127.0.0.1:12346 as forward one.
|
|
247
|
+
2. Host match, e.g. mapping 127.0.0.1 -> 127.0.0.1:12346
|
|
248
|
+
All the messages that match the host, e.g. 127.0.0.1:12345 and 127.0.0.1:12347
|
|
249
|
+
will be sent to 127.0.0.1:12346 as forward one.
|
|
250
|
+
3. Wildcard, e.g. mapping * -> 127.0.0.1:12346
|
|
251
|
+
All the messages will be sent to 127.0.0.1:12346 as forward one.
|
|
252
|
+
"""
|
|
253
|
+
|
|
254
|
+
host = from_addr.split(":", 1)[0]
|
|
255
|
+
|
|
256
|
+
proxy_map = self._proxy_config
|
|
257
|
+
addr = proxy_map.get(from_addr)
|
|
258
|
+
if addr and addr != from_addr:
|
|
259
|
+
return addr
|
|
260
|
+
addr = proxy_map.get(host)
|
|
261
|
+
if addr and addr != from_addr:
|
|
262
|
+
return addr
|
|
263
|
+
addr = proxy_map.get("*")
|
|
264
|
+
if addr and addr != from_addr:
|
|
265
|
+
return addr
|
|
266
|
+
return None
|
|
267
|
+
|
|
268
|
+
def get_proxies(self, from_addr: str) -> list[str] | None:
|
|
269
|
+
"""
|
|
270
|
+
Get all proxies
|
|
271
|
+
|
|
272
|
+
e.g. Proxy mapping {'a': 'b', 'b': 'c'}
|
|
273
|
+
get_proxies('a') will return ['b', 'c']
|
|
274
|
+
"""
|
|
275
|
+
|
|
276
|
+
proxies: list[str] = []
|
|
277
|
+
while True:
|
|
278
|
+
proxy = self.get_proxy(from_addr)
|
|
279
|
+
if not proxies and not proxy:
|
|
280
|
+
return None
|
|
281
|
+
elif not proxy:
|
|
282
|
+
return proxies
|
|
283
|
+
else:
|
|
284
|
+
proxies.append(proxy)
|
|
285
|
+
from_addr = proxy
|
|
Binary file
|
|
Binary file
|
xoscar/core.pxd
CHANGED
xoscar/core.pyx
CHANGED
|
@@ -95,7 +95,7 @@ cpdef create_local_actor_ref(address, uid):
|
|
|
95
95
|
return None
|
|
96
96
|
|
|
97
97
|
|
|
98
|
-
cpdef create_actor_ref(address, uid):
|
|
98
|
+
cpdef create_actor_ref(address, uid, list proxy_addresses = None):
|
|
99
99
|
"""
|
|
100
100
|
Create an actor reference.
|
|
101
101
|
TODO(fyrestone): Remove the create_actor_ref in _utils.pyx
|
|
@@ -105,18 +105,20 @@ cpdef create_actor_ref(address, uid):
|
|
|
105
105
|
ActorRef or LocalActorRef
|
|
106
106
|
"""
|
|
107
107
|
actor = _get_local_actor(address, uid)
|
|
108
|
-
return ActorRef(address, uid)
|
|
108
|
+
return ActorRef(address, uid, proxy_addresses=proxy_addresses) \
|
|
109
|
+
if actor is None else LocalActorRef(actor)
|
|
109
110
|
|
|
110
111
|
|
|
111
112
|
cdef class ActorRef:
|
|
112
113
|
"""
|
|
113
114
|
Reference of an Actor at user side
|
|
114
115
|
"""
|
|
115
|
-
def __init__(self, str address, object uid):
|
|
116
|
+
def __init__(self, str address, object uid, list proxy_addresses = None):
|
|
116
117
|
if isinstance(uid, str):
|
|
117
118
|
uid = uid.encode()
|
|
118
119
|
self.uid = uid
|
|
119
120
|
self.address = address
|
|
121
|
+
self.proxy_addresses = proxy_addresses
|
|
120
122
|
self._methods = dict()
|
|
121
123
|
|
|
122
124
|
def destroy(self, object callback=None):
|
|
@@ -124,7 +126,7 @@ cdef class ActorRef:
|
|
|
124
126
|
return ctx.destroy_actor(self)
|
|
125
127
|
|
|
126
128
|
def __reduce__(self):
|
|
127
|
-
return create_actor_ref, (self.address, self.uid)
|
|
129
|
+
return create_actor_ref, (self.address, self.uid, self.proxy_addresses)
|
|
128
130
|
|
|
129
131
|
def __getattr__(self, item):
|
|
130
132
|
if item.startswith('_') and item not in ["__xoscar_next__", "__xoscar_destroy_generator__"]:
|
|
@@ -146,7 +148,11 @@ cdef class ActorRef:
|
|
|
146
148
|
return False
|
|
147
149
|
|
|
148
150
|
def __repr__(self):
|
|
149
|
-
|
|
151
|
+
if not self.proxy_addresses:
|
|
152
|
+
return 'ActorRef(uid={!r}, address={!r})'.format(self.uid, self.address)
|
|
153
|
+
else:
|
|
154
|
+
return (f"ActorRef(uid={self.uid}, address={self.address}, "
|
|
155
|
+
f"proxy_addresses={self.proxy_addresses})")
|
|
150
156
|
|
|
151
157
|
|
|
152
158
|
cdef class _DelayedArgument:
|
xoscar/serialization/__init__.py
CHANGED
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
# See the License for the specific language governing permissions and
|
|
14
14
|
# limitations under the License.
|
|
15
15
|
|
|
16
|
-
from . import cuda, exception, numpy, scipy
|
|
16
|
+
from . import cuda, exception, mlx, numpy, scipy
|
|
17
17
|
from .aio import AioDeserializer, AioSerializer
|
|
18
18
|
from .core import Serializer, deserialize, serialize, serialize_with_spawn
|
|
19
19
|
|
|
20
|
-
del cuda, numpy, scipy, exception
|
|
20
|
+
del cuda, numpy, scipy, mlx, exception
|
|
Binary file
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# Copyright 2022-2025 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
|
+
from typing import Any, List
|
|
16
|
+
|
|
17
|
+
import numpy as np
|
|
18
|
+
|
|
19
|
+
from ..utils import lazy_import
|
|
20
|
+
from .core import Serializer, buffered
|
|
21
|
+
|
|
22
|
+
mx = lazy_import("mlx.core")
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
dtype_map = {
|
|
26
|
+
"b": np.int8,
|
|
27
|
+
"B": np.uint8,
|
|
28
|
+
"h": np.int16,
|
|
29
|
+
"H": np.uint16,
|
|
30
|
+
"i": np.int32,
|
|
31
|
+
"I": np.uint32,
|
|
32
|
+
"q": np.int64,
|
|
33
|
+
"Q": np.uint64,
|
|
34
|
+
"e": np.float16,
|
|
35
|
+
"f": np.float32,
|
|
36
|
+
"d": np.float64,
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class MLXSerislizer(Serializer):
|
|
41
|
+
@buffered
|
|
42
|
+
def serial(self, obj: "mx.array", context: dict): # type: ignore
|
|
43
|
+
mv = memoryview(obj)
|
|
44
|
+
header = dict(shape=mv.shape, format=mv.format)
|
|
45
|
+
if not mv.c_contiguous:
|
|
46
|
+
mv = memoryview(bytes(mv))
|
|
47
|
+
return (header,), [mv], True
|
|
48
|
+
|
|
49
|
+
def deserial(self, serialized: tuple, context: dict, subs: List[Any]):
|
|
50
|
+
header = serialized[0]
|
|
51
|
+
shape, format = header["shape"], header["format"]
|
|
52
|
+
mv = memoryview(subs[0])
|
|
53
|
+
if mv.format != format:
|
|
54
|
+
dtype = dtype_map.get(format, np.uint8)
|
|
55
|
+
np_arr = np.frombuffer(mv, dtype=dtype).reshape(shape) # parse
|
|
56
|
+
mv = memoryview(np_arr) # recreate memoryview
|
|
57
|
+
elif mv.shape != shape:
|
|
58
|
+
mv = mv.cast(format, shape) # cast directly
|
|
59
|
+
return mx.array(mv)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
if mx is not None:
|
|
63
|
+
MLXSerislizer.register(mx.array)
|
|
@@ -1,79 +1,80 @@
|
|
|
1
|
-
xoscar-0.
|
|
2
|
-
xoscar-0.
|
|
3
|
-
xoscar-0.
|
|
4
|
-
xoscar-0.
|
|
1
|
+
xoscar-0.5.0.dist-info/WHEEL,sha256=OyU_a3_0g4nHrDfscT3ntE6UTOgLWum2-dKsAfzpQqc,150
|
|
2
|
+
xoscar-0.5.0.dist-info/RECORD,,
|
|
3
|
+
xoscar-0.5.0.dist-info/top_level.txt,sha256=vYlqqY4Nys8Thm1hePIuUv8eQePdULVWMmt7lXtX_ZA,21
|
|
4
|
+
xoscar-0.5.0.dist-info/METADATA,sha256=O_aAm6bQaZF9HvTXJsquvDrePWla--QdgpuPPnlqFds,9042
|
|
5
|
+
xoscar/context.cpython-39-aarch64-linux-gnu.so,sha256=qpQRWk0vMVKnoiP-MIP2hcUzYGhQnsebZSHLMK8trRE,1443792
|
|
6
|
+
xoscar/core.pxd,sha256=I_C2ka7XryyGnnAVXUVm8xfS1gtIrCs6X-9rswgOcUU,1317
|
|
7
|
+
xoscar/core.pyx,sha256=phN-yYV0A0QI8WFi2jCu0nc4CnShTepfDi0V7ZrLYPY,22092
|
|
8
|
+
xoscar/backend.py,sha256=is436OPkZfSpQXaoqTRVta5eoye_pp45RFgCstAk2hU,1850
|
|
9
|
+
xoscar/_version.py,sha256=ClSPrUjgGRGHIkVMQV9XQnkQ-n0akJMnq_rh819nqFE,23719
|
|
10
|
+
xoscar/constants.py,sha256=QHHSREw6uWBBjQDCFqlNfTvBZgniJPGy42KSIsR8Fqw,787
|
|
11
|
+
xoscar/api.py,sha256=3hztPoOxg8A_mlhWyWgVP7FMXG0PATA1TP4Rbaj7A-g,13327
|
|
12
|
+
xoscar/driver.py,sha256=498fowtJr6b3FE8FIOA_Tc1Vwx88nfZw7p0FxrML0h4,1372
|
|
5
13
|
xoscar/errors.py,sha256=wBlQOKsXf0Fc4skN39tDie0YZT-VIAuLNRgoDl2pZcA,1241
|
|
6
|
-
xoscar/
|
|
14
|
+
xoscar/_utils.cpython-39-aarch64-linux-gnu.so,sha256=v5F2FYKiXpV-tMJmjNrMkeaZBvopmSVpRIPNwXuiMdM,1181960
|
|
7
15
|
xoscar/utils.py,sha256=jUw6OICZUPBbmS1b3GE4vLctJf6fCKXrYtLtBuK-Oqc,16483
|
|
8
16
|
xoscar/context.pxd,sha256=qKa0OyDPZtVymftSh447m-RzFZgmz8rGqQBa7qlauvc,725
|
|
9
|
-
xoscar/
|
|
10
|
-
xoscar/
|
|
11
|
-
xoscar/core.pyx,sha256=Aqc2i8Fetsd5wRAPF4kL0ddnBZn3E2HRNCvup79BbQc,21730
|
|
12
|
-
xoscar/context.cpython-39-aarch64-linux-gnu.so,sha256=LV5N5Jhm721j5CYlFbWRXGsrjI2a6tKZj62HQ11jvDg,1443768
|
|
13
|
-
xoscar/debug.py,sha256=9Z8SgE2WaKYQcyDo-5-DxEJQ533v7kWjrvCd28pSx3E,5069
|
|
14
|
-
xoscar/_utils.cpython-39-aarch64-linux-gnu.so,sha256=WLy2j01X0tgDymLsJl3M1KDgDLGsgaBVDCbAV0kmgRg,1107656
|
|
15
|
-
xoscar/constants.py,sha256=QHHSREw6uWBBjQDCFqlNfTvBZgniJPGy42KSIsR8Fqw,787
|
|
16
|
-
xoscar/driver.py,sha256=498fowtJr6b3FE8FIOA_Tc1Vwx88nfZw7p0FxrML0h4,1372
|
|
17
|
+
xoscar/libcpp.pxd,sha256=DJqBxLFOKL4iRr9Kale5UH3rbvPRD1x5bTSOPHFpz9I,1147
|
|
18
|
+
xoscar/nvutils.py,sha256=qmW4mKLU0WB2yCs198ccQOgLL02zB7Fsa-AotO3NOmg,20412
|
|
17
19
|
xoscar/profiling.py,sha256=BC5OF0HzSaXv8V7w-y-B8r5gV5DgxHFoTEIF6jCMioQ,8015
|
|
18
20
|
xoscar/__init__.py,sha256=0zX8kKaio3ZIrlzB79WybcravMJw1OxPWjDspTgJFyQ,1608
|
|
19
|
-
xoscar/
|
|
20
|
-
xoscar/core.cpython-39-aarch64-linux-gnu.so,sha256=ntP_ZHnfDSUQgePgqQMMTCvSaTNvW441nwh2mCQGdIk,3476960
|
|
21
|
-
xoscar/core.pxd,sha256=4lBq8J0kjcXcsGuvN7Kv4xcL5liHwTTFWlqyK7XAEnw,1280
|
|
22
|
-
xoscar/_version.py,sha256=ClSPrUjgGRGHIkVMQV9XQnkQ-n0akJMnq_rh819nqFE,23719
|
|
23
|
-
xoscar/context.pyx,sha256=8CdgPnWcE9eOp3N600WgDQ03MCi8P73eUOGcfV7Zksg,10942
|
|
24
|
-
xoscar/backend.py,sha256=is436OPkZfSpQXaoqTRVta5eoye_pp45RFgCstAk2hU,1850
|
|
25
|
-
xoscar/libcpp.pxd,sha256=DJqBxLFOKL4iRr9Kale5UH3rbvPRD1x5bTSOPHFpz9I,1147
|
|
21
|
+
xoscar/core.cpython-39-aarch64-linux-gnu.so,sha256=FoIqGQbK82pTGFndl4uOyTOPO7EHYQndUAmQVIFR_Xs,3505232
|
|
26
22
|
xoscar/batch.py,sha256=DpArS0L3WYJ_HVPG-6hSYEwoAFY1mY2-mlC4Jp5M_Dw,7872
|
|
23
|
+
xoscar/_utils.pxd,sha256=5KYAL3jfPdejsHnrGGT2s--ZUX5SXznQWpHVSno429k,1157
|
|
24
|
+
xoscar/context.pyx,sha256=8CdgPnWcE9eOp3N600WgDQ03MCi8P73eUOGcfV7Zksg,10942
|
|
25
|
+
xoscar/debug.py,sha256=9Z8SgE2WaKYQcyDo-5-DxEJQ533v7kWjrvCd28pSx3E,5069
|
|
26
|
+
xoscar/_utils.pyx,sha256=6iqO4eTwEI-n9i39n_TKz7MWqbytMRnVNubdJ5egL6o,7279
|
|
27
27
|
xoscar/collective/process_group.py,sha256=zy7LcIFnEcmrcxuECI89v0bQlUbSqQMkVyBw468WBnk,22599
|
|
28
|
-
xoscar/collective/utils.py,sha256=3S4qF4JEnAUD3RiWVBUj-ZptL83CBSwGYyVZyIasAsE,1178
|
|
29
|
-
xoscar/collective/common.py,sha256=INAnISbfnRicbbbDHTqbSr9ITb89ZphH5BUkSpEdXXU,3561
|
|
30
|
-
xoscar/collective/__init__.py,sha256=XsClIkO_3Jd8GDifYuAbZCmJLAo9ZqGvnjUn9iuogmU,774
|
|
31
28
|
xoscar/collective/core.py,sha256=NVR-7Iaq3aDPCN6fgXcq9Ew6uFEszRwxYqmUG9FLcws,23502
|
|
32
29
|
xoscar/collective/xoscar_pygloo.cpython-39-aarch64-linux-gnu.so,sha256=cZVQDMX6ci3d3GJxLujGNPzpmE6cF8TfqSifaTzxOaI,1583168
|
|
33
|
-
xoscar/
|
|
34
|
-
xoscar/
|
|
35
|
-
xoscar/
|
|
36
|
-
xoscar/
|
|
37
|
-
xoscar/
|
|
38
|
-
xoscar/
|
|
39
|
-
xoscar/
|
|
40
|
-
xoscar/metrics/backends/console/__init__.py,sha256=h_JgzSqV5lP6vQ6XX_17kE4IY4BRnvKta_7VLQAL1ms,581
|
|
41
|
-
xoscar/backends/context.py,sha256=Vr_PibRxYCDQ_gYK7r-BOlw9TXw8VQbFsVTH7K7mHPk,15470
|
|
42
|
-
xoscar/backends/__init__.py,sha256=VHEBQcUWM5bj027W8EUf9PiJUAP7JoMrRw3Tsvy5ySw,643
|
|
43
|
-
xoscar/backends/core.py,sha256=rXJ73IC5lgERXCWvVrDEEyGAILlwVJs7XIWBCFUEVCc,10166
|
|
30
|
+
xoscar/collective/utils.py,sha256=3S4qF4JEnAUD3RiWVBUj-ZptL83CBSwGYyVZyIasAsE,1178
|
|
31
|
+
xoscar/collective/__init__.py,sha256=XsClIkO_3Jd8GDifYuAbZCmJLAo9ZqGvnjUn9iuogmU,774
|
|
32
|
+
xoscar/collective/common.py,sha256=INAnISbfnRicbbbDHTqbSr9ITb89ZphH5BUkSpEdXXU,3561
|
|
33
|
+
xoscar/backends/context.py,sha256=XfDPG2eDhAhE6hWBEkEsHTnyyOYN9R3houlMjAL7BFw,16329
|
|
34
|
+
xoscar/backends/message.pyx,sha256=krGVtZ1YDaZX8yWhaNHwZiudQooLvcGlw6x3Sq7jxjE,19685
|
|
35
|
+
xoscar/backends/pool.py,sha256=omYqaPyv1WW1YrU3OSZhk3kr0JyfI7MYhBtTemVJKZA,60895
|
|
36
|
+
xoscar/backends/core.py,sha256=EH-fHlV9x3bnruEHaUtGYO7osKLfLJ4AQHtuzA_mr2g,10857
|
|
44
37
|
xoscar/backends/allocate_strategy.py,sha256=tC1Nbq2tJohahUwd-zoRYHEDX65wyuX8tmeY45uWj_w,4845
|
|
45
|
-
xoscar/backends/
|
|
46
|
-
xoscar/backends/
|
|
47
|
-
xoscar/backends/message.
|
|
48
|
-
xoscar/backends/
|
|
49
|
-
xoscar/backends/
|
|
50
|
-
xoscar/backends/
|
|
51
|
-
xoscar/backends/test/pool.py,sha256=TW4X6J-92Pti66103poQBNDBznX6CBD3RLOc_zixjTo,7257
|
|
52
|
-
xoscar/backends/test/backend.py,sha256=nv9WFhH5Bbq4Q1HB9yfpciZBaeHT4IQAtzugBWESrUY,1263
|
|
38
|
+
xoscar/backends/config.py,sha256=4tZMiXAMMS8qQ4SX_LjONLtSQVfZTx3m-IK3EqbkYdk,5375
|
|
39
|
+
xoscar/backends/__init__.py,sha256=VHEBQcUWM5bj027W8EUf9PiJUAP7JoMrRw3Tsvy5ySw,643
|
|
40
|
+
xoscar/backends/message.cpython-39-aarch64-linux-gnu.so,sha256=EWCPWsLgHq4S8w1WzPvvmhX7tZd2mO76lJ5zxVxJ2O4,3337768
|
|
41
|
+
xoscar/backends/router.py,sha256=MVl5naz-FYf-Wla7XRn3kRxOpWV0SjKDsKNluifVA8M,10532
|
|
42
|
+
xoscar/backends/communication/ucx.py,sha256=_Dp9Ld2MWIa1txSGMnmfYwJDT0esxS-GOd2FQ4BdHiM,19960
|
|
43
|
+
xoscar/backends/communication/base.py,sha256=0P4Tr35GSWpRp394e9jVWUUoKKa-gIk177eYPw1BnSU,7421
|
|
53
44
|
xoscar/backends/communication/dummy.py,sha256=6kLkxjNk4xTQ-IlNZD6cftNCx5UsGOur2jk7ikrNUCg,8157
|
|
54
45
|
xoscar/backends/communication/errors.py,sha256=V3CdBe2xX9Rwv32f2dH2Msc84yaUhlyerZ42-739o1Q,723
|
|
55
|
-
xoscar/backends/communication/utils.py,sha256=AmovE-hmWLXNCPwHafYuaRjOk8m42BUyT3XBqfXQRVI,3664
|
|
56
|
-
xoscar/backends/communication/__init__.py,sha256=tB05BlK63iWQnfJgRzKt4mFKRtmWUki5hUGSZQwAotc,1050
|
|
57
46
|
xoscar/backends/communication/core.py,sha256=sJeE3foRIqVPXldzYpFKHDSsabfAIFBU4JuXY4OyklY,2130
|
|
58
|
-
xoscar/backends/communication/
|
|
59
|
-
xoscar/backends/communication/
|
|
60
|
-
xoscar/backends/communication/
|
|
47
|
+
xoscar/backends/communication/socket.py,sha256=6Pf9RJWHuvobjZ1eAU6bUuGY7PzYga3Vyc4PAKF-k2M,14428
|
|
48
|
+
xoscar/backends/communication/utils.py,sha256=AmovE-hmWLXNCPwHafYuaRjOk8m42BUyT3XBqfXQRVI,3664
|
|
49
|
+
xoscar/backends/communication/__init__.py,sha256=oFIg83Ga93-AhrG52TE85Z2LgpGZu1RCgQu1RWi62zQ,1063
|
|
50
|
+
xoscar/backends/test/backend.py,sha256=nv9WFhH5Bbq4Q1HB9yfpciZBaeHT4IQAtzugBWESrUY,1263
|
|
51
|
+
xoscar/backends/test/pool.py,sha256=TW4X6J-92Pti66103poQBNDBznX6CBD3RLOc_zixjTo,7257
|
|
52
|
+
xoscar/backends/test/__init__.py,sha256=j2ZfD6prD9WjUxRUDC7Eq5Z7N7TkL6fFr59oNyc_vY4,682
|
|
53
|
+
xoscar/backends/indigen/backend.py,sha256=znl_fZzWGEtLH8hZ9j9Kkf0fva25jEem2_KO7I1RVvc,1612
|
|
61
54
|
xoscar/backends/indigen/driver.py,sha256=VGzkacYKykegW5qhCuhx01gdgBZEKJjNIyfNCnA6Nm8,952
|
|
55
|
+
xoscar/backends/indigen/pool.py,sha256=v0Ps79W0WyeFSt2YxCJnh7q_1dnRQmo9887gcW3pNoc,17226
|
|
62
56
|
xoscar/backends/indigen/__init__.py,sha256=tKHP5ClzedBRBpZsLRVErR3EUNbbDm4CY4u0rCFJr44,685
|
|
63
|
-
xoscar/
|
|
64
|
-
xoscar/
|
|
65
|
-
xoscar/
|
|
57
|
+
xoscar/metrics/api.py,sha256=BBlMIFvVAGVfrtpeJ1YlH9Tqhy9OzGavwvGyeHcQ0Tk,8856
|
|
58
|
+
xoscar/metrics/__init__.py,sha256=9Badi7rxYikGm2dQiNCrj9GgMRBxwuR3JaEKcFZmfak,705
|
|
59
|
+
xoscar/metrics/backends/metric.py,sha256=aPhyc8JgH22L3rcHP8IjsmgrhSODjg6B5TZVnre97y8,4446
|
|
60
|
+
xoscar/metrics/backends/__init__.py,sha256=h_JgzSqV5lP6vQ6XX_17kE4IY4BRnvKta_7VLQAL1ms,581
|
|
61
|
+
xoscar/metrics/backends/console/__init__.py,sha256=h_JgzSqV5lP6vQ6XX_17kE4IY4BRnvKta_7VLQAL1ms,581
|
|
62
|
+
xoscar/metrics/backends/console/console_metric.py,sha256=y5CCtH33j3AqI5_Uhwi4mgOcAhyhb4cWv_YvR6fxcbQ,2082
|
|
63
|
+
xoscar/metrics/backends/prometheus/prometheus_metric.py,sha256=MxoMvVrg0pOkKpkjJ0PcAuEaaEJR2FZljmPrLjQ1-oc,2050
|
|
64
|
+
xoscar/metrics/backends/prometheus/__init__.py,sha256=h_JgzSqV5lP6vQ6XX_17kE4IY4BRnvKta_7VLQAL1ms,581
|
|
66
65
|
xoscar/aio/lru.py,sha256=rpXCqSLtPV5xnWtd6uDwQQFGgIPEgvmWEQDkPNUx9cM,6311
|
|
67
|
-
xoscar/aio/
|
|
66
|
+
xoscar/aio/file.py,sha256=PBtkLp-Q7XtYl-zk00s18TtgIrkNr60J3Itf66ctO1o,1486
|
|
68
67
|
xoscar/aio/base.py,sha256=9j0f1piwfE5R5GIvV212vSD03ixdaeSzSSsO2kxJZVE,2249
|
|
69
68
|
xoscar/aio/parallelism.py,sha256=VSsjk8wP-Bw7tLeUsTyLVNgp91thjxEfE3pCrw_vF5Q,1293
|
|
70
|
-
xoscar/
|
|
71
|
-
xoscar/serialization/__init__.py,sha256=5Y_C3cYbQJIZ09LRjeCf-jrkLma7mfN8I5bznHrdsbg,846
|
|
72
|
-
xoscar/serialization/core.cpython-39-aarch64-linux-gnu.so,sha256=TdQdUNxNy34Amc0tPv9VRVE-RNepWa64LCG9yAStiBA,3203944
|
|
73
|
-
xoscar/serialization/exception.py,sha256=Jy8Lsk0z-VJyEUaWeuZIwkmxqaoB-nLKMa1D15Cl4js,1634
|
|
69
|
+
xoscar/aio/__init__.py,sha256=kViDKR_kJe59VQViHITKEfBcIgN4ZJblUyd8zl0E3ZI,675
|
|
74
70
|
xoscar/serialization/core.pxd,sha256=k4RoJgX5E5LGs4jdCQ7vvcn26MabXbrWoWhkO49X6YI,985
|
|
75
|
-
xoscar/serialization/
|
|
71
|
+
xoscar/serialization/core.pyx,sha256=bjR-zXGm9qersk7kYPzpjpMIxDl_Auur4BCubRfKmfA,29626
|
|
76
72
|
xoscar/serialization/aio.py,sha256=5DySPgDxU43ec7_5Ct44-Oqt7YNSJBfuf8VdQgQlChA,4731
|
|
77
|
-
xoscar/serialization/
|
|
73
|
+
xoscar/serialization/mlx.py,sha256=N_cvbTUBKc14XWYsPIMz4kDstyRN1DNhb4BVRgnQm8Y,1872
|
|
78
74
|
xoscar/serialization/pyfury.py,sha256=sifOnVMYoS82PzZEkzkfxesmMHei23k5UAUUKUyoOYQ,1163
|
|
75
|
+
xoscar/serialization/scipy.py,sha256=yOEi0NB8cqQ6e2UnCZ1w006RsB7T725tIL-DM_hNcsU,2482
|
|
76
|
+
xoscar/serialization/__init__.py,sha256=v76XC2OQLp-Yk4_U3_IVguEylMeyRw1UrkU_DPDMh0U,856
|
|
77
|
+
xoscar/serialization/numpy.py,sha256=5Kem87CvpJmzUMp3QHk4WeHU30FoQWTJJP2SwIcaQG0,2919
|
|
78
|
+
xoscar/serialization/exception.py,sha256=Jy8Lsk0z-VJyEUaWeuZIwkmxqaoB-nLKMa1D15Cl4js,1634
|
|
79
|
+
xoscar/serialization/core.cpython-39-aarch64-linux-gnu.so,sha256=-s3jpW0EsGNGS4r8EG7LpjZUSQVXB87tBcNev-DIdqk,3203944
|
|
79
80
|
xoscar/serialization/cuda.py,sha256=iFUEnN4SiquBIhyieyOrfw3TnKnW-tU_vYgqOxO_DrA,3758
|
|
File without changes
|
|
File without changes
|