Skip to content

Commit 9d6dbb8

Browse files
committed
[envpool] Restore JAX XLA and keep Python 3.10 installs
1 parent b00ac67 commit 9d6dbb8

6 files changed

Lines changed: 46 additions & 84 deletions

File tree

envpool/atari/atari_envpool_test.py

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -171,10 +171,7 @@ def test_xla_api(self) -> None:
171171
num_threads=2,
172172
thread_affinity_offset=0,
173173
)
174-
try:
175-
handle, recv, send, step = env.xla()
176-
except RuntimeError as exc:
177-
self.skipTest(str(exc))
174+
handle, recv, send, step = env.xla()
178175
env.async_reset()
179176
handle, states = recv(handle)
180177
info = states[-1]
@@ -209,10 +206,7 @@ def test_xla_correctness(self) -> None:
209206
num_threads=2,
210207
thread_affinity_offset=0,
211208
)
212-
try:
213-
handle, recv, send, step = env1.xla()
214-
except RuntimeError as exc:
215-
self.skipTest(str(exc))
209+
handle, recv, send, step = env1.xla()
216210
env1.async_reset()
217211
env2.async_reset()
218212

envpool/python/xla_template.py

Lines changed: 32 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -14,107 +14,69 @@
1414
"""xla template on python side."""
1515

1616
from collections import namedtuple
17-
from functools import partial
1817
from typing import Any, Callable, List, Tuple, Union, cast
1918

2019
import numpy as np
21-
from jax import core, dtypes
20+
from jax import ShapeDtypeStruct, dtypes, ffi
2221
from jax import numpy as jnp
23-
from jax._src.lib import xla_client
24-
from jax.core import ShapedArray
25-
from jax.interpreters import xla
26-
27-
_core = cast(Any, core)
28-
_xla = cast(Any, xla)
29-
_xla_client = cast(Any, xla_client)
30-
31-
32-
def _shape_with_layout(
33-
specs: Tuple[Tuple[List[int], Any], ...]
34-
) -> Tuple[xla_client.Shape, ...]:
35-
return tuple(
36-
xla_client.Shape
37-
.array_shape(dtype, shape, tuple(range(len(shape) -
38-
1, -1, -1))) if len(shape) >
39-
0 else xla_client.Shape.scalar_shape(dtype) for shape, dtype in specs
40-
)
4122

4223

4324
def _normalize_specs(
4425
specs: Tuple[Tuple[Any, List[int]], ...]
45-
) -> Tuple[Tuple[List[int], Any], ...]:
26+
) -> Tuple[Tuple[Tuple[int, ...], Any], ...]:
4627
return tuple(
47-
(shape, dtypes.canonicalize_dtype(dtype)) for dtype, shape in specs
28+
(tuple(shape), dtypes.canonicalize_dtype(dtype)) for dtype, shape in specs
4829
)
4930

5031

