diff --git a/PR_DESCRIPTION.md b/PR_DESCRIPTION.md deleted file mode 100644 index 1c8ff8f..0000000 --- a/PR_DESCRIPTION.md +++ /dev/null @@ -1,9 +0,0 @@ -[bug fix] Require arctic-inference 0.3.0+ for the [rl] extra - -## Summary - -`[rl]` asks for `arctic-inference[server,vllm]>=0.3.0` and does not declare `vllm`. That extra pulls vLLM and applies that release's pin. `tensordict` lives on `[sft]`. `[testing]` is pytest plugins only. Unit Tests Setup environment is `uv pip install ".[sft,testing]"` after CPU torch, so the CPU runner does not pull arctic-inference. - -## Testing - -`tests/test_dependency_groups.py`. GitHub Unit Tests Setup environment is unrun on this SHA. diff --git a/arctic_platform/common/utils/batch.py b/arctic_platform/common/utils/batch.py index a4110fd..933c390 100644 --- a/arctic_platform/common/utils/batch.py +++ b/arctic_platform/common/utils/batch.py @@ -79,7 +79,7 @@ def _split_value(val, num_chunks: int): f"{num_chunks}. The client must send at least one sample per " "DP worker." ) - return list(torch.chunk(val, num_chunks, dim=0)) + return list(torch.tensor_split(val, num_chunks, dim=0)) if isinstance(val, list): if len(val) < num_chunks: raise ValueError( diff --git a/tests/common/test_split_dict.py b/tests/common/test_split_dict.py new file mode 100644 index 0000000..0bd012f --- /dev/null +++ b/tests/common/test_split_dict.py @@ -0,0 +1,40 @@ +# Copyright 2025 Snowflake Inc. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""``split_dict`` must return one shard per DP rank for any batch size ``B >= n``.""" + +from __future__ import annotations + +import torch + +from arctic_platform.common.utils.batch import split_dict +from arctic_platform.testing_utils import TestCasePlus +from arctic_platform.testing_utils import torch_assert_equal + + +class TestSplitDictRemainder(TestCasePlus): + def test_tensor_split_returns_one_shard_per_rank(self): + # torch.chunk(B, n) can return fewer than n tensors (B=6 n=4 → 3 chunks). + for batch_size, num_chunks in ((6, 4), (5, 4), (9, 4), (13, 8), (4, 4), (7, 4)): + ids = torch.arange(batch_size * 3).view(batch_size, 3) + shards = split_dict({"input_ids": ids}, num_chunks) + self.assertEqual(len(shards), num_chunks, msg=f"B={batch_size} n={num_chunks}") + rows = [int(s["input_ids"].shape[0]) for s in shards] + self.assertEqual(sum(rows), batch_size, msg=f"B={batch_size} n={num_chunks} rows={rows}") + torch_assert_equal(torch.cat([s["input_ids"] for s in shards], dim=0), ids) + + def test_batch_smaller_than_ranks_is_rejected(self): + ids = torch.arange(6).view(3, 2) + with self.assertRaises(ValueError): + split_dict({"input_ids": ids}, 4)