use std::{ptr::NonNull, slice};
use crate::{
core::{
Error, ErrorCode, Result,
column::{
self, column_view_copy_fixed_width_to_host_for_benchmark,
trigger_fixed_width_host_byte_range_overflow_for_test,
},
error,
},
testing::ColumnView,
};
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum D2hBenchmarkHostMemory {
Pageable,
Pinned,
}
enum D2hBenchmarkStorage {
Pageable(Vec<u8>),
Pinned { ptr: NonNull<u8>, capacity: usize },
}
pub struct D2hBenchmarkBuffer {
storage: D2hBenchmarkStorage,
initialized_len: usize,
}
impl D2hBenchmarkBuffer {
pub fn new(kind: D2hBenchmarkHostMemory, capacity: usize) -> Result<Self> {
if capacity == 0 {
return Err(Error::new_with(
ErrorCode::EmptyInput,
"testing::D2hBenchmarkBuffer::new",
"D2H benchmark buffer capacity must be greater than zero",
));
}
let storage = match kind {
D2hBenchmarkHostMemory::Pageable => D2hBenchmarkStorage::Pageable(vec![0u8; capacity]),
D2hBenchmarkHostMemory::Pinned => {
let mut raw = std::ptr::null_mut();
error::check_status_in(
unsafe { cudf_sys::cudf_pinned_host_alloc(capacity, &mut raw) },
"testing::D2hBenchmarkBuffer::new",
)?;
let ptr = NonNull::new(raw.cast::<u8>()).ok_or_else(|| {
Error::new_with(
ErrorCode::ForeignInvariantViolation,
"testing::D2hBenchmarkBuffer::new",
"pinned host allocation returned null",
)
})?;
D2hBenchmarkStorage::Pinned { ptr, capacity }
},
};
Ok(Self { storage, initialized_len: 0 })
}
pub fn kind(&self) -> D2hBenchmarkHostMemory {
match self.storage {
D2hBenchmarkStorage::Pageable(_) => D2hBenchmarkHostMemory::Pageable,
D2hBenchmarkStorage::Pinned { .. } => D2hBenchmarkHostMemory::Pinned,
}
}
pub fn capacity(&self) -> usize {
match &self.storage {
D2hBenchmarkStorage::Pageable(bytes) => bytes.len(),
D2hBenchmarkStorage::Pinned { capacity, .. } => *capacity,
}
}
pub fn copy_from_fixed_width(&mut self, view: &ColumnView<'_>) -> Result<usize> {
let capacity = self.capacity();
let host_ptr = match &mut self.storage {
D2hBenchmarkStorage::Pageable(bytes) => bytes.as_mut_ptr(),
D2hBenchmarkStorage::Pinned { ptr, .. } => ptr.as_ptr(),
};
let copied = column_view_copy_fixed_width_to_host_for_benchmark(view, host_ptr, capacity)?;
self.initialized_len = copied;
Ok(copied)
}
pub fn initialized_bytes(&self) -> &[u8] {
match &self.storage {
D2hBenchmarkStorage::Pageable(bytes) => &bytes[..self.initialized_len],
D2hBenchmarkStorage::Pinned { ptr, .. } => {
unsafe { slice::from_raw_parts(ptr.as_ptr(), self.initialized_len) }
},
}
}
}
impl Drop for D2hBenchmarkBuffer {
fn drop(&mut self) {
if let D2hBenchmarkStorage::Pinned { ptr, .. } = &self.storage {
let _ = unsafe { cudf_sys::cudf_pinned_host_free(ptr.as_ptr().cast()) };
}
}
}
pub unsafe fn adopt_owned_column_view_for_test(
raw: cudf_sys::cudf_column_view_handle,
runtime: &crate::Runtime,
) -> Result<ColumnView<'static>> {
unsafe { column::adopt_owned_column_view_for_test(raw, runtime) }
}
pub fn column_view_to_raw_bytes_for_test(view: &ColumnView<'_>) -> Result<Vec<u8>> {
column::column_view_to_raw_bytes_for_test(view)
}
pub fn column_view_to_fixed_width_host_bytes_for_test(view: &ColumnView<'_>) -> Result<Vec<u8>> {
column::column_view_to_fixed_width_host_bytes_for_test(view)
}
pub fn trigger_column_view_fixed_width_host_byte_range_overflow_for_test() -> Result<()> {
trigger_fixed_width_host_byte_range_overflow_for_test()
}