use opencl3::Result;
use opencl3::command_queue::{CL_QUEUE_PROFILING_ENABLE, CommandQueue};
use opencl3::context::Context;
use opencl3::device::{CL_DEVICE_TYPE_GPU, Device, get_all_devices};
use opencl3::kernel::{ExecuteKernel, Kernel};
use opencl3::memory::{Buffer, CL_MEM_READ_ONLY, CL_MEM_WRITE_ONLY};
use opencl3::program::Program;
use opencl3::types::{CL_BLOCKING, CL_NON_BLOCKING, cl_event, cl_float};
use std::ptr;
const PROGRAM_SOURCE: &str = r#"
kernel void saxpy_float (global float* z,
global float const* x,
global float const* y,
float a)
{
const size_t i = get_global_id(0);
z[i] = a*x[i] + y[i];
}"#;
const KERNEL_NAME: &str = "saxpy_float";
fn main() -> Result<()> {
let device_id = *get_all_devices(CL_DEVICE_TYPE_GPU)?
.first()
.expect("no device found in platform");
let device = Device::new(device_id);
let context = Context::from_device(&device).expect("Context::from_device failed");
let queue = CommandQueue::create_default(&context, CL_QUEUE_PROFILING_ENABLE)
.expect("CommandQueue::create_default failed");
let program = Program::create_and_build_from_source(&context, PROGRAM_SOURCE, "")
.expect("Program::create_and_build_from_source failed");
let kernel = Kernel::create(&program, KERNEL_NAME).expect("Kernel::create failed");
const ARRAY_SIZE: usize = 1000;
let ones: [cl_float; ARRAY_SIZE] = [1.0; ARRAY_SIZE];
let mut sums: [cl_float; ARRAY_SIZE] = [0.0; ARRAY_SIZE];
for i in 0..ARRAY_SIZE {
sums[i] = 1.0 + 1.0 * i as cl_float;
}
let mut x = unsafe {
Buffer::<cl_float>::create(&context, CL_MEM_READ_ONLY, ARRAY_SIZE, ptr::null_mut())?
};
let mut y = unsafe {
Buffer::<cl_float>::create(&context, CL_MEM_READ_ONLY, ARRAY_SIZE, ptr::null_mut())?
};
let z = unsafe {
Buffer::<cl_float>::create(&context, CL_MEM_WRITE_ONLY, ARRAY_SIZE, ptr::null_mut())?
};
let _x_write_event = unsafe { queue.enqueue_write_buffer(&mut x, CL_BLOCKING, 0, &ones, &[])? };
let y_write_event =
unsafe { queue.enqueue_write_buffer(&mut y, CL_NON_BLOCKING, 0, &sums, &[])? };
let a: cl_float = 300.0;
let kernel_event = unsafe {
ExecuteKernel::new(&kernel)
.set_arg(&z)
.set_arg(&x)
.set_arg(&y)
.set_arg(&a)
.set_global_work_size(ARRAY_SIZE)
.set_wait_event(&y_write_event)
.enqueue_nd_range(&queue)?
};
let mut events: Vec<cl_event> = Vec::default();
events.push(kernel_event.get());
let mut results: [cl_float; ARRAY_SIZE] = [0.0; ARRAY_SIZE];
let read_event =
unsafe { queue.enqueue_read_buffer(&z, CL_NON_BLOCKING, 0, &mut results, &events)? };
read_event.wait()?;
println!("results front: {}", results[0]);
println!("results back: {}", results[ARRAY_SIZE - 1]);
let start_time = kernel_event.profiling_command_start()?;
let end_time = kernel_event.profiling_command_end()?;
let duration = end_time - start_time;
println!("kernel execution duration (ns): {}", duration);
Ok(())
}