(&self, names: &[&str])
| 503 | } |
| 504 | |
| 505 | fn read_tensors(&self, names: &[&str]) -> Result<Vec<TensorData>> { |
| 506 | if names.is_empty() { |
| 507 | return Ok(Vec::new()); |
| 508 | } |
| 509 | |
| 510 | // Resolve all metadata first |
| 511 | let metas: Vec<&TensorMeta> = names |
| 512 | .iter() |
| 513 | .map(|n| { |
| 514 | self.index |
| 515 | .get(*n) |
| 516 | .ok_or_else(|| anyhow::anyhow!("tensor '{}' not found in storage", n)) |
| 517 | }) |
| 518 | .collect::<Result<_>>()?; |
| 519 | |
| 520 | // Check if all tensors are in the same shard and contiguous |
| 521 | let same_shard = metas.windows(2).all(|w| w[0].shard_idx == w[1].shard_idx); |
| 522 | let contiguous = same_shard |
| 523 | && metas |
| 524 | .windows(2) |
| 525 | .all(|w| w[0].abs_offset + w[0].byte_size == w[1].abs_offset); |
| 526 | |
| 527 | if contiguous && metas.len() > 1 { |
| 528 | // Single pread for the entire contiguous region |
| 529 | let first = metas[0]; |
| 530 | let last = metas[metas.len() - 1]; |
| 531 | let total_size = (last.abs_offset + last.byte_size - first.abs_offset) as usize; |
| 532 | |
| 533 | let shard = self |
| 534 | .shards |
| 535 | .get(first.shard_idx as usize) |
| 536 | .ok_or_else(|| anyhow::anyhow!("shard index {} out of range", first.shard_idx))?; |
| 537 | |
| 538 | // mmap: zero-syscall read — just memcpy from mapped memory |
| 539 | #[cfg(unix)] |
| 540 | let buf = shard.read_bytes(first.abs_offset, total_size); |
| 541 | |
| 542 | #[cfg(not(unix))] |
| 543 | let buf = { |
| 544 | use std::io::{Read as _, Seek, SeekFrom}; |
| 545 | let mut f = shard.file.try_clone()?; |
| 546 | let mut buf = vec![0u8; total_size]; |
| 547 | f.seek(SeekFrom::Start(first.abs_offset))?; |
| 548 | f.read_exact(&mut buf)?; |
| 549 | buf |
| 550 | }; |
| 551 | |
| 552 | // Split the buffer into individual tensor data |
| 553 | let mut results = Vec::with_capacity(metas.len()); |
| 554 | let mut offset = 0usize; |
| 555 | for meta in &metas { |
| 556 | let size = meta.byte_size as usize; |
| 557 | let bytes = buf[offset..offset + size].to_vec(); |
| 558 | results.push(TensorData { |
| 559 | bytes, |
| 560 | dtype: meta.dtype, |
| 561 | shape: meta.shape.to_vec(), |
| 562 | }); |
no test coverage detected