Skip to content

Conversation

@ahadnagy
Copy link

@ahadnagy ahadnagy commented Nov 27, 2025

This PR adds support for pinned-memory backed tensors. Since the custom allocator trait is not stable in Rust yet (and I don't see that happening soon), this PR uses polyfill libraries to stay on the stable release. If there's a better approach, I'm all ears. :)

All of this is gated behind the pinned-memory feature which also enables cuda due to its nature.

@ahadnagy ahadnagy marked this pull request as draft November 27, 2025 13:45
@ahadnagy ahadnagy changed the title WIP: Pinned memory [WIP] Pinned memory Nov 27, 2025
Copy link
Member

@ivarflakstad ivarflakstad left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This review was performed with a fever. The author takes no responsibility for its quality nor relevance.

Comment on lines 14 to 19
// Conditionally use polyfill Vec when pinned-memory feature is enabled
#[cfg(not(feature = "pinned-memory"))]
use std::vec::Vec;

#[cfg(feature = "pinned-memory")]
use allocator_api2::vec::Vec;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we perhaps move this to a candle_core/src/vec module, where based on the feature flag we import either the std or allocator_api2 impl?

Comment on lines 40 to 46
macro_rules! storage_vec {
($val:expr; $len:expr) => {{
let mut v = Vec::with_capacity($len);
v.resize($len, $val);
v
}};
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Kind of a nit but I'd like for this to support the same branches as the original macro.
So something like

Suggested change
macro_rules! storage_vec {
($val:expr; $len:expr) => {{
let mut v = Vec::with_capacity($len);
v.resize($len, $val);
v
}};
}
#[cfg(feature = "pinned-memory")]
pub use allocator_api2::vec as storage_vec;
#[cfg(not(feature = "pinned-memory")]
pub use std::vec as storage_vec;

//! The `pinned-memory` feature automatically enables `cuda` (see Cargo.toml), so checking
//! for `pinned-memory` is sufficient.
#[cfg(feature = "pinned-memory")]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we need all these as the entire file is behind the feature flag

.device
.memcpy_dtov(&self.data.inner.slice(..self.data.len))?;
let mut out = vec![0.0; elem_count];
let mut out_std: std::vec::Vec<f32> = (0..elem_count).map(|_| 0.0).collect();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you're specifically using std::vec::Vec then I don't see why you can't simply use good ol' vec!

Comment on lines 52 to 53
# pinned-memory requires cuda because it uses CUDA APIs for pinned host memory allocation
pinned-memory = ["cuda", "dep:allocator-api2"]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clearly documented here, but when running across the feature flag in the wild it could be confusing as pinning memory is not a cuda specific concept.
Could we rename to cuda-pinned-memory. Perhaps cuda-pin-mem if you think it's getting tedious to read/write.

We may find uses for pinned memory in other contexts in the future, in which case I think we're approaching a structure like

pinned-memory = ["dep:allocator-api2"]
cuda-pin-mem = ["cuda", "pinned-memory"]
xxx-pin-mem = ["xxx", "pinned-memory"]

Where pinned-memory would surface a generic API and *-pin-mem would enable the backend specific implementations taking advantage of it.

@ahadnagy ahadnagy marked this pull request as ready for review November 28, 2025 22:46
@ahadnagy ahadnagy requested a review from ivarflakstad December 3, 2025 19:18
@ahadnagy ahadnagy changed the title [WIP] Pinned memory Pinned memory Dec 8, 2025
@ivarflakstad
Copy link
Member

Officially alive again. Yay.

I think that covering every usage of Vec with the feature toggled StorageVec is kind of suboptimal. I think it would be better if we only create pinned memory where we need it.
I see how that could be difficult if you want CpuStorage to be backed by pinned memory, but when do you actually need that?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants