blob: 6575ec905d7844ba86bcf5b394cdd2f240d1efb7 [file]
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you 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.
from __future__ import annotations
import ctypes
import pickle
import numpy
import pytest
import tvm_ffi
from tvm_ffi import DLDeviceType
def test_device() -> None:
device = tvm_ffi.Device("cuda", 0)
assert device.dlpack_device_type() == tvm_ffi.DLDeviceType.kDLCUDA
assert device.index == 0
assert str(device) == "cuda:0"
assert device.__repr__() == "device(type='cuda', index=0)"
def test_device_from_str() -> None:
device = tvm_ffi.device("ext_dev:0")
assert device.dlpack_device_type() == tvm_ffi.DLDeviceType.kDLExtDev
assert device.index == 0
assert str(device) == "ext_dev:0"
assert device.__repr__() == "device(type='ext_dev', index=0)"
@pytest.mark.parametrize(
"dev_str, expected_device_type, expect_device_id",
[
("cpu", DLDeviceType.kDLCPU, 0),
("cuda", DLDeviceType.kDLCUDA, 0),
("cuda:0", DLDeviceType.kDLCUDA, 0),
("cuda:3", DLDeviceType.kDLCUDA, 3),
("metal:2", DLDeviceType.kDLMetal, 2),
],
)
def test_device_dlpack_device_type(
dev_str: str,
expected_device_type: DLDeviceType,
expect_device_id: int,
) -> None:
dev = tvm_ffi.device(dev_str)
assert dev.dlpack_device_type() == expected_device_type
assert dev.index == expect_device_id
@pytest.mark.parametrize(
"dev_type, dev_id, expected_device_type, expect_device_id",
[
("cpu", 0, DLDeviceType.kDLCPU, 0),
("cuda", 0, DLDeviceType.kDLCUDA, 0),
(DLDeviceType.kDLCUDA, 0, DLDeviceType.kDLCUDA, 0),
("cuda", 3, DLDeviceType.kDLCUDA, 3),
(DLDeviceType.kDLMetal, 2, DLDeviceType.kDLMetal, 2),
# id from numpy
("cpu", numpy.int32(1), DLDeviceType.kDLCPU, 1),
# id from torch (py dependency not ready in environment)
# ("cpu", torch.tensor(1, dtype=torch.int32), DLDeviceType.kDLCPU, 1),
],
)
def test_device_with_dev_id(
dev_type: str | DLDeviceType,
dev_id: int,
expected_device_type: DLDeviceType,
expect_device_id: int,
) -> None:
dev = tvm_ffi.device(dev_type, dev_id)
assert dev.dlpack_device_type() == expected_device_type
assert dev.index == expect_device_id
@pytest.mark.parametrize("dev_type, dev_id", [("cpu:0:0", None), ("cpu:?", None), ("cpu:", None)])
def test_deive_type_error(dev_type: str, dev_id: int | None) -> None:
with pytest.raises(ValueError):
tvm_ffi.device(dev_type, dev_id)
def test_deive_id_error() -> None:
with pytest.raises(TypeError):
tvm_ffi.device("cpu", "?") # ty: ignore[invalid-argument-type]
def test_device_pickle() -> None:
device = tvm_ffi.device("cuda", 0)
device_pickled = pickle.loads(pickle.dumps(device))
assert device_pickled.dlpack_device_type() == device.dlpack_device_type()
assert device_pickled.index == device.index
def test_device_class_override() -> None:
class MyDevice(tvm_ffi.Device):
pass
old_device = tvm_ffi.core._CLASS_DEVICE
tvm_ffi.core._set_class_device(MyDevice)
device = tvm_ffi.device("cuda", 0)
assert isinstance(device, MyDevice)
tvm_ffi.core._set_class_device(old_device)
def test_cuda_stream_handling() -> None:
class MyDummyStream:
def __init__(self, stream: int) -> None:
self.stream = stream
def __cuda_stream__(self) -> tuple[str, int]:
return ("cuda", self.stream)
stream = MyDummyStream(1)
echo = tvm_ffi.get_global_func("testing.echo")
y = echo(stream)
assert isinstance(y, ctypes.c_void_p)
assert y.value == 1