0
tests/ut/device_allocator/__init__.py
Normal file
0
tests/ut/device_allocator/__init__.py
Normal file
14
tests/ut/device_allocator/a2/__init__.py
Normal file
14
tests/ut/device_allocator/a2/__init__.py
Normal file
@@ -0,0 +1,14 @@
|
||||
#
|
||||
# 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 language governing permissions and
|
||||
# limitations under the License.
|
||||
# This file is a part of the vllm-ascend project.
|
||||
#
|
||||
28
tests/ut/device_allocator/a2/test_find_loaded_library.py
Normal file
28
tests/ut/device_allocator/a2/test_find_loaded_library.py
Normal file
@@ -0,0 +1,28 @@
|
||||
#
|
||||
# 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 language governing permissions and
|
||||
# limitations under the License.
|
||||
# This file is a part of the vllm-ascend project.
|
||||
#
|
||||
|
||||
from tests.ut.base import PytestBase
|
||||
from vllm_ascend.device_allocator.camem import find_loaded_library
|
||||
|
||||
|
||||
class TestFindLoadedLibrary(PytestBase):
|
||||
def test_find_loaded_library_success_and_not_found(self):
|
||||
path = find_loaded_library("libc")
|
||||
assert path is not None, "Expected to find libc library"
|
||||
assert path.endswith(".so.6") or ".so" in path
|
||||
assert "libc" in path
|
||||
|
||||
path = find_loaded_library("non_existent_library")
|
||||
assert path is None, "Expected to not find non-existent library"
|
||||
@@ -19,11 +19,13 @@ import pytest
|
||||
import torch
|
||||
|
||||
from tests.ut.base import PytestBase
|
||||
from vllm_ascend.device_allocator.camem import (AllocationData, CaMemAllocator,
|
||||
create_and_map,
|
||||
find_loaded_library,
|
||||
get_pluggable_allocator,
|
||||
unmap_and_release)
|
||||
from vllm_ascend.device_allocator.camem import (
|
||||
AllocationData,
|
||||
CaMemAllocator,
|
||||
create_and_map,
|
||||
get_pluggable_allocator,
|
||||
unmap_and_release,
|
||||
)
|
||||
|
||||
|
||||
def dummy_malloc(args):
|
||||
@@ -35,44 +37,34 @@ def dummy_free(ptr):
|
||||
|
||||
|
||||
class TestCaMem(PytestBase):
|
||||
|
||||
def test_find_loaded_library_success_and_not_found(self):
|
||||
path = find_loaded_library("libc")
|
||||
assert path is not None, "Expected to find libc library"
|
||||
assert path.endswith(".so.6") or ".so" in path
|
||||
assert "libc" in path
|
||||
|
||||
path = find_loaded_library("non_existent_library")
|
||||
assert path is None, "Expected to not find non-existent library"
|
||||
|
||||
@pytest.mark.parametrize("handle", [
|
||||
(1, 2, 3),
|
||||
("device", 99),
|
||||
(None, ),
|
||||
])
|
||||
@pytest.mark.parametrize(
|
||||
"handle",
|
||||
[
|
||||
(1, 2, 3),
|
||||
("device", 99),
|
||||
(None,),
|
||||
],
|
||||
)
|
||||
def test_create_and_map_calls_python_create_and_map(self, handle):
|
||||
with patch("vllm_ascend.device_allocator.camem.python_create_and_map"
|
||||
) as mock_create:
|
||||
with patch("vllm_ascend.device_allocator.camem.python_create_and_map") as mock_create:
|
||||
create_and_map(handle)
|
||||
mock_create.assert_called_once_with(*handle)
|
||||
|
||||
@pytest.mark.parametrize("handle", [
|
||||
(42, "bar"),
|
||||
("foo", ),
|
||||
])
|
||||
@pytest.mark.parametrize(
|
||||
"handle",
|
||||
[
|
||||
(42, "bar"),
|
||||
("foo",),
|
||||
],
|
||||
)
|
||||
def test_unmap_and_release_calls_python_unmap_and_release(self, handle):
|
||||
with patch(
|
||||
"vllm_ascend.device_allocator.camem.python_unmap_and_release"
|
||||
) as mock_release:
|
||||
with patch("vllm_ascend.device_allocator.camem.python_unmap_and_release") as mock_release:
|
||||
unmap_and_release(handle)
|
||||
mock_release.assert_called_once_with(*handle)
|
||||
|
||||
@patch("vllm_ascend.device_allocator.camem.init_module")
|
||||
@patch(
|
||||
"vllm_ascend.device_allocator.camem.torch.npu.memory.NPUPluggableAllocator"
|
||||
)
|
||||
def test_get_pluggable_allocator(self, mock_allocator_class,
|
||||
mock_init_module):
|
||||
@patch("vllm_ascend.device_allocator.camem.torch.npu.memory.NPUPluggableAllocator")
|
||||
def test_get_pluggable_allocator(self, mock_allocator_class, mock_init_module):
|
||||
mock_allocator_instance = MagicMock()
|
||||
mock_allocator_class.return_value = mock_allocator_instance
|
||||
|
||||
@@ -128,10 +120,16 @@ class TestCaMem(PytestBase):
|
||||
2000: data2,
|
||||
}
|
||||
|
||||
# mock is_pin_memory_available, return False as some machine only has cpu
|
||||
with patch(
|
||||
"vllm_ascend.device_allocator.camem.NPUPlatform.is_pin_memory_available",
|
||||
return_value=False):
|
||||
# Mock torch.empty to force pin_memory=False
|
||||
original_torch_empty = torch.empty
|
||||
|
||||
def mock_torch_empty(*args, **kwargs):
|
||||
# If pin_memory was explicitly set to True, change it to False
|
||||
if "pin_memory" in kwargs and kwargs["pin_memory"] is True:
|
||||
kwargs["pin_memory"] = False
|
||||
return original_torch_empty(*args, **kwargs)
|
||||
|
||||
with patch("vllm_ascend.device_allocator.camem.torch.empty", side_effect=mock_torch_empty):
|
||||
allocator.sleep(offload_tags="tag1")
|
||||
|
||||
# only offload tag1, other tag2 call unmap_and_release
|
||||
@@ -144,8 +142,7 @@ class TestCaMem(PytestBase):
|
||||
|
||||
@patch("vllm_ascend.device_allocator.camem.create_and_map")
|
||||
@patch("vllm_ascend.device_allocator.camem.memcpy")
|
||||
def test_wake_up_loads_and_clears_cpu_backup(self, mock_memcpy,
|
||||
mock_create_and_map):
|
||||
def test_wake_up_loads_and_clears_cpu_backup(self, mock_memcpy, mock_create_and_map):
|
||||
allocator = CaMemAllocator.get_instance()
|
||||
|
||||
handle = (1, 10, 1000, 0)
|
||||
@@ -168,9 +165,7 @@ class TestCaMem(PytestBase):
|
||||
mock_ctx.__enter__.return_value = "data"
|
||||
mock_ctx.__exit__.return_value = None
|
||||
|
||||
with patch(
|
||||
"vllm_ascend.device_allocator.camem.use_memory_pool_with_allocator",
|
||||
return_value=mock_ctx):
|
||||
with patch("vllm_ascend.device_allocator.camem.use_memory_pool_with_allocator", return_value=mock_ctx):
|
||||
with allocator.use_memory_pool(tag="my_tag"):
|
||||
assert allocator.current_tag == "my_tag"
|
||||
# restore old tag after context manager exits
|
||||
|
||||
1254
tests/ut/device_allocator/test_cpu_binding.py
Normal file
1254
tests/ut/device_allocator/test_cpu_binding.py
Normal file
File diff suppressed because it is too large
Load Diff
107
tests/ut/device_allocator/test_sleep_mem_optimized.py
Normal file
107
tests/ut/device_allocator/test_sleep_mem_optimized.py
Normal file
@@ -0,0 +1,107 @@
|
||||
#
|
||||
# Copyright (c) 2026 Huawei Technologies Co., Ltd. All Rights Reserved.
|
||||
#
|
||||
# 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.
|
||||
# This file is a part of the vllm-ascend project.
|
||||
#
|
||||
|
||||
from contextlib import nullcontext
|
||||
from dataclasses import dataclass
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
from vllm_ascend.device_allocator.sleep_mem_optimized import (
|
||||
AclGraphSleepWakeupManager,
|
||||
HcclSleepWakeupManager,
|
||||
SleepWakeupManager,
|
||||
)
|
||||
|
||||
|
||||
@dataclass
|
||||
class DummyGraphParams:
|
||||
events: dict[int, list]
|
||||
workspaces: dict[int, object]
|
||||
extra_handles: dict[int, list]
|
||||
metadata: dict[int, tuple]
|
||||
|
||||
|
||||
def test_acl_graph_reset_graph_params_clears_list_values_only():
|
||||
workspace = object()
|
||||
params = DummyGraphParams(
|
||||
events={1: ["event"]},
|
||||
workspaces={1: workspace},
|
||||
extra_handles={1: ["handle"]},
|
||||
metadata={1: ("keep",)},
|
||||
)
|
||||
|
||||
AclGraphSleepWakeupManager.reset_graph_params(params)
|
||||
|
||||
assert params.events == {1: []}
|
||||
assert params.extra_handles == {1: []}
|
||||
assert params.workspaces == {1: workspace}
|
||||
assert params.metadata == {1: ("keep",)}
|
||||
|
||||
|
||||
def test_acl_graph_wakeup_waits_for_kv_cache_tag():
|
||||
model_runner = MagicMock()
|
||||
manager = AclGraphSleepWakeupManager(MagicMock(), lambda: model_runner)
|
||||
|
||||
manager.wakeup(tags=["weights"])
|
||||
model_runner.capture_model.assert_not_called()
|
||||
|
||||
manager.wakeup(tags=["kv_cache"])
|
||||
model_runner.capture_model.assert_called_once_with()
|
||||
|
||||
|
||||
def test_sleep_wakeup_manager_skips_acl_sleep_when_aclgraph_disabled():
|
||||
model_runner = MagicMock()
|
||||
model_runner.use_aclgraph = False
|
||||
manager = SleepWakeupManager(MagicMock(), MagicMock(), lambda: model_runner)
|
||||
manager.acl_graph.sleep = MagicMock()
|
||||
manager.hccl.sleep = MagicMock()
|
||||
with patch(
|
||||
"vllm_ascend.device_allocator.sleep_mem_optimized.torch.npu.mem_get_info",
|
||||
side_effect=[(10, 20), (12, 20)],
|
||||
):
|
||||
manager.sleep()
|
||||
|
||||
manager.acl_graph.sleep.assert_not_called()
|
||||
manager.hccl.sleep.assert_called_once_with()
|
||||
|
||||
|
||||
def test_sleep_wakeup_manager_cleans_acl_before_hccl_when_aclgraph_enabled():
|
||||
model_runner = MagicMock()
|
||||
model_runner.use_aclgraph = True
|
||||
manager = SleepWakeupManager(MagicMock(), MagicMock(), lambda: model_runner)
|
||||
calls = []
|
||||
manager.acl_graph.sleep = MagicMock(side_effect=lambda: calls.append("acl"))
|
||||
manager.hccl.sleep = MagicMock(side_effect=lambda: calls.append("hccl"))
|
||||
|
||||
mem_info = [(10, 20), (12, 20), (12, 20), (13, 20)]
|
||||
with patch("vllm_ascend.device_allocator.sleep_mem_optimized.torch.npu.mem_get_info", side_effect=mem_info):
|
||||
manager.sleep()
|
||||
|
||||
assert calls == ["acl", "hccl"]
|
||||
|
||||
|
||||
def test_hccl_wakeup_restores_and_refreshes_moe_groups():
|
||||
manager = HcclSleepWakeupManager(MagicMock(), MagicMock())
|
||||
|
||||
with (
|
||||
patch("vllm_ascend.device_allocator.sleep_mem_optimized.set_current_vllm_config", return_value=nullcontext()),
|
||||
patch.object(manager, "restore_hccl", return_value=2) as mock_restore,
|
||||
patch.object(manager, "refresh_moe_hccl_groups") as mock_refresh,
|
||||
):
|
||||
manager.wakeup()
|
||||
|
||||
mock_restore.assert_called_once_with()
|
||||
mock_refresh.assert_called_once_with()
|
||||
Reference in New Issue
Block a user