EnvPool for Parallel Reinforcement Learning Environments
C++-based high-performance parallel environment execution engine (vectorized env) for general RL environments.
At a glance
- What is it?
- EnvPool is a C++ execution engine that batches reinforcement learning environments through Python bindings and a thread pool. It fits workloads that need many synchronous or asynchronous environments across Atari, MuJoCo, dm_env, robotics, and other supported suites.
- Who is it for?
- EnvPool is appropriate for Python reinforcement learning developers whose algorithms need many repeated environments and whose targets are among the supported suites. It is a poor fit when GPU-based simulation, custom Python-only behavior, or an unsupported environment is the priority.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly C++, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on November 7, 2026, and from our analysis. They are not legal advice.
Star history
- sail-sg/envpool1,533 ★ · +3
| Repository | 2026-10-16 | 2026-11-07 |
|---|---|---|
| sail-sg/envpool | 1.5k | 1.5k |
3 Stars in the last 22 days, measured from the daily GitHub snapshot. Compare with other projects
Editorial analysis
Why EnvPool Moves RL Environments Out of Python
EnvPool addresses a specific bottleneck in reinforcement learning: an algorithm often needs multiple environment copies, but conventional Python execution adds substantial coordination overhead. EnvPool keeps environment simulation in C++, exposes environments to Python through pybind11, and manages execution with a thread pool. Its public interfaces follow Gymnasium or DeepMind dm_env conventions, so the intended audience is Python reinforcement learning developers who need higher environment throughput without replacing their learning framework entirely.
The project is aimed more specifically at batched training and evaluation than at an interactive demonstration. A pool holds multiple environments and its default interface operates on them as a batch. Both synchronous and asynchronous execution are supported, as are single-player and multi-player environments. That matters because Atari and classic-control tasks usually fit the first model, while supported multi-player environments introduce state and result handling that a plain vector interface may obscure.
The README reports approximately 1 million raw Atari frames per second and 3 million MuJoCo steps per second with 256 CPU cores. It also reports about 20 times the throughput of a Python subprocess-based vector environment in that configuration, and about three times on a 12-core setup. These are project-reported figures under specified large-scale conditions, not independent measurements. The practical point is narrower: EnvPool targets CPU-side environment parallelism, which can spend available CPU capacity on reset, step, and rendering work.
EnvPool Batch and Thread Execution Path
Based on the repository layout and README, the execution path has two layers. Simulation and environment state live in C++, while `envpool/` contains Python-facing integration code and the packaging process builds native extension modules. The `setup.py` explicitly marks the distribution as impure and declares that it contains extension modules. Its Windows build path also normalizes pybind11 artifacts into importable `.pyd` files, which confirms that Python interacts with compiled components rather than with a pure Python simulator.
A pool accepts actions and produces batched transitions. This avoids treating every environment as an isolated Python object with its own control path. The documented thread pool supplies concurrent execution, while the batched API presents environment results together. Asynchronous mode is available when immediate synchronization is not required. The README also describes a JAX XLA interface, so supported environments can cross into a JAX-compiled function rather than forcing every interaction through ordinary Python calls.
Rendering is part of the execution surface. EnvPool advertises batched `rgb_array` output and a `human` display mode, avoiding the assumption that it is only a headless numeric simulator. The listed environments span fixed Atari games, MuJoCo and DeepMind Control tasks, ViZDoom, Box2D, Google Research Football, Procgen, MiniGrid, MetaWorld, robotics suites, PGX, Jumanji, Craftax, MuJoCo Playground, and MJLab. This broad list is useful only where a matching implementation is maintained for the specific environment and platform. It should not be read as evidence that arbitrary Python environments can be loaded into the pool.
Installing EnvPool and Starting an RL Workflow
The project documentation directs users to install EnvPool from PyPI and publishes its documentation at `envpool.readthedocs.io`. The repository supports Linux, macOS, and Windows wheels for Python 3.12 through 3.14. However, the README is truncated immediately after the start of its PyPI installation section, so it does not provide a complete package-install command. Inventing a command or version qualifier would go beyond the documented instructions.
A first real use is documented through concrete training examples rather than a short generic snippet in the README. The `examples/` tree includes Stable-Baselines3 PPO examples for `Pendulum-v1`, Tianshou CartPole, Pendulum, Atari, and MuJoCo workflows, plus ACME `HalfCheetah`, CleanRL `Pong-v5`, and rl_games Atari and MuJoCo examples. For a novice, the Stable-Baselines3 Pendulum file is the most compact starting point among the named examples because it connects one classic-control environment to an existing learning library. The four `demo/` notebooks cover Ant, Breakout, Pong, and HalfCheetah.
Before selecting an example, check the documentation page for that environment and the library integration guide. The first execution should confirm that the native wheel imports successfully, the pool constructs the intended environment, one batched step returns aligned arrays for every pooled instance, and reset handles completed environments. The README does not document a universal first-run command, rollback procedure, or troubleshooting sequence in its installation section.
Gymnasium, dm_env, XLA, and RL Library Boundaries
EnvPool offers two compatibility paths rather than requiring every framework to use the same convention. Gymnasium-oriented users can work with batched APIs following Gymnasium semantics, while dm_env users have a corresponding interface. The repository advertises compatibility with Stable-Baselines3, Tianshou, ACME, CleanRL, and rl_games, and names examples for each. These integrations matter more than the generic label of compatibility because each library has its own expectation for vector environments, episode statistics, device placement, and asynchronous transitions.
XLA support adds a second decision point for JAX-based systems. It is intended to reduce overhead between JAX and the environment execution engine, but the README does not claim that every environment or rendering mode supports that path. Users should therefore treat Gymnasium compatibility, dm_env compatibility, XLA support, and third-party library integration as separate capabilities.
There is also a platform boundary around rendering. Linux, macOS, and Windows wheels are advertised, but that does not establish identical graphics dependencies or display behavior on every platform. The repository includes Docker and build files, while `Makefile` contains platform-specific handling for Windows and MuJoCo test environments. Building from source is a separate path from installing a wheel and should not be assumed necessary for the supported combinations.
EnvPool Versus Brax, Isaac-Gym, and Python Vector Environments
EnvPool's stated alternative is a GPU-oriented environment stack such as Brax or Isaac-Gym. The architectural difference is primary. EnvPool is described as a general solution for parallelizing various reinforcement learning environments, while the README groups Brax and Isaac-Gym as GPU-based solutions. EnvPool supports both synchronous and asynchronous execution.
Against Python subprocess-based vector environments, EnvPool keeps the environment implementation in C++, binds it into one Python-facing package, and uses a thread pool. The project reports roughly 20 times the throughput with 256 CPU cores and roughly three times on 12 cores. Those comparisons are most relevant when CPU capacity and environment step cost are the constraint. If the surrounding learning code depends on Python subprocess isolation or arbitrary Python-defined environment hooks, that shared native pool may not preserve the same flexibility.
EnvPool also targets ordinary reinforcement learning environments rather than requiring every workload to become GPU-native. This makes it relevant across its listed Atari, control, text, robotics, and game suites. The trade-off is that native packaging and environment-specific integration can constrain supported versions. Its breadth is valuable when a supported task is present, but it does not remove the need to verify a specific platform, Python version, environment, renderer, and framework combination.
EnvPool Constraints in Custom and Rendering Workloads
The clearest wrong-tool case is a project whose defining requirement is an arbitrary Python environment that EnvPool does not implement. The README lists native integrations and points to a customization guide for adding environments through the C++ developer API. It does not say that arbitrary Python environment classes can be dropped into the pool. A workload built around Python-only observation logic, dynamic code generation, or runtime-created components may therefore require a Python vector environment instead.
EnvPool is also a weak fit when the central requirement is GPU-accelerated simulation. It is a CPU execution engine with C++, pybind11, and thread-pool architecture. Brax and Isaac-Gym represent a different approach, but neither should be assumed to satisfy an EnvPool workload without checking its own environment and API constraints. The relevant comparison is execution architecture, not a blanket judgment about performance.
Rendering introduces separate risks. Built-in `rgb_array` output is advertised, but the repository's build files contain platform-specific handling for graphics libraries and test environments. The README does not establish that Windows, Linux, and macOS provide identical headless rendering dependencies or that every simulator works in `human` mode. Projects that need exact pixel behavior should verify renderer availability for the chosen operating system and simulator before changing their training stack.
Maintenance, Native Extensions, and Apache-2.0 Use
The repository is not archived, and the last push was on 2026-09-15. Releases v1.2.7 and v1.2.6 were published on 2026-09-15 and 2026-08-28, respectively, following v1.2.5 on 2026-05-20. Those dates show recent project activity, but they do not establish compatibility with every environment or platform.
The main upgrade cost comes from the native boundary. EnvPool ships compiled extension modules, requires attention to Python ABI compatibility, and has platform-specific packaging logic. A new Python runtime, operating system, graphics stack, or reinforcement learning library may require a corresponding wheel or source-build work. The repository's `MODULE.bazel`, `BUILD`, `.bazelversion`, `third_party/`, `setup.py`, and `Makefile` show that development involves a C++ and Bazel build rather than only Python packaging.
EnvPool is licensed under Apache-2.0. That identifier permits use and modification under the license's conditions, including its notice and patent provisions, but this article does not interpret those legal terms. Organizations should review the repository's `LICENSE` file themselves and account for the licenses of simulators, native libraries, rendering stacks, and separately distributed environments when evaluating a deployment.
Editorial conclusion
EnvPool is appropriate for Python reinforcement learning developers whose algorithms need many repeated environments and whose targets are among the supported suites. It is a poor fit when GPU-based simulation, custom Python-only behavior, or an unsupported environment is the priority. Before adoption, verify that the required environment and Python version have a matching wheel, inspect the relevant documentation page, and confirm that batched observations, rewards, terminations, and resets fit the training loop.
Frequently asked questions
Does EnvPool support Gymnasium and dm_env?
Yes. The README states that EnvPool exposes compatible Gymnasium and dm_env APIs, with both synchronous and asynchronous execution and both single-player and multi-player environments.
Which platforms and Python versions does EnvPool provide wheels for?
The README advertises wheels for Linux, macOS, and Windows using Python 3.12 through 3.14. It does not imply that every environment or rendering feature behaves identically across those platforms.
Can I use EnvPool with an existing reinforcement learning library?
The README names Stable-Baselines3, Tianshou, ACME, CleanRL, and rl_games as supported or compatible integrations. It also links examples for Pendulum, CartPole, Atari, MuJoCo, and HalfCheetah tasks.
Does EnvPool run environments on the GPU?
The README describes EnvPool as a C++ batched execution engine using pybind11 and a thread pool. It compares EnvPool with GPU-based solutions such as Brax and Isaac-Gym, but it does not describe EnvPool itself as a GPU simulator.
Can EnvPool produce batched image observations?
The README advertises built-in rendering with batched `rgb_array` output and a `human` display mode. Platform-specific rendering dependencies still need to be checked in the relevant environment documentation.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/sail-sg-envpool)Star history chart for your README
[](https://hysenlabs.com/projects/sail-sg-envpool)Was this useful?