1use anyhow::{anyhow, Result};
9
10#[derive(Debug)]
12pub struct GpuBuffer {
13 ptr: *mut f32,
14 size: usize,
15 device_id: i32,
16}
17
18unsafe impl Send for GpuBuffer {}
19unsafe impl Sync for GpuBuffer {}
20
21impl GpuBuffer {
22 pub fn new(size: usize, device_id: i32) -> Result<Self> {
23 let ptr = Self::allocate_gpu_memory(size * std::mem::size_of::<f32>(), device_id)?;
24 Ok(Self {
25 ptr: ptr as *mut f32,
26 size,
27 device_id,
28 })
29 }
30
31 pub fn copy_from_host(&mut self, data: &[f32]) -> Result<()> {
32 if data.len() > self.size {
33 return Err(anyhow!("Data size exceeds buffer capacity"));
34 }
35 self.copy_host_to_device(data.as_ptr(), self.ptr, std::mem::size_of_val(data))
36 }
37
38 pub fn copy_to_host(&self, data: &mut [f32]) -> Result<()> {
39 if data.len() > self.size {
40 return Err(anyhow!("Host buffer too small"));
41 }
42 self.copy_device_to_host(self.ptr, data.as_mut_ptr(), std::mem::size_of_val(data))
43 }
44
45 #[allow(unused_variables)]
46 fn allocate_gpu_memory(size: usize, device_id: i32) -> Result<*mut u8> {
47 let layout = std::alloc::Layout::from_size_align(size, std::mem::align_of::<f32>())
50 .map_err(|e| anyhow!("Invalid memory layout: {}", e))?;
51 unsafe {
52 let ptr = std::alloc::alloc(layout);
53 if ptr.is_null() {
54 return Err(anyhow!("Failed to allocate memory"));
55 }
56 Ok(ptr)
57 }
58 }
59
60 fn copy_host_to_device(&self, src: *const f32, dst: *mut f32, size: usize) -> Result<()> {
61 unsafe {
63 std::ptr::copy_nonoverlapping(src, dst, size / std::mem::size_of::<f32>());
64 }
65 Ok(())
66 }
67
68 fn copy_device_to_host(&self, src: *const f32, dst: *mut f32, size: usize) -> Result<()> {
69 unsafe {
71 std::ptr::copy_nonoverlapping(src, dst, size / std::mem::size_of::<f32>());
72 }
73 Ok(())
74 }
75
76 pub fn ptr(&self) -> *mut f32 {
77 self.ptr
78 }
79
80 pub fn size(&self) -> usize {
81 self.size
82 }
83
84 pub fn device_id(&self) -> i32 {
85 self.device_id
86 }
87
88 pub fn is_valid(&self) -> bool {
89 !self.ptr.is_null()
90 }
91
92 pub fn zero(&mut self) -> Result<()> {
94 unsafe {
95 std::ptr::write_bytes(self.ptr, 0, self.size);
96 }
97 Ok(())
98 }
99}
100
101impl Drop for GpuBuffer {
102 fn drop(&mut self) {
103 if !self.ptr.is_null() {
104 let layout = std::alloc::Layout::from_size_align(
105 self.size * std::mem::size_of::<f32>(),
106 std::mem::align_of::<f32>(),
107 );
108 if let Ok(layout) = layout {
109 unsafe {
110 std::alloc::dealloc(self.ptr as *mut u8, layout);
111 }
112 }
113 }
114 }
115}