Ray mental model: tasks, actors, objects, scheduling, placement

Ray is best understood as a distributed execution substrate for Python programs.

Ray is best understood as a distributed execution substrate for Python programs. It lets an application express stateful and stateless units of work while the runtime handles placement, resource accounting, object references, retries, and cluster membership. Ray Data, Ray Train, Ray Serve, and many RL stacks are higher-level patterns on top of these primitives.

PrimitiveUse it forSystems implication
TaskStateless or short-lived distributed function callsCheap parallel fan-out; dependencies are object refs; retries can be safe when work is idempotent.
ActorStateful, long-lived process such as a model server, environment pool, cache manager, or trainer coordinatorOwns mutable state and resources; lifecycle/failure semantics matter; ideal for GPU-bound stateful services.
Object reference / object storePassing immutable results between tasks and actorsEnables zero/low-copy local sharing where possible, distributed ownership, spilling, and backpressure-sensitive pipelines.
Placement groupReserve/arrange bundles of CPUs/GPUs across nodesExpresses co-location or anti-affinity constraints; critical when NCCL/NVLink/RDMA topology matters.
Resource labelsCPU, GPU, custom accelerator or logical resource quantitiesTurns scheduling into explicit resource matching instead of hidden process assumptions.
Autoscaling + job/runtime environmentCluster elasticity and dependency isolationUseful for bursty data/inference jobs; dangerous if startup/model-loading time is ignored in SLO planning.

The critical design choice is where state lives. If a unit of work is cheap and recomputable, prefer tasks. If it owns an expensive model, cache, connection pool, simulator, or device context, prefer actors. Once actors own scarce accelerators, placement and backpressure become architecture, not implementation detail.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# Conceptual Ray pattern
@ray.remote(num_gpus=1)
class RolloutWorker:
    def **init**(self, model):
        self.engine = load_inference_engine(model)

    def generate(self, prompts, policy_version):
        return trajectories(prompts, policy_version)

@ray.remote(num_gpus=8)
class Learner:
    def update(self, batch):
        return new_policy_version

# The orchestrator moves references/metadata, not Python objects by value.

References