add/
add.rs

1use rust_gpu_tools::{cuda, opencl, program_closures, Device, GPUError, Program};
2
3/// Returns a `Program` that runs on CUDA.
4fn cuda(device: &Device) -> Program {
5    // The kernel was compiled with:
6    // nvcc -fatbin -gencode=arch=compute_52,code=sm_52 -gencode=arch=compute_60,code=sm_60 -gencode=arch=compute_61,code=sm_61 -gencode=arch=compute_70,code=sm_70 -gencode=arch=compute_75,code=sm_75 -gencode=arch=compute_75,code=compute_75 --x cu add.cl
7    let cuda_kernel = include_bytes!("./add.fatbin");
8    let cuda_device = device.cuda_device().unwrap();
9    let cuda_program = cuda::Program::from_bytes(cuda_device, cuda_kernel).unwrap();
10    Program::Cuda(cuda_program)
11}
12
13/// Returns a `Program` that runs on OpenCL.
14fn opencl(device: &Device) -> Program {
15    let opencl_kernel = include_str!("./add.cl");
16    let opencl_device = device.opencl_device().unwrap();
17    let opencl_program = opencl::Program::from_opencl(opencl_device, opencl_kernel).unwrap();
18    Program::Opencl(opencl_program)
19}
20
21pub fn main() {
22    // Define some data that should be operated on.
23    let aa: Vec<u32> = vec![1, 2, 3, 4];
24    let bb: Vec<u32> = vec![5, 6, 7, 8];
25
26    // This is the core. Here we write the interaction with the GPU independent of whether it is
27    // CUDA or OpenCL.
28    let closures = program_closures!(|program, _args| -> Result<Vec<u32>, GPUError> {
29        // Make sure the input data has the same length.
30        assert_eq!(aa.len(), bb.len());
31        let length = aa.len();
32
33        // Copy the data to the GPU.
34        let aa_buffer = program.create_buffer_from_slice(&aa)?;
35        let bb_buffer = program.create_buffer_from_slice(&bb)?;
36
37        // The result buffer has the same length as the input buffers.
38        let result_buffer = unsafe { program.create_buffer::<u32>(length)? };
39
40        // Get the kernel.
41        let kernel = program.create_kernel("add", 1, 1)?;
42
43        // Execute the kernel.
44        kernel
45            .arg(&(length as u32))
46            .arg(&aa_buffer)
47            .arg(&bb_buffer)
48            .arg(&result_buffer)
49            .run()?;
50
51        // Get the resulting data.
52        let mut result = vec![0u32; length];
53        program.read_into_buffer(&result_buffer, &mut result)?;
54
55        Ok(result)
56    });
57
58    // Get the first available device.
59    let device = *Device::all().first().unwrap();
60
61    // First we run it on CUDA.
62    let cuda_program = cuda(device);
63    let cuda_result = cuda_program.run(closures, ()).unwrap();
64    assert_eq!(cuda_result, [6, 8, 10, 12]);
65    println!("CUDA result: {:?}", cuda_result);
66
67    // Then we run it on OpenCL.
68    let opencl_program = opencl(device);
69    let opencl_result = opencl_program.run(closures, ()).unwrap();
70    assert_eq!(opencl_result, [6, 8, 10, 12]);
71    println!("OpenCL result: {:?}", opencl_result);
72}