fix(rayon): remove mutexes in favor of fold for counters
authorMA Beaudet <ma@beaudet.xyz>
Sun, 14 Nov 2021 20:56:10 +0000 (21:56 +0100)
committerMA Beaudet <ma@beaudet.xyz>
Sun, 14 Nov 2021 20:56:10 +0000 (21:56 +0100)
src/lib.rs

index 28deb5c..4db01e0 100644 (file)
@@ -379,30 +379,40 @@ pub fn parallel_deck_freq_evaluator(deck: &[u32]) -> [u32; 10] {
 }
 
 /// Concurrent evaluation of all five-card poker hands using rayon crate.
-///
-/// This implementation is actually slower in release builds.
 #[cfg(feature = "rayon")]
 pub fn concurrent_deck_freq_evaluator(deck: &[u32]) -> [u32; 10] {
-    use rayon::prelude::*;
+    use std::sync::mpsc;
 
-    let freq: Mutex<[u32; 10]> = Mutex::new([0; 10]);
+    fn fold_counters(mut acc: [u32; 10], count: [u32; 10]) -> [u32; 10] {
+        count.iter().enumerate().for_each(|(k, v)| acc[k] += v);
+        acc
+    }
 
-    (0..48).into_par_iter().for_each(|a| {
-        for b in a + 1..49 {
-            for c in b + 1..50 {
-                for d in c + 1..51 {
-                    for e in d + 1..52 {
-                        let i = eval_5hand(&[deck[a], deck[b], deck[c], deck[d], deck[e]]);
-                        let j = hand_rank(i);
-                        let mut freq = freq.lock().unwrap();
-                        freq[j as usize] += 1;
+    let (tx, rx) = mpsc::channel();
+
+    rayon::scope(move |scope| {
+        for a in (0..48).into_iter() {
+            let tx = tx.clone();
+            scope.spawn(move |_| {
+                // let mut freq = HashMap::new();
+                let mut freq = [0; 10];
+                for b in a + 1..49 {
+                    for c in b + 1..50 {
+                        for d in c + 1..51 {
+                            for e in d + 1..52 {
+                                let i = eval_5hand(&[deck[a], deck[b], deck[c], deck[d], deck[e]]);
+                                let j = hand_rank(i);
+                                freq[j as usize] += 1;
+                                // *freq.entry(j).or_insert(0) += 1;
+                            }
+                        }
                     }
                 }
-            }
+                let _ = tx.send(freq);
+            });
         }
     });
-    let x = *freq.lock().unwrap();
-    x
+    rx.into_iter().fold([0; 10], fold_counters)
 }
 
 #[cfg(test)]