Environment structure
An Ocean environment consists of three main components:Python wrapper
Handles Gymnasium API and shared memory
C binding
Compiles C code as Python extension
C implementation
Core simulation logic
Step-by-step guide
Define environment types and constants
Create
myenv.h with your environment struct and simulation constants:myenv.h
The
Log struct must contain only float fields. PufferLib’s binding code iterates over it as a float array.Implement core functions
In
myenv.h, implement the required environment functions:myenv.h (continued)
Create Python binding
Create The
binding.c that includes the PufferLib binding template:binding.c
env_binding.h template provides:env_init()- Initialize single environmentvec_init()- Initialize vectorized environmentsenv_step(),vec_step()- Step functionsenv_reset(),vec_reset()- Reset functionsenv_render(),vec_render()- Render functionsenv_close(),vec_close()- Cleanup functionsvec_log()- Aggregate logs from all environments
Understanding env_binding.h
Theenv_binding.h template handles the interface between Python and C:
Initialization
Memory management
Buffers are allocated by Python and passed to C as pointers. Nevermalloc or free these buffers:
Vectorization
The binding handles vectorization automatically:Logging
vec_log() aggregates logs across all environments:
Performance optimization tips
Minimize Python calls
Keep all simulation logic in C:Use struct-of-arrays for many entities
Avoid dynamic allocation
Use compiler optimizations
setup.py
Profile your code
Benchmark SPS (steps per second):Real-world examples
Simple: Cartpole
Seepufferlib/ocean/cartpole/ for a complete simple environment:
- Single agent per environment
- Continuous actions
- Simple physics
- ~5M SPS
Medium: Snake
Seepufferlib/ocean/snake/ for multi-agent:
- 256+ agents per environment
- Grid-based observations
- Complex collision detection
- ~10M SPS
Advanced: Battle
Seepufferlib/ocean/battle/ for large-scale multi-agent:
- 1024+ agents per environment
- Continuous actions and observations
- Spatial partitioning for efficiency
- ~1M SPS with complex interactions
CUDA environments
For GPU acceleration, use CUDA instead of C:myenv.cu
setup.py
Common patterns
Multi-agent environments
For multiple agents per environment, flatten observations:myenv.py
Variable-length observations
Pad observations to maximum size:Action masking
Return valid actions in info dict:Troubleshooting
Segmentation faults
Common causes:- Buffer overflow: Check array indices
- Null pointers: Verify initialization
- Stale pointers: Don’t cache buffer addresses
Performance issues
- Profile with
perf: - Check Python overhead: Most time should be in C
- Verify compiler optimizations: Use
-O3 - Reduce memory allocations: Preallocate buffers
Build errors
- Include paths: Add
-Iflags in setup.py - Missing libraries: Install raylib, numpy headers
- Numpy version: Match numpy version at build and runtime
Next steps
Study existing environments
Browse Ocean environments for reference implementations
Learn architecture
Understand Ocean’s performance optimizations