Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions benchmarks/test_envs_benchmark.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.
import argparse
import time
from functools import partial

import pytest
import torch
Expand All @@ -12,6 +14,30 @@
from torchrl.envs.libs.dm_control import DMControlEnv
from torchrl.envs.libs.libero import _has_libero, LiberoEnv
from torchrl.envs.transforms.functional import cat_frames
from torchrl.testing.mocking_classes import CountingEnv


class _SlowStartEnv(CountingEnv):
def __init__(self, delay: float = 0.1):
time.sleep(delay)
super().__init__()


def _make_slow_start_env(delay: float) -> _SlowStartEnv:
return _SlowStartEnv(delay)


def _run_parallel_cold_start(metadata_from_workers: bool) -> None:
env = ParallelEnv(
4,
partial(_make_slow_start_env, 0.1),
mp_start_method="spawn",
metadata_from_workers=metadata_from_workers,
)
try:
env.reset()
finally:
env.close(raise_if_closed=False)


def make_simple_env():
Expand Down Expand Up @@ -111,6 +137,16 @@ def test_parallel(benchmark):
benchmark(execute_env, c)


@pytest.mark.parametrize("metadata_from_workers", [False, True])
def test_parallel_cold_start(benchmark, metadata_from_workers):
benchmark.pedantic(
_run_parallel_cold_start,
args=(metadata_from_workers,),
rounds=3,
iterations=1,
)


@pytest.mark.skipif(not _has_libero, reason="libero not found")
def test_libero(benchmark):
# raw simulation + render throughput of the LIBERO adapter (steps/s)
Expand Down
22 changes: 22 additions & 0 deletions docs/source/reference/envs_vectorized.rst
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,28 @@ It is important that your environment specs match the input and output that it s
:class:`ParallelEnv` will create buffers from these specs to communicate with the spawn processes.
Check the :func:`~torchrl.envs.check_env_specs` method for a sanity check.

By default, :class:`ParallelEnv` obtains those specs by creating temporary
environments in the parent process. For environments that are expensive or
unsafe to construct in the parent, ``metadata_from_workers=True`` obtains the
metadata from the real, long-lived worker environments instead. The workers
start during :class:`ParallelEnv` construction, their schemas are validated,
and no parent-side environment is created. This opt-in mode currently requires
``use_buffers=False`` (which is selected automatically when the argument is
unset); passing ``use_buffers=True`` raises an error. A common factory can still
receive per-worker settings through ``create_env_kwargs``:

.. code-block:: python

from functools import partial

make_env = partial(GymEnv, "Pendulum-v1")
env = ParallelEnv(
4,
make_env,
create_env_kwargs=[{"frame_skip": i + 1} for i in range(4)],
metadata_from_workers=True,
)

.. code-block::
:caption: Parallel environment

Expand Down
24 changes: 24 additions & 0 deletions sota-implementations/vla_grpo/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,30 @@ workers plus the evaluator share one process policy server.
python sota-implementations/vla_grpo/vla-grpo.py --config-name vla_grpo_libero
```

The LIBERO recipe enables worker-originated environment metadata. This keeps
MuJoCo/EGL construction inside the long-lived rollout workers and avoids a
temporary parent-side environment wave. The nested startup path can be measured
without loading the VLA policy:

```bash
python sota-implementations/vla_grpo/bench_libero_startup.py \
--mode legacy-parent --inner-start-method spawn \
--output-dir /root/artifacts/libero-startup/legacy-spawn
python sota-implementations/vla_grpo/bench_libero_startup.py \
--mode worker-metadata --inner-start-method spawn \
--output-dir /root/artifacts/libero-startup/worker-spawn
python sota-implementations/vla_grpo/bench_libero_startup.py \
--mode worker-metadata --inner-start-method forkserver \
--output-dir /root/artifacts/libero-startup/worker-forkserver
```

Outer subcollector processes always use ``spawn``. The script permits
``forkserver`` or diagnostic ``fork`` only in worker-metadata mode, after the
subcollector parent has been kept free of EGL contexts. Each output directory
contains the exact command, per-construction marker files, and a JSON summary
covering nested environment readiness, first-step latency, peak process count,
and shutdown cleanup.

Rollout clients request random sampling; eval and video clients request
deterministic decoding from the same server, so rollout and eval are synced by
one explicit TensorDict weight update after each optimizer step. The replay
Expand Down
Loading
Loading