Repository navigation
Conversation
|
Tested out zeros loading to GPU memory using Program for anyone to test :) use candle_core::{Device, Tensor};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let device = Device::new_rocm(0)?;
println!("Device discovered: {:?}", device);
let size = 100000000usize;
for i in 0..1000000 {
let a = Tensor::zeros(size, candle_core::DType::F32, &device)?;
println!("{a}");
drop(a);
println!("[{i}] dropped tensor");
// std::thread::sleep(std::time::Duration::from_secs(2));
}
Ok(())
} |
|
Alrighty so the example code for candle-core from README.md does work now with Code for reference that was used. use candle_core::{Device, Tensor};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let device = Device::new_rocm(0)?;
println!("Device discovered: {:?}", device);
let a = Tensor::randn(0f32, 1., (2, 3), &device)?;
let b = Tensor::randn(0f32, 1., (3, 4), &device)?;
let c = a.matmul(&b)?;
println!("{c}");
Ok(())
}This is great news :) Next steps: |
|
Current situation: Need to implement ROCm kernels for running mathematical operations like Sigmoid etc. Cuda kernels are using JIT for which functionality is present in cudarc and nvcc but runtime compilation isn't available in hipcc but inside of hiprtc for which rocm-rs doesn't have the bindings/functionality available Implementing AOT (Ahead of Time) compilation instead so initial compilation time would be very slow cause you will have to compile the kernels, but it would be optimized for your GPU's architecture :D Sounds like a good idea. Open to suggestions |
|
Candle-nn now trains a primitive nn (linear layer) through using ROCm use candle_core::{DType, Device, Result, Tensor};
use candle_nn::{Linear, Module, Optimizer, VarBuilder, VarMap, SGD};
fn main() -> Result<()> {
let device = Device::new_rocm(0)?;
println!("Device: {:?}", device);
let n_samples = 1000;
let input_dim = 10;
let output_dim = 1;
let x = Tensor::randn(0f32, 1., (n_samples, input_dim), &device)?;
let true_weight = Tensor::randn(0f32, 1., (output_dim, input_dim), &device)?;
let true_bias = Tensor::randn(0f32, 1., output_dim, &device)?;
let noise = Tensor::randn(0f32, 0.1, (n_samples, output_dim), &device)?;
let y = x
.matmul(&true_weight.t()?)?
.broadcast_add(&true_bias)?
.add(&noise)?;
let varmap = VarMap::new();
let vs = VarBuilder::from_varmap(&varmap, DType::F32, &device);
let linear = Linear::new(
vs.get((output_dim, input_dim), "weight")?,
Some(vs.get(output_dim, "bias")?),
);
let learning_rate = 0.01;
let mut sgd = SGD::new(varmap.all_vars(), learning_rate)?;
let n_epochs = 100;
for epoch in 1..=n_epochs {
let preds = linear.forward(&x)?;
let diff = preds.sub(&y)?;
let loss = diff.sqr()?.mean_all()?;
sgd.backward_step(&loss)?;
if epoch % 10 == 0 {
let loss_val = loss.to_vec0::<f32>()?;
println!("Epoch {}: loss = {:.6}", epoch, loss_val);
}
}
println!("\nTraining completed!");
let final_preds = linear.forward(&x)?;
let final_loss = final_preds.sub(&y)?.sqr()?.mean_all()?.to_vec0::<f32>()?;
println!("Final loss: {:.6}", final_loss);
Ok(())
} |
Still drafting, squash commits
small step, but big milestone. Still drafting, squash commits
Still drafting, squash commits
Still drafting, squash commits
Still drafting, squash commits. It creates as f64/f32 and then casts it as f16 if that's the dtype, hence the TODO
Still drafting, squash commits. implementation is not KISS though
… use the same function
…ate candle-core to use candle-rocm-kernels new API
…nn ops (sigmoid, softmax, rmsnorm, layernorm) for ROCm backend
|
another force push cause I forgot to sync things in my main branch |
…/mod.rs to reduce duplication of kernel launch calls to just a function call for launch_kernel
|
alot of things are still unsafe and not implemented but slowly can be done over time. Bert works atleast which was one of the milestones. |
|
confirming that I got this working on a strix halo (gfx1151) on debian 13 with a few fixes:
built with: small test program: // main.rs
use candle_core::{Device, Tensor};
fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("attempting to create ROCm device...");
let device = Device::new_rocm(0)?;
println!("device: {:?}", device);
let a = Tensor::randn(0f32, 1., (2, 3), &device)?;
println!("random tensor on GPU: {}", a);
let b = Tensor::randn(0f32, 1., (2, 3), &device)?;
let c = (&a + &b)?;
println!("a + b = {}", c);
let d = Tensor::randn(0f32, 1., (2, 4), &device)?;
let e = Tensor::randn(0f32, 1., (4, 3), &device)?;
let f = d.matmul(&e)?;
println!("matmul result: {}", f);
println!("all tests passed!");
Ok(())
}run with: output: machine specs: I'd love to see this pushed forward, happy to help in any way! |
|
**Confirming ROCm support works on RDNA 4 (RX 9070 XT) 🎉 Hardware / OS:
Build adjustments needed:
Build command: cargo build -p candle-core --features rocmcargo run --example bert --features rocm
...
score: 0.06 'The new movie is awesome' 'The cat plays in the garden'
score: 0.04 'The cat plays in the garden' 'A woman watches TV'
score: 0.04 'The cat sits outside' 'The cat plays in the garden'
score: 0.03 'I love pasta' 'The new movie is awesome'
score: 0.02 'A man is playing guitar' 'I love pasta'Great work — excited to see ROCm support land in Candle! |
The backend began as airpods69's huggingface#3424, which chose rocm-rs for the bindings, added the rocm feature and its wiring through Device, Storage and the backend traits, shaped rocm_backend as a mirror of cuda_backend, and got a device, allocator, RNG and matmul working. Its open checklist -- convolutions, training a model, and making the API make sense -- is what this work continued, on the same gfx1101 architecture one ROCm major version newer. Records that lineage in both READMEs, including the one place the two diverge: huggingface#3424 hand-wrote the HIP kernels where this compiles the shared CUDA sources.
|
I hope I have finished your PR in #3801. |
|
@xmiksay thanks for taking care of it! Its fine if we lose my authorship :) I don't mind as long as candle gets AMD support |
The backend began as airpods69's huggingface#3424, which chose rocm-rs for the bindings, added the rocm feature and its wiring through Device, Storage and the backend traits, shaped rocm_backend as a mirror of cuda_backend, and got a device, allocator, RNG and matmul working. Its open checklist -- convolutions, training a model, and making the API make sense -- is what this work continued, on the same gfx1101 architecture one ROCm major version newer. Records that lineage in both READMEs, including the one place the two diverge: huggingface#3424 hand-wrote the HIP kernels where this compiles the shared CUDA sources.
The backend began as airpods69's huggingface#3424, which chose rocm-rs for the bindings, added the rocm feature and its wiring through Device, Storage and the backend traits, shaped rocm_backend as a mirror of cuda_backend, and got a device, allocator, RNG and matmul working. Its open checklist -- convolutions, training a model, and making the API make sense -- is what this work continued, on the same gfx1101 architecture one ROCm major version newer. Records that lineage in both READMEs, including the one place the two diverge: huggingface#3424 hand-wrote the HIP kernels where this compiles the shared CUDA sources.
The backend began as airpods69's huggingface#3424, which chose rocm-rs for the bindings, added the rocm feature and its wiring through Device, Storage and the backend traits, shaped rocm_backend as a mirror of cuda_backend, and got a device, allocator, RNG and matmul working. Its open checklist -- convolutions, training a model, and making the API make sense -- is what this work continued, on the same gfx1101 architecture one ROCm major version newer. Records that lineage in both READMEs, including the one place the two diverge: huggingface#3424 hand-wrote the HIP kernels where this compiles the shared CUDA sources.
The backend began as airpods69's huggingface#3424, which chose rocm-rs for the bindings, added the rocm feature and its wiring through Device, Storage and the backend traits, shaped rocm_backend as a mirror of cuda_backend, and got a device, allocator, RNG and matmul working. Its open checklist -- convolutions, training a model, and making the API make sense -- is what this work continued, on the same gfx1101 architecture one ROCm major version newer. Records that lineage in both READMEs, including the one place the two diverge: huggingface#3424 hand-wrote the HIP kernels where this compiles the shared CUDA sources.
The backend began as airpods69's huggingface#3424, which chose rocm-rs for the bindings, added the rocm feature and its wiring through Device, Storage and the backend traits, shaped rocm_backend as a mirror of cuda_backend, and got a device, allocator, RNG and matmul working. Its open checklist -- convolutions, training a model, and making the API make sense -- is what this work continued, on the same gfx1101 architecture one ROCm major version newer. Records that lineage in both READMEs, including the one place the two diverge: huggingface#3424 hand-wrote the HIP kernels where this compiles the shared CUDA sources.
The backend began as airpods69's huggingface#3424, which chose rocm-rs for the bindings, added the rocm feature and its wiring through Device, Storage and the backend traits, shaped rocm_backend as a mirror of cuda_backend, and got a device, allocator, RNG and matmul working. Its open checklist -- convolutions, training a model, and making the API make sense -- is what this work continued, on the same gfx1101 architecture one ROCm major version newer. Records that lineage in both READMEs, including the one place the two diverge: huggingface#3424 hand-wrote the HIP kernels where this compiles the shared CUDA sources.

The lack of ROCm support has been taken up in candle for a while now
Earlier there was a PR raised #3186 which was a completely AI generated pull request and was meant to be shut down anyways.
Since then there was no follow up but in the issue #3327 so I thought it would be nice to begin with the implementation.
This is still an initial draft but would love to get reviews on the code structure and all.
The current code is AI generated (guided by me for each small thing though) and definitely needs alot of clean up and fixing, most of the structure has been kept similar to that of
cuda_backend.rocm-rswas chosen as the crate for ROCm bindings due to the recent activity and tested that it does compile the example GPU kernel on my GPU.Fedora has
6.4.2that's why I used that, would love to test this out for7.1.0as well if someone can get me access to that machineSpecs for current test machine:
OS: Fedora Linux 43 (KDE Plasma Desktop Edition) x86_64
Kernel: Linux 6.19.8-200.fc43.x86_64
CPU: AMD Ryzen 7 7700X (16) @ 5.58 GHz
GPU: AMD Radeon RX 7700 XT (Discrete, gfx1101), AMD Raphael (Integrated)
ROCM: 6.4.2
Current status:
Discovering GPU works for now and we can successfully discover the GPU present.
Next steps: