(&self, weight: &Tensor)
| 1343 | } |
| 1344 | |
| 1345 | fn preprocess_linear_weight(&self, weight: &Tensor) -> Result<Tensor> { |
| 1346 | // Pre-upload F32 version to GPU cache (tensor_matmul will find it via get_or_upload). |
| 1347 | // Return original dtype weight so linear_forward's x.matmul(&w) has matching dtypes. |
| 1348 | let w = weight.to_dtype(DType::F32)?.contiguous()?; |
| 1349 | let _ = self.get_or_upload(&w)?; |
| 1350 | |
| 1351 | // Also pre-upload the TRANSPOSED F16 data for GEMV (halves bandwidth). |
| 1352 | if weight.dtype() == DType::F16 { |
| 1353 | let wt_f16 = weight.t()?.contiguous()?; |
| 1354 | let f16_data: Vec<f32> = wt_f16.to_dtype(DType::F32)?.flatten_all()?.to_vec1()?; |
| 1355 | let n = wt_f16.elem_count(); |
| 1356 | let f16_vals: Vec<half::f16> = f16_data.iter().map(|&v| half::f16::from_f32(v)).collect(); |
| 1357 | let f16_bytes: &[u8] = bytemuck::cast_slice(&f16_vals); |
| 1358 | let buf_bytes = (f16_bytes.len()) as u64; |
| 1359 | let mut alloc_guard = self.allocator.lock().unwrap(); |
| 1360 | let alloc = alloc_guard.as_mut().unwrap(); |
| 1361 | let buf = Self::alloc_mapped_buffer( |
| 1362 | &self.vk_device, alloc, buf_bytes, |
| 1363 | vk::BufferUsageFlags::STORAGE_BUFFER, self.uma_memory_type, |
| 1364 | ).map_err(candle_core::Error::Msg)?; |
| 1365 | unsafe { |
| 1366 | std::ptr::copy_nonoverlapping(f16_bytes.as_ptr(), buf.mapped_ptr, f16_bytes.len()); |
| 1367 | } |
| 1368 | let wt_f32 = w.t()?; |
| 1369 | if let Some(key) = Self::view_key(&wt_f32) { |
| 1370 | let mut cache = self.weight_cache.lock().unwrap(); |
| 1371 | cache.f16_views.insert(key, Arc::new(buf)); |
| 1372 | log::debug!("pre-uploaded F16 GEMV weight: {} elements", n); |
| 1373 | } |
| 1374 | drop(alloc_guard); |
| 1375 | } |
| 1376 | |
| 1377 | // Return original dtype — don't break linear_forward's dtype assumptions |
| 1378 | let w_orig = if weight.is_contiguous() { weight.clone() } else { weight.contiguous()? }; |
| 1379 | Ok(w_orig) |
| 1380 | } |
| 1381 | |
| 1382 | fn matmul(&self, a: &Tensor, b: &Tensor) -> Result<Tensor> { |
| 1383 | let a_dims = a.dims(); |
nothing calls this directly
no test coverage detected