torchmonarch-nightly 2025.6.13__cp310-cp310-manylinux2014_x86_64.whl → 2025.6.14__cp310-cp310-manylinux2014_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.
monarch/_rust_bindings.so CHANGED
Binary file
monarch/actor_mesh.py CHANGED
@@ -276,11 +276,11 @@ class Endpoint(Generic[P, R]):
276
276
  return self.choose(*args, **kwargs)
277
277
 
278
278
  def call(self, *args: P.args, **kwargs: P.kwargs) -> "Future[ValueMesh[R]]":
279
- p: PortId
280
- r: PortReceiver[R]
281
- p, r = port(self)
279
+ p: Port[R]
280
+ r: RankedPortReceiver[R]
281
+ p, r = ranked_port(self)
282
282
  # pyre-ignore
283
- send(self, args, kwargs, port=p, rank_in_response=True)
283
+ send(self, args, kwargs, port=p)
284
284
 
285
285
  async def process() -> ValueMesh[R]:
286
286
  results: List[R] = [None] * len(self._actor_mesh) # pyre-fixme[9]
@@ -375,9 +375,8 @@ def send(
375
375
  endpoint: Endpoint[P, R],
376
376
  args: Tuple[Any, ...],
377
377
  kwargs: Dict[str, Any],
378
- port: "Optional[PortId]" = None,
378
+ port: "Optional[Port]" = None,
379
379
  selection: Selection = "all",
380
- rank_in_response: bool = False,
381
380
  ) -> None:
382
381
  """
383
382
  Fire-and-forget broadcast invocation of the endpoint across all actors in the mesh.
@@ -386,7 +385,10 @@ def send(
386
385
  """
387
386
  endpoint._signature.bind(None, *args, **kwargs)
388
387
  message = PythonMessage(
389
- endpoint._name, _pickle((args, kwargs)), port, rank_in_response
388
+ endpoint._name,
389
+ _pickle((args, kwargs)),
390
+ None if port is None else port._port,
391
+ None,
390
392
  )
391
393
  endpoint._actor_mesh.cast(message, selection)
392
394
 
@@ -408,18 +410,16 @@ def endpoint(
408
410
  return EndpointProperty(method)
409
411
 
410
412
 
411
- class Port:
412
- def __init__(self, port: PortId, mailbox: Mailbox, rank_in_response: bool) -> None:
413
+ class Port(Generic[R]):
414
+ def __init__(self, port: PortId, mailbox: Mailbox, rank: Optional[int]) -> None:
413
415
  self._port = port
414
416
  self._mailbox = mailbox
415
- self._rank_in_response = rank_in_response
417
+ self._rank = rank
416
418
 
417
- def send(self, method: str, obj: object) -> None:
418
- if self._rank_in_response:
419
- obj = (MonarchContext.get().point.rank, obj)
419
+ def send(self, method: str, obj: R) -> None:
420
420
  self._mailbox.post(
421
421
  self._port,
422
- PythonMessage(method, _pickle(obj), None),
422
+ PythonMessage(method, _pickle(obj), None, self._rank),
423
423
  )
424
424
 
425
425
 
@@ -428,12 +428,21 @@ class Port:
428
428
  # and handles concerns is different.
429
429
  def port(
430
430
  endpoint: Endpoint[P, R], once: bool = False
431
- ) -> Tuple["PortId", "PortReceiver[R]"]:
431
+ ) -> Tuple["Port[R]", "PortReceiver[R]"]:
432
432
  handle, receiver = (
433
433
  endpoint._mailbox.open_once_port() if once else endpoint._mailbox.open_port()
434
434
  )
435
435
  port_id: PortId = handle.bind()
436
- return port_id, PortReceiver(endpoint._mailbox, receiver)
436
+ return Port(port_id, endpoint._mailbox, rank=None), PortReceiver(
437
+ endpoint._mailbox, receiver
438
+ )
439
+
440
+
441
+ def ranked_port(
442
+ endpoint: Endpoint[P, R], once: bool = False
443
+ ) -> Tuple["Port[R]", "RankedPortReceiver[R]"]:
444
+ p, receiver = port(endpoint, once)
445
+ return p, RankedPortReceiver[R](receiver._mailbox, receiver._receiver)
437
446
 
438
447
 
439
448
  class PortReceiver(Generic[R]):
@@ -458,18 +467,20 @@ class PortReceiver(Generic[R]):
458
467
  return payload
459
468
  else:
460
469
  assert msg.method == "exception"
461
- if isinstance(payload, tuple):
462
- # If the payload is a tuple, it's because we requested the rank
463
- # to be included in the response; just ignore it.
464
- raise payload[1]
465
- else:
466
- # pyre-ignore
467
- raise payload
470
+ # pyre-ignore
471
+ raise payload
468
472
 
469
473
  def recv(self) -> "Future[R]":
470
474
  return Future(lambda: self._recv(), self._blocking_recv)
471
475
 
472
476
 
