blob: ffdd122e1b18c486ef1f7eb0589d38b3d7ce9e99 [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 pytest
import tvm_ffi
import tvm_ffi.cpp
from tvm_ffi.testing import run_with_gpu_lock
try:
import torch
except ImportError:
torch = None # ty: ignore[invalid-assignment]
try:
from cuda.bindings import driver as cuda_driver
except ImportError:
cuda_driver = None
@pytest.mark.skipif(cuda_driver is None, reason="Requires cuda-python")
def test_cuda_driver_stream() -> None:
assert cuda_driver is not None
echo = tvm_ffi.get_global_func("testing.echo")
stream = cuda_driver.CUstream(0)
y = echo(stream)
assert y is not None
z = echo(cuda_driver.CUstream(1))
assert isinstance(z, ctypes.c_void_p)
assert z.value == 1
def gen_check_stream_mod() -> tvm_ffi.Module:
return tvm_ffi.cpp.load_inline(
name="check_stream",
cpp_sources="""
void check_stream(int device_type, int device_id, uint64_t stream) {
uint64_t cur_stream = reinterpret_cast<uint64_t>(TVMFFIEnvGetStream(device_type, device_id));
TVM_FFI_ICHECK_EQ(cur_stream, stream);
}
""",
functions=["check_stream"],
)
def test_raw_stream() -> None:
mod = gen_check_stream_mod()
device = tvm_ffi.device("cuda:0")
stream_1 = 123456789
stream_2 = 987654321
with tvm_ffi.use_raw_stream(device, stream_1):
mod.check_stream(device.dlpack_device_type(), device.index, stream_1)
assert tvm_ffi.get_raw_stream(device) == stream_1
with tvm_ffi.use_raw_stream(device, stream_2):
mod.check_stream(device.dlpack_device_type(), device.index, stream_2)
assert tvm_ffi.get_raw_stream(device) == stream_2
mod.check_stream(device.dlpack_device_type(), device.index, stream_1)
assert tvm_ffi.get_raw_stream(device) == stream_1
@pytest.mark.skipif(
torch is None or not torch.cuda.is_available(), reason="Requires torch and CUDA"
)
def test_torch_stream() -> None:
assert torch is not None
mod = gen_check_stream_mod()
def run_and_check() -> None:
assert torch is not None
device_id = torch.cuda.current_device()
device = tvm_ffi.device("cuda", device_id)
device_type = device.dlpack_device_type()
stream_1 = torch.cuda.Stream(device_id)
stream_2 = torch.cuda.Stream(device_id)
with tvm_ffi.use_torch_stream(torch.cuda.stream(stream_1)):
assert torch.cuda.current_stream() == stream_1
mod.check_stream(device_type, device_id, stream_1.cuda_stream)
with tvm_ffi.use_torch_stream(torch.cuda.stream(stream_2)):
assert torch.cuda.current_stream() == stream_2
mod.check_stream(device_type, device_id, stream_2.cuda_stream)
assert torch.cuda.current_stream() == stream_1
mod.check_stream(device_type, device_id, stream_1.cuda_stream)
run_with_gpu_lock(run_and_check)
@pytest.mark.skipif(
torch is None or not torch.cuda.is_available(), reason="Requires torch and CUDA"
)
def test_torch_current_stream() -> None:
assert torch is not None
mod = gen_check_stream_mod()
def run_and_check() -> None:
assert torch is not None
device_id = torch.cuda.current_device()
device = tvm_ffi.device("cuda", device_id)
device_type = device.dlpack_device_type()
stream_1 = torch.cuda.Stream(device_id)
stream_2 = torch.cuda.Stream(device_id)
with torch.cuda.stream(stream_1):
assert torch.cuda.current_stream() == stream_1
with tvm_ffi.use_torch_stream():
mod.check_stream(device_type, device_id, stream_1.cuda_stream)
with torch.cuda.stream(stream_2):
assert torch.cuda.current_stream() == stream_2
with tvm_ffi.use_torch_stream():
mod.check_stream(device_type, device_id, stream_2.cuda_stream)
assert torch.cuda.current_stream() == stream_1
with tvm_ffi.use_torch_stream():
mod.check_stream(device_type, device_id, stream_1.cuda_stream)
run_with_gpu_lock(run_and_check)
@pytest.mark.skipif(
torch is None or not torch.cuda.is_available(), reason="Requires torch and CUDA"
)
def test_torch_graph() -> None:
assert torch is not None
mod = gen_check_stream_mod()
def run_and_check() -> None:
assert torch is not None
device_id = torch.cuda.current_device()
device = tvm_ffi.device("cuda", device_id)
device_type = device.dlpack_device_type()
graph = torch.cuda.CUDAGraph()
stream = torch.cuda.Stream(device_id)
x = torch.zeros(1, device="cuda")
with tvm_ffi.use_torch_stream(torch.cuda.graph(graph, stream=stream)):
assert torch.cuda.current_stream() == stream
mod.check_stream(device_type, device_id, stream.cuda_stream)
# avoid cuda graph no capture warning
x = x + 1
run_with_gpu_lock(run_and_check)