summaryrefslogtreecommitdiff
path: root/src/solvers/gpu/manager.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/solvers/gpu/manager.rs')
-rw-r--r--src/solvers/gpu/manager.rs104
1 files changed, 104 insertions, 0 deletions
diff --git a/src/solvers/gpu/manager.rs b/src/solvers/gpu/manager.rs
new file mode 100644
index 0000000..1dd6a4d
--- /dev/null
+++ b/src/solvers/gpu/manager.rs
@@ -0,0 +1,104 @@
+use std::sync::mpsc::{Receiver, Sender, channel};
+use std::thread::JoinHandle;
+use super::*;
+
+#[derive(Debug)]
+struct RequestBuffer {
+ mask_buff: Vec<u64>,
+ pointer: usize,
+}
+
+impl RequestBuffer {
+ pub fn new(size: usize) -> Self {
+ RequestBuffer {
+ mask_buff: vec![0; size],
+ pointer: 0,
+ }
+ }
+ pub fn read(&mut self, request: CheckRequest) -> Option<&[u64]> {
+ self.mask_buff[self.pointer] = request.bitmask;
+ self.pointer += 1;
+ if self.pointer == self.mask_buff.len() {
+ self.pointer = 0;
+ return Some(self.mask_buff.as_ref());
+ }
+ None
+ }
+}
+
+pub struct OclManager {
+ job_id: u64,
+ host_sender: Sender<Message>,
+ output_sender: Sender<Message>,
+ reciever: Receiver<Message>,
+ buffers: Vec<RequestBuffer>,
+ output_handle: JoinHandle<String>,
+ host_handle: JoinHandle<String>,
+}
+
+impl OclManager {
+ pub fn launch_sevice(
+ permutations: &[&[u32]],
+ permutations_mask: &[u64],
+ n: u32,
+ // Workgroup size, set to 0 for max
+ wg_size: u32,
+ ) -> (Sender<Message>, JoinHandle<String>) {
+ let (h, w) = crate::solvers::wall_stats(n);
+ let src = include_str!("check.cl");
+ let (output_sender, output_handle) =
+ super::output::Output::launch_sevice(permutations, permutations_mask, n, h, w);
+ let (host_sender, host_handle) =
+ super::host::Host::launch_sevice(permutations_mask, n, h, w, wg_size as usize, src);
+
+ let (receiver, sender) = channel();
+
+ let mut buffers = Vec::with_capacity((n - h + 1) as usize);
+ for _ in 0..=(n - h) {
+ buffers.push(RequestBuffer::new(wg_size as usize));
+ }
+
+ let manager = Self {
+ 0,
+ host_sender,
+ output_sender,
+ receiver,
+ buffers,
+ output_handle,
+ host_handle,
+ }
+ (sender,
+ std::thread::Builder::new()
+ .name("GPU Manager Deamon".into())
+ .spawn(move || {
+ manager.run();
+ })
+ .unwrap())
+
+ }
+
+ fn run(mut self) {
+ loop {
+ match self.reciever.recv().expect("Channel to GPU Manager broke") {
+ Message::CheckRequest(request) => {
+ if let Some(buffer) = self.buffers[request.queue as usize].read(request) {
+ self.host_sender
+ .send(Message::HostMessage((self.job_id, buffer.0.into())));
+ self.output_sender
+ .send(Message::OutputMessage((self.job_id, buffer.1.into())));
+ self.job_id += 1;
+ }
+ }
+ Message::Terminate => {
+ panic!("flush buffers");
+ self.host_sender.send(Message::Terminate);
+ self.host_handle.join();
+ self.output_sender.send(Message::Terminate);
+ self.output_handle.join();
+ return;
+ }
+ _ => println!("Invalid MessageType"),
+ }
+ }
+ }
+}