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.
Files changed (94) hide show
  1. xoscar/__init__.py +61 -0
  2. xoscar/_utils.cpython-312-darwin.so +0 -0
  3. xoscar/_utils.pxd +36 -0
  4. xoscar/_utils.pyx +246 -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 +527 -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 +253 -0
  19. xoscar/backends/communication/errors.py +20 -0
  20. xoscar/backends/communication/socket.py +444 -0
  21. xoscar/backends/communication/ucx.py +538 -0
  22. xoscar/backends/communication/utils.py +97 -0
  23. xoscar/backends/config.py +157 -0
  24. xoscar/backends/context.py +437 -0
  25. xoscar/backends/core.py +352 -0
  26. xoscar/backends/indigen/__init__.py +16 -0
  27. xoscar/backends/indigen/__main__.py +19 -0
  28. xoscar/backends/indigen/backend.py +51 -0
  29. xoscar/backends/indigen/driver.py +26 -0
  30. xoscar/backends/indigen/fate_sharing.py +221 -0
  31. xoscar/backends/indigen/pool.py +515 -0
  32. xoscar/backends/indigen/shared_memory.py +548 -0
  33. xoscar/backends/message.cpython-312-darwin.so +0 -0
  34. xoscar/backends/message.pyi +255 -0
  35. xoscar/backends/message.pyx +646 -0
  36. xoscar/backends/pool.py +1630 -0
  37. xoscar/backends/router.py +285 -0
  38. xoscar/backends/test/__init__.py +16 -0
  39. xoscar/backends/test/backend.py +38 -0
  40. xoscar/backends/test/pool.py +233 -0
  41. xoscar/batch.py +256 -0
  42. xoscar/collective/__init__.py +27 -0
  43. xoscar/collective/backend/__init__.py +13 -0
  44. xoscar/collective/backend/nccl_backend.py +160 -0
  45. xoscar/collective/common.py +102 -0
  46. xoscar/collective/core.py +737 -0
  47. xoscar/collective/process_group.py +687 -0
  48. xoscar/collective/utils.py +41 -0
  49. xoscar/collective/xoscar_pygloo.cpython-312-darwin.so +0 -0
  50. xoscar/collective/xoscar_pygloo.pyi +239 -0
  51. xoscar/constants.py +23 -0
  52. xoscar/context.cpython-312-darwin.so +0 -0
  53. xoscar/context.pxd +21 -0
  54. xoscar/context.pyx +368 -0
  55. xoscar/core.cpython-312-darwin.so +0 -0
  56. xoscar/core.pxd +51 -0
  57. xoscar/core.pyx +664 -0
  58. xoscar/debug.py +188 -0
  59. xoscar/driver.py +42 -0
  60. xoscar/errors.py +63 -0
  61. xoscar/libcpp.pxd +31 -0
  62. xoscar/metrics/__init__.py +21 -0
  63. xoscar/metrics/api.py +288 -0
  64. xoscar/metrics/backends/__init__.py +13 -0
  65. xoscar/metrics/backends/console/__init__.py +13 -0
  66. xoscar/metrics/backends/console/console_metric.py +82 -0
  67. xoscar/metrics/backends/metric.py +149 -0
  68. xoscar/metrics/backends/prometheus/__init__.py +13 -0
  69. xoscar/metrics/backends/prometheus/prometheus_metric.py +70 -0
  70. xoscar/nvutils.py +717 -0
  71. xoscar/profiling.py +260 -0
  72. xoscar/serialization/__init__.py +20 -0
  73. xoscar/serialization/aio.py +141 -0
  74. xoscar/serialization/core.cpython-312-darwin.so +0 -0
  75. xoscar/serialization/core.pxd +28 -0
  76. xoscar/serialization/core.pyi +57 -0
  77. xoscar/serialization/core.pyx +944 -0
  78. xoscar/serialization/cuda.py +111 -0
  79. xoscar/serialization/exception.py +48 -0
  80. xoscar/serialization/mlx.py +67 -0
  81. xoscar/serialization/numpy.py +82 -0
  82. xoscar/serialization/pyfury.py +37 -0
  83. xoscar/serialization/scipy.py +72 -0
  84. xoscar/serialization/torch.py +180 -0
  85. xoscar/utils.py +522 -0
  86. xoscar/virtualenv/__init__.py +34 -0
  87. xoscar/virtualenv/core.py +268 -0
  88. xoscar/virtualenv/platform.py +56 -0
  89. xoscar/virtualenv/utils.py +100 -0
  90. xoscar/virtualenv/uv.py +321 -0
  91. xoscar-0.9.0.dist-info/METADATA +230 -0
  92. xoscar-0.9.0.dist-info/RECORD +94 -0
  93. xoscar-0.9.0.dist-info/WHEEL +6 -0
  94. xoscar-0.9.0.dist-info/top_level.txt +2 -0
