Small change to testspeed file.

PiperOrigin-RevId: 618323795
Change-Id: I3a6307b8ae6d9af0d17c0ae85eae673d60112ddf
This commit is contained in:
Baruch Tabanpour
2024-03-22 17:03:44 -07:00
committed by Copybara-Service
parent 4660a297d1
commit 2019d42ca6
4 changed files with 124 additions and 85 deletions
+1
View File
@@ -49,4 +49,5 @@ from mujoco.mjx._src.solver import solve
from mujoco.mjx._src.support import full_m from mujoco.mjx._src.support import full_m
from mujoco.mjx._src.support import is_sparse from mujoco.mjx._src.support import is_sparse
from mujoco.mjx._src.support import mul_m from mujoco.mjx._src.support import mul_m
from mujoco.mjx._src.test_util import benchmark
from mujoco.mjx._src.types import * from mujoco.mjx._src.types import *
-1
View File
@@ -13,7 +13,6 @@
# limitations under the License. # limitations under the License.
# ============================================================================== # ==============================================================================
"""Engine support functions.""" """Engine support functions."""
from typing import Optional, Tuple, Union from typing import Optional, Tuple, Union
import jax import jax
+82
View File
@@ -14,14 +14,96 @@
# ============================================================================== # ==============================================================================
"""Utilities for testing.""" """Utilities for testing."""
import os
import sys import sys
import time
from typing import Dict, Tuple from typing import Dict, Tuple
from xml.etree import ElementTree as ET from xml.etree import ElementTree as ET
from etils import epath from etils import epath
import jax
import mujoco import mujoco
# pylint: disable=g-importing-member
from mujoco.mjx._src import forward
from mujoco.mjx._src import io
# pylint: enable=g-importing-member
import numpy as np import numpy as np
def _measure(fn, *args) -> Tuple[float, float]:
"""Reports jit time and op time for a function."""
beg = time.perf_counter()
compiled_fn = fn.lower(*args).compile()
end = time.perf_counter()
jit_time = end - beg
beg = time.perf_counter()
result = compiled_fn(*args)
jax.block_until_ready(result)
end = time.perf_counter()
run_time = end - beg
return jit_time, run_time
def benchmark(
m: mujoco.MjModel,
nstep: int = 1000,
batch_size: int = 1024,
unroll_steps: int = 1,
solver: str = 'cg',
iterations: int = 1,
ls_iterations: int = 4,
) -> Tuple[float, float, int]:
"""Benchmark a model."""
xla_flags = os.environ.get('XLA_FLAGS', '')
xla_flags += ' --xla_gpu_triton_gemm_any=True'
os.environ['XLA_FLAGS'] = xla_flags
m.opt.solver = {
'cg': mujoco.mjtSolver.mjSOL_CG,
'newton': mujoco.mjtSolver.mjSOL_NEWTON,
}[solver.lower()]
m.opt.iterations = iterations
m.opt.ls_iterations = ls_iterations
m = io.put_model(m)
@jax.pmap
def init(key):
key = jax.random.split(key, batch_size // jax.device_count())
@jax.vmap
def random_init(key):
d = io.make_data(m)
qvel = 0.01 * jax.random.normal(key, shape=(m.nv,))
d = d.replace(qvel=qvel)
return d
return random_init(key)
key = jax.random.split(jax.random.key(0), jax.device_count())
d = init(key)
jax.block_until_ready(d)
@jax.pmap
def unroll(d):
@jax.vmap
def step(d, _):
d = forward.step(m, d)
return d, None
d, _ = jax.lax.scan(step, d, None, length=nstep, unroll=unroll_steps)
return d
jit_time, run_time = _measure(unroll, d)
steps = nstep * batch_size
return jit_time, run_time, steps
_ACTUATOR_TYPES = ['motor', 'velocity', 'position', 'general', 'intvelocity'] _ACTUATOR_TYPES = ['motor', 'velocity', 'position', 'general', 'intvelocity']
_DYN_TYPES = ['none', 'integrator', 'filter', 'filterexact'] _DYN_TYPES = ['none', 'integrator', 'filter', 'filterexact']
_DYN_PRMS = ['0.189', '2.1'] _DYN_PRMS = ['0.189', '2.1']
+41 -84
View File
@@ -14,110 +14,67 @@
# ============================================================================== # ==============================================================================
"""Run benchmarks on various devices.""" """Run benchmarks on various devices."""
import os from typing import Sequence
import time
from typing import Sequence, Tuple
from absl import app from absl import app
from absl import flags from absl import flags
from etils import epath from etils import epath
import jax
import mujoco import mujoco
from mujoco import mjx from mujoco import mjx
FLAGS = flags.FLAGS _MJCF = flags.DEFINE_string('mjcf', None, 'path to model', required=True)
_BASE_PATH = flags.DEFINE_string(
flags.DEFINE_string('mjcf', None, 'path to model', required=True) 'base_path', None, 'base path, defaults to mujoco.mjx resource path'
flags.DEFINE_integer('nstep', 1000, 'number of steps per rollout') )
flags.DEFINE_integer('batch_size', 1024, 'number of parallel rollouts') _NSTEP = flags.DEFINE_integer('nstep', 1000, 'number of steps per rollout')
flags.DEFINE_integer('unroll', 1, 'loop unroll length') _BATCH_SIZE = flags.DEFINE_integer(
flags.DEFINE_enum('solver', 'cg', ['cg', 'newton'], 'constraint solver') 'batch_size', 1024, 'number of parallel rollouts'
flags.DEFINE_integer('iterations', 1, 'number of solver iterations') )
flags.DEFINE_integer('ls_iterations', 4, 'number of linesearch iterations') _UNROLL = flags.DEFINE_integer('unroll', 1, 'loop unroll length')
flags.DEFINE_enum('output', 'text', ['text', 'tsv'], 'format to print results') _SOLVER = flags.DEFINE_enum(
'solver', 'cg', ['cg', 'newton'], 'constraint solver'
)
def _measure(fn, *args) -> Tuple[float, float]: _ITERATIONS = flags.DEFINE_integer(
"""Reports jit time and op time for a function.""" 'iterations', 1, 'number of solver iterations'
)
beg = time.perf_counter() _LS_ITERATIONS = flags.DEFINE_integer(
compiled_fn = fn.lower(*args).compile() 'ls_iterations', 4, 'number of linesearch iterations'
end = time.perf_counter() )
jit_time = end - beg _OUTPUT = flags.DEFINE_enum(
'output', 'text', ['text', 'tsv'], 'format to print results'
beg = time.perf_counter() )
result = compiled_fn(*args)
jax.block_until_ready(result)
end = time.perf_counter()
run_time = end - beg
return jit_time, run_time
def _main(argv: Sequence[str]): def _main(argv: Sequence[str]):
"""Benchmark a model.""" """Runs testpeed function."""
base_path = _BASE_PATH.value or epath.resource_path('mujoco.mjx')
xla_flags = os.environ.get('XLA_FLAGS', '') f = base_path / 'test_data' / _MJCF.value
xla_flags += ' --xla_gpu_triton_gemm_any=True'
os.environ['XLA_FLAGS'] = xla_flags
f = epath.resource_path('mujoco.mjx') / 'test_data' / FLAGS.mjcf
m = mujoco.MjModel.from_xml_path(f.as_posix()) m = mujoco.MjModel.from_xml_path(f.as_posix())
m.opt.solver = {
'cg': mujoco.mjtSolver.mjSOL_CG,
'newton': mujoco.mjtSolver.mjSOL_NEWTON,
}[FLAGS.solver.lower()]
m.opt.iterations = FLAGS.iterations
m.opt.ls_iterations = FLAGS.ls_iterations
m = mjx.put_model(m)
if FLAGS.output == 'text': print(f'Rolling out {_NSTEP.value} steps at dt = {m.opt.timestep:.3f}...')
print(f"Rolling out {FLAGS.nstep} steps at dt = {m.opt.timestep:.3f}...") jit_time, run_time, steps = mjx.benchmark(
m,
_NSTEP.value,
_BATCH_SIZE.value,
_UNROLL.value,
_SOLVER.value,
_ITERATIONS.value,
_LS_ITERATIONS.value,
)
@jax.pmap name = argv[0]
def init(key): if _OUTPUT.value == 'text':
key = jax.random.split(key, FLAGS.batch_size // jax.device_count())
@jax.vmap
def random_init(key):
d = mjx.make_data(m)
qvel = 0.01 * jax.random.normal(key, shape=(m.nv,))
d = d.replace(qvel=qvel)
return d
return random_init(key)
key = jax.random.split(jax.random.key(0), jax.device_count())
d = init(key)
jax.block_until_ready(d)
@jax.pmap
def unroll(d):
@jax.vmap
def step(d, _):
d = mjx.step(m, d)
return d, None
d, _ = jax.lax.scan(step, d, None, length=FLAGS.nstep, unroll=FLAGS.unroll)
return d
jit_time, run_time = _measure(unroll, d)
steps = FLAGS.nstep * FLAGS.batch_size
if FLAGS.output == 'text':
print(f""" print(f"""
Summary for {FLAGS.batch_size} parallel rollouts Summary for {_BATCH_SIZE.value} parallel rollouts
Total JIT time: {jit_time:.2f} s Total JIT time: {jit_time:.2f} s
Total simulation time: {run_time:.2f} s Total simulation time: {run_time:.2f} s
Total steps per second: { steps / run_time:.0f} Total steps per second: { steps / run_time:.0f}
Total realtime factor: { steps * m.opt.timestep / run_time:.2f} x Total realtime factor: { steps * m.opt.timestep / run_time:.2f} x
Total time per step: { 1e6 * run_time / steps:.2f} µs""") Total time per step: { 1e6 * run_time / steps:.2f} µs""")
elif FLAGS.output == 'tsv': elif _OUTPUT.value == 'tsv':
name = argv[0].split('/')[-1].replace('testspeed_', '') name = name.split('/')[-1].replace('testspeed_', '')
print(f"{name}\tjit: {jit_time:.2f}s\tsteps/second: {steps / run_time:.0f}") print(f'{name}\tjit: {jit_time:.2f}s\tsteps/second: {steps / run_time:.0f}')
def main(): def main():