mirror of
https://github.com/vosen/ZLUDA.git
synced 2025-09-11 03:56:37 +00:00
Reorganize driver host tests, fix bugs around pointer host code (#492)
This commit is contained in:
parent
08f7e874e3
commit
8a7a5b45be
11 changed files with 182 additions and 119 deletions
17
Cargo.lock
generated
17
Cargo.lock
generated
|
@ -447,21 +447,6 @@ dependencies = [
|
||||||
"syn 2.0.89",
|
"syn 2.0.89",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "cuda_tests"
|
|
||||||
version = "0.0.0"
|
|
||||||
dependencies = [
|
|
||||||
"cuda_macros",
|
|
||||||
"cuda_types",
|
|
||||||
"dtor 0.0.6",
|
|
||||||
"lazy_static",
|
|
||||||
"lz4-sys",
|
|
||||||
"num_enum",
|
|
||||||
"paste",
|
|
||||||
"rustc-hash 1.1.0",
|
|
||||||
"tempfile",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cuda_types"
|
name = "cuda_types"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
|
@ -3729,13 +3714,13 @@ dependencies = [
|
||||||
"blake3",
|
"blake3",
|
||||||
"comgr",
|
"comgr",
|
||||||
"cuda_macros",
|
"cuda_macros",
|
||||||
"cuda_tests",
|
|
||||||
"cuda_types",
|
"cuda_types",
|
||||||
"dark_api",
|
"dark_api",
|
||||||
"dtor 0.0.7",
|
"dtor 0.0.7",
|
||||||
"hip_runtime-sys",
|
"hip_runtime-sys",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"libc",
|
"libc",
|
||||||
|
"libloading",
|
||||||
"lz4-sys",
|
"lz4-sys",
|
||||||
"num_enum",
|
"num_enum",
|
||||||
"paste",
|
"paste",
|
||||||
|
|
|
@ -6,7 +6,6 @@ members = [
|
||||||
"comgr",
|
"comgr",
|
||||||
"cuda_macros",
|
"cuda_macros",
|
||||||
"cuda_types",
|
"cuda_types",
|
||||||
"cuda_tests",
|
|
||||||
"dark_api",
|
"dark_api",
|
||||||
"detours-sys",
|
"detours-sys",
|
||||||
"ext/amd_comgr-sys",
|
"ext/amd_comgr-sys",
|
||||||
|
|
|
@ -2,7 +2,7 @@ extern crate proc_macro;
|
||||||
|
|
||||||
use proc_macro::TokenStream;
|
use proc_macro::TokenStream;
|
||||||
use proc_macro2::Span;
|
use proc_macro2::Span;
|
||||||
use quote::{quote, ToTokens};
|
use quote::{format_ident, quote, ToTokens};
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
use std::iter;
|
use std::iter;
|
||||||
use syn::parse::{Parse, ParseStream};
|
use syn::parse::{Parse, ParseStream};
|
||||||
|
@ -10,7 +10,7 @@ use syn::punctuated::Punctuated;
|
||||||
use syn::visit_mut::VisitMut;
|
use syn::visit_mut::VisitMut;
|
||||||
use syn::{
|
use syn::{
|
||||||
bracketed, parse_macro_input, File, ForeignItem, ForeignItemFn, Ident, Item, Path, Signature,
|
bracketed, parse_macro_input, File, ForeignItem, ForeignItemFn, Ident, Item, Path, Signature,
|
||||||
Token, token
|
Token
|
||||||
};
|
};
|
||||||
|
|
||||||
const CUDA_RS: &'static str = include_str! {"cuda.rs"};
|
const CUDA_RS: &'static str = include_str! {"cuda.rs"};
|
||||||
|
@ -309,39 +309,22 @@ fn join(
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[proc_macro]
|
#[proc_macro_attribute]
|
||||||
pub fn generate_api_macro(input: TokenStream) -> TokenStream {
|
pub fn test_cuda(_attr: TokenStream, item: TokenStream) -> TokenStream {
|
||||||
let input = parse_macro_input!(input as ApiMacroInput);
|
let fn_ = parse_macro_input!(item as syn::ItemFn);
|
||||||
let ApiMacroInput(_, trait_name, _, type_name, _, macro_name) = input;
|
let cuda_fn = format_ident!("{}{}", fn_.sig.ident, "_nvidia");
|
||||||
let expanded = quote! {
|
let zluda_fn = format_ident!("{}{}", fn_.sig.ident, "_amdgpu");
|
||||||
struct #type_name;
|
let fn_name = fn_.sig.ident.clone();
|
||||||
macro_rules! #macro_name {
|
quote! {
|
||||||
($($abi:literal fn $fn_name:ident( $( $arg_id:ident : $arg_type:ty ),* ) -> $ret_type:ty;)*) => {
|
#[test]
|
||||||
impl #trait_name for #type_name {
|
fn #cuda_fn() {
|
||||||
fn new() -> Self { Self }
|
unsafe { #fn_name(<crate::tests::Cuda>::new()) }
|
||||||
$(
|
|
||||||
#[inline(always)]
|
|
||||||
fn $fn_name(&self, $( $arg_id : $arg_type ),* ) -> $ret_type {
|
|
||||||
unsafe { super::$fn_name( $( $arg_id ),* ) }
|
|
||||||
}
|
|
||||||
)*
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
};
|
#[test]
|
||||||
TokenStream::from(expanded)
|
fn #zluda_fn() {
|
||||||
}
|
unsafe { #fn_name(<crate::tests::Zluda>::new()) }
|
||||||
#[allow(dead_code)]
|
}
|
||||||
struct ApiMacroInput(token::Impl, Path, token::For, Path, token::Use, Ident);
|
|
||||||
impl syn::parse::Parse for ApiMacroInput {
|
#fn_
|
||||||
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
|
}.into()
|
||||||
Ok(ApiMacroInput(
|
|
||||||
input.parse()?, // impl
|
|
||||||
input.parse()?, // trait
|
|
||||||
input.parse()?, // for
|
|
||||||
input.parse()?, // type
|
|
||||||
input.parse()?, // using
|
|
||||||
input.parse()? // macro
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -1,16 +0,0 @@
|
||||||
[package]
|
|
||||||
name = "cuda_tests"
|
|
||||||
version = "0.0.0"
|
|
||||||
authors = ["Andrzej Janik <vosen@vosen.pl>"]
|
|
||||||
edition = "2021"
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
cuda_types = { path = "../cuda_types" }
|
|
||||||
cuda_macros = { path = "../cuda_macros" }
|
|
||||||
lazy_static = "1.4"
|
|
||||||
num_enum = "0.4"
|
|
||||||
lz4-sys = "1.9"
|
|
||||||
tempfile = "3"
|
|
||||||
paste = "1.0"
|
|
||||||
rustc-hash = "1.1"
|
|
||||||
dtor = "0.0.6"
|
|
|
@ -1,8 +0,0 @@
|
||||||
use crate::api_trait;
|
|
||||||
use cuda_types::cuda::*;
|
|
||||||
|
|
||||||
cuda_macros::cuda_function_declarations!(api_trait);
|
|
||||||
|
|
||||||
pub unsafe fn init_check<T: Api>(api: T) {
|
|
||||||
assert_eq!(api.cuInit(0), CUresult::SUCCESS);
|
|
||||||
}
|
|
|
@ -1,24 +0,0 @@
|
||||||
#[macro_export]
|
|
||||||
macro_rules! api_trait {
|
|
||||||
($($abi:literal fn $fn_name:ident( $($arg_id:ident : $arg_type:ty),* ) -> $ret_type:ty;)*) => {
|
|
||||||
pub trait Api {
|
|
||||||
fn new() -> Self;
|
|
||||||
$(fn $fn_name(&self, $( $arg_id : $arg_type ),* ) -> $ret_type;)*
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! api_test {
|
|
||||||
($func:ident, $type:ty) => {
|
|
||||||
paste::paste! {
|
|
||||||
#[test]
|
|
||||||
#[allow(non_snake_case)]
|
|
||||||
fn [<$func _test>]() {
|
|
||||||
unsafe { $func::<$type>(<$type>::new()) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub mod cuda;
|
|
|
@ -27,7 +27,6 @@ zluda_common = { path = "../zluda_common" }
|
||||||
blake3 = "1.8.2"
|
blake3 = "1.8.2"
|
||||||
serde = "1.0.219"
|
serde = "1.0.219"
|
||||||
serde_json = "1.0.142"
|
serde_json = "1.0.142"
|
||||||
cuda_tests = { path = "../cuda_tests" }
|
|
||||||
|
|
||||||
[target.'cfg(windows)'.dependencies]
|
[target.'cfg(windows)'.dependencies]
|
||||||
winapi = { version = "0.3", features = ["heapapi", "std"] }
|
winapi = { version = "0.3", features = ["heapapi", "std"] }
|
||||||
|
@ -39,6 +38,9 @@ dtor = "0.0.7"
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
vergen-gix = "1.0.9"
|
vergen-gix = "1.0.9"
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
libloading = "0.8"
|
||||||
|
|
||||||
[package.metadata.zluda]
|
[package.metadata.zluda]
|
||||||
linux_symlinks = [
|
linux_symlinks = [
|
||||||
"libcuda.so",
|
"libcuda.so",
|
||||||
|
|
|
@ -528,8 +528,15 @@ pub(crate) unsafe fn launch_kernel_ex(
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::r#impl::driver::AllocationInfo;
|
use crate::r#impl::driver::AllocationInfo;
|
||||||
|
use crate::tests::CudaApi;
|
||||||
|
use cuda_macros::test_cuda;
|
||||||
use cuda_types::cuda::CUcontext;
|
use cuda_types::cuda::CUcontext;
|
||||||
|
|
||||||
|
#[test_cuda]
|
||||||
|
fn init(api: impl CudaApi) {
|
||||||
|
api.cuInit(0);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn get_allocation() {
|
fn get_allocation() {
|
||||||
let ctx1 = CUcontext(0x1234 as _);
|
let ctx1 = CUcontext(0x1234 as _);
|
||||||
|
|
|
@ -27,12 +27,8 @@ pub(crate) unsafe fn get_attribute(
|
||||||
}
|
}
|
||||||
match attribute {
|
match attribute {
|
||||||
hipPointer_attribute::HIP_POINTER_ATTRIBUTE_CONTEXT => {
|
hipPointer_attribute::HIP_POINTER_ATTRIBUTE_CONTEXT => {
|
||||||
let globals = driver::global_state()?;
|
let context = get_context(ptr)?;
|
||||||
let allocations = globals.allocations.lock().map_err(|_| CUerror::UNKNOWN)?;
|
unsafe { *(data.cast()) = context };
|
||||||
let (_, alloc) = allocations
|
|
||||||
.get_offset_and_info(ptr.0 as usize)
|
|
||||||
.ok_or(CUerror::INVALID_VALUE)?;
|
|
||||||
unsafe { *(data.cast()) = alloc.context };
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
hipPointer_attribute::HIP_POINTER_ATTRIBUTE_MEMORY_TYPE => {
|
hipPointer_attribute::HIP_POINTER_ATTRIBUTE_MEMORY_TYPE => {
|
||||||
|
@ -48,6 +44,15 @@ pub(crate) unsafe fn get_attribute(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_context(ptr: hipDeviceptr_t) -> Result<CUcontext, CUerror> {
|
||||||
|
let globals = driver::global_state()?;
|
||||||
|
let allocations = globals.allocations.lock().map_err(|_| CUerror::UNKNOWN)?;
|
||||||
|
let (_, alloc) = allocations
|
||||||
|
.get_offset_and_info(ptr.0 as usize)
|
||||||
|
.ok_or(CUerror::INVALID_VALUE)?;
|
||||||
|
Ok(alloc.context)
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) unsafe fn get_attributes(
|
pub(crate) unsafe fn get_attributes(
|
||||||
num_attributes: ::core::ffi::c_uint,
|
num_attributes: ::core::ffi::c_uint,
|
||||||
attributes: &mut hipPointer_attribute,
|
attributes: &mut hipPointer_attribute,
|
||||||
|
@ -59,15 +64,102 @@ pub(crate) unsafe fn get_attributes(
|
||||||
let data = std::slice::from_raw_parts_mut(data, num_attributes as usize);
|
let data = std::slice::from_raw_parts_mut(data, num_attributes as usize);
|
||||||
for (attr, data_ptr) in attributes.iter().copied().zip(data.iter().copied()) {
|
for (attr, data_ptr) in attributes.iter().copied().zip(data.iter().copied()) {
|
||||||
match attr {
|
match attr {
|
||||||
|
hipPointer_attribute::HIP_POINTER_ATTRIBUTE_HOST_POINTER => {
|
||||||
|
if (*(data_ptr.cast::<hipDeviceptr_t>())).0.is_null() {
|
||||||
|
*(data_ptr.cast::<hipDeviceptr_t>()) = ptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
hipPointer_attribute::HIP_POINTER_ATTRIBUTE_CONTEXT => {
|
hipPointer_attribute::HIP_POINTER_ATTRIBUTE_CONTEXT => {
|
||||||
get_attribute(data_ptr, attr, ptr).ok();
|
*(data_ptr.cast::<CUcontext>()) =
|
||||||
|
get_context(ptr).unwrap_or(CUcontext(ptr::null_mut()));
|
||||||
}
|
}
|
||||||
hipPointer_attribute::HIP_POINTER_ATTRIBUTE_MEMORY_TYPE => {
|
hipPointer_attribute::HIP_POINTER_ATTRIBUTE_MEMORY_TYPE => {
|
||||||
*(data_ptr.cast::<CUmemorytype>()) =
|
*(data_ptr.cast::<CUmemorytype>()) =
|
||||||
to_cu_memory_type(*data_ptr.cast::<hipMemoryType>())?;
|
to_cu_memory_type(*data_ptr.cast::<hipMemoryType>()).unwrap_or(CUmemorytype(0));
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use crate::tests::CudaApi;
|
||||||
|
use cuda_macros::test_cuda;
|
||||||
|
use cuda_types::cuda::*;
|
||||||
|
use std::{ffi::c_void, mem, ptr};
|
||||||
|
|
||||||
|
#[test_cuda]
|
||||||
|
pub unsafe fn unknown_ptr_attribute(api: impl CudaApi) {
|
||||||
|
api.cuInit(0);
|
||||||
|
api.cuCtxCreate_v2(&mut mem::zeroed(), 0, 0);
|
||||||
|
let mut ctx = mem::zeroed::<CUcontext>();
|
||||||
|
assert_eq!(
|
||||||
|
CUresult::ERROR_INVALID_VALUE,
|
||||||
|
api.cuPointerGetAttribute_unchecked(
|
||||||
|
std::ptr::from_mut(&mut ctx).cast(),
|
||||||
|
CUpointer_attribute::CU_POINTER_ATTRIBUTE_CONTEXT,
|
||||||
|
CUdeviceptr_v2(0xDEAD as _)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test_cuda]
|
||||||
|
pub unsafe fn unknown_ptr_attributes(api: impl CudaApi) {
|
||||||
|
api.cuInit(0);
|
||||||
|
api.cuCtxCreate_v2(&mut mem::zeroed(), 0, 0);
|
||||||
|
let mut mem_type = mem::zeroed::<CUmemorytype>();
|
||||||
|
let mut host_ptr = mem::zeroed::<*mut c_void>();
|
||||||
|
let mut dev_ptr = mem::zeroed::<*mut c_void>();
|
||||||
|
let mut is_managed = mem::zeroed::<bool>();
|
||||||
|
let mut ordinal = mem::zeroed::<i32>();
|
||||||
|
let mut attrs = [
|
||||||
|
CUpointer_attribute::CU_POINTER_ATTRIBUTE_MEMORY_TYPE,
|
||||||
|
CUpointer_attribute::CU_POINTER_ATTRIBUTE_DEVICE_POINTER,
|
||||||
|
CUpointer_attribute::CU_POINTER_ATTRIBUTE_HOST_POINTER,
|
||||||
|
CUpointer_attribute::CU_POINTER_ATTRIBUTE_IS_MANAGED,
|
||||||
|
CUpointer_attribute::CU_POINTER_ATTRIBUTE_DEVICE_ORDINAL,
|
||||||
|
];
|
||||||
|
let mut values = [
|
||||||
|
std::ptr::from_mut(&mut mem_type).cast::<c_void>(),
|
||||||
|
std::ptr::from_mut(&mut dev_ptr).cast(),
|
||||||
|
std::ptr::from_mut(&mut host_ptr).cast(),
|
||||||
|
std::ptr::from_mut(&mut is_managed).cast(),
|
||||||
|
std::ptr::from_mut(&mut ordinal).cast(),
|
||||||
|
];
|
||||||
|
assert_eq!(
|
||||||
|
CUresult::SUCCESS,
|
||||||
|
api.cuPointerGetAttributes_unchecked(
|
||||||
|
attrs.len() as u32,
|
||||||
|
attrs.as_mut_ptr(),
|
||||||
|
values.as_mut_ptr(),
|
||||||
|
CUdeviceptr_v2(0xDEAD as _)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
assert_eq!(mem_type, CUmemorytype(0));
|
||||||
|
assert_eq!(host_ptr, 0xDEAD as _);
|
||||||
|
assert_eq!(dev_ptr, ptr::null_mut());
|
||||||
|
assert_eq!(is_managed, false);
|
||||||
|
assert_eq!(ordinal, -2);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test_cuda]
|
||||||
|
pub unsafe fn unknown_ptr_attributes_no_context(api: impl CudaApi) {
|
||||||
|
api.cuInit(0);
|
||||||
|
api.cuCtxCreate_v2(&mut mem::zeroed(), 0, 0);
|
||||||
|
let mut context = CUcontext(1 as _);
|
||||||
|
let mut attrs = [CUpointer_attribute::CU_POINTER_ATTRIBUTE_CONTEXT];
|
||||||
|
let mut values = [std::ptr::from_mut(&mut context).cast::<c_void>()];
|
||||||
|
assert_eq!(
|
||||||
|
CUresult::SUCCESS,
|
||||||
|
api.cuPointerGetAttributes_unchecked(
|
||||||
|
attrs.len() as u32,
|
||||||
|
attrs.as_mut_ptr(),
|
||||||
|
values.as_mut_ptr(),
|
||||||
|
CUdeviceptr_v2(0xDEAD as _)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
assert_eq!(context, CUcontext(ptr::null_mut()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
51
zluda/src/tests.rs
Normal file
51
zluda/src/tests.rs
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
pub(crate) struct Zluda;
|
||||||
|
|
||||||
|
pub(crate) struct Cuda(libloading::Library);
|
||||||
|
|
||||||
|
impl Cuda {
|
||||||
|
#[cfg(not(windows))]
|
||||||
|
const CUDA_PATH: &'static str = "/usr/lib/x86_64-linux-gnu/libcuda.so.1";
|
||||||
|
#[cfg(windows)]
|
||||||
|
const CUDA_PATH: &'static str = "C:\\Windows\\System32\\nvcuda.dll";
|
||||||
|
|
||||||
|
fn load() -> Self {
|
||||||
|
unsafe { Self(libloading::Library::new(Self::CUDA_PATH).unwrap()) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! implemented_test {
|
||||||
|
($($abi:literal fn $fn_name:ident( $( $arg_id:ident : $arg_type:ty ),* ) -> $ret_type:ty;)* ) => {
|
||||||
|
pub(crate) trait CudaApi {
|
||||||
|
fn new() -> Self;
|
||||||
|
$(
|
||||||
|
#[allow(non_snake_case, dead_code)]
|
||||||
|
fn $fn_name(&self, $( $arg_id : $arg_type ),* ) {
|
||||||
|
paste::paste!{ self.[< $fn_name _unchecked >]( $( $arg_id ),* ) }.unwrap()
|
||||||
|
}
|
||||||
|
paste::paste!{ #[allow(non_snake_case, dead_code)] fn [< $fn_name _unchecked>](&self, $( $arg_id : $arg_type ),* ) -> $ret_type; }
|
||||||
|
)*
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
impl CudaApi for Cuda {
|
||||||
|
fn new() -> Self { Self::load() }
|
||||||
|
$(
|
||||||
|
paste::paste!{ fn [< $fn_name _unchecked >](&self, $( $arg_id : $arg_type ),* ) -> $ret_type {
|
||||||
|
let func = unsafe { self.0.get::<unsafe extern $abi fn ( $( $arg_type ),* ) -> $ret_type>(concat!(stringify!($fn_name), "\0").as_bytes()) }.unwrap();
|
||||||
|
unsafe { (func)( $( $arg_id ),* ) }
|
||||||
|
}}
|
||||||
|
)*
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CudaApi for Zluda {
|
||||||
|
fn new() -> Self { Self }
|
||||||
|
$(
|
||||||
|
paste::paste!{ fn [< $fn_name _unchecked >](&self, $( $arg_id : $arg_type ),* ) -> $ret_type {
|
||||||
|
unsafe { super::$fn_name( $( $arg_id ),* ) }
|
||||||
|
}}
|
||||||
|
)*
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
cuda_macros::cuda_function_declarations!(implemented_test);
|
|
@ -1,8 +0,0 @@
|
||||||
use cuda_macros::generate_api_macro;
|
|
||||||
use cuda_tests::api_test;
|
|
||||||
use cuda_tests::cuda::*;
|
|
||||||
|
|
||||||
generate_api_macro!(impl cuda_tests::cuda::Api for TestApi use implemented_test);
|
|
||||||
cuda_macros::cuda_function_declarations!(implemented_test);
|
|
||||||
|
|
||||||
api_test!(init_check, TestApi);
|
|
Loading…
Add table
Add a link
Reference in a new issue