xoscar 0.4.0__cp312-cp312-win_amd64.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.

Files changed (83) hide show
  1. xoscar/__init__.py +60 -0
  2. xoscar/_utils.cp312-win_amd64.pyd +0 -0
  3. xoscar/_utils.pxd +36 -0
  4. xoscar/_utils.pyx +241 -0
  5. xoscar/_version.py +693 -0
  6. xoscar/aio/__init__.py +16 -0
  7. xoscar/aio/base.py +86 -0
  8. xoscar/aio/file.py +59 -0
  9. xoscar/aio/lru.py +228 -0
  10. xoscar/aio/parallelism.py +39 -0
  11. xoscar/api.py +493 -0
  12. xoscar/backend.py +67 -0
  13. xoscar/backends/__init__.py +14 -0
  14. xoscar/backends/allocate_strategy.py +160 -0
  15. xoscar/backends/communication/__init__.py +30 -0
  16. xoscar/backends/communication/base.py +315 -0
  17. xoscar/backends/communication/core.py +69 -0
  18. xoscar/backends/communication/dummy.py +242 -0
  19. xoscar/backends/communication/errors.py +20 -0
  20. xoscar/backends/communication/socket.py +414 -0
  21. xoscar/backends/communication/ucx.py +531 -0
  22. xoscar/backends/communication/utils.py +97 -0
  23. xoscar/backends/config.py +145 -0
  24. xoscar/backends/context.py +404 -0
  25. xoscar/backends/core.py +193 -0
  26. xoscar/backends/indigen/__init__.py +16 -0
  27. xoscar/backends/indigen/backend.py +51 -0
  28. xoscar/backends/indigen/driver.py +26 -0
  29. xoscar/backends/indigen/pool.py +469 -0
  30. xoscar/backends/message.cp312-win_amd64.pyd +0 -0
  31. xoscar/backends/message.pyi +239 -0
  32. xoscar/backends/message.pyx +599 -0
  33. xoscar/backends/pool.py +1596 -0
  34. xoscar/backends/router.py +207 -0
  35. xoscar/backends/test/__init__.py +16 -0
  36. xoscar/backends/test/backend.py +38 -0
  37. xoscar/backends/test/pool.py +208 -0
  38. xoscar/batch.py +256 -0
  39. xoscar/collective/__init__.py +27 -0
  40. xoscar/collective/common.py +102 -0
  41. xoscar/collective/core.py +737 -0
  42. xoscar/collective/process_group.py +687 -0
  43. xoscar/collective/utils.py +41 -0
  44. xoscar/collective/uv.dll +0 -0
  45. xoscar/collective/xoscar_pygloo.cp312-win_amd64.pyd +0 -0
  46. xoscar/collective/xoscar_pygloo.pyi +239 -0
  47. xoscar/constants.py +21 -0
  48. xoscar/context.cp312-win_amd64.pyd +0 -0
  49. xoscar/context.pxd +21 -0
  50. xoscar/context.pyx +368 -0
  51. xoscar/core.cp312-win_amd64.pyd +0 -0
  52. xoscar/core.pxd +50 -0
  53. xoscar/core.pyx +658 -0
  54. xoscar/debug.py +188 -0
  55. xoscar/driver.py +42 -0
  56. xoscar/errors.py +63 -0
  57. xoscar/libcpp.pxd +31 -0
  58. xoscar/metrics/__init__.py +21 -0
  59. xoscar/metrics/api.py +288 -0
  60. xoscar/metrics/backends/__init__.py +13 -0
  61. xoscar/metrics/backends/console/__init__.py +13 -0
  62. xoscar/metrics/backends/console/console_metric.py +82 -0
  63. xoscar/metrics/backends/metric.py +149 -0
  64. xoscar/metrics/backends/prometheus/__init__.py +13 -0
  65. xoscar/metrics/backends/prometheus/prometheus_metric.py +70 -0
  66. xoscar/nvutils.py +717 -0
  67. xoscar/profiling.py +260 -0
  68. xoscar/serialization/__init__.py +20 -0
  69. xoscar/serialization/aio.py +138 -0
  70. xoscar/serialization/core.cp312-win_amd64.pyd +0 -0
  71. xoscar/serialization/core.pxd +28 -0
  72. xoscar/serialization/core.pyi +57 -0
  73. xoscar/serialization/core.pyx +944 -0
  74. xoscar/serialization/cuda.py +111 -0
  75. xoscar/serialization/exception.py +48 -0
  76. xoscar/serialization/numpy.py +82 -0
  77. xoscar/serialization/pyfury.py +37 -0
  78. xoscar/serialization/scipy.py +72 -0
  79. xoscar/utils.py +517 -0
  80. xoscar-0.4.0.dist-info/METADATA +223 -0
  81. xoscar-0.4.0.dist-info/RECORD +83 -0
  82. xoscar-0.4.0.dist-info/WHEEL +5 -0
  83. xoscar-0.4.0.dist-info/top_level.txt +2 -0
