Fully enable non-parallel mode
This commit is contained in:
parent
ca2eecf0c2
commit
418db71482
1 changed files with 38 additions and 12 deletions
|
|
@ -17,6 +17,7 @@ use rayon;
|
||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
use std::sync::atomic::AtomicUsize;
|
use std::sync::atomic::AtomicUsize;
|
||||||
use std::sync::atomic::Ordering::SeqCst;
|
use std::sync::atomic::Ordering::SeqCst;
|
||||||
|
#[cfg(feature = "parallel")]
|
||||||
use std::sync::mpsc::*;
|
use std::sync::mpsc::*;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::thread;
|
use std::thread;
|
||||||
|
|
@ -92,19 +93,27 @@ pub(crate) struct Evaluator {
|
||||||
nth: AtomicUsize,
|
nth: AtomicUsize,
|
||||||
best_candidate_size: Arc<AtomicMin>,
|
best_candidate_size: Arc<AtomicMin>,
|
||||||
/// images are sent to the thread for evaluation
|
/// images are sent to the thread for evaluation
|
||||||
|
#[cfg(feature = "parallel")]
|
||||||
eval_send: SyncSender<Candidate>,
|
eval_send: SyncSender<Candidate>,
|
||||||
// the thread helps evaluate images asynchronously
|
// the thread helps evaluate images asynchronously
|
||||||
|
#[cfg(feature = "parallel")]
|
||||||
eval_thread: thread::JoinHandle<Option<PngData>>,
|
eval_thread: thread::JoinHandle<Option<PngData>>,
|
||||||
|
// in non-parallel mode, images are evaluated synchronously
|
||||||
|
#[cfg(not(feature = "parallel"))]
|
||||||
|
eval_comparator: std::cell::RefCell<Comparator>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Evaluator {
|
impl Evaluator {
|
||||||
pub fn new(deadline: Arc<Deadline>) -> Self {
|
pub fn new(deadline: Arc<Deadline>) -> Self {
|
||||||
|
#[cfg(feature = "parallel")]
|
||||||
let (tx, rx) = sync_channel(4);
|
let (tx, rx) = sync_channel(4);
|
||||||
Self {
|
Self {
|
||||||
deadline,
|
deadline,
|
||||||
best_candidate_size: Arc::new(AtomicMin::new(None)),
|
best_candidate_size: Arc::new(AtomicMin::new(None)),
|
||||||
nth: AtomicUsize::new(0),
|
nth: AtomicUsize::new(0),
|
||||||
|
#[cfg(feature = "parallel")]
|
||||||
eval_send: tx,
|
eval_send: tx,
|
||||||
|
#[cfg(feature = "parallel")]
|
||||||
eval_thread: thread::spawn(move || {
|
eval_thread: thread::spawn(move || {
|
||||||
let mut comparator = Comparator::default();
|
let mut comparator = Comparator::default();
|
||||||
for candidate in rx {
|
for candidate in rx {
|
||||||
|
|
@ -112,16 +121,24 @@ impl Evaluator {
|
||||||
}
|
}
|
||||||
comparator.get_result()
|
comparator.get_result()
|
||||||
}),
|
}),
|
||||||
|
#[cfg(not(feature = "parallel"))]
|
||||||
|
eval_comparator: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Wait for all evaluations to finish and return smallest reduction
|
/// Wait for all evaluations to finish and return smallest reduction
|
||||||
/// Or `None` if all reductions were worse than baseline.
|
/// Or `None` if all reductions were worse than baseline.
|
||||||
|
#[cfg(feature = "parallel")]
|
||||||
pub fn get_result(self) -> Option<PngData> {
|
pub fn get_result(self) -> Option<PngData> {
|
||||||
drop(self.eval_send); // disconnect the sender, breaking the loop in the thread
|
drop(self.eval_send); // disconnect the sender, breaking the loop in the thread
|
||||||
self.eval_thread.join().expect("eval thread")
|
self.eval_thread.join().expect("eval thread")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "parallel"))]
|
||||||
|
pub fn get_result(self) -> Option<PngData> {
|
||||||
|
self.eval_comparator.into_inner().get_result()
|
||||||
|
}
|
||||||
|
|
||||||
/// Set baseline image. It will be used only to measure minimum compression level required
|
/// Set baseline image. It will be used only to measure minimum compression level required
|
||||||
pub fn set_baseline(&self, image: Arc<PngImage>) {
|
pub fn set_baseline(&self, image: Arc<PngImage>) {
|
||||||
self.try_image_inner(image, 1.0, false)
|
self.try_image_inner(image, 1.0, false)
|
||||||
|
|
@ -141,6 +158,7 @@ impl Evaluator {
|
||||||
let best_candidate_size = self.best_candidate_size.clone();
|
let best_candidate_size = self.best_candidate_size.clone();
|
||||||
// sends it off asynchronously for compression,
|
// sends it off asynchronously for compression,
|
||||||
// but results will be collected via the message queue
|
// but results will be collected via the message queue
|
||||||
|
#[cfg(feature = "parallel")]
|
||||||
let eval_send = self.eval_send.clone();
|
let eval_send = self.eval_send.clone();
|
||||||
rayon::spawn(move || {
|
rayon::spawn(move || {
|
||||||
let filters_iter = STD_FILTERS.par_iter().with_max_len(1);
|
let filters_iter = STD_FILTERS.par_iter().with_max_len(1);
|
||||||
|
|
@ -163,8 +181,7 @@ impl Evaluator {
|
||||||
) {
|
) {
|
||||||
best_candidate_size.set_min(idat_data.len());
|
best_candidate_size.set_min(idat_data.len());
|
||||||
// the rest is shipped to the evavluation/collection thread
|
// the rest is shipped to the evavluation/collection thread
|
||||||
eval_send
|
let new = Candidate {
|
||||||
.send(Candidate {
|
|
||||||
image: PngData {
|
image: PngData {
|
||||||
idat_data,
|
idat_data,
|
||||||
raw: Arc::clone(&image),
|
raw: Arc::clone(&image),
|
||||||
|
|
@ -173,8 +190,17 @@ impl Evaluator {
|
||||||
filter,
|
filter,
|
||||||
is_reduction,
|
is_reduction,
|
||||||
nth,
|
nth,
|
||||||
})
|
};
|
||||||
.expect("send");
|
|
||||||
|
#[cfg(feature = "parallel")]
|
||||||
|
{
|
||||||
|
eval_send.send(new).expect("send");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "parallel"))]
|
||||||
|
{
|
||||||
|
self.eval_comparator.borrow_mut().evaluate(new);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue