mirror of
https://github.com/deepset-ai/haystack.git
synced 2025-06-26 22:00:13 +00:00

* feat: add support for torch xpu device support * test: xpu based tests ci/cd * test: add xpu code device support --------- Co-authored-by: Sebastian Husch Lee <10526848+sjrl@users.noreply.github.com> Co-authored-by: David S. Batista <dsbatista@gmail.com>
155 lines
5.9 KiB
Python
155 lines
5.9 KiB
Python
# SPDX-FileCopyrightText: 2022-present deepset GmbH <info@deepset.ai>
|
|
#
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
|
|
import os
|
|
from unittest.mock import patch
|
|
|
|
import pytest
|
|
|
|
from haystack.utils import ComponentDevice, Device, DeviceMap, DeviceType
|
|
|
|
|
|
def test_device_type():
|
|
for e in DeviceType:
|
|
assert e == DeviceType.from_str(e.value)
|
|
|
|
with pytest.raises(ValueError, match="Unknown device type string"):
|
|
DeviceType.from_str("tpu")
|
|
|
|
|
|
def test_device_creation():
|
|
assert Device.cpu().type == DeviceType.CPU
|
|
assert Device.gpu().type == DeviceType.GPU
|
|
assert Device.mps().type == DeviceType.MPS
|
|
assert Device.xpu().type == DeviceType.XPU
|
|
assert Device.disk().type == DeviceType.DISK
|
|
|
|
assert Device.from_str("cpu") == Device.cpu()
|
|
assert Device.from_str("cuda:1") == Device.gpu(1)
|
|
assert Device.from_str("disk") == Device.disk()
|
|
assert Device.from_str("mps:0") == Device(DeviceType.MPS, 0)
|
|
assert Device.from_str("xpu:0") == Device(DeviceType.XPU, 0)
|
|
|
|
with pytest.raises(ValueError, match="Device id must be >= 0"):
|
|
Device.gpu(-1)
|
|
|
|
|
|
def test_device_map():
|
|
map = DeviceMap({"layer1": Device.cpu(), "layer2": Device.gpu(1), "layer3": Device.disk()})
|
|
|
|
assert all(x in map for x in ["layer1", "layer2", "layer3"])
|
|
assert len(map) == 3
|
|
assert map["layer1"] == Device.cpu()
|
|
assert map["layer2"] == Device.gpu(1)
|
|
assert map["layer3"] == Device.disk()
|
|
|
|
for k, d in map:
|
|
assert k in ["layer1", "layer2", "layer3"]
|
|
assert d in [Device.cpu(), Device.gpu(1), Device.disk()]
|
|
|
|
map["layer1"] = Device.gpu(0)
|
|
assert map["layer1"] == Device.gpu(0)
|
|
|
|
map["layer2"] = Device.cpu()
|
|
assert DeviceMap.from_hf({"layer1": 0, "layer2": "cpu", "layer3": "disk"}) == DeviceMap(
|
|
{"layer1": Device.gpu(0), "layer2": Device.cpu(), "layer3": Device.disk()}
|
|
)
|
|
|
|
with pytest.raises(ValueError, match="unexpected device"):
|
|
DeviceMap.from_hf({"layer1": 0.1})
|
|
|
|
assert map.first_device == Device.gpu(0)
|
|
assert DeviceMap({}).first_device is None
|
|
|
|
|
|
def test_component_device_empty_and_full():
|
|
with pytest.raises(ValueError, match="neither be empty nor contain"):
|
|
ComponentDevice().first_device
|
|
|
|
with pytest.raises(ValueError, match="neither be empty nor contain"):
|
|
ComponentDevice(Device.cpu(), DeviceMap({})).to_hf()
|
|
|
|
|
|
def test_component_device_single():
|
|
single = ComponentDevice.from_single(Device.gpu(1))
|
|
assert not single.has_multiple_devices
|
|
assert single._single_device == Device.gpu(1)
|
|
assert single._multiple_devices is None
|
|
|
|
with pytest.raises(ValueError, match="disk device can only be used as a part of device maps"):
|
|
ComponentDevice.from_single(Device.disk())
|
|
|
|
assert single.to_torch_str() == "cuda:1"
|
|
assert single.to_spacy() == 1
|
|
assert single.to_hf() == "cuda:1"
|
|
assert single.update_hf_kwargs({}, overwrite=False) == {"device": "cuda:1"}
|
|
assert single.update_hf_kwargs({"device": 0}, overwrite=True) == {"device": "cuda:1"}
|
|
assert single.first_device == ComponentDevice.from_single(single._single_device)
|
|
|
|
|
|
def test_component_device_multiple():
|
|
multiple = ComponentDevice.from_multiple(
|
|
DeviceMap({"layer1": Device.cpu(), "layer2": Device.gpu(1), "layer3": Device.disk()})
|
|
)
|
|
assert multiple.has_multiple_devices
|
|
assert multiple._single_device is None
|
|
assert multiple._multiple_devices == DeviceMap(
|
|
{"layer1": Device.cpu(), "layer2": Device.gpu(1), "layer3": Device.disk()}
|
|
)
|
|
|
|
with pytest.raises(ValueError, match="Only single devices"):
|
|
multiple.to_torch()
|
|
|
|
with pytest.raises(ValueError, match="Only single devices"):
|
|
multiple.to_torch_str()
|
|
|
|
with pytest.raises(ValueError, match="Only single devices"):
|
|
multiple.to_spacy()
|
|
|
|
assert multiple.to_hf() == {"layer1": "cpu", "layer2": 1, "layer3": "disk"}
|
|
assert multiple.update_hf_kwargs({}, overwrite=False) == {
|
|
"device_map": {"layer1": "cpu", "layer2": 1, "layer3": "disk"}
|
|
}
|
|
assert multiple.update_hf_kwargs({"device_map": {None: None}}, overwrite=True) == {
|
|
"device_map": {"layer1": "cpu", "layer2": 1, "layer3": "disk"}
|
|
}
|
|
assert multiple.first_device == ComponentDevice.from_single(Device.cpu())
|
|
|
|
|
|
@patch("torch.xpu.is_available")
|
|
@patch("torch.backends.mps.is_available")
|
|
@patch("torch.cuda.is_available")
|
|
def test_component_device_resolution(torch_cuda_is_available, torch_backends_mps_is_available, torch_xpu_is_available):
|
|
assert ComponentDevice.resolve_device(ComponentDevice.from_single(Device.cpu()))._single_device == Device.cpu()
|
|
|
|
torch_cuda_is_available.return_value = True
|
|
assert ComponentDevice.resolve_device(None)._single_device == Device.gpu(0)
|
|
|
|
torch_cuda_is_available.return_value = False
|
|
torch_xpu_is_available.return_value = True
|
|
torch_backends_mps_is_available.return_value = False
|
|
assert ComponentDevice.resolve_device(None)._single_device == Device.xpu()
|
|
|
|
torch_cuda_is_available.return_value = False
|
|
torch_xpu_is_available.return_value = False
|
|
torch_backends_mps_is_available.return_value = True
|
|
assert ComponentDevice.resolve_device(None)._single_device == Device.mps()
|
|
|
|
torch_cuda_is_available.return_value = False
|
|
torch_xpu_is_available.return_value = False
|
|
torch_backends_mps_is_available.return_value = False
|
|
assert ComponentDevice.resolve_device(None)._single_device == Device.cpu()
|
|
|
|
torch_cuda_is_available.return_value = False
|
|
torch_xpu_is_available.return_value = False
|
|
torch_backends_mps_is_available.return_value = True
|
|
os.environ["HAYSTACK_MPS_ENABLED"] = "false"
|
|
assert ComponentDevice.resolve_device(None)._single_device == Device.cpu()
|
|
|
|
torch_cuda_is_available.return_value = False
|
|
torch_xpu_is_available.return_value = True
|
|
os.environ["HAYSTACK_XPU_ENABLED"] = "false"
|
|
torch_backends_mps_is_available.return_value = False
|
|
assert ComponentDevice.resolve_device(None)._single_device == Device.cpu()
|