477
+ class RankedPortReceiver(PortReceiver[Tuple[int, R]]):
478
+ def _process(self, msg: PythonMessage) -> Tuple[int, R]:
479
+ if msg.rank is None:
480
+ raise ValueError("RankedPort receiver got a message without a rank")
481
+ return msg.rank, super()._process(msg)
482
+
483
+
473
484
  singleton_shape = Shape([], NDSlice(offset=0, sizes=[], strides=[]))
474
485
 
475
486
 
@@ -493,7 +504,7 @@ class _Actor:
493
504
  panic_flag: PanicFlag,
494
505
  ) -> Optional[Coroutine[Any, Any, Any]]:
495
506
  port = (
496
- Port(message.response_port, mailbox, message.rank_in_response)
507
+ Port(message.response_port, mailbox, rank)
497
508
  if message.response_port
498
509
  else None
499
510
  )
Binary file
@@ -8,6 +8,7 @@ import asyncio
8
8
  import operator
9
9
  import os
10
10
  import re
11
+ import threading
11
12
  from types import ModuleType
12
13
  from unittest.mock import AsyncMock, patch
13
14
 
@@ -549,3 +550,44 @@ async def test_debug() -> None:
549
550
 
550
551
  with pytest.raises(monarch.actor_mesh.ActorError, match="ValueError: bad rank"):
551
552
  await fut
553
+
554
+
555
+ class TLSActor(Actor):
556
+ """An actor that manages thread-local state."""
557
+
558
+ def __init__(self):
559
+ self.local = threading.local()
560
+ self.local.value = 0
561
+
562
+ @endpoint
563
+ def increment(self):
564
+ self.local.value += 1
565
+
566
+ @endpoint
567
+ async def increment_async(self):
568
+ self.local.value += 1
569
+
570
+ @endpoint
571
+ def get(self):
572
+ return self.local.value
573
+
574
+ @endpoint
575
+ async def get_async(self):
576
+ return self.local.value
577
+
578
+
579
+ async def test_actor_tls() -> None:
580
+ """Test that thread-local state is respected."""
581
+ pm = await proc_mesh(gpus=1)
582
+ am = await pm.spawn("tls", TLSActor)
583
+ await am.increment.call_one()
584
+ # TODO(suo): TLS is NOT preserved across async/sync endpoints, because currently
585
+ # we run async endpoints on a different thread than sync ones.
586
+ # Will fix this in a followup diff.
587
+
588
+ # await am.increment_async.call_one()
589
+ await am.increment.call_one()
590
+ # await am.increment_async.call_one()
591
+
592
+ assert 2 == await am.get.call_one()
593
+ # assert 4 == await am.get_async.call_one()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: torchmonarch-nightly
3
- Version: 2025.6.13
3
+ Version: 2025.6.14
4
4
  Summary: Monarch: Single controller library
5
5
  Author: Meta
6
6
  Author-email: oncall+monarch@xmail.facebook.com
@@ -1,7 +1,7 @@
1
1
  monarch/__init__.py,sha256=iUvWHc0-7Q2tovRoRxOIiA3TsefMXCbWl-jEfQ2djew,6897
2
- monarch/_rust_bindings.so,sha256=FJb4gGPNDWqT1nPkxEYSX4hEsIbjb_v8Oa0RDwMcH5A,40302936
2
+ monarch/_rust_bindings.so,sha256=iHKENTGdgZf4uRXWLL61j9Z7z-MOAIKabPo5JD0b6dw,40611888
3
3
  monarch/_testing.py,sha256=jOIOG6jcZBzvEvG_DwSnwCkaMVXvSun6sJAG6nXemww,7859
4
- monarch/actor_mesh.py,sha256=8Ih3CIArLTyZmWSHppXm5N2WlAjmGXpaQhkkFtjJFxc,25351
4
+ monarch/actor_mesh.py,sha256=nAW65WFEWMJWCv8zuH9GSOyTNXwFN8QNqZxMZTuSYxw,25537
5
5
  monarch/allocator.py,sha256=ylvYTf31o-PT385cYJPhi17uNbC4yl_RAraqD0fVe4g,4112
6
6
  monarch/bootstrap_main.py,sha256=RCUQhJk07yMFiKp6HzQuqZFUpkgsT9kVEyimiwjn6_E,1827
7
7
  monarch/cached_remote_function.py,sha256=kYdB6r4OHx_T_uX4q3tCNcp1t2DJwF8tPTIahUiT2pU,8785
@@ -11,7 +11,7 @@ monarch/future.py,sha256=lcdFEe7m1shYPPuvZ1RkS6JUIChEKGBWe3v7x_nu4Hg,731
11
11
  monarch/gradient_generator.py,sha256=Rl3dmXGceTdCc1mYBg2JciR88ywGPnW7TVkL86KwqEA,6366
12
12
  monarch/memory.py,sha256=ol86dBhFAJqg78iF25-BuK0wuwj1onR8FIioZ_B0gjw,1377
13
13
  monarch/mesh_controller.py,sha256=Xft2edk7rz8_PPe-iIUZ09P-j4JDPGADBGHBiuiZ7YY,10363
