Skip to content

Commit 5d336a8

Browse files
evilsocketclaude
andcommitted
Merge autoresearch/network/inference-io-v2: direct storage access for tensor serialization
Bypass candle's data().into_owned() path for CPU contiguous tensors in RawTensor::from_tensor(). Access CpuStorage variant directly and copy bytes in a single memcpy instead of flatten_all → to_vec1 → reinterpret. Key result: raw_tensor_from_tensor benchmark 53% faster (300ns → 141ns). Combined with v1 optimizations already on main: - single_op_encode: 126ns → 99ns (21% faster) - single_op_decode: 191ns → 146ns (24% faster) - buf_reuse_pipe_roundtrip: 2.1µs → 1.8µs (14% faster) - raw_tensor_from_tensor(1024): 300ns → 141ns (53% faster) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2 parents 257ec7e + ba60405 commit 5d336a8

1 file changed

Lines changed: 48 additions & 1 deletion

File tree

cake-core/src/cake/sharding/proto/message.rs

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,12 +56,59 @@ impl std::fmt::Debug for RawTensor {
5656
}
5757
}
5858

59+
/// Extract raw bytes from a CpuStorage slice range as a newly-allocated Vec<u8>.
60+
/// This avoids the flatten_all + to_vec1 + reinterpret chain in candle's data() path.
61+
fn cpu_storage_bytes_range(storage: &candle_core::CpuStorage, start: usize, end: usize) -> Vec<u8> {
62+
if start == end {
63+
return Vec::new();
64+
}
65+
use candle_core::CpuStorage;
66+
macro_rules! extract {
67+
($slice:expr) => {{
68+
let data = &$slice[start..end];
69+
let byte_len = data.len() * std::mem::size_of_val(&data[0]);
70+
let ptr = data.as_ptr() as *const u8;
71+
unsafe { std::slice::from_raw_parts(ptr, byte_len) }.to_vec()
72+
}};
73+
}
74+
match storage {
75+
CpuStorage::U8(s) => extract!(s),
76+
CpuStorage::U32(s) => extract!(s),
77+
CpuStorage::I16(s) => extract!(s),
78+
CpuStorage::I32(s) => extract!(s),
79+
CpuStorage::I64(s) => extract!(s),
80+
CpuStorage::BF16(s) => extract!(s),
81+
CpuStorage::F16(s) => extract!(s),
82+
CpuStorage::F32(s) => extract!(s),
83+
CpuStorage::F64(s) => extract!(s),
84+
CpuStorage::F8E4M3(s) => extract!(s),
85+
// Dummy dtype variants store raw bytes
86+
CpuStorage::F6E2M3(s) | CpuStorage::F6E3M2(s) | CpuStorage::F4(s) | CpuStorage::F8E8M0(s) => {
87+
s[start..end].to_vec()
88+
}
89+
}
90+
}
91+
5992
impl RawTensor {
6093
/// Convert x into a RawTensor.
6194
pub fn from_tensor(x: &Tensor) -> Self {
62-
let data: Vec<u8> = x.data().into_owned();
6395
let dtype = dtype_to_u8(x.dtype());
6496
let shape = x.shape().dims().to_vec();
97+
// Fast path: CPU contiguous tensors — access storage directly.
98+
let data = if x.device().is_cpu() {
99+
if let Some((start, end)) = x.layout().contiguous_offsets() {
100+
let (storage, _) = x.storage_and_layout();
101+
if let candle_core::Storage::Cpu(cpu) = &*storage {
102+
cpu_storage_bytes_range(cpu, start, end)
103+
} else {
104+
x.data().into_owned()
105+
}
106+
} else {
107+
x.data().into_owned()
108+
}
109+
} else {
110+
x.data().into_owned()
111+
};
65112
Self { data, dtype, shape }
66113
}
67114

0 commit comments

Comments
 (0)