1extern crate ocl;
2
3mod kernel;
4
5use ocl::{Platform, Device, ProQue, Buffer};
6use ocl::core;
7use ocl::core::{DeviceInfo};
8
9pub struct Context{
10 pub compute_units: u32,
11 pro_que: ocl::ProQue,
12}
13
14
15pub struct Matrix {
16 pub rows: usize,
17 pub cols: usize,
18 pub data: Vec<f32>,
19}
20
21impl Context {
22 pub fn mul_matrix_scalar(&mut self, matrix: &Matrix, scalar: f32) -> Matrix {
23 let ref mut ocl_pq = self.pro_que;
24
25 ocl_pq.set_dims([matrix.rows*matrix.cols]);
27
28 let source_buffer = Buffer::new(
30 &ocl_pq.queue().clone(),
31 Some(core::MEM_READ_WRITE | core::MEM_COPY_HOST_PTR),
32 ocl_pq.dims().clone(),
33 Some(&matrix.data)).unwrap();
34
35 let mut result = vec![0.0f32; matrix.cols*matrix.rows];
37 let result_buffer: Buffer<f32> = ocl_pq.create_buffer().unwrap();
38
39 let kernel = ocl_pq.create_kernel("mul_matrix_scalar").unwrap()
41 .arg_scl(scalar)
42 .arg_buf(&source_buffer)
43 .arg_buf(&result_buffer);
44
45 kernel.enq().unwrap(); result_buffer.read(&mut result).enq().unwrap();
50
51 Matrix{rows: matrix.rows,cols: matrix.cols, data: result}
53 }
54
55 pub fn mul_matrix_matrix(&mut self, matrix_a: &Matrix, matrix_b: &Matrix) -> Matrix {
56 let ref mut ocl_pq = self.pro_que;
57
58 ocl_pq.set_dims([matrix_a.rows,matrix_a.cols]);
60
61 let matrix_a_buffer = Buffer::new(
63 &ocl_pq.queue().clone(),
64 Some(core::MEM_READ_WRITE | core::MEM_COPY_HOST_PTR),
65 ocl_pq.dims().clone(),
66 Some(&matrix_a.data)).unwrap();
67
68 ocl_pq.set_dims([matrix_b.rows,matrix_b.cols]);
70 let matrix_b_buffer = Buffer::new(
72 &ocl_pq.queue().clone(),
73 Some(core::MEM_READ_WRITE | core::MEM_COPY_HOST_PTR),
74 ocl_pq.dims().clone(),
75 Some(&matrix_b.data)).unwrap();
76
77 ocl_pq.set_dims([matrix_a.rows,matrix_b.cols]);
79 let mut result = vec![0.0f32; matrix_a.rows*matrix_b.cols];
82 let result_buffer: Buffer<f32> = ocl_pq.create_buffer().unwrap();
83
84 let kernel = ocl_pq.create_kernel("mul_matrix_matrix").unwrap()
86 .arg_buf(&matrix_a_buffer)
87 .arg_buf(&matrix_b_buffer)
88 .arg_buf(&result_buffer)
89 .arg_scl(matrix_a.rows as i32)
90 .arg_scl(matrix_a.cols as i32)
91 .arg_scl(matrix_b.cols as i32);
92 kernel.enq().unwrap(); result_buffer.read(&mut result).enq().unwrap();
99
100 Matrix{rows: matrix_a.rows, cols: matrix_b.cols, data: result}
102 }
103}
104
105pub fn new() -> Option<Context> {
106 let mut compute_units = 0;
109 let mut ocl_device = None;
110 let platforms = Platform::list();
111 for p_idx in 0..platforms.len() {
112 let platform = &platforms[p_idx];
113 let devices = Device::list_all(platform);
114 for d_idx in 0..devices.len() {
115 let device = devices[d_idx];
116 let deviceinforesult = core::get_device_info(&device, DeviceInfo::MaxComputeUnits);
117 let units = deviceinforesult.to_string().parse().unwrap();
118 if units > compute_units {
119 ocl_device = Some(device);
120 compute_units = units;
121 }
122 }
123 }
124 if compute_units == 0 {
126 return None
127 }
128 let que = ProQue::builder()
129 .device(ocl_device.unwrap())
130 .src(kernel::OCL_KERNEL)
131 .build().expect("Build ProQue");
132 Some(Context{
133 compute_units: compute_units,
134 pro_que : que,
135 })
136}
137
138#[test]
139fn single_test() {
140 let eps = 1.0e-6;
141 let mut c = new().unwrap();
142 let m0 = Matrix{rows: 2, cols: 2, data: vec![1.0, 2.0, 3.0, 4.0]};
143 let m1 = Matrix{rows: 2, cols: 1, data: vec![4.0, 5.0]};
144
145 let m = c.mul_matrix_matrix(&m0,&m1);
149 assert!((m.data[0] - 14.0f32).abs() < eps);
150 assert!((m.data[1] - 32.0f32).abs() < eps);
151
152 let m = c.mul_matrix_scalar(&m0,1.5);
156 assert!( (m.data[0] - 1.5f32) < eps);
157 assert!( (m.data[1] - 3.0f32) < eps);
158 assert!( (m.data[2] - 4.5f32) < eps);
159 assert!( (m.data[3] - 6.0f32) < eps);
160}