@@ -0,0 +1,193 @@
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
+ from __future__ import annotations
17
+
18
+ import asyncio
19
+ import copy
20
+ import logging
21
+ from typing import Type, Union
22
+
23
+ from .._utils import Timer
24
+ from ..errors import ServerClosed
25
+ from ..profiling import get_profiling_data
26
+ from .communication import Client, UCXClient
27
+ from .message import DeserializeMessageFailed, ErrorMessage, ResultMessage, _MessageBase
28
+ from .router import Router
29
+
30
+ ResultMessageType = Union[ResultMessage, ErrorMessage]
31
+ logger = logging.getLogger(__name__)
32
+
33
+
34
+ class ActorCaller:
35
+ __slots__ = "_client_to_message_futures", "_clients", "_profiling_data"
36
+
37
+ _client_to_message_futures: dict[Client, dict[bytes, asyncio.Future]]
38
+ _clients: dict[Client, asyncio.Task]
39
+
40
+ def __init__(self):
41
+ self._client_to_message_futures = dict()
42
+ self._clients = dict()
43
+ self._profiling_data = get_profiling_data()
44
+
45
+ def _listen_client(self, client: Client):
46
+ if client not in self._clients:
47
+ self._clients[client] = asyncio.create_task(self._listen(client))
48
+ self._client_to_message_futures[client] = dict()
49
+ client_count = len(self._clients)
50
+ if client_count >= 100: # pragma: no cover
51
+ if (client_count - 100) % 10 == 0: # pragma: no cover
52
+ logger.warning(
53
+ "Actor caller has created too many clients (%s >= 100), "
54
+ "the global router may not be set.",
55
+ client_count,
56
+ )
57
+
58
+ async def get_client_via_type(
59
+ self, router: Router, dest_address: str, client_type: Type[Client]
60
+ ) -> Client:
61
+ client = await router.get_client_via_type(
62
+ dest_address, client_type, from_who=self
63
+ )
64
+ self._listen_client(client)
65
+ return client
66
+
67
+ async def get_client(self, router: Router, dest_address: str) -> Client:
68
+ client = await router.get_client(dest_address, from_who=self)
69
+ self._listen_client(client)
70
+ return client
71
+
72
+ async def _listen(self, client: Client):
73
+ while not client.closed:
74
+ try:
75
+ try:
76
+ message: _MessageBase = await client.recv()
77
+ except (EOFError, ConnectionError, BrokenPipeError):
78
+ # remote server closed, close client and raise ServerClosed
79
+ try:
80
+ await client.close()
81
+ except (ConnectionError, BrokenPipeError):
82
+ # close failed, ignore it
83
+ pass
84
+ raise ServerClosed(
85
+ f"Remote server {client.dest_address} closed"
86
+ ) from None
87
+ future = self._client_to_message_futures[client].pop(message.message_id)
88
+ if not future.done():
89
+ future.set_result(message)
90
+ except DeserializeMessageFailed as e:
91
+ message_id = e.message_id
92
+ future = self._client_to_message_futures[client].pop(message_id)
93
+ future.set_exception(e.__cause__) # type: ignore
94
+ except Exception as e: # noqa: E722 # pylint: disable=bare-except
95
+ message_futures = self._client_to_message_futures[client]
96
+ self._client_to_message_futures[client] = dict()
97
+ for future in message_futures.values():
98
+ future.set_exception(copy.copy(e))
99
+ finally:
100
+ # message may have Ray ObjectRef, delete it early in case next loop doesn't run
101
+ # as soon as expected.
102
+ try:
103
+ del message
104
+ except NameError:
105
+ pass
106
+ try:
107
+ del future
108
+ except NameError:
109
+ pass
110
+ await asyncio.sleep(0)
111
+
112
+ message_futures = self._client_to_message_futures[client]
113
+ self._client_to_message_futures[client] = dict()
114
+ error = ServerClosed(f"Remote server {client.dest_address} closed")
115
+ for future in message_futures.values():
116
+ future.set_exception(copy.copy(error))
117
+
118
+ async def call_with_client(
119
+ self, client: Client, message: _MessageBase, wait: bool = True
120
+ ) -> ResultMessage | ErrorMessage | asyncio.Future:
121
+ loop = asyncio.get_running_loop()
122
+ wait_response = loop.create_future()
123
+ self._client_to_message_futures[client][message.message_id] = wait_response
124
+
125
+ with Timer() as timer:
126
+ try:
127
+ await client.send(message)
128
+ except ConnectionError:
129
+ try:
130
+ await client.close()
131
+ except ConnectionError:
132
+ # close failed, ignore it
133
+ pass
134
+ raise ServerClosed(f"Remote server {client.dest_address} closed")
135
+
136
+ if not wait:
137
+ r = wait_response
138
+ else:
139
+ r = await wait_response
140
+
141
+ self._profiling_data.collect_actor_call(message, timer.duration)
142
+ return r
143
+
144
+ async def call_send_buffers(
145
+ self,
146
+ client: UCXClient,
147
+ local_buffers: list,
148
+ meta_message: _MessageBase,
149
+ wait: bool = True,
150
+ ) -> ResultMessage | ErrorMessage | asyncio.Future:
151
+ loop = asyncio.get_running_loop()
152
+ wait_response = loop.create_future()
153
+ self._client_to_message_futures[client][meta_message.message_id] = wait_response
154
+
155
+ with Timer() as timer:
156
+ try:
157
+ await client.send_buffers(local_buffers, meta_message)
158
+ except ConnectionError: # pragma: no cover
159
+ try:
160
+ await client.close()
161
+ except ConnectionError:
162
+ # close failed, ignore it
163
+ pass
164
+ raise ServerClosed(f"Remote server {client.dest_address} closed")
165
+
166
+ if not wait: # pragma: no cover
167
+ r = wait_response
168
+ else:
169
+ r = await wait_response
170
+
171
+ self._profiling_data.collect_actor_call(meta_message, timer.duration)
172
+ return r
173
+
174
+ async def call(
175
+ self,
176
+ router: Router,
177
+ dest_address: str,
178
+ message: _MessageBase,
179
+ wait: bool = True,
180
+ ) -> ResultMessage | ErrorMessage | asyncio.Future:
181
+ client = await self.get_client(router, dest_address)
182
+ return await self.call_with_client(client, message, wait)
183
+
184
+ async def stop(self):
185
+ try:
186
+ await asyncio.gather(*[client.close() for client in self._clients])
187
+ except (ConnectionError, ServerClosed):
188
+ pass
189
+ self.cancel_tasks()
190
+
191
+ def cancel_tasks(self):
192
+ # cancel listening for all clients
193
+ _ = [task.cancel() for task in self._clients.values()]
@@ -0,0 +1,16 @@
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
+ from .backend import IndigenActorBackend
@@ -0,0 +1,51 @@
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
+ from __future__ import annotations
17
+
18
+ from ...backend import BaseActorBackend, register_backend
19
+ from ..context import IndigenActorContext
20
+ from .driver import IndigenActorDriver
21
+ from .pool import MainActorPool
22
+
23
+ __all__ = ["IndigenActorBackend"]
24
+
25
+
26
+ @register_backend
27
+ class IndigenActorBackend(BaseActorBackend):
28
+ @staticmethod
29
+ def name():
30
+ # None means Indigen is default scheme
31
+ # ucx can be recognized as Indigen backend as well
32
+ return [None, "ucx"]
33
+
34
+ @staticmethod
35
+ def get_context_cls():
36
+ return IndigenActorContext
37
+
38
+ @staticmethod
39
+ def get_driver_cls():
40
+ return IndigenActorDriver
41
+
42
+ @classmethod
43
+ async def create_actor_pool(
44
+ cls, address: str, n_process: int | None = None, **kwargs
45
+ ):
46
+ from ..pool import create_actor_pool
47
+
48
+ assert n_process is not None
49
+ return await create_actor_pool(
50
+ address, pool_cls=MainActorPool, n_process=n_process, **kwargs
51
+ )
@@ -0,0 +1,26 @@
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
+ from numbers import Number
17
+ from typing import Dict
18
+
19
+ from ...driver import BaseActorDriver
20
+
21
+
22
+ class IndigenActorDriver(BaseActorDriver):
23
+ @classmethod
24
+ def setup_cluster(cls, address_to_resources: Dict[str, Dict[str, Number]]):
25
+ # nothing need to be done in driver of Indigen backend
26
+ pass