14
- monarch/monarch_controller,sha256=mE9pvcBDKwW_4zOZlO17PJDk7W6z5skzIX5rxHQfKOs,20238936
14
+ monarch/monarch_controller,sha256=P6ijudU0UZcrZW34d1lafCnJ1Hf90yo764rnkEg45dI,20399544
15
15
  monarch/notebook.py,sha256=zu9MKDFKf1-rCM2TqFSRJjMBeiWuKcJSyUFLvoZRQzs,25949
16
16
  monarch/opaque_module.py,sha256=oajOu_WD1hD4hxE8HDdO-tvWY7KDHWd7VaAhJEa5L2I,10446
17
17
  monarch/opaque_object.py,sha256=IVpll4pyuKZMo_EnPh4s0qnx8RlAcJrJ1yoLX6E75wQ,2782
@@ -144,7 +144,7 @@ tests/test_future.py,sha256=cXzaNi2YDwVyjR541ScXmgktX1YFsKzbl8wep0DMVbk,3032
144
144
  tests/test_grad_generator.py,sha256=p4Pm4kMEeGldt2jUVAkGKCB0mLccKI28pltH6OTGbQA,3412
145
145
  tests/test_mock_cuda.py,sha256=5hisElxeLJ5MHw3KM9gwxBiXiMaG-Rm382u3AsQcDOI,3068
146
146
  tests/test_pdb_actor.py,sha256=5KJhuhcZDPWMdjC6eAtDdwnz1W7jNFXvIrMSFaCWaPw,3858
147
- tests/test_python_actors.py,sha256=MPdXtnj4ZeyAaecDFJMXdz29KvimF9iB3bASgoo6-iM,16201
147
+ tests/test_python_actors.py,sha256=MzGeuhGVICzwiNaQt8SFCKyfwhNzdRzZ4s2rJxYbeoo,17283
148
148
  tests/test_remote_functions.py,sha256=5nxYB8dfA9NT9f9Od9O3htgQtPbiRNiXZ1Kgtn75sOQ,50056
149
149
  tests/test_rust_backend.py,sha256=94S3R995ZkyIhEiBsM5flcjf5X7bscEAHBtInbTRFe8,7776
150
150
  tests/test_signal_safe_block_on.py,sha256=bmal0XgzJowZXJV6T1Blow5a-vZluYWusCThLMGxyTE,3336
@@ -154,9 +154,9 @@ tests/simulator/test_profiling.py,sha256=TGYCfzTLdkpIwnOuO6KApprmrgPIRQe60KRX3wk
154
154
  tests/simulator/test_simulator.py,sha256=LO8lA0ssY-OGEBL5ipEu74f97Y765TEwfUOv-DtIptM,14568
155
155
  tests/simulator/test_task.py,sha256=ipqBDuDAysuo1xOB9S5psaFvwe6VATD43IovCTSs0t4,2327
156
156
  tests/simulator/test_worker.py,sha256=QrWWIJ3HDgDLkBPRc2mwYPlOQoXQcj1qRfc0WUfKkFY,3507
157
- torchmonarch_nightly-2025.6.13.dist-info/licenses/LICENSE,sha256=e0Eotbf_rHOYPuEUlppIbvwy4SN98CZnl_hqwvbDA4Q,1530
158
- torchmonarch_nightly-2025.6.13.dist-info/METADATA,sha256=WhintlKk3a9WRrjo-QLNntfi87q98I4gcZW_0f42q48,2772
159
- torchmonarch_nightly-2025.6.13.dist-info/WHEEL,sha256=_wZSFk0d90K9wOBp8Q-UGxshyiJ987JoPiyUBNC6VLk,104
160
- torchmonarch_nightly-2025.6.13.dist-info/entry_points.txt,sha256=sqfQ16oZqjEvttUI-uj9BBXIIE6jt05bYFSmy-2hyXI,106
161
- torchmonarch_nightly-2025.6.13.dist-info/top_level.txt,sha256=E-ZssZzyM17glpVrh-S9--qJ-w9p2EjuYOuNw9tQ4Eg,33
162
- torchmonarch_nightly-2025.6.13.dist-info/RECORD,,
157
+ torchmonarch_nightly-2025.6.14.dist-info/licenses/LICENSE,sha256=e0Eotbf_rHOYPuEUlppIbvwy4SN98CZnl_hqwvbDA4Q,1530
158
+ torchmonarch_nightly-2025.6.14.dist-info/METADATA,sha256=NZRNanfPhkjOMapMX_WCs34wphY1w-zccgncjQWmylk,2772
159
+ torchmonarch_nightly-2025.6.14.dist-info/WHEEL,sha256=_wZSFk0d90K9wOBp8Q-UGxshyiJ987JoPiyUBNC6VLk,104
160
+ torchmonarch_nightly-2025.6.14.dist-info/entry_points.txt,sha256=sqfQ16oZqjEvttUI-uj9BBXIIE6jt05bYFSmy-2hyXI,106
161
+ torchmonarch_nightly-2025.6.14.dist-info/top_level.txt,sha256=E-ZssZzyM17glpVrh-S9--qJ-w9p2EjuYOuNw9tQ4Eg,33
162
+ torchmonarch_nightly-2025.6.14.dist-info/RECORD,,