Stage Worker Sizing
Use ProcessingStage.num_workers() or stage.with_(num_workers=...) to set a backend-neutral worker request. Use ray_stage_spec and xenna_stage_spec for backend-specific execution behavior.
Worker count and per-worker resources are separate controls:
num_workers()controls how many workers the executor requests.Resourcescontrols CPU and GPU resources reserved for each worker.ray_stage_spec()andxenna_stage_spec()provide backend-specific scheduling options.
A worker count does not create cluster capacity. Ensure the cluster can satisfy worker count × per-worker Resources, or use autoscaling bounds that fit the cluster.
Common Stage for the Examples
The examples on this page configure this minimal stage:
Worker Controls by Backend
Ray Data and Ray Actor Pool also treat 0 and negative values as no fixed-size request. Xenna passes every non-None value to its stage specification, so use a positive count or None; do not use zero or negative Xenna worker counts.
Ray Data Worker Pools
Ray Data uses actor stages for stateful setup or GPU-backed work and task stages for stateless work. A stage is an actor stage when either condition is true:
ray_stage_spec[RayStageSpecKeys.IS_ACTOR_STAGE]is explicitlyTrue.- The stage overrides
setup(), or requests both CPU and GPU resources.
Set IS_ACTOR_STAGE to False to force task execution. Do this only when the stage does not depend on worker-local setup state.
Fixed actor pool
Set a positive num_workers and mark the stage as an actor stage:
Ray Data receives ActorPoolStrategy(size=4). Cluster resources must be able to place four actors with the stage’s per-worker Resources.
Autoscaling actor pool
Use the exact RayStageSpecKeys members MIN_WORKERS, MAX_WORKERS, and INITIAL_WORKERS:
Ray Data receives ActorPoolStrategy(min_size=2, max_size=8, initial_size=4).
Ray validates the relationship among the three values. For example, an initial size greater than the maximum raises ValueError with the stage name and the underlying actor-pool validation message.
Fixed task pool
For a stateless task stage, a positive worker count selects TaskPoolStrategy(size=N):
Without a positive num_workers, a task stage does not set compute; Ray Data uses its default task scheduler.
Ray Data precedence and errors
Xenna Worker Counts
Xenna supports either a cluster-wide fixed count or a per-node count, but not both on one stage.
Cluster-wide
Per node
Use the common worker hook. This example requests 12 workers in total, regardless of node count:
The following combinations are invalid:
When neither setting is present, Xenna controls worker allocation using stage resources and pipeline demand.
Ray Actor Pool Resource Capping
RayActorPoolExecutor calculates how many actors fit from available CPU and GPU resources. A positive num_workers() is honored when it fits. If it exceeds capacity, Curator warns and caps the actor count instead of waiting for impossible placements.
For example, a stage that requests Resources(cpus=2.0) and num_workers=8 can place at most four actors when eight CPUs are available. Work batch count can further reduce the automatically chosen pool size when num_workers is unset.
Configure a Stage with with_()
with_() deep-copies the stage and returns the configured copy. It can override portable properties and merge backend stage specs in one call:
The original stage remains unchanged. resources, batch_size, runtime_env, and num_workers apply across supported executors. ray_stage_spec configures Ray Data and the Ray-specific flags used by Ray Actor Pool; xenna_stage_spec configures Xenna.
Shallow-merge behavior
ray_stage_spec and xenna_stage_spec are shallow-merged with the stage’s existing dictionary. New top-level keys are preserved, and user values replace existing values at the same top-level key. Nested dictionaries are replaced, not recursively merged.
For example, if a stage returns:
then this override:
produces a spec where max_workers is explicitly None and ray_remote_args contains only {"max_retries": 0}. The original scheduling_strategy nested key is not retained.
Omitted values and explicit None
Chained with_() calls merge against the already configured copy, so later values win while unrelated top-level keys from earlier calls remain.
Reserved num_workers Hook
num_workers is reserved as a method on ProcessingStage. Do not define it as a dataclass field or ordinary stage attribute:
Alternatively, keep the class executor-neutral and use stage.with_(num_workers=4) at pipeline construction time. Defining num_workers: int = 4 as a class or dataclass field raises TypeError when the subclass is created.
Some built-in single-input and fanout stages override num_workers() to return 1, preventing duplicate source enumeration. Use with_(num_workers=None) only when executor-controlled parallelism is safe for that stage’s input contract.
For ASR stages, the stage-local NeMo DataLoader setting is named dataloader_num_workers. When migrating an ASR constructor or configuration, rename the previous stage field num_workers to dataloader_num_workers; the common num_workers() hook is now reserved for Curator backend workers:
Resource Matching and Ray Data Fusion
Ray Data may fuse compatible adjacent operators to avoid materializing and serializing intermediate blocks. Fusion is an optimizer decision, not a guaranteed stage behavior.
Ray Data determines the per-worker reservation in this order:
Use RAY_NUM_CPUS when Ray Data needs a different scheduling reservation from other executors:
The CPU paths of VideoFrameExtractionStage and ClipTranscodingStage use a Ray Data reservation of 1.0 CPU by default while preserving their larger Resources.cpus values for Xenna. Matching the adjacent video operators’ Ray Data reservations makes fusion possible and can remove inter-stage serialization overhead. Different resources, execution constraints, or optimizer decisions can still keep stages separate; inspect the Ray Data execution plan or dashboard instead of assuming fusion occurred.
Lowering the scheduler reservation does not reduce the CPU work performed by FFmpeg. Confirm that the resulting concurrency does not oversubscribe the host.