@@ -0,0 +1,253 @@
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 concurrent.futures as futures
20
+ import logging
21
+ import weakref
22
+ from typing import Any, Callable, Coroutine, Dict, Optional, Type
23
+ from urllib.parse import urlparse
24
+
25
+ from ...errors import ServerClosed
26
+ from ...utils import abc_type_require_weakref_slot, classproperty, implements
27
+ from .base import Channel, ChannelType, Client, Server
28
+ from .core import register_client, register_server
29
+ from .errors import ChannelClosed
30
+
31
+ DEFAULT_DUMMY_ADDRESS = "dummy://0"
32
+
33
+ logger = logging.getLogger(__name__)
34
+
35
+
36
+ class DummyChannel(Channel):
37
+ """
38
+ Channel for communications in same process.
39
+ """
40
+
41
+ __slots__ = "__weakref__", "_in_queue", "_out_queue", "_closed"
42
+
43
+ name = "dummy"
44
+
45
+ def __init__(
46
+ self,
47
+ in_queue: asyncio.Queue,
48
+ out_queue: asyncio.Queue,
49
+ closed: asyncio.Event,
50
+ local_address: str | None = None,
51
+ dest_address: str | None = None,
52
+ compression: str | None = None,
53
+ ):
54
+ super().__init__(
55
+ local_address=local_address,
56
+ dest_address=dest_address,
57
+ compression=compression,
58
+ )
59
+ self._in_queue = in_queue
60
+ self._out_queue = out_queue
61
+ self._closed = closed
62
+
63
+ @property
64
+ @implements(Channel.type)
65
+ def type(self) -> int:
66
+ return ChannelType.local
67
+
68
+ @implements(Channel.send)
69
+ async def send(self, message: Any):
70
+ if self._closed.is_set(): # pragma: no cover
71
+ raise ChannelClosed("Channel already closed, cannot send message")
72
+ # put message directly into queue
73
+ self._out_queue.put_nowait(message)
74
+
75
+ @implements(Channel.recv)
76
+ async def recv(self):
77
+ if self._closed.is_set(): # pragma: no cover
78
+ raise ChannelClosed("Channel already closed, cannot write message")
79
+ try:
80
+ return await self._in_queue.get()
81
+ except RuntimeError:
82
+ if self._closed.is_set():
83
+ pass
84
+
85
+ @implements(Channel.close)
86
+ async def close(self):
87
+ self._closed.set()
88
+
89
+ @property
90
+ @implements(Channel.closed)
91
+ def closed(self) -> bool:
92
+ return self._closed.is_set()
93
+
94
+
95
+ @register_server
96
+ class DummyServer(Server):
97
+ __slots__ = (
98
+ ("_closed", "_channels", "_tasks") + ("__weakref__",)
99
+ if abc_type_require_weakref_slot
100
+ else tuple()
101
+ )
102
+
103
+ _address_to_instances: weakref.WeakValueDictionary[str, "DummyServer"] = (
104
+ weakref.WeakValueDictionary()
105
+ )
106
+ _channels: weakref.WeakSet[Channel]
107
+ _tasks: set[asyncio.Task]
108
+ scheme: str | None = "dummy"
109
+
110
+ def __init__(
111
+ self,
112
+ address: str,
113
+ channel_handler: Callable[[Channel], Coroutine] | None = None,
114
+ ):
115
+ super().__init__(address, channel_handler)
116
+ self._closed = asyncio.Event()
117
+ self._channels = weakref.WeakSet()
118
+ self._tasks = set()
119
+
120
+ @classmethod
121
+ def get_instance(cls, address: str):
122
+ return cls._address_to_instances[address]
123
+
124
+ @classproperty
125
+ @implements(Server.client_type)
126
+ def client_type(self) -> Type["Client"]:
127
+ return DummyClient
128
+
129
+ @property
130
+ @implements(Server.channel_type)
131
+ def channel_type(self) -> int:
132
+ return ChannelType.local
133
+
134
+ @staticmethod
135
+ @implements(Server.create)
136
+ async def create(config: Dict) -> "DummyServer":
137
+ config = config.copy()
138
+ address = config.pop("address", DEFAULT_DUMMY_ADDRESS)
139
+ handle_channel = config.pop("handle_channel")
140
+ if urlparse(address).scheme != DummyServer.scheme: # pragma: no cover
141
+ raise ValueError(
142
+ f"Address for DummyServer "
143
+ f'should be starts with "dummy://", '
144
+ f"got {address}"
145
+ )
146
+ if config: # pragma: no cover
147
+ raise TypeError(
148
+ f"Creating DummyServer got unexpected " f'arguments: {",".join(config)}'
149
+ )
150
+ try:
151
+ server = DummyServer.get_instance(address)
152
+ if server.stopped:
153
+ raise KeyError("server closed")
154
+ except KeyError:
155
+ server = DummyServer(address, handle_channel)
156
+ DummyServer._address_to_instances[address] = server
157
+ return server
158
+
159
+ @implements(Server.start)
160
+ async def start(self):
161
+ # nothing needs to do for dummy server
162
+ pass
163
+
164
+ @implements(Server.join)
165
+ async def join(self, timeout=None):
166
+ wait_coro = self._closed.wait()
167
+ try:
168
+ await asyncio.wait_for(wait_coro, timeout=timeout)
169
+ except (futures.TimeoutError, asyncio.TimeoutError):
170
+ pass
171
+
172
+ @implements(Server.on_connected)
173
+ async def on_connected(self, *args, **kwargs):
174
+ if self._closed.is_set(): # pragma: no cover
175
+ raise ServerClosed("Dummy server already closed")
176
+
177
+ channel = args[0]
178
+ assert isinstance(channel, DummyChannel)
179
+ if kwargs: # pragma: no cover
180
+ raise TypeError(
181
+ f"{type(self).__name__} got unexpected "
182
+ f'arguments: {",".join(kwargs)}'
183
+ )
184
+ self._channels.add(channel)
185
+ await self.channel_handler(channel)
186
+
187
+ @implements(Server.stop)
188
+ async def stop(self):
189
+ self._closed.set()
190
+ _ = [t.cancel() for t in self._tasks]
191
+ await asyncio.gather(*(channel.close() for channel in self._channels))
192
+
193
+ @property
194
+ @implements(Server.stopped)
195
+ def stopped(self) -> bool:
196
+ return self._closed.is_set()
197
+
198
+
199
+ @register_client
200
+ class DummyClient(Client):
201
+ __slots__ = ("_task",)
202
+
203
+ scheme: str | None = DummyServer.scheme
204
+
205
+ def __init__(
206
+ self, local_address: str | None, dest_address: str | None, channel: Channel
207
+ ):
208
+ super().__init__(local_address, dest_address, channel)
209
+ self._task: Optional[asyncio.Task] = None
210
+
211
+ @staticmethod
212
+ @implements(Client.connect)
213
+ async def connect(
214
+ dest_address: str, local_address: str | None = None, **kwargs
215
+ ) -> "Client":
216
+ if urlparse(dest_address).scheme != DummyServer.scheme: # pragma: no cover
217
+ raise ValueError(
218
+ f'Destination address should start with "dummy://" '
219
+ f"for DummyClient, got {dest_address}"
220
+ )
221
+ server = DummyServer.get_instance(dest_address)
222
+ if server is None: # pragma: no cover
223
+ raise RuntimeError(
224
+ f"DummyServer {dest_address} needs to be created first before DummyClient"
225
+ )
226
+ if server.stopped: # pragma: no cover
227
+ raise ConnectionError(f"Dummy server {dest_address} closed")
228
+
229
+ q1: asyncio.Queue = asyncio.Queue()
230
+ q2: asyncio.Queue = asyncio.Queue()
231
+ closed = asyncio.Event()
232
+ client_channel = DummyChannel(q1, q2, closed, local_address=local_address)
233
+ server_channel = DummyChannel(q2, q1, closed, dest_address=local_address)
234
+
235
+ conn_coro = server.on_connected(server_channel)
236
+ task = asyncio.create_task(conn_coro)
237
+ client = DummyClient(local_address, dest_address, client_channel)
238
+ client._task = task
239
+ server._tasks.add(task)
240
+
241
+ def _discard(t):
242
+ server._tasks.discard(t)
243
+ logger.info("Channel exit: %s", server_channel.info)
244
+
245
+ task.add_done_callback(_discard)
246
+ return client
247
+
248
+ @implements(Client.close)
249
+ async def close(self):
250
+ await super().close()
251
+ if self._task is not None:
252
+ self._task.cancel()
253
+ self._task = None
@@ -0,0 +1,20 @@
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 ...errors import XoscarError
17
+
18
+
19
+ class ChannelClosed(XoscarError):
20
+ pass