Skip to content

Commit 876717e

Browse files
committed
Add shared ModelParallel distribution-test helper; refactor Gemma onto it
Adds TestCase.run_distribution_test, a shared helper used by every model's test_distribution: sharding-spec + full-weight-coverage assertions, a real forward/backward/optimizer step (not just build()), and a numerical-parity + short-training-convergence check against an undistributed twin model. Adds a CI-safe mesh-shape sweep (test_layout_map_mesh_shapes) across representative 2D/3D device-mesh shapes sized to mirror real accelerator-pod topologies, using frozen realistic dimensions with a memory-conscious scale (full production-scale dims are exercised by the separate live-preset sweep, gated behind a per-width-class memory estimate so it never attempts an unsafe local build). Adds a manual live-preset sweep (test_layout_map_live_presets) that fetches every real preset's config from the registry and validates sharding across the same mesh-shape matrix. conftest.py now exposes 8 virtual CPU devices to JAX so distribution tests run instead of silently skipping on a single-device host, and registers the multi_device pytest marker. Gemma's existing test_distribution and test_distribution_with_lora are refactored onto the new helper; Gemma's layout map itself is unchanged (already correct).
1 parent 8375767 commit 876717e

4 files changed

Lines changed: 679 additions & 53 deletions

File tree

conftest.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
import os
22

3-
import keras
4-
import pytest
3+
if os.environ.get("KERAS_BACKEND") == "jax" and "XLA_FLAGS" not in os.environ:
4+
# Expose virtual CPU devices so keras.distribution tests run in CI.
5+
os.environ["XLA_FLAGS"] = "--xla_force_host_platform_device_count=8"
6+
7+
import keras # noqa: E402
8+
import pytest # noqa: E402
59

610
# OpenVINO supported test paths
711
OPENVINO_SUPPORTED_PATHS = [
@@ -95,6 +99,10 @@ def pytest_configure(config):
9599
"markers",
96100
"kaggle_key_required: mark test needing a kaggle key",
97101
)
102+
config.addinivalue_line(
103+
"markers",
104+
"multi_device: mark test as needing multiple devices",
105+
)
98106

99107

100108
def pytest_collection_modifyitems(config, items):

keras_hub/src/models/gemma/gemma_backbone.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -296,11 +296,22 @@ def get_layout_map(
296296
# See https://arxiv.org/abs/2403.08295
297297
layout_map = keras.distribution.LayoutMap(device_mesh)
298298
layout_map["token_embedding/embeddings"] = (model_dim, data_dim)
299-
layout_map["decoder_block.*attention.*(query|key|value).kernel"] = (
299+
# Key/value kernels are sized by num_key_value_heads (GQA/MQA),
300+
# which is independent of and typically much smaller than
301+
# num_query_heads -- sharding that small axis on the model-parallel
302+
# dim would raise an IndivisibleError whenever the device count
303+
# doesn't divide it, so they are left replicated on that axis while
304+
# query stays sharded.
305+
layout_map["decoder_block.*attention.*query.kernel"] = (
300306
model_dim,
301307
data_dim,
302308
None,
303309
)
310+
layout_map["decoder_block.*attention.*(key|value).kernel"] = (
311+
None,
312+
data_dim,
313+
None,
314+
)
304315
layout_map["decoder_block.*attention_output.kernel"] = (
305316
model_dim,
306317
None,

0 commit comments

Comments
 (0)