Repository navigation
feat(chs): single-host TPU init for node-local diagnostics + libtpu 0.0.48 - #142
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces support for running benchmarks on a local node (single host without slicebuilder) and updates JAX/libtpu dependencies. Key feedback points out that appending TPU initialization flags using substring checks on LIBTPU_INIT_ARGS can cause silent bugs, recommending exact flag name matching instead. Additionally, in benchmark_gemm.py, several issues were identified regarding local data initialization, including incorrect indexing of seed_arr, shape mismatches with per_dev_seeds, and non-standard usage of jax.block_until_ready on a tuple. Finally, is_local_node_benchmark in run_benchmark.py should be expanded to check both benchmark_params and benchmark_sweep_params to ensure local node configurations are not missed.
10fd65a to
034c740
Compare
227d3f9 to
2c3d0eb
Compare
…st_tpu_init flag - Add 'single_host_tpu_init' as a benchmark-level config key that triggers configure_single_host_tpu() (renamed from configure_local_node_tpu). It acts at the libtpu init layer, once per process. - 'run_on_local_node' stays a sweep-param-only knob (JAX device selection) and is no longer injected from benchmark_config. - Revert the unused run_on_local_node kwargs in benchmark_hbm.py and benchmark_host_device.py since params are no longer injected.
Prints the env vars and final LIBTPU_INIT_ARGS so a run's logs show that single_host_tpu_init actually took effect before libtpu initialized.
libtpu 0.0.48 rejects --xla_tpu_enable_async_collective_fusion=true at
backend init on v6e (ghostlite) and 7x with FAILED_PRECONDITION
("Continuation fusion for AllGather ... not supported on platforms other
than Viperlite"), which broke gemm_multiple_run regardless of the
single_host_tpu_init flag. These benchmarks are per-device matmuls with no
all-gathers, so the fusion flags have no effect on what is measured. Turn
them off unconditionally in all modules that set them, and drop the
now-redundant rewrite from configure_single_host_tpu().
Keep --xla_tpu_enable_async_collective_fusion=false (required by libtpu 0.0.48 on v6e/7x), restore _multiple_steps=true and drop _fuse_all_gather, matching the gemm_flags set in AI-Hypercomputer/accelerator-microbenchmarks main. No behavioral change while the master switch is off.
Keep the PR scoped to the benchmarks CHS runs. Other modules that set --xla_tpu_enable_async_collective_fusion=true will need the same change to run on libtpu 0.0.48; see op_flags.yaml on main.
…pu_init The per-device data path exists because SliceBuilder is skipped under single_host_tpu_init, leaving intra-host ICI unprogrammed so a device_put from device 0 would be a cross-chip DMA. Tie the branch to that condition (via is_single_host_tpu_init()) instead of to the mesh choice (run_on_local_node), which keeps the default path unchanged for all non-single-host runs.
5179b35 to
9d68aa1
Compare
…igure_single_host_tpu Substring matching could skip a flag whose name is a prefix of an already-present flag. Compare against the set of exact flag names instead.
- benchmark_utils.py: wrap docstring to 80 cols, use maxsplit=1 in flag name splits, strip trailing whitespace - requirements.txt: add missing trailing newline
|
Some side note:
|
… multi-host slices Adds a benchmark-level `single_host_tpu_init: true` config key and a `--single_host_tpu_init` CLI flag (default off) that initialize the current host standalone inside a multi-host slice, so single-host benchmarks such as `gemm` and `hbm` can be used for node-local diagnostics (e.g. Cluster Health Scanner) without the other hosts of the slice participating. Existing behaviour is unchanged when the flag is off. When enabled, `core/single_host.py` (applied after op_flags and before the first JAX device call) forces a 1-host topology (`TPU_HOST_BOUNDS`, `TPU_WORKER_ID`, `TPU_WORKER_HOSTNAMES`, `TPU_SKIP_MDS_QUERY`), skips SliceBuilder/tpunetd (`--deepsea_hal_test_skip_slicebuilder=true`, `--deepsea_hal_test_allow_multichip_skip_slicebuilder=true`) and disables the cross-host launch barrier. This mirrors the `chs` branch (AI-Hypercomputer#142). Because the slice's ICI routing is left untouched, device-to-device transfers hang in this mode. `GeneralizedGemmBenchmark.generate_inputs` previously sampled the operands on the default device and broadcast them with `jax.device_put(x, replicated_sharding)`, which hung for any matrix size ("Slow PjRt TPU operation detected" on all local devices). With the flag on, the operands are now generated independently on each local mesh device from a CPU-pinned key and assembled with `jax.make_array_from_single_device_arrays`, so the only transfers are host->device. The default path is untouched (pure additions). Verified on a tpu7x-standard-4t host of a 2x2x4 slice (jax 0.12.0, libtpu 0.0.50), with no manual environment set up in the pod: - `single_host_tpu_init: true`, gemm 16384^3 bf16 x20, xprof local_slowest_device: 2127 TFLOP/s per chip, 20/20 xprof runs, 78 s. - `--single_host_tpu_init` gemm 1024^3: 20 s; hbm copy 1G elems: 2790 GB/s. - Control without the flag on the same node fails at init ("Expected 4 worker addresses, got 1"). - CPU: the flagged and default input paths yield identical replicated arrays and outputs; config/CLI validation covered.
Summary
Lets a benchmark initialize libtpu as a standalone single host on one VM of a multi-host TPU slice, without touching the slice's ICI routing or contacting
tpunetd. Enabled per benchmark via a new config keysingle_host_tpu_init: true. Also bumps JAX/libtpu to pick up--deepsea_hal_test_allow_multichip_skip_slicebuilder.Changes
requirements.txtjax[tpu]/jaxlib0.10.1 → 0.11.2,libtpu0.0.41 → 0.0.48Ironwood/src/benchmark_utils.pyconfigure_single_host_tpu(): setsTPU_HOST_BOUNDS=1,1,1,TPU_SKIP_MDS_QUERY=true,TPU_WORKER_ID=0,TPU_WORKER_HOSTNAMES=localhost; appends--deepsea_hal_test_skip_slicebuilder=true --deepsea_hal_test_allow_multichip_skip_slicebuilder=true --xla_tpu_use_enhanced_launch_barrier=falsetoLIBTPU_INIT_ARGS(existing flags matched by exact name).is_single_host_tpu_init()exposes the state to benchmark modules. (b) libtpu 0.0.48 HLO dump format:rename_xla_dump()skips subdirectories now present in the dump dir, andextract_hlo_features_from_file()parses the newreplica_groups=mesh[...]{...}syntax in addition to the explicit{{...}}list form.Ironwood/src/run_benchmark.pyconfigure_single_host_tpu()when the benchmark config hassingle_host_tpu_init: true. Runs after the benchmark module import (which setsLIBTPU_INIT_ARGS) and before the first JAX device call.Ironwood/src/benchmark_gemm.pysingle_host_tpu_initis active, generate inputs independently on each local device (jax.make_array_from_single_device_arrays) instead ofdevice_putfrom device 0: SliceBuilder is skipped, so intra-host ICI is unprogrammed and a cross-chip copy would fault. Default path unchanged otherwise. (b)--xla_tpu_enable_async_collective_fusion=false, drop_fuse_all_gather— libtpu 0.0.48 rejects=trueon v6e and 7x (FAILED_PRECONDITION: Continuation fusion for AllGather … not supported on platforms other than Viperlite); aligned withop_flags.yamlonmain.Usage
single_host_tpu_initcontrols libtpu process init;run_on_local_node(existing) controls the mesh. Do not setsingle_host_tpu_initfor multi-host benchmarks (e.g. collectives).Validation (CHS, 16-node pools, PR head 9d68aa1)
v6e-off3v6e-on37x-off37x-on3Notes
--xla_tpu_enable_async_collective_fusion=true(benchmark_compute.py,benchmark_gemm_numerics.py,benchmark_gemm_throttling.py,benchmark_inference_compute.py) will need the same change on libtpu 0.0.48; left out to keep this PR minimal.