32+
def _shape_dtype_struct(shape: Tuple[int, ...], dtype: Any) -> ShapeDtypeStruct:
33+
return ShapeDtypeStruct(shape, dtype)
34+
35+
36+
def _layout(shape: Tuple[int, ...]) -> Tuple[int, ...]:
37+
return tuple(range(len(shape)))
38+
39+
5140
def _make_xla_function(
5241
obj: Any,
5342
handle: bytes,
5443
name: str,
5544
specs: Tuple[Tuple[Any, ...], Tuple[Any, ...]],
5645
capsules: Tuple[Any, Any],
5746
) -> Callable:
58-
if not (
59-
hasattr(_core, "Primitive") and
60-
hasattr(_xla, "backend_specific_translations")
61-
):
62-
raise RuntimeError(
63-
"XLA is unavailable because this JAX version removed the legacy "
64-
"primitive/translation APIs used by envpool."
65-
)
6647
in_specs, out_specs = specs
6748
in_specs = _normalize_specs(in_specs)
6849
out_specs = _normalize_specs(out_specs)
6950
cpu_capsule, gpu_capsule = capsules
70-
_xla_client.register_custom_call_target(
71-
f"{type(obj).__name__}_{id(obj)}_{name}_cpu".encode(),
51+
call_target_name = f"{type(obj).__name__}_{id(obj)}_{name}"
52+
ffi.register_ffi_target(
53+
call_target_name,
7254
cpu_capsule,
73-
platform="cpu"
55+
platform="cpu",
56+
api_version=0,
7457
)
75-
_xla_client.register_custom_call_target(
76-
f"{type(obj).__name__}_{id(obj)}_{name}_gpu".encode(),
58+
ffi.register_ffi_target(
59+
call_target_name,
7760
gpu_capsule,
7861
platform="gpu",
62+
api_version=0,
7963
)
80-
81-
def abstract(
82-
*args: List[jnp.ndarray]
83-
) -> Union[ShapedArray, Tuple[ShapedArray, ...]]:
84-
if len(out_specs) > 1:
85-
return tuple(ShapedArray(*spec) for spec in out_specs)
86-
else:
87-
return ShapedArray(*out_specs[0])
88-
89-
def translation(c: Any, *args: Any, platform: str = "cpu") -> Any:
90-
output_shape_with_layout = _shape_with_layout(out_specs)
91-
if len(out_specs) == 1:
92-
output_shape = output_shape_with_layout[0]
93-
else:
94-
output_shape = xla_client.Shape.tuple_shape(output_shape_with_layout)
95-
return _xla_client.ops.CustomCallWithLayout(
96-
c,
97-
f"{type(obj).__name__}_{id(obj)}_{name}_{platform}".encode(),
98-
operands=args,
99-
operand_shapes_with_layout=_shape_with_layout(in_specs),
100-
shape_with_layout=output_shape,
101-
opaque=handle,
102-
has_side_effect=True,
103-
)
104-
105-
prim = _core.Primitive(f"{type(obj).__name__}_{id(obj)}_{name}")
106-
prim.multiple_results = (len(out_specs) > 1)
107-
prim.def_impl(partial(xla.apply_primitive, prim))
108-
prim.def_abstract_eval(abstract)
109-
_xla.backend_specific_translations["cpu"][prim] = partial(
110-
translation, platform="cpu"
111-
)
112-
_xla.backend_specific_translations["gpu"][prim] = partial(
113-
translation, platform="gpu"
64+
result_specs = tuple(_shape_dtype_struct(*spec) for spec in out_specs)
65+
xla_func = ffi.ffi_call(
66+
call_target_name,
67+
result_specs if len(result_specs) > 1 else result_specs[0],
68+
has_side_effect=True,
69+
input_layouts=tuple(_layout(shape) for shape, _ in in_specs),
70+
output_layouts=(
71+
tuple(_layout(shape) for shape, _ in out_specs)
72+
if len(out_specs) > 1 else _layout(out_specs[0][0])
73+
),
74+
custom_call_api_version=0,
75+
legacy_backend_config=cast(Any, handle),
11476
)
11577

11678
def call(*args: Any) -> Any:
117-
return prim.bind(*args)
79+
return xla_func(*args)
11880

11981
return call
12082

third_party/pip_requirements/requirements-dev-lock.txt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,10 @@ gymnasium==1.2.3
2424
h5py==3.16.0
2525
idna==3.11
2626
imageio==2.37.3
27-
jax==0.9.2
28-
jaxlib==0.9.2
27+
jax==0.6.2; python_version < "3.11"
28+
jax==0.9.2; python_version >= "3.11"
29+
jaxlib==0.6.2; python_version < "3.11"
30+
jaxlib==0.9.2; python_version >= "3.11"
2931
jinja2==3.1.6
3032
labmaze==1.0.6
3133
llvmlite==0.46.0

third_party/pip_requirements/requirements-dev.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ dm-env>=1.6
55
gym>=0.26.2
66
gymnasium>=1.2.3
77
optree>=0.19.0
8-
jax[cpu]>=0.9.2,<0.10
8+
jax[cpu]>=0.6.2,<0.7; python_version<'3.11'
9+
jax[cpu]>=0.9.2,<0.10; python_version>='3.11'
910
absl-py
1011
packaging>=26.0
1112
tqdm

third_party/pip_requirements/requirements-release-lock.txt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,10 @@ farama-notifications==0.0.4
77
gym==0.26.2
88
gym-notices==0.1.0
99
gymnasium==1.2.3
10-
jax==0.9.2
11-
jaxlib==0.9.2
10+
jax==0.6.2; python_version < "3.11"
11+
jax==0.9.2; python_version >= "3.11"
12+
jaxlib==0.6.2; python_version < "3.11"
13+
jaxlib==0.9.2; python_version >= "3.11"
1214
ml-dtypes==0.5.4
1315
numpy==2.4.3
1416
opt-einsum==3.4.0

third_party/pip_requirements/requirements-release.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,6 @@ dm-env>=1.6
55
gym>=0.26.2
66
gymnasium>=1.2.3
77
optree>=0.19.0
8-
jax[cpu]>=0.9.2,<0.10
8+
jax[cpu]>=0.6.2,<0.7; python_version<'3.11'
9+
jax[cpu]>=0.9.2,<0.10; python_version>='3.11'
910
packaging>=26.0

0 commit comments

Comments
 (0)