Merge branch 'google-deepmind:main' into mjx-warp-segmentation
This commit is contained in:
+19
-15
@@ -1,21 +1,25 @@
|
||||
jax-cuda12-plugin==0.5.3; python_version >= '3.10' \
|
||||
--hash=sha256:1862595b2b6d815679d11e0e889e523185ee54a46d46e022689f70fc4554dd91 \
|
||||
--hash=sha256:21fec1b56c98783ea0569b747a56751f1f9ff2187b48acc11c700d3bfc5e1a31 \
|
||||
jax-cuda12-plugin==0.8.3; python_version >= '3.13' \
|
||||
--hash=sha256:11d7cb222cfd4d5f6b7691df61516a5edc9298b7879dd6caaccc6dfc64678c70 \
|
||||
--hash=sha256:7bb68f693e16038cad77197aba914375795e5bb7e99f4a4f023b67bb50cad8c2 \
|
||||
--hash=sha256:9e3f1335a6812f5b28ace211a17d9ede46b8b46ceb4b8d9c8c697d3b4ada513f \
|
||||
--hash=sha256:b38c4bd34062c01d22a8c6a2225254dcd429771e97e024f3a2ccc1d6d24fd856 \
|
||||
--hash=sha256:b3f64b5059a39c18ec006c136475f46d088a11164e7e6ee2444e76305da87a1b \
|
||||
--hash=sha256:bb20d8b794ce52d644967c7229c5e0a01d3b1fac7efc60fbbfcd046a745a66c6 \
|
||||
--hash=sha256:f9a722128e2b423469a5dab8f9f96d77257d153ca7d96850b25a475191efaacc \
|
||||
--hash=sha256:fb9d49d43c4447793630079632e6fbb4a5ce30c388955131fe3ba96efec91817
|
||||
jax-cuda12-plugin==0.5.3; python_version < '3.13' \
|
||||
--hash=sha256:2030cf1208ce4ea70ee56cac61ddd239f9798695fc39bb7739c50a25d6e9da44 \
|
||||
--hash=sha256:c2517a7c2186f8708894696e26cf96ebd60b7879ceca398b2c46abb28d2c96c8 \
|
||||
--hash=sha256:aaa704a5ef547595d022db1c1e4878a0677116412a9360c115d67ff4b64e1596 \
|
||||
--hash=sha256:298d2d768f1029b74a0b1d01270e549349d2c37dc07658796542cda967eb7bd3 \
|
||||
--hash=sha256:6171aed2f4b3bdd5fc13782de1072c6a634fce13731b75d0cb0a6ab8f4e6e650 \
|
||||
--hash=sha256:aaa704a5ef547595d022db1c1e4878a0677116412a9360c115d67ff4b64e1596 \
|
||||
--hash=sha256:ba2555967f9b6c381c8b4ef9fb03d05bc55ec25ecfee5cfe45c5ace34f7d4152 \
|
||||
--hash=sha256:6171aed2f4b3bdd5fc13782de1072c6a634fce13731b75d0cb0a6ab8f4e6e650
|
||||
jax-cuda12-plugin==0.4.30; python_version == '3.9' \
|
||||
--hash=sha256:d8d196241b9253ecb1144a4409b5deacbb9771624f097b2bbf025da3c7d8f4f8 \
|
||||
--hash=sha256:cb8edccdce358451205f689e3536272200761c625c8e8059ab10523984cf8b61
|
||||
jax-cuda12-pjrt==0.5.3; python_version >= '3.10' \
|
||||
--hash=sha256:c5378306568ba0c81b230a779dd3194c9dd10339ab6360ae80928108d37e7f75 \
|
||||
--hash=sha256:04ee111eaf5fc2692978ad4a5c84d5925e42eb05c1701849ba3a53f6515400cc
|
||||
jax-cuda12-pjrt==0.4.30; python_version == '3.9' \
|
||||
--hash=sha256:895d0198ad99638fcaf976c47592e2a543eef79ea15fabd24a402d055390c328 \
|
||||
--hash=sha256:c36fb1e0c236563bf3a87e70f4d1ab28a31d7cf5d722c9ede30c4172116e8bcb
|
||||
--hash=sha256:c2517a7c2186f8708894696e26cf96ebd60b7879ceca398b2c46abb28d2c96c8
|
||||
jax-cuda12-pjrt==0.8.3; python_version >= '3.13' \
|
||||
--hash=sha256:f6d085fa7b2836cd79b14cabf1058ddb50c5161bfca9ede407993fa4f7547b7b \
|
||||
--hash=sha256:f740c661dd4064ff45dedf170fd0c4ff1a25d077636ad293307e8d28c78e65d7
|
||||
jax-cuda12-pjrt==0.5.3; python_version < '3.13' \
|
||||
--hash=sha256:04ee111eaf5fc2692978ad4a5c84d5925e42eb05c1701849ba3a53f6515400cc \
|
||||
--hash=sha256:c5378306568ba0c81b230a779dd3194c9dd10339ab6360ae80928108d37e7f75
|
||||
warp-lang==1.12.1 \
|
||||
--hash=sha256:98df3533a6c40a33cce961f8efa991006b30c9d286356e4cd77ea8ce86928f1d \
|
||||
--hash=sha256:6bf01f10509488ba8eacaf4ec7fcf7cfbd503118b22e002ecba407b40a17424e \
|
||||
|
||||
+13
-17
@@ -96,16 +96,15 @@ def _resolve_device(
|
||||
return cpu_0
|
||||
|
||||
if impl == types.Impl.WARP:
|
||||
# WARP implementation requires a CUDA GPU.
|
||||
cuda_gpus = [d for d in jax.devices('cuda')]
|
||||
if not cuda_gpus:
|
||||
raise AssertionError(
|
||||
'No CUDA GPU devices found in'
|
||||
f' jax.devices("cuda")={jax.devices("cuda")}.'
|
||||
)
|
||||
# WARP implementation requires a CUDA GPU or CPU.
|
||||
if has_cuda_gpu_device():
|
||||
cuda_gpus = [d for d in jax.devices('cuda')]
|
||||
if cuda_gpus:
|
||||
logging.debug('Picking default device: %s', cuda_gpus[0])
|
||||
return cuda_gpus[0]
|
||||
|
||||
logging.debug('Picking default device: %s', cuda_gpus[0])
|
||||
return cuda_gpus[0]
|
||||
logging.debug('Picking default device for Warp: CPU')
|
||||
return jax.devices('cpu')[0]
|
||||
|
||||
raise ValueError(f'Unsupported implementation: {impl}')
|
||||
|
||||
@@ -121,9 +120,12 @@ def _check_impl_device_compatibility(
|
||||
impl = types.Impl(impl)
|
||||
|
||||
if impl == types.Impl.WARP:
|
||||
if not _is_cuda_gpu_device(device):
|
||||
is_cuda_device = _is_cuda_gpu_device(device)
|
||||
is_cpu_device = device.platform == 'cpu'
|
||||
if not (is_cuda_device or is_cpu_device):
|
||||
raise AssertionError(
|
||||
f'Warp implementation requires a CUDA GPU device, got {device}.'
|
||||
'Warp implementation requires a CUDA GPU or CPU device, got '
|
||||
f'{device}.'
|
||||
)
|
||||
_check_warp_installed()
|
||||
|
||||
@@ -425,8 +427,6 @@ def _put_model_jax(
|
||||
return _strip_weak_type(model)
|
||||
|
||||
|
||||
|
||||
|
||||
def _put_model_warp(
|
||||
m: mujoco.MjModel,
|
||||
graph_mode: mjxw.types.GraphMode,
|
||||
@@ -719,8 +719,6 @@ def _make_data_jax(
|
||||
return d
|
||||
|
||||
|
||||
|
||||
|
||||
def _get_nested_attr(obj: Any, attr_name: str, split: str) -> Any:
|
||||
"""Returns the nested attribute from an object."""
|
||||
for part in attr_name.split(split):
|
||||
@@ -1084,8 +1082,6 @@ def _put_data_jax(
|
||||
return _strip_weak_type(data)
|
||||
|
||||
|
||||
|
||||
|
||||
# TODO(josechenf): Iterate on the keepalive implementation to make it easier to
|
||||
# use before OSS.
|
||||
def _put_data_cpp(
|
||||
|
||||
@@ -934,8 +934,8 @@ _DEVICE_TEST_CASES = [
|
||||
('gpu-nvidia', 'jax', ('gpu', Impl.JAX)),
|
||||
('tpu', 'jax', ('tpu', Impl.JAX)),
|
||||
# WARP backend specified.
|
||||
('cpu', 'warp', ('cpu', 'error')),
|
||||
('gpu-notnvidia', 'warp', ('cpu', 'error')),
|
||||
('cpu', 'warp', ('cpu', Impl.WARP)),
|
||||
('gpu-notnvidia', 'warp', ('gpu', 'error')),
|
||||
('gpu-nvidia', 'warp', ('gpu', Impl.WARP)),
|
||||
('tpu', 'warp', ('tpu', 'error')),
|
||||
# CPP backend specified.
|
||||
@@ -962,10 +962,10 @@ _DEFAULT_DEVICE_TEST_CASES = [
|
||||
('gpu-nvidia', 'jax', ('gpu', Impl.JAX)),
|
||||
('tpu', 'jax', ('tpu', Impl.JAX)),
|
||||
# WARP backend impl specified.
|
||||
('cpu', 'warp', ('cpu', 'error')),
|
||||
('gpu-notnvidia', 'warp', ('cpu', 'error')),
|
||||
('cpu', 'warp', ('cpu', Impl.WARP)),
|
||||
('gpu-notnvidia', 'warp', ('cpu', Impl.WARP)),
|
||||
('gpu-nvidia', 'warp', ('gpu', Impl.WARP)),
|
||||
('tpu', 'warp', ('tpu', 'error')),
|
||||
('tpu', 'warp', ('cpu', Impl.WARP)),
|
||||
# CPP backend impl specified, CPU should always be available.
|
||||
('cpu', 'cpp', ('cpu', Impl.CPP)),
|
||||
('gpu-notnvidia', 'cpp', ('cpu', Impl.CPP)),
|
||||
@@ -1140,15 +1140,6 @@ class ResolveImplAndDeviceTest(parameterized.TestCase):
|
||||
self.mock_jax_backends.side_effect = backends_side_effect
|
||||
|
||||
expected_device, expected_impl = expected
|
||||
if (
|
||||
expected_impl == 'error'
|
||||
and default_device_str != 'gpu-nvidia'
|
||||
and impl_str == 'warp'
|
||||
):
|
||||
with self.assertRaisesRegex(RuntimeError, 'cuda backend not supported'):
|
||||
mjx_io._resolve_impl_and_device(impl=impl_str, device=None)
|
||||
return
|
||||
|
||||
if expected_impl == 'error':
|
||||
with self.assertRaises(AssertionError):
|
||||
mjx_io._resolve_impl_and_device(impl=impl_str, device=None)
|
||||
|
||||
@@ -776,6 +776,10 @@ class Model(PyTreeNode):
|
||||
flex_vertadr: np.ndarray
|
||||
flex_vertnum: np.ndarray
|
||||
flex_vert0: np.ndarray
|
||||
flex_nodeadr: np.ndarray
|
||||
flex_nodenum: np.ndarray
|
||||
flex_nodebodyid: np.ndarray
|
||||
flex_node0: np.ndarray
|
||||
hfield_size: np.ndarray
|
||||
hfield_nrow: np.ndarray
|
||||
hfield_ncol: np.ndarray
|
||||
|
||||
+111
-48
@@ -210,11 +210,19 @@ class FfiKernel:
|
||||
self.input_output_aliases = input_output_aliases
|
||||
|
||||
# register the callback
|
||||
FFI_CCALLFUNC = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.POINTER(XLA_FFI_CallFrame))
|
||||
self.callback_func = FFI_CCALLFUNC(self.ffi_callback)
|
||||
ffi_ccall_address = ctypes.cast(self.callback_func, ctypes.c_void_p)
|
||||
ffi_capsule = jax.ffi.pycapsule(ffi_ccall_address.value)
|
||||
jax.ffi.register_ffi_target(self.name, ffi_capsule, platform="CUDA")
|
||||
FFI_CCALLFUNC = ctypes.CFUNCTYPE(
|
||||
ctypes.c_void_p, ctypes.POINTER(XLA_FFI_CallFrame)
|
||||
)
|
||||
|
||||
self.callback_func_cuda = FFI_CCALLFUNC(lambda call_frame: self.ffi_callback(call_frame, platform="CUDA"))
|
||||
ffi_ccall_address_cuda = ctypes.cast(self.callback_func_cuda, ctypes.c_void_p)
|
||||
ffi_capsule_cuda = jax.ffi.pycapsule(ffi_ccall_address_cuda.value)
|
||||
jax.ffi.register_ffi_target(self.name, ffi_capsule_cuda, platform="CUDA")
|
||||
|
||||
self.callback_func_host = FFI_CCALLFUNC(lambda call_frame: self.ffi_callback(call_frame, platform="Host"))
|
||||
ffi_ccall_address_host = ctypes.cast(self.callback_func_host, ctypes.c_void_p)
|
||||
ffi_capsule_host = jax.ffi.pycapsule(ffi_ccall_address_host.value)
|
||||
jax.ffi.register_ffi_target(self.name, ffi_capsule_host, platform="Host")
|
||||
|
||||
def __call__(self, *args, output_dims=None, launch_dims=None, vmap_method=None):
|
||||
num_inputs = len(args)
|
||||
@@ -241,18 +249,19 @@ class FfiKernel:
|
||||
# check dtype
|
||||
if input_value.dtype != input_arg.jax_scalar_type:
|
||||
raise TypeError(
|
||||
f"Invalid data type for array argument '{input_arg.name}', expected {input_arg.jax_scalar_type}, got {input_value.dtype}"
|
||||
f"Invalid data type for array argument '{input_arg.name}',"
|
||||
f" expected {input_arg.jax_scalar_type}, got {input_value.dtype}"
|
||||
)
|
||||
# check ndim
|
||||
if input_value.ndim != input_arg.jax_ndim:
|
||||
raise TypeError(
|
||||
f"Invalid dimensionality for array argument '{input_arg.name}', expected {input_arg.jax_ndim} dimensions, got {input_value.ndim}"
|
||||
f"Invalid dimensionality for array argument '{input_arg.name}', expected {input_arg.jax_ndim} dimensions, got {input_value.ndim}"
|
||||
)
|
||||
# check inner dims
|
||||
for d in range(input_arg.dtype_ndim):
|
||||
if input_value.shape[input_arg.type.ndim + d] != input_arg.dtype_shape[d]:
|
||||
raise TypeError(
|
||||
f"Invalid inner dimensions for array argument '{input_arg.name}', expected {input_arg.dtype_shape}, got {input_value.shape[-input_arg.dtype_ndim :]}"
|
||||
f"Invalid inner dimensions for array argument '{input_arg.name}', expected {input_arg.dtype_shape}, got {input_value.shape[-input_arg.dtype_ndim :]}"
|
||||
)
|
||||
else:
|
||||
# make sure scalar is not a traced variable, should be static
|
||||
@@ -328,7 +337,7 @@ class FfiKernel:
|
||||
|
||||
return call(*args, launch_id=launch_id)
|
||||
|
||||
def ffi_callback(self, call_frame):
|
||||
def ffi_callback(self, call_frame, platform="CUDA"):
|
||||
try:
|
||||
# On the first call, XLA runtime will query the API version and traits
|
||||
# metadata using the |extension| field. Let us respond to that query
|
||||
@@ -340,10 +349,11 @@ class FfiKernel:
|
||||
metadata_ext = ctypes.cast(extension, ctypes.POINTER(XLA_FFI_Metadata_Extension))
|
||||
metadata_ext.contents.metadata.contents.api_version.major_version = 0
|
||||
metadata_ext.contents.metadata.contents.api_version.minor_version = 1
|
||||
# Turn on CUDA graphs for this handler.
|
||||
metadata_ext.contents.metadata.contents.traits = (
|
||||
XLA_FFI_Handler_TraitsBits.COMMAND_BUFFER_COMPATIBLE
|
||||
)
|
||||
# Turn on CUDA graphs for this handler if on CUDA platform.
|
||||
if platform == "CUDA":
|
||||
metadata_ext.contents.metadata.contents.traits = (
|
||||
XLA_FFI_Handler_TraitsBits.COMMAND_BUFFER_COMPATIBLE
|
||||
)
|
||||
return None
|
||||
|
||||
# Lock is required to prevent race conditions when callback is invoked
|
||||
@@ -423,29 +433,43 @@ class FfiKernel:
|
||||
kernel_params[0] = ctypes.addressof(launch_bounds)
|
||||
|
||||
# get device and stream
|
||||
device = wp.get_cuda_device(get_device_ordinal_from_callframe(call_frame.contents))
|
||||
stream = get_stream_from_callframe(call_frame.contents)
|
||||
if platform == "CUDA":
|
||||
device = wp.get_cuda_device(get_device_ordinal_from_callframe(call_frame.contents))
|
||||
stream = get_stream_from_callframe(call_frame.contents)
|
||||
else:
|
||||
device = wp.get_device("cpu")
|
||||
stream = None
|
||||
|
||||
# get kernel hooks
|
||||
hooks = self.kernel.module.get_kernel_hooks(self.kernel, device)
|
||||
assert hooks.forward, "Failed to find kernel entry point"
|
||||
|
||||
# launch the kernel
|
||||
wp._src.context.runtime.core.wp_cuda_launch_kernel(
|
||||
device.context,
|
||||
hooks.forward,
|
||||
launch_bounds.size,
|
||||
0,
|
||||
256,
|
||||
hooks.forward_smem_bytes,
|
||||
kernel_params,
|
||||
stream,
|
||||
)
|
||||
if device.is_cuda:
|
||||
wp._src.context.runtime.core.wp_cuda_launch_kernel(
|
||||
device.context,
|
||||
hooks.forward,
|
||||
launch_bounds.size,
|
||||
0,
|
||||
256,
|
||||
hooks.forward_smem_bytes,
|
||||
kernel_params,
|
||||
stream,
|
||||
)
|
||||
else:
|
||||
wp._src.context.runtime.core.wp_cpu_launch_kernel(
|
||||
device.context,
|
||||
hooks.forward,
|
||||
launch_bounds.size,
|
||||
kernel_params,
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
print(traceback.format_exc())
|
||||
return create_ffi_error(
|
||||
call_frame.contents.api, XLA_FFI_Error_Code.UNKNOWN, f"FFI callback error: {type(e).__name__}: {e}"
|
||||
call_frame.contents.api,
|
||||
XLA_FFI_Error_Code.UNKNOWN,
|
||||
f"FFI callback error: {type(e).__name__}: {e}",
|
||||
)
|
||||
|
||||
|
||||
@@ -594,10 +618,16 @@ class FfiCallable:
|
||||
|
||||
# register the callback
|
||||
FFI_CCALLFUNC = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.POINTER(XLA_FFI_CallFrame))
|
||||
self.callback_func = FFI_CCALLFUNC(self.ffi_callback)
|
||||
ffi_ccall_address = ctypes.cast(self.callback_func, ctypes.c_void_p)
|
||||
ffi_capsule = jax.ffi.pycapsule(ffi_ccall_address.value)
|
||||
jax.ffi.register_ffi_target(self.name, ffi_capsule, platform="CUDA")
|
||||
|
||||
self.callback_func_cuda = FFI_CCALLFUNC(lambda call_frame: self.ffi_callback(call_frame, platform="CUDA"))
|
||||
ffi_ccall_address_cuda = ctypes.cast(self.callback_func_cuda, ctypes.c_void_p)
|
||||
ffi_capsule_cuda = jax.ffi.pycapsule(ffi_ccall_address_cuda.value)
|
||||
jax.ffi.register_ffi_target(self.name, ffi_capsule_cuda, platform="CUDA")
|
||||
|
||||
self.callback_func_host = FFI_CCALLFUNC(lambda call_frame: self.ffi_callback(call_frame, platform="Host"))
|
||||
ffi_ccall_address_host = ctypes.cast(self.callback_func_host, ctypes.c_void_p)
|
||||
ffi_capsule_host = jax.ffi.pycapsule(ffi_ccall_address_host.value)
|
||||
jax.ffi.register_ffi_target(self.name, ffi_capsule_host, platform="Host")
|
||||
|
||||
def __call__(self, *args, output_dims=None, vmap_method=None):
|
||||
num_inputs = len(args)
|
||||
@@ -688,8 +718,7 @@ class FfiCallable:
|
||||
except Exception:
|
||||
# ignore unsupported devices like TPUs
|
||||
pass
|
||||
# we only support CUDA devices for now
|
||||
if dev.is_cuda:
|
||||
if dev.is_cuda or dev.is_cpu:
|
||||
module.load(dev)
|
||||
|
||||
# save call data to be retrieved by callback
|
||||
@@ -698,7 +727,7 @@ class FfiCallable:
|
||||
self.call_id += 1
|
||||
return call(*args, call_id=call_id)
|
||||
|
||||
def ffi_callback(self, call_frame):
|
||||
def ffi_callback(self, call_frame, platform="CUDA"):
|
||||
try:
|
||||
# On the first call, XLA runtime will query the API version and traits
|
||||
# metadata using the |extension| field. Let us respond to that query
|
||||
@@ -710,8 +739,8 @@ class FfiCallable:
|
||||
metadata_ext = ctypes.cast(extension, ctypes.POINTER(XLA_FFI_Metadata_Extension))
|
||||
metadata_ext.contents.metadata.contents.api_version.major_version = 0
|
||||
metadata_ext.contents.metadata.contents.api_version.minor_version = 1
|
||||
# Turn on CUDA graphs for this handler.
|
||||
if self.graph_mode is GraphMode.JAX:
|
||||
# Turn on CUDA graphs for this handler if on CUDA platform.
|
||||
if self.graph_mode is GraphMode.JAX and platform == "CUDA":
|
||||
metadata_ext.contents.metadata.contents.traits = (
|
||||
XLA_FFI_Handler_TraitsBits.COMMAND_BUFFER_COMPATIBLE
|
||||
)
|
||||
@@ -738,6 +767,35 @@ class FfiCallable:
|
||||
assert num_inputs == self.num_inputs
|
||||
assert num_outputs == self.num_outputs
|
||||
|
||||
if platform == "Host":
|
||||
device = wp.get_device("cpu")
|
||||
# reconstruct the argument list
|
||||
arg_list = []
|
||||
|
||||
# input and in-out args
|
||||
for i, arg in enumerate(self.input_args):
|
||||
if arg.is_array:
|
||||
buffer = inputs[i].contents
|
||||
shape = collapse_batch_dims(buffer.dims[: buffer.rank - arg.dtype_ndim], arg.type.ndim)
|
||||
arr = wp.array(ptr=buffer.data, dtype=arg.type.dtype, shape=shape, device=device)
|
||||
arg_list.append(arr)
|
||||
else:
|
||||
# scalar argument, get stashed value
|
||||
value = call_desc.static_inputs[arg.name]
|
||||
arg_list.append(value)
|
||||
|
||||
# pure output args (skip in-out FFI buffers)
|
||||
for i, arg in enumerate(self.output_args):
|
||||
buffer = outputs[i + self.num_in_out].contents
|
||||
shape = collapse_batch_dims(buffer.dims[: buffer.rank - arg.dtype_ndim], arg.type.ndim)
|
||||
arr = wp.array(ptr=buffer.data, dtype=arg.type.dtype, shape=shape, device=device)
|
||||
arg_list.append(arr)
|
||||
|
||||
# call the Python function with reconstructed arguments
|
||||
with wp.ScopedDevice(device):
|
||||
self.func(*arg_list)
|
||||
return
|
||||
|
||||
cuda_stream = get_stream_from_callframe(call_frame.contents)
|
||||
device_ordinal = get_device_ordinal_from_callframe(call_frame.contents)
|
||||
|
||||
@@ -870,8 +928,8 @@ class FfiCallable:
|
||||
arg_list.append(arr)
|
||||
|
||||
# call the Python function with reconstructed arguments
|
||||
with wp.ScopedStream(stream, sync_enter=False):
|
||||
if stream.is_capturing:
|
||||
with wp.ScopedStream(stream, sync_enter=False) if stream else wp.ScopedDevice(device):
|
||||
if stream and stream.is_capturing:
|
||||
# capturing with JAX
|
||||
with wp.ScopedCapture(external=True) as capture:
|
||||
self.func(*arg_list)
|
||||
@@ -879,7 +937,7 @@ class FfiCallable:
|
||||
# keep a reference to the capture object to prevent required modules getting unloaded
|
||||
call_desc.capture = capture
|
||||
|
||||
elif self.graph_mode == GraphMode.WARP:
|
||||
elif self.graph_mode == GraphMode.WARP and device.is_cuda:
|
||||
# capturing with WARP
|
||||
with wp.ScopedCapture() as capture:
|
||||
self.func(*arg_list)
|
||||
@@ -892,7 +950,7 @@ class FfiCallable:
|
||||
if self._graph_cache_max is not None and len(self.captures) > self._graph_cache_max:
|
||||
self.captures.popitem(last=False)
|
||||
|
||||
elif self.graph_mode == GraphMode.WARP_STAGED_EX:
|
||||
elif self.graph_mode == GraphMode.WARP_STAGED_EX and device.is_cuda:
|
||||
# capturing with WARP using staging buffers and memcopies done outside of the graph
|
||||
wp_memcpy_batch = wp._src.context.runtime.core.wp_memcpy_batch
|
||||
|
||||
@@ -935,7 +993,7 @@ class FfiCallable:
|
||||
# TODO: we should have a way of freeing this
|
||||
call_desc.capture = capture
|
||||
|
||||
elif self.graph_mode == GraphMode.WARP_STAGED:
|
||||
elif self.graph_mode == GraphMode.WARP_STAGED and device.is_cuda:
|
||||
# capturing with WARP using staging buffers and memcopies done inside of the graph
|
||||
wp_cuda_graph_insert_memcpy_batch = (
|
||||
wp._src.context.runtime.core.wp_cuda_graph_insert_memcpy_batch
|
||||
@@ -1013,7 +1071,7 @@ class FfiCallable:
|
||||
call_desc.capture = capture
|
||||
|
||||
else:
|
||||
# not capturing
|
||||
# not capturing or on CPU
|
||||
self.func(*arg_list)
|
||||
|
||||
except Exception as e:
|
||||
@@ -1621,7 +1679,7 @@ def register_ffi_callback(name: str, func: Callable, graph_compatible: bool = Tr
|
||||
|
||||
# TODO check that the name is not already registered
|
||||
|
||||
def ffi_callback(call_frame):
|
||||
def ffi_callback(call_frame, platform="CUDA"):
|
||||
try:
|
||||
extension = call_frame.contents.extension_start
|
||||
# On the first call, XLA runtime will query the API version and traits
|
||||
@@ -1633,7 +1691,7 @@ def register_ffi_callback(name: str, func: Callable, graph_compatible: bool = Tr
|
||||
metadata_ext = ctypes.cast(extension, ctypes.POINTER(XLA_FFI_Metadata_Extension))
|
||||
metadata_ext.contents.metadata.contents.api_version.major_version = 0
|
||||
metadata_ext.contents.metadata.contents.api_version.minor_version = 1
|
||||
if graph_compatible:
|
||||
if graph_compatible and platform == "CUDA":
|
||||
# Turn on CUDA graphs for this handler.
|
||||
metadata_ext.contents.metadata.contents.traits = (
|
||||
XLA_FFI_Handler_TraitsBits.COMMAND_BUFFER_COMPATIBLE
|
||||
@@ -1666,12 +1724,17 @@ def register_ffi_callback(name: str, func: Callable, graph_compatible: bool = Tr
|
||||
return None
|
||||
|
||||
FFI_CCALLFUNC = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.POINTER(XLA_FFI_CallFrame))
|
||||
callback_func = FFI_CCALLFUNC(ffi_callback)
|
||||
callback_func_cuda = FFI_CCALLFUNC(lambda call_frame: ffi_callback(call_frame, platform="CUDA"))
|
||||
callback_func_host = FFI_CCALLFUNC(lambda call_frame: ffi_callback(call_frame, platform="Host"))
|
||||
with _FFI_REGISTRY_LOCK:
|
||||
_FFI_CALLBACK_REGISTRY[name] = callback_func
|
||||
ffi_ccall_address = ctypes.cast(callback_func, ctypes.c_void_p)
|
||||
ffi_capsule = jax.ffi.pycapsule(ffi_ccall_address.value)
|
||||
jax.ffi.register_ffi_target(name, ffi_capsule, platform="CUDA")
|
||||
_FFI_CALLBACK_REGISTRY[f"{name}_cuda"] = callback_func_cuda
|
||||
_FFI_CALLBACK_REGISTRY[f"{name}_host"] = callback_func_host
|
||||
ffi_ccall_address_cuda = ctypes.cast(callback_func_cuda, ctypes.c_void_p)
|
||||
ffi_capsule_cuda = jax.ffi.pycapsule(ffi_ccall_address_cuda.value)
|
||||
jax.ffi.register_ffi_target(name, ffi_capsule_cuda, platform="CUDA")
|
||||
ffi_ccall_address_host = ctypes.cast(callback_func_host, ctypes.c_void_p)
|
||||
ffi_capsule_host = jax.ffi.pycapsule(ffi_ccall_address_host.value)
|
||||
jax.ffi.register_ffi_target(name, ffi_capsule_host, platform="Host")
|
||||
|
||||
|
||||
###############################################################################
|
||||
|
||||
@@ -31,6 +31,7 @@ from mujoco.mjx.warp import test_util as tu
|
||||
from mujoco.mjx.warp import warp as wp # pylint: disable=g-importing-member
|
||||
import numpy as np
|
||||
|
||||
|
||||
try:
|
||||
from mujoco.mjx.warp import forward # pylint: disable=g-import-not-at-top
|
||||
except ImportError:
|
||||
@@ -300,6 +301,56 @@ class StepTest(parameterized.TestCase):
|
||||
tu.assert_attr_eq(dx, d, 'mocap_quat')
|
||||
tu.assert_attr_eq(dx, d, 'sensordata')
|
||||
|
||||
@parameterized.parameters(
|
||||
'humanoid/humanoid.xml',
|
||||
'pendula.xml',
|
||||
)
|
||||
def test_step_cpu(self, xml: str):
|
||||
"""Tests step on the CPU device."""
|
||||
if not _FORCE_TEST:
|
||||
if not mjxw.WARP_INSTALLED:
|
||||
self.skipTest('Warp not installed.')
|
||||
|
||||
batch_size = 1
|
||||
m = test_util.load_test_file(xml)
|
||||
m.opt.iterations = 10
|
||||
m.opt.ls_iterations = 10
|
||||
|
||||
cpu_device = jax.devices('cpu')[0]
|
||||
mx = mjx.put_model(m, impl='warp', device=cpu_device)
|
||||
|
||||
d = mujoco.MjData(m)
|
||||
worldids = jp.arange(batch_size)
|
||||
dx_batch = jax.vmap(functools.partial(tu.make_data, m))(worldids)
|
||||
dx_batch = jax.device_put(dx_batch, cpu_device)
|
||||
dx_batch_orig = dx_batch
|
||||
|
||||
for _ in range(10):
|
||||
dx_batch = jax.vmap(forward.step, in_axes=(None, 0))(
|
||||
mx, dx_batch
|
||||
)
|
||||
|
||||
for i in range(batch_size):
|
||||
dx = dx_batch[i]
|
||||
dx_orig = dx_batch_orig[i]
|
||||
|
||||
d.qpos[:] = dx_orig.qpos
|
||||
d.qvel[:] = dx_orig.qvel
|
||||
d.ctrl[:] = dx_orig.ctrl
|
||||
d.mocap_pos[:] = dx_orig.mocap_pos
|
||||
d.mocap_quat[:] = dx_orig.mocap_quat
|
||||
d.time = dx_orig.time
|
||||
mujoco.mj_step(m, d, 10)
|
||||
|
||||
tu.assert_attr_eq(dx, d, 'qpos')
|
||||
tu.assert_attr_eq(dx, d, 'qvel')
|
||||
tu.assert_attr_eq(dx, d, 'time')
|
||||
tu.assert_attr_eq(dx, d, 'ctrl')
|
||||
tu.assert_attr_eq(dx, d, 'act')
|
||||
tu.assert_attr_eq(dx, d, 'mocap_pos')
|
||||
tu.assert_attr_eq(dx, d, 'mocap_quat')
|
||||
tu.assert_attr_eq(dx, d, 'sensordata')
|
||||
|
||||
def test_step_leading_dim_mismatch(self):
|
||||
if not _FORCE_TEST:
|
||||
if not mjxw.WARP_INSTALLED:
|
||||
|
||||
@@ -133,10 +133,11 @@ class SmoothTest(parameterized.TestCase):
|
||||
|
||||
def test_kinematics_vmap(self):
|
||||
"""Tests kinematics with batched data."""
|
||||
if not mjxw.WARP_INSTALLED:
|
||||
self.skipTest('Warp not installed.')
|
||||
if not io.has_cuda_gpu_device():
|
||||
self.skipTest('No CUDA GPU device available.')
|
||||
if not _FORCE_TEST:
|
||||
if not mjxw.WARP_INSTALLED:
|
||||
self.skipTest('Warp not installed.')
|
||||
if not io.has_cuda_gpu_device():
|
||||
self.skipTest('No CUDA GPU device available.')
|
||||
|
||||
m = tu.load_test_file('pendula.xml')
|
||||
|
||||
|
||||
@@ -153,7 +153,9 @@ def _mjx_efc(dx, worldid: int):
|
||||
efc_pos = select(dx._impl.efc__pos)[:nefc]
|
||||
efc_type = select(dx._impl.efc__type)[:nefc]
|
||||
efc_d = select(dx._impl.efc__D)[:nefc]
|
||||
keys_sorted = np.lexsort((-efc_pos, efc_type, efc_d))
|
||||
keys_sorted = np.lexsort(
|
||||
(-np.round(efc_pos, 12), efc_type, np.round(efc_d, 12))
|
||||
)
|
||||
keys = keys[keys_sorted]
|
||||
|
||||
nefc = len(keys)
|
||||
@@ -180,7 +182,9 @@ def _mj_efc(d):
|
||||
else:
|
||||
efc_j = d.efc_J.reshape((-1, d.qvel.shape[0]))
|
||||
|
||||
keys = np.lexsort((-d.efc_pos, d.efc_type, d.efc_D))
|
||||
keys = np.lexsort(
|
||||
(-np.round(d.efc_pos, 12), d.efc_type, np.round(d.efc_D, 12))
|
||||
)
|
||||
type_ = d.efc_type[keys]
|
||||
pos = d.efc_pos[keys]
|
||||
efc_j = efc_j[keys]
|
||||
|
||||
+5
-4
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name="mujoco-mjx"
|
||||
version = "3.7.1"
|
||||
version = "3.8.1"
|
||||
authors = [
|
||||
{name = "Google DeepMind", email = "mujoco@deepmind.com"},
|
||||
]
|
||||
@@ -21,6 +21,7 @@ classifiers = [
|
||||
"Programming Language :: Python :: 3.11",
|
||||
"Programming Language :: Python :: 3.12",
|
||||
"Programming Language :: Python :: 3.13",
|
||||
"Programming Language :: Python :: 3.14",
|
||||
"Topic :: Scientific/Engineering",
|
||||
]
|
||||
requires-python = ">=3.10"
|
||||
@@ -29,7 +30,7 @@ dependencies = [
|
||||
"etils[epath]",
|
||||
"jax",
|
||||
"jaxlib",
|
||||
"mujoco>=3.7.1.dev0",
|
||||
"mujoco>=3.8.1.dev0",
|
||||
"scipy",
|
||||
"trimesh",
|
||||
]
|
||||
@@ -45,9 +46,9 @@ mjx-viewer = "mujoco.mjx.viewer:main"
|
||||
|
||||
[project.urls]
|
||||
Homepage = "https://github.com/google-deepmind/mujoco/tree/main/mjx"
|
||||
Documentation = "https://mujoco.readthedocs.io/en/3.7.1"
|
||||
Documentation = "https://mujoco.readthedocs.io/en/3.8.1"
|
||||
Repository = "https://github.com/google-deepmind/mujoco/tree/main/mjx"
|
||||
Changelog = "https://mujoco.readthedocs.io/en/3.7.1/changelog.html"
|
||||
Changelog = "https://mujoco.readthedocs.io/en/3.8.1/changelog.html"
|
||||
|
||||
[tool.isort]
|
||||
force_single_line = true
|
||||
|
||||
+177
-78
@@ -2,29 +2,48 @@ absl-py==2.1.0 \
|
||||
--hash=sha256:526a04eadab8b4ee719ce68f204172ead1027549089702d99b9059f129ff1308
|
||||
etils[epath]==1.10.0; python_version >= '3.10' \
|
||||
--hash=sha256:0777fe60a234b4c65ca53470fc64f2dd2d0c6bca7fcc623fdaa8d7fa5a317098
|
||||
jax==0.5.3; python_version >= '3.10' and (sys_platform != 'darwin' or platform_machine != 'x86_64') \
|
||||
jax==0.8.3; python_version >= '3.13' and (sys_platform != 'darwin' or platform_machine != 'x86_64') \
|
||||
--hash=sha256:fb75f4cfee64e990ce6d7a0424cb11eb0520e4de19d7a52d0ca3498bff78261a
|
||||
jax==0.5.3; python_version >= '3.10' and python_version < '3.13' and (sys_platform != 'darwin' or platform_machine != 'x86_64') \
|
||||
--hash=sha256:1483dc237b4f47e41755d69429e8c3c138736716147cd43bb2b99b259d4e3c41 \
|
||||
--hash=sha256:f17fcb0fd61dc289394af6ce4de2dada2312f2689bb0d73642c6f026a95fbb2c
|
||||
jax==0.4.38; python_version >= '3.10' and sys_platform == 'darwin' and platform_machine == 'x86_64' \
|
||||
# 0.4.38 is the last Jax release that provides macOS x86-64 wheels, and only up
|
||||
# to Python 3.13. Unfortunately, later releases can't readily be built from
|
||||
# sources because some dependencies, like jaxlib, don't provide tarballs.
|
||||
# Thus, building with Python 3.14+ on macOS x86-64 is disabled in the build
|
||||
# scripts; if it's still needed, we'll have to come up with another method.
|
||||
jax==0.4.38; python_version >= '3.10' and python_version <= '3.13' and sys_platform == 'darwin' and platform_machine == 'x86_64' \
|
||||
--hash=sha256:78987306f7041ea8500d99df1a17c33ed92620c2268c4c3677fb24e06712be64
|
||||
jaxlib==0.5.3; python_version >= '3.10' and (sys_platform != 'darwin' or platform_machine != 'x86_64') \
|
||||
jaxlib==0.8.3; python_version >= '3.13' and (sys_platform != 'darwin' or platform_machine != 'x86_64') \
|
||||
--hash=sha256:1b3acadba65863254cc5482455d31a41f1fc8d38a449701f13cdbbc45beb240d \
|
||||
--hash=sha256:1e5481f9d7df9bfc0ae053d9f9d4f97ee77639a0169b45beb1cced070dc26da6 \
|
||||
--hash=sha256:3233198422c7ef49e5340785fc23f61c25ee61a5d767aa6f9183b8015e6ac6e2 \
|
||||
--hash=sha256:41067d2ec14a140e1d692fc84bc714f3372e208966b5f29cc309f4fca63c081b \
|
||||
--hash=sha256:4be4273edeb2cc75c409e446fd4f59a63d2e14f1311e714a978b5fa67ac16b70 \
|
||||
--hash=sha256:4d80575513f351eef4582908039c6e456d4e2ca028a043d2cdcbd059fa55e56c \
|
||||
--hash=sha256:56adca7fc1e24972633e2f33c758a28d924e116ba54b2a4e73f8ae4647657cf1 \
|
||||
--hash=sha256:831d817fa04218cc91b813920229c8ee0bec076c03ea744bec398e570b699d1c \
|
||||
--hash=sha256:92e755030e7862d3ba15929f25c0d7647baa95b083c87ed0c2da297aeb50c48c \
|
||||
--hash=sha256:9e76868758330eb63c5e4dd31e4d7c500a7e5523c7f09b34f64780c4a0503c7c \
|
||||
--hash=sha256:be237754eead89788264e112b2b5c722ab2a941406d19f1a8da6bf48bfde0bf2 \
|
||||
--hash=sha256:c96e562ad771fc81dfbb9a696519caa7e214f9b6dab1ce1df8bcd4759597d4a3 \
|
||||
--hash=sha256:ef3376145cc6c768f7847b688b004f37382e952bdc34b9a9404eb28b15ab50f8 \
|
||||
--hash=sha256:fe490fe3d81b02d21aaf936475fc4f47171473599e9d3907f6be0823ec4321bb
|
||||
jaxlib==0.5.3; python_version >= '3.10' and python_version < '3.13' and (sys_platform != 'darwin' or platform_machine != 'x86_64') \
|
||||
--hash=sha256:29e1530fc81833216f1e28b578d0c59697654f72ee31c7a44ed7753baf5ac466 \
|
||||
--hash=sha256:48ff5c89fb8a0fe04d475e9ddc074b4879a91d7ab68a51cec5cd1e87f81e6c47 \
|
||||
--hash=sha256:972400db4af6e85270d81db5e6e620d31395f0472e510c50dfcd4cb3f72b7220 \
|
||||
--hash=sha256:520665929649f29f7d948d4070dbaf3e032a4c1f7c11f2863eac73320fcee784 \
|
||||
--hash=sha256:52be6c9775aff738a61170d8c047505c75bb799a45518e66a7a0908127b11785 \
|
||||
--hash=sha256:5a5e88ab1cd6fdf78d69abe3544e8f09cce200dd339bb85fbe3c2ea67f2a5e68 \
|
||||
--hash=sha256:8eb54e38d789557579f900ea3d70f104a440f8555a9681ed45f4a122dcbfd92e \
|
||||
--hash=sha256:972400db4af6e85270d81db5e6e620d31395f0472e510c50dfcd4cb3f72b7220 \
|
||||
--hash=sha256:a4666f81d72c060ed3e581ded116a9caa9b0a70a148a54cb12a1d3afca3624b5 \
|
||||
--hash=sha256:b41a6fcaeb374fabc4ee7e74cfed60843bdab607cd54f60a68b7f7655cde2b66 \
|
||||
--hash=sha256:b62bd8b29e5a4f9bfaa57c8daf6e04820b2c994f448f3dec602d64255545e9f2 \
|
||||
--hash=sha256:a4666f81d72c060ed3e581ded116a9caa9b0a70a148a54cb12a1d3afca3624b5 \
|
||||
--hash=sha256:29e1530fc81833216f1e28b578d0c59697654f72ee31c7a44ed7753baf5ac466 \
|
||||
--hash=sha256:8eb54e38d789557579f900ea3d70f104a440f8555a9681ed45f4a122dcbfd92e \
|
||||
--hash=sha256:d394dbde4a1c6bd67501cfb29d3819a10b900cb534cc0fc603319f7092f24cfa \
|
||||
--hash=sha256:bddf6360377aa1c792e47fd87f307c342e331e5ff3582f940b1bca00f6b4bc73 \
|
||||
--hash=sha256:5a5e88ab1cd6fdf78d69abe3544e8f09cce200dd339bb85fbe3c2ea67f2a5e68 \
|
||||
--hash=sha256:520665929649f29f7d948d4070dbaf3e032a4c1f7c11f2863eac73320fcee784 \
|
||||
--hash=sha256:31321c25282a06a6dfc940507bc14d0a0ac838d8ced6c07aa00a7fae34ce7b3f \
|
||||
--hash=sha256:e904b92dedfbc7e545725a8d7676987030ae9c069001d94701bc109c6dab4100 \
|
||||
--hash=sha256:bb7593cb7fffcb13963f22fa5229ed960b8fb4ae5ec3b0820048cbd67f1e8e31 \
|
||||
--hash=sha256:8019f73a10b1290f988dd3768c684f3a8a147239091c3b790ce7e47e3bbc00bd
|
||||
jaxlib==0.4.38; python_version >= '3.10' and sys_platform == 'darwin' and platform_machine == 'x86_64' \
|
||||
--hash=sha256:d394dbde4a1c6bd67501cfb29d3819a10b900cb534cc0fc603319f7092f24cfa
|
||||
# See note above about macOS x86-64 support.
|
||||
jaxlib==0.4.38; python_version >= '3.10' and python_version <= '3.13' and sys_platform == 'darwin' and platform_machine == 'x86_64' \
|
||||
--hash=sha256:55c19b9d3f33a6fc59f644aa5a21fba02639ccdd776cb4a9b5526625f57839ff \
|
||||
--hash=sha256:30b2f52cb50d74734af2f477c2533a7a583e3bb7b2c8acdeb361ee77d940577a \
|
||||
--hash=sha256:ee19c163a8fdf0839d4c18b88a5fbfb4e731ba7c437416d3e5483e570bb764e4 \
|
||||
@@ -52,35 +71,68 @@ pytest==8.3.3 \
|
||||
--hash=sha256:a6853c7375b2663155079443d2e45de913a911a11d669df02a50814944db57b2
|
||||
pytest-xdist==3.6.1 \
|
||||
--hash=sha256:9ed4adfb68a016610848639bb7e02c9352d5d9f03d04809919e2dafc3be4cca7
|
||||
scipy==1.14.1; python_version >= '3.10' \
|
||||
--hash=sha256:baff393942b550823bfce952bb62270ee17504d02a1801d7fd0719534dfb9c84 \
|
||||
--hash=sha256:5149e3fd2d686e42144a093b206aef01932a0059c2a33ddfa67f5f035bdfe13e \
|
||||
--hash=sha256:b99722ea48b7ea25e8e015e8341ae74624f72e5f21fc2abd45f3a93266de4c5d \
|
||||
--hash=sha256:0c2f95de3b04e26f5f3ad5bb05e74ba7f68b837133a4492414b3afd79dfe540e \
|
||||
--hash=sha256:e0cf28db0f24a38b2a0ca33a85a54852586e43cf6fd876365c86e0657cfe7d73 \
|
||||
--hash=sha256:4079b90df244709e675cdc8b93bfd8a395d59af40b72e339c2287c91860deb8e \
|
||||
--hash=sha256:1729560c906963fc8389f6aac023739ff3983e727b1a4d87696b7bf108316a79 \
|
||||
--hash=sha256:2ff38e22128e6c03ff73b6bb0f85f897d2362f8c052e3b8ad00532198fbdae3f \
|
||||
--hash=sha256:8f9ea80f2e65bdaa0b7627fb00cbeb2daf163caa015e59b7516395fe3bd1e066 \
|
||||
--hash=sha256:30ac8812c1d2aab7131a79ba62933a2a76f582d5dbbc695192453dae67ad6310 \
|
||||
--hash=sha256:eb58ca0abd96911932f688528977858681a59d61a7ce908ffd355957f7025cfc \
|
||||
scipy==1.17.0; python_version >= '3.13' \
|
||||
--hash=sha256:00fb5f8ec8398ad90215008d8b6009c9db9fa924fd4c7d6be307c6f945f9cd73 \
|
||||
--hash=sha256:130d12926ae34399d157de777472bf82e9061c60cc081372b3118edacafe1d00 \
|
||||
--hash=sha256:13c4096ac6bc31d706018f06a49abe0485f96499deb82066b94d19b02f664209 \
|
||||
--hash=sha256:13e861634a2c480bd237deb69333ac79ea1941b94568d4b0efa5db5e263d4fd1 \
|
||||
--hash=sha256:1f9586a58039d7229ce77b52f8472c972448cded5736eaf102d5658bbac4c269 \
|
||||
--hash=sha256:1ff269abf702f6c7e67a4b7aad981d42871a11b9dd83c58d2d2ea624efbd1088 \
|
||||
--hash=sha256:2b531f57e09c946f56ad0b4a3b2abee778789097871fc541e267d2eca081cff1 \
|
||||
--hash=sha256:33af70d040e8af9d5e7a38b5ed3b772adddd281e3062ff23fec49e49681c38cf \
|
||||
--hash=sha256:3625c631a7acd7cfd929e4e31d2582cf00f42fcf06011f59281271746d77e061 \
|
||||
--hash=sha256:363ad4ae2853d88ebcde3ae6ec46ccca903ea9835ee8ba543f12f575e7b07e4e \
|
||||
--hash=sha256:423ca1f6584fc03936972b5f7c06961670dbba9f234e71676a7c7ccf938a0d61 \
|
||||
--hash=sha256:4e00562e519c09da34c31685f6acc3aa384d4d50604db0f245c14e1b4488bfa2 \
|
||||
--hash=sha256:5fb10d17e649e1446410895639f3385fd2bf4c3c7dfc9bea937bddcbc3d7b9ba \
|
||||
--hash=sha256:65ec32f3d32dfc48c72df4291345dae4f048749bc8d5203ee0a3f347f96c5ce6 \
|
||||
--hash=sha256:6680f2dfd4f6182e7d6db161344537da644d1cf85cf293f015c60a17ecf08752 \
|
||||
--hash=sha256:6e886000eb4919eae3a44f035e63f0fd8b651234117e8f6f29bad1cd26e7bc45 \
|
||||
--hash=sha256:819fc26862b4b3c73a60d486dbb919202f3d6d98c87cf20c223511429f2d1a97 \
|
||||
--hash=sha256:8547e7c57f932e7354a2319fab613981cde910631979f74c9b542bb167a8b9db \
|
||||
--hash=sha256:87b411e42b425b84777718cc41516b8a7e0795abfa8e8e1d573bf0ef014f0812 \
|
||||
--hash=sha256:979c3a0ff8e5ba254d45d59ebd38cde48fce4f10b5125c680c7a4bfe177aab07 \
|
||||
--hash=sha256:9fad7d3578c877d606b1150135c2639e9de9cecd3705caa37b66862977cc3e72 \
|
||||
--hash=sha256:a38c3337e00be6fd8a95b4ed66b5d988bac4ec888fd922c2ea9fe5fb1603dd67 \
|
||||
--hash=sha256:aabf057c632798832f071a8dde013c2e26284043934f53b00489f1773b33527e \
|
||||
--hash=sha256:c17514d11b78be8f7e6331b983a65a7f5ca1fd037b95e27b280921fe5606286a \
|
||||
--hash=sha256:c5e8647f60679790c2f5c76be17e2e9247dc6b98ad0d3b065861e082c56e078d \
|
||||
--hash=sha256:cacbaddd91fcffde703934897c5cd2c7cb0371fac195d383f4e1f1c5d3f3bd04 \
|
||||
--hash=sha256:d7425fcafbc09a03731e1bc05581f5fad988e48c6a861f441b7ab729a49a55ea \
|
||||
--hash=sha256:dbf133ced83889583156566d2bdf7a07ff89228fe0c0cb727f777de92092ec6b \
|
||||
--hash=sha256:eb2651271135154aa24f6481cbae5cc8af1f0dd46e6533fb7b56aa9727b6a232 \
|
||||
--hash=sha256:ec0827aa4d36cb79ff1b81de898e948a51ac0b9b1c43e4a372c0508c38c0f9a3 \
|
||||
--hash=sha256:edce1a1cf66298cccdc48a1bdf8fb10a3bf58e8b58d6c3883dd1530e103f87c0 \
|
||||
--hash=sha256:eec3842ec9ac9de5917899b277428886042a93db0b227ebbe3a333b64ec7643d \
|
||||
--hash=sha256:f2a4942b0f5f7c23c7cd641a0ca1955e2ae83dedcff537e3a0259096635e186b \
|
||||
--hash=sha256:f7df7941d71314e60a481e02d5ebcb3f0185b8d799c70d03d8258f6c80f3d467 \
|
||||
--hash=sha256:f9eb55bb97d00f8b7ab95cb64f873eb0bf54d9446264d9f3609130381233483f \
|
||||
--hash=sha256:fe508b5690e9eaaa9467fc047f833af58f1152ae51a0d0aed67aa5801f4dd7d6
|
||||
scipy==1.14.1; python_version >= '3.10' and python_version < '3.13' \
|
||||
--hash=sha256:278266012eb69f4a720827bdd2dc54b2271c97d84255b2faaa8f161a158c3b37 \
|
||||
--hash=sha256:2843f2d527d9eebec9a43e6b406fb7266f3af25a751aa91d62ff416f54170bc5 \
|
||||
--hash=sha256:af29a935803cc707ab2ed7791c44288a682f9c8107bc00f0eccc4f92c08d6e07 \
|
||||
--hash=sha256:2da0469a4ef0ecd3693761acbdc20f2fdeafb69e6819cc081308cc978153c675 \
|
||||
--hash=sha256:2ff0a7e01e422c15739ecd64432743cf7aae2b03f3084288f399affcefe5222d \
|
||||
--hash=sha256:2ff38e22128e6c03ff73b6bb0f85f897d2362f8c052e3b8ad00532198fbdae3f \
|
||||
--hash=sha256:30ac8812c1d2aab7131a79ba62933a2a76f582d5dbbc695192453dae67ad6310 \
|
||||
--hash=sha256:3a1b111fac6baec1c1d92f27e76511c9e7218f1695d61b59e05e0fe04dc59617 \
|
||||
--hash=sha256:631f07b3734d34aced009aaf6fedfd0eb3498a97e581c3b1e5f14a04164a456d \
|
||||
--hash=sha256:716e389b694c4bb564b4fc0c51bc84d381735e0d39d3f26ec1af2556ec6aad94 \
|
||||
--hash=sha256:fef8c87f8abfb884dac04e97824b61299880c43f4ce675dd2cbeadd3c9b466d2 \
|
||||
--hash=sha256:278266012eb69f4a720827bdd2dc54b2271c97d84255b2faaa8f161a158c3b37 \
|
||||
--hash=sha256:8426251ad1e4ad903a4514712d2fa8fdd5382c978010d1c6f5f37ef286a713ad \
|
||||
--hash=sha256:8475230e55549ab3f207bff11ebfc91c805dc3463ef62eda3ccf593254524ce8 \
|
||||
--hash=sha256:3a1b111fac6baec1c1d92f27e76511c9e7218f1695d61b59e05e0fe04dc59617 \
|
||||
--hash=sha256:c0ee987efa6737242745f347835da2cc5bb9f1b42996a4d97d5c7ff7928cb6f2 \
|
||||
--hash=sha256:2da0469a4ef0ecd3693761acbdc20f2fdeafb69e6819cc081308cc978153c675 \
|
||||
--hash=sha256:a49f6ed96f83966f576b33a44257d869756df6cf1ef4934f59dd58b25e0327e5 \
|
||||
--hash=sha256:8e32dced201274bf96899e6491d9ba3e9a5f6b336708656466ad0522d8528f69 \
|
||||
--hash=sha256:2ff0a7e01e422c15739ecd64432743cf7aae2b03f3084288f399affcefe5222d \
|
||||
--hash=sha256:97c5dddd5932bd2a1a31c927ba5e1463a53b87ca96b5c9bdf5dfd6096e27efc3 \
|
||||
--hash=sha256:8bddf15838ba768bb5f5083c1ea012d64c9a444e16192762bd858f1e126196d0 \
|
||||
--hash=sha256:8e32dced201274bf96899e6491d9ba3e9a5f6b336708656466ad0522d8528f69 \
|
||||
--hash=sha256:8f9ea80f2e65bdaa0b7627fb00cbeb2daf163caa015e59b7516395fe3bd1e066 \
|
||||
--hash=sha256:97c5dddd5932bd2a1a31c927ba5e1463a53b87ca96b5c9bdf5dfd6096e27efc3 \
|
||||
--hash=sha256:a49f6ed96f83966f576b33a44257d869756df6cf1ef4934f59dd58b25e0327e5 \
|
||||
--hash=sha256:af29a935803cc707ab2ed7791c44288a682f9c8107bc00f0eccc4f92c08d6e07 \
|
||||
--hash=sha256:b05d43735bb2f07d689f56f7b474788a13ed8adc484a85aa65c0fd931cf9ccd2 \
|
||||
--hash=sha256:b28d2ca4add7ac16ae8bb6632a3c86e4b9e4d52d3e34267f6e1b0c1f8d87e389 \
|
||||
--hash=sha256:c0ee987efa6737242745f347835da2cc5bb9f1b42996a4d97d5c7ff7928cb6f2 \
|
||||
--hash=sha256:d0d2821003174de06b69e58cef2316a6622b60ee613121199cb2852a873f8cf3 \
|
||||
--hash=sha256:b28d2ca4add7ac16ae8bb6632a3c86e4b9e4d52d3e34267f6e1b0c1f8d87e389
|
||||
--hash=sha256:eb58ca0abd96911932f688528977858681a59d61a7ce908ffd355957f7025cfc \
|
||||
--hash=sha256:edaf02b82cd7639db00dbff629995ef185c8df4c3ffa71a5562a595765a06ce1 \
|
||||
--hash=sha256:fef8c87f8abfb884dac04e97824b61299880c43f4ce675dd2cbeadd3c9b466d2
|
||||
setuptools==78.1.1 \
|
||||
--hash=sha256:c3a9c4211ff4c309edb8b8c4f1cbfa7ae324c4ba9f91ff254e3d305b9fd54561 \
|
||||
--hash=sha256:fcc17fd9cd898242f6b4adfaca46137a9edef687f43e6f78469692a5e70d851d
|
||||
@@ -100,56 +152,103 @@ zipp==3.21.0 \
|
||||
--hash=sha256:ac1bbe05fd2991f160ebce24ffbac5f6d11d83dc90891255885223d42b3cd931
|
||||
|
||||
# Transitive dependencies of jax and jaxlib
|
||||
ml-dtypes==0.5.0 \
|
||||
--hash=sha256:cb5cc7b25acabd384f75bbd78892d0c724943f3e2e1986254665a1aa10982e07 \
|
||||
--hash=sha256:54415257f00eb44fbcc807454efac3356f75644f1cbfc2d4e5522a72ae1dacab \
|
||||
--hash=sha256:e04fde367b2fe901b1d47234426fe8819909bd1dd862a5adb630f27789c20599 \
|
||||
--hash=sha256:d3b3db9990c3840986a0e70524e122cfa32b91139c3653df76121ba7776e015f \
|
||||
--hash=sha256:afa08343069874a30812871d639f9c02b4158ace065601406a493a8511180c02 \
|
||||
ml-dtypes==0.5.4; python_version >= '3.13' \
|
||||
--hash=sha256:0d2ffd05a2575b1519dc928c0b93c06339eb67173ff53acb00724502cda231cf \
|
||||
--hash=sha256:14a4fd3228af936461db66faccef6e4f41c1d82fcc30e9f8d58a08916b1d811f \
|
||||
--hash=sha256:2314892cdc3fcf05e373d76d72aaa15fda9fb98625effa73c1d646f331fcecb7 \
|
||||
--hash=sha256:2b857d3af6ac0d39db1de7c706e69c7f9791627209c3d6dedbfca8c7e5faec22 \
|
||||
--hash=sha256:304ad47faa395415b9ccbcc06a0350800bc50eda70f0e45326796e27c62f18b6 \
|
||||
--hash=sha256:4381fe2f2452a2d7589689693d3162e876b3ddb0a832cde7a414f8e1adf7eab1 \
|
||||
--hash=sha256:531eff30e4d368cb6255bc2328d070e35836aa4f282a0fb5f3a0cd7260257298 \
|
||||
--hash=sha256:533ce891ba774eabf607172254f2e7260ba5f57bdd64030c9a4fcfbd99815d0d \
|
||||
--hash=sha256:6a0df4223b514d799b8a1629c65ddc351b3efa833ccf7f8ea0cf654a61d1e35d \
|
||||
--hash=sha256:805cef3a38f4eafae3a5bf9ebdcdb741d0bcfd9e1bd90eb54abd24f928cd2465 \
|
||||
--hash=sha256:8c6a2dcebd6f3903e05d51960a8058d6e131fe69f952a5397e5dbabc841b6d56 \
|
||||
--hash=sha256:8c760d85a2f82e2bed75867079188c9d18dae2ee77c25a54d60e9cc79be1bc48 \
|
||||
--hash=sha256:bfc534409c5d4b0bf945af29e5d0ab075eae9eecbb549ff8a29280db822f34f9 \
|
||||
--hash=sha256:cb73dccfc991691c444acc8c0012bee8f2470da826a92e3a20bb333b1a7894e6 \
|
||||
--hash=sha256:ce756d3a10d0c4067172804c9cc276ba9cc0ff47af9078ad439b075d1abdc29b \
|
||||
--hash=sha256:f21c9219ef48ca5ee78402d5cc831bd58ea27ce89beda894428bc67a52da5328
|
||||
ml-dtypes==0.5.0; python_version < '3.13' \
|
||||
--hash=sha256:2e7534392682c3098bc7341648c650864207169c654aed83143d7a19c67ae06f \
|
||||
--hash=sha256:60275f2b51b56834e840c4809fca840565f9bf8e9a73f6d8c94f5b5935701215 \
|
||||
--hash=sha256:76942f6aeb5c40766d5ea62386daa4148e6a54322aaf5b53eae9e7553240222f \
|
||||
--hash=sha256:8c32138975797e681eb175996d64356bcfa124bdbb6a70460b9768c2b35a6fa4 \
|
||||
--hash=sha256:968fede07d1f9b926a63df97d25ac656cac1a57ebd33701734eaf704bc55d8d8 \
|
||||
--hash=sha256:a38df8df61194aeaae1ab7579075779b4ad32cd1cffd012c28be227fa7f2a70a \
|
||||
--hash=sha256:a988bac6572630e1e9c2edd9b1277b4eefd1c86209e52b0d061b775ac33902ff \
|
||||
--hash=sha256:d4b1a70a3e5219790d6b55b9507606fc4e02911d1497d16c18dd721eb7efe7d0 \
|
||||
--hash=sha256:dc74fd9995513d33eac63d64e436240f5494ec74d522a9f0920194942fc3d2d7 \
|
||||
--hash=sha256:2e7534392682c3098bc7341648c650864207169c654aed83143d7a19c67ae06f \
|
||||
--hash=sha256:76942f6aeb5c40766d5ea62386daa4148e6a54322aaf5b53eae9e7553240222f \
|
||||
--hash=sha256:60275f2b51b56834e840c4809fca840565f9bf8e9a73f6d8c94f5b5935701215 \
|
||||
--hash=sha256:968fede07d1f9b926a63df97d25ac656cac1a57ebd33701734eaf704bc55d8d8 \
|
||||
--hash=sha256:c7a9152f5876fef565516aa5dd1dccd6fc298a5891b2467973905103eb5c7856 \
|
||||
--hash=sha256:ab046f2ff789b1f11b2491909682c5d089934835f9a760fafc180e47dcb676b8 \
|
||||
--hash=sha256:8c32138975797e681eb175996d64356bcfa124bdbb6a70460b9768c2b35a6fa4 \
|
||||
--hash=sha256:7ee9c320bb0f9ffdf9f6fa6a696ef2e005d1f66438d6f1c1457338e00a02e8cf \
|
||||
--hash=sha256:a03fc861b86cc586728e3d093ba37f0cc05e65330c3ebd7688e7bae8290f8859 \
|
||||
--hash=sha256:099e09edd54e676903b4538f3815b5ab96f5b119690514602d96bfdb67172cbe \
|
||||
--hash=sha256:5f2b59233a0dbb6a560b3137ed6125433289ccba2f8d9c3695a52423a369ed15
|
||||
numpy==2.1.3; python_version >= '3.10' \
|
||||
--hash=sha256:747641635d3d44bcb380d950679462fae44f54b131be347d5ec2bce47d3df9ed \
|
||||
--hash=sha256:5641516794ca9e5f8a4d17bb45446998c6554704d888f86df9b200e66bdcce56 \
|
||||
--hash=sha256:c181ba05ce8299c7aa3125c27b9c2167bca4a4445b7ce73d5febc411ca692e43 \
|
||||
--hash=sha256:016d0f6f5e77b0f0d45d77387ffa4bb89816b57c835580c3ce8e099ef830befe \
|
||||
--hash=sha256:dc258a761a16daa791081d026f0ed4399b582712e6fc887a95af09df10c5ca57 \
|
||||
--hash=sha256:f653490b33e9c3a4c1c01d41bc2aef08f9475af51146e4a7710c450cf9761598 \
|
||||
--hash=sha256:96fe52fcdb9345b7cd82ecd34547fca4321f7656d500eca497eb7ea5a926692f \
|
||||
--hash=sha256:afa08343069874a30812871d639f9c02b4158ace065601406a493a8511180c02 \
|
||||
--hash=sha256:c7a9152f5876fef565516aa5dd1dccd6fc298a5891b2467973905103eb5c7856 \
|
||||
--hash=sha256:d4b1a70a3e5219790d6b55b9507606fc4e02911d1497d16c18dd721eb7efe7d0 \
|
||||
--hash=sha256:dc74fd9995513d33eac63d64e436240f5494ec74d522a9f0920194942fc3d2d7
|
||||
numpy==2.4.4; python_version >= '3.13' \
|
||||
--hash=sha256:08f2e31ed5e6f04b118e49821397f12767934cfdd12a1ce86a058f91e004ee50 \
|
||||
--hash=sha256:0aec54fd785890ecca25a6003fd9a5aed47ad607bbac5cd64f836ad8666f4959 \
|
||||
--hash=sha256:2483e4584a1cb3092da4470b38866634bafb223cbcd551ee047633fd2584599a \
|
||||
--hash=sha256:27a8d92cd10f1382a67d7cf4db7ce18341b66438bdd9f691d7b0e48d104c2a9d \
|
||||
--hash=sha256:2aa0613a5177c264ff5921051a5719d20095ea586ca88cc802c5c218d1c67d3e \
|
||||
--hash=sha256:2d19e6e2095506d1736b7d80595e0f252d76b89f5e715c35e06e937679ea7d7a \
|
||||
--hash=sha256:42c16925aa5a02362f986765f9ebabf20de75cdefdca827d14315c568dcab113 \
|
||||
--hash=sha256:45dbed2ab436a9e826e302fcdcbe9133f9b0006e5af7168afb8963a6520da103 \
|
||||
--hash=sha256:4636de7fd195197b7535f231b5de9e4b36d2c440b6e566d2e4e4746e6af0ca93 \
|
||||
--hash=sha256:4a19d9dba1a76618dd86b164d608566f393f8ec6ac7c44f0cc879011c45e65af \
|
||||
--hash=sha256:4bbc7f303d125971f60ec0aaad5e12c62d0d2c925f0ab1273debd0e4ba37aba5 \
|
||||
--hash=sha256:4d6d57903571f86180eb98f8f0c839fa9ebbfb031356d87f1361be91e433f5b7 \
|
||||
--hash=sha256:4e874c976154687c1f71715b034739b45c7711bec81db01914770373d125e392 \
|
||||
--hash=sha256:5a285b3b96f951841799528cd1f4f01cd70e7e0204b4abebac9463eecfcf2a40 \
|
||||
--hash=sha256:5c70f1cc1c4efbe316a572e2d8b9b9cc44e89b95f79ca3331553fbb63716e2bf \
|
||||
--hash=sha256:6a246d5914aa1c820c9443ddcee9c02bec3e203b0c080349533fae17727dfd1b \
|
||||
--hash=sha256:715d1c092715954784bc79e1174fc2a90093dc4dc84ea15eb14dad8abdcdeb74 \
|
||||
--hash=sha256:874f200b2a981c647340f841730fc3a2b54c9d940566a3c4149099591e2c4c3d \
|
||||
--hash=sha256:8e3ed142f2728df44263aaf5fb1f5b0b99f4070c553a0d7f033be65338329150 \
|
||||
--hash=sha256:93e15038125dc1e5345d9b5b68aa7f996ec33b98118d18c6ca0d0b7d6198b7e8 \
|
||||
--hash=sha256:989824e9faf85f96ec9c7761cd8d29c531ad857bfa1daa930cba85baaecf1a9a \
|
||||
--hash=sha256:99d838547ace2c4aace6c4f76e879ddfe02bb58a80c1549928477862b7a6d6ed \
|
||||
--hash=sha256:a7164afb23be6e37ad90b2f10426149fd75aee07ca55653d2aa41e66c4ef697e \
|
||||
--hash=sha256:ac6b31e35612a26483e20750126d30d0941f949426974cace8e6b5c58a3657b0 \
|
||||
--hash=sha256:ad2e2ef14e0b04e544ea2fa0a36463f847f113d314aa02e5b402fdf910ef309e \
|
||||
--hash=sha256:b268594bccac7d7cf5844c7732e3f20c50921d94e36d7ec9b79e9857694b1b2f \
|
||||
--hash=sha256:c901b15172510173f5cb310eae652908340f8dede90fff9e3bf6c0d8dfd92f83 \
|
||||
--hash=sha256:c9b39d38a9bd2ae1becd7eac1303d031c5c110ad31f2b319c6e7d98b135c934d \
|
||||
--hash=sha256:d2a8490669bfe99a233298348acc2d824d496dee0e66e31b66a6022c2ad74a5c \
|
||||
--hash=sha256:e44319a2953c738205bf3354537979eaa3998ed673395b964c1176083dd46252 \
|
||||
--hash=sha256:e823b8b6edc81e747526f70f71a9c0a07ac4e7ad13020aa736bb7c9d67196115 \
|
||||
--hash=sha256:e892aff75639bbef0d2a2cfd55535510df26ff92f63c92cd84ef8d4ba5a5557f \
|
||||
--hash=sha256:f169b9a863d34f5d11b8698ead99febeaa17a13ca044961aa8e2662a6c7766a0 \
|
||||
--hash=sha256:f8474c4241bc18b750be2abea9d7a9ec84f46ef861dbacf86a4f6e043401f79e
|
||||
numpy==2.1.3; python_version >= '3.10' and python_version < '3.13' \
|
||||
--hash=sha256:02135ade8b8a84011cbb67dc44e07c58f28575cf9ecf8ab304e51c05528c19f0 \
|
||||
--hash=sha256:0d30c543f02e84e92c4b1f415b7c6b5326cbe45ee7882b6b77db7195fb971e3a \
|
||||
--hash=sha256:2312b2aa89e1f43ecea6da6ea9a810d06aae08321609d8dc0d0eda6d946a541b \
|
||||
--hash=sha256:8637dcd2caa676e475503d1f8fdb327bc495554e10838019651b76d17b98e512 \
|
||||
--hash=sha256:0fa14563cc46422e99daef53d725d0c326e99e468a9320a240affffe87852564 \
|
||||
--hash=sha256:a6b46587b14b888e95e4a24d7b13ae91fa22386c199ee7b418f449032b2fa3b8 \
|
||||
--hash=sha256:13138eadd4f4da03074851a698ffa7e405f41a0845a6b1ad135b81596e4e9958 \
|
||||
--hash=sha256:f55ba01150f52b1027829b50d70ef1dafd9821ea82905b63936668403c3b471e \
|
||||
--hash=sha256:d89dd2b6da69c4fff5e39c28a382199ddedc3a5be5390115608345dec660b9e2 \
|
||||
--hash=sha256:bc6f24b3d1ecc1eebfbf5d6051faa49af40b03be1aaa781ebdadcbc090b4539b \
|
||||
--hash=sha256:762479be47a4863e261a840e8e01608d124ee1361e48b96916f38b119cfda04a \
|
||||
--hash=sha256:973faafebaae4c0aaa1a1ca1ce02434554d67e628b8d805e61f874b84e136b09 \
|
||||
--hash=sha256:576a1c1d25e9e02ed7fa5477f30a127fe56debd53b8d2c89d5578f9857d03ca9 \
|
||||
--hash=sha256:c80e4a09b3d95b4e1cac08643f1152fa71a0a821a2d4277334c88d54b2219a41 \
|
||||
--hash=sha256:15cb89f39fa6d0bdfb600ea24b250e5f1a3df23f901f51c8debaa6a5d122b2f0 \
|
||||
--hash=sha256:17ee83a1f4fef3c94d16dc1802b998668b5419362c8a4f4e8a491de1b41cc3ee \
|
||||
--hash=sha256:2312b2aa89e1f43ecea6da6ea9a810d06aae08321609d8dc0d0eda6d946a541b \
|
||||
--hash=sha256:3522b0dfe983a575e6a9ab3a4a4dfe156c3e428468ff08ce582b9bb6bd1d71d4 \
|
||||
--hash=sha256:4d1167c53b93f1f5d8a139a742b3c6f4d429b54e74e6b57d0eff40045187b15d \
|
||||
--hash=sha256:ecc76a9ba2911d8d37ac01de72834d8849e55473457558e12995f4cd53e778e0 \
|
||||
--hash=sha256:78574ac2d1a4a02421f25da9559850d59457bac82f2b8d7a44fe83a64f770098 \
|
||||
--hash=sha256:e711e02f49e176a01d0349d82cb5f05ba4db7d5e7e0defd026328e5cfb3226d3 \
|
||||
--hash=sha256:4f2015dfe437dfebbfce7c85c7b53d81ba49e71ba7eadbf1df40c915af75979f \
|
||||
--hash=sha256:576a1c1d25e9e02ed7fa5477f30a127fe56debd53b8d2c89d5578f9857d03ca9 \
|
||||
--hash=sha256:6a4825252fcc430a182ac4dee5a505053d262c807f8a924603d411f6718b88fd \
|
||||
--hash=sha256:762479be47a4863e261a840e8e01608d124ee1361e48b96916f38b119cfda04a \
|
||||
--hash=sha256:78574ac2d1a4a02421f25da9559850d59457bac82f2b8d7a44fe83a64f770098 \
|
||||
--hash=sha256:825656d0743699c529c5943554d223c021ff0494ff1442152ce887ef4f7561a1 \
|
||||
--hash=sha256:8637dcd2caa676e475503d1f8fdb327bc495554e10838019651b76d17b98e512 \
|
||||
--hash=sha256:973faafebaae4c0aaa1a1ca1ce02434554d67e628b8d805e61f874b84e136b09 \
|
||||
--hash=sha256:a38c19106902bb19351b83802531fea19dee18e5b37b36454f27f11ff956f7fc \
|
||||
--hash=sha256:a6b46587b14b888e95e4a24d7b13ae91fa22386c199ee7b418f449032b2fa3b8 \
|
||||
--hash=sha256:b47fbb433d3260adcd51eb54f92a2ffbc90a4595f8970ee00e064c644ac788f5 \
|
||||
--hash=sha256:c894b4305373b9c5576d7a12b473702afdf48ce5369c074ba304cc5ad8730dff
|
||||
--hash=sha256:bc6f24b3d1ecc1eebfbf5d6051faa49af40b03be1aaa781ebdadcbc090b4539b \
|
||||
--hash=sha256:c006b607a865b07cd981ccb218a04fc86b600411d83d6fc261357f1c0966755d \
|
||||
--hash=sha256:c7662f0e3673fe4e832fe07b65c50342ea27d989f92c80355658c7f888fcc83c \
|
||||
--hash=sha256:c80e4a09b3d95b4e1cac08643f1152fa71a0a821a2d4277334c88d54b2219a41 \
|
||||
--hash=sha256:c894b4305373b9c5576d7a12b473702afdf48ce5369c074ba304cc5ad8730dff \
|
||||
--hash=sha256:d89dd2b6da69c4fff5e39c28a382199ddedc3a5be5390115608345dec660b9e2 \
|
||||
--hash=sha256:e14e26956e6f1696070788252dcdff11b4aca4c3e8bd166e0df1bb8f315a67cb \
|
||||
--hash=sha256:e711e02f49e176a01d0349d82cb5f05ba4db7d5e7e0defd026328e5cfb3226d3 \
|
||||
--hash=sha256:ecc76a9ba2911d8d37ac01de72834d8849e55473457558e12995f4cd53e778e0 \
|
||||
--hash=sha256:f55ba01150f52b1027829b50d70ef1dafd9821ea82905b63936668403c3b471e \
|
||||
--hash=sha256:fa2d1337dc61c8dc417fbccf20f6d1e139896a30721b7f1e832b2bb6ef4eb6c4
|
||||
opt-einsum==3.4.0 \
|
||||
--hash=sha256:69bb92469f86a1565195ece4ac0323943e83477171b91d24c35afe028a90d7cd
|
||||
|
||||
|
||||
Reference in New Issue
Block a user