JaxAgentParallelRunner¶
- class pams.runners.JaxAgentParallelRunner(settings, prng=None, logger=None, simulator_class=<class 'pams.simulator.Simulator'>)[source]¶
JAX Agent Parallel runner class. This is experimental.
This runner is
pams.runners.MultiProcessAgentParallelRunnerfor agents whosepams.agents.Agent.submit_orders()uses JAX, e.g., neural network models of Flax. The simulation results are identical to those ofpams.runners.SequentialRunnerwith the same settings and the same seed if the agents are deterministic given their pseudo random number generators.JAX is an optional dependency of pams. It is imported when this runner is created, and an ImportError is raised if it is not installed.
import pamsdoes not import it.The worker processes are started by
spawnby default, i.e.,default_start_methodis"spawn", becauseforkis unsafe for JAX. Once JAX is initialized on the main process, e.g., when the agents create their models, JAX runs its own threads. A forked worker process has only a copy of the thread callingfork, so a lock held by another thread is never released and the worker process can deadlock. JAX warns about it whenforkis called.simulation.startMethodin the config still takes precedence.Each worker process configures JAX once before it runs any task, by the following keys in
simulationof the config. Each key overrides the corresponding environment variable, which the worker processes otherwise inherit from the main process:jaxPlatforms(str, Optional): platforms that JAX uses on the worker processes, e.g.,"cpu"or"cuda", i.e.,jax_platformsof JAX. If it is not set,JAX_PLATFORMSin the environment is used if it is set; otherwise, JAX chooses the platform.jaxPreallocate(bool, Optional): whether JAX preallocates the memory of GPUs on each worker process, i.e.,XLA_PYTHON_CLIENT_PREALLOCATE. If it is not set,XLA_PYTHON_CLIENT_PREALLOCATEin the environment is used if it is set; otherwise, it is false, so that several worker processes can share a GPU, because JAX preallocates 75% of the memory of the GPU by default.jaxMemoryFraction(float, Optional): fraction of the memory of the GPU that JAX on each worker process can use, in (0, 1], i.e.,XLA_PYTHON_CLIENT_MEM_FRACTION. If it is not set,XLA_PYTHON_CLIENT_MEM_FRACTIONorXLA_CLIENT_MEM_FRACTIONin the environment is used if it is set; otherwise, the default of JAX (0.75) is used.
Then, the initializer given by
_get_worker_initializeris called as inpams.runners.MultiProcessAgentParallelRunner, e.g., to load a read-only model once per worker process. The environment variables set on the worker processes are given by_get_worker_environment, which subclasses can override.Note
The worker processes persist during the simulation. Thus, a function compiled by
jax.jit()is compiled once per worker process (for each shape and type of the arguments) at its first call, and the compiled function is reused in the following steps. The functions compiled byjax.jit()cannot be pickled, so define them at the top level of a module instead of keeping them as attributes of the agents.Note
The agents are pickled and copied to a worker process for each task, including their jax arrays and Flax modules and parameters, which are copied to the default device of the worker process. Large models should be loaded once per worker process by the worker initializer instead (see
pams.runners.MultiProcessAgentParallelRunner). Only the state ofagent.prngis sent back to the main process, so the agents should derive their random numbers, including the keys ofjax.random, fromagent.prng.Note
Do not run JAX, e.g., create jax arrays, at the top level of the modules imported by the worker processes, such as the main module, and do not pass jax arrays to the worker initializer; otherwise, JAX is initialized before it is configured, and the settings above are ignored. The main process is not configured by the settings above, so set
XLA_PYTHON_CLIENT_PREALLOCATE=falsein the environment too if the agents use JAX on a GPU when they are created on the main process.-
default_start_method:
Optional[str] = 'spawn'¶ start method of the worker processes used when
simulation.startMethodis not set in the config. None means the default start method of the platform. Subclasses can override it, e.g., with"spawn"for libraries that are not fork-safe.- Type:
Optional[str]