Rate this Page

Source code for monarch.common.stream

# Copyright (c) Meta Platforms, Inc. and affiliates.
# All rights reserved.
#
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.

# pyre-unsafe
from typing import Callable, List, Tuple, TYPE_CHECKING
from weakref import ref, WeakKeyDictionary

from . import messages
from .borrows import Borrow
from .context_manager import activate_first_context_manager
from .fake import fake_call
from .reference import Referenceable

if TYPE_CHECKING:
    from monarch.common.client import Client  # @manual

    from .tensor import Tensor


[docs]class Stream:
[docs] def __init__(self, name: str, _default=False): self.name = name self.default: bool = _default self.clients: WeakKeyDictionary["Client", "StreamRef"] = WeakKeyDictionary()
def __repr__(self): return f"<Stream({repr(self.name)}) at {hex(id(self))}>" def __str__(self): return f"stream {repr(self.name)}"
[docs] def activate(self): return _active_stream(self)
def _to_ref(self, client: "Client"): if client not in self.clients: self.clients[client] = StreamRef(client, self.name, self.default) return self.clients[client]
[docs] def borrow(self, t: "Tensor", mutable: bool = False) -> Tuple["Tensor", "Borrow"]: """ borrowed_tensor, borrow = self.borrow(t) Borrows tensor 't' for use on this stream. The memory of t will stay alive until borrow.drop() is called, which will free t and and any of its alises on stream `self` and will cause t.stream to wait on self at that point so that the memory of t can be reused. If `mutable` then self can write to the storage of `t`, but t.stream cannot read or write `t` until, the borrow is returned (becomes free and a wait_for has been issued). If not `mutable` both `self` and `t.stream` can read from t's storage but neither can write to it. """ client = t.mesh.client aliases = t._aliases r = type(t)(fake_call(t._fake.clone), t.mesh, self) client.new_node((r,), (t,)) borrow = r._aliases.borrow_from(client.new_ref(), t.mesh, aliases, mutable) client.new_borrow(borrow) assert r.ref is not None t.mesh._send( messages.BorrowCreate( r, borrow._id, t, t.stream._to_ref(client), self._to_ref(client) ) ) r._on_first_use = lambda t: borrow._use() return r, borrow
class StreamRef(Referenceable): def __init__(self, client: "Client", name: str, default: bool): self.ref = client.new_ref() self.client = ref(client) self.name = name self.default = default client.send( client.all_ranks, messages.CreateStream(self, self.default), ) def __repr__(self): return f"<StreamRef {repr(self.name)} {self.ref}>" def delete_ref(self, ref): client = self.client() if client is not None and not client._shutdown: client.handle_deletes(client.all_ranks, [ref]) _active = Stream("main", _default=True) _on_change: List[Callable] = []
[docs]def get_active_stream(): return _active
@activate_first_context_manager def _active_stream(stream: Stream): global _active for on_change in _on_change: on_change(_active, stream) _active, old = stream, _active try: yield finally: for on_change in _on_change: on_change(_active, old) _active = old