瀏覽代碼

Commented code. Added test. Corrected loop count.

themultiplexer 7 年之前
父節點
當前提交
d5c58392a8
共有 3 個檔案被更改,包括 126 行新增64 行删除
  1. 96
    49
      hw8/task1/src/lib.rs
  2. 6
    7
      hw8/task1/src/main.rs
  3. 24
    8
      hw8/task1/src/tests/mod.rs

+ 96
- 49
hw8/task1/src/lib.rs 查看文件

@@ -105,12 +105,16 @@ impl HashResult for [u8; 32] {
105 105
     }
106 106
 }
107 107
 
108
-#[derive(Debug,PartialEq)]
108
+#[derive(Debug, PartialEq)]
109 109
 pub struct Solution {
110 110
     pub number: usize,
111 111
     pub hash: String,
112 112
 }
113 113
 
114
+/// Überprüft ob *base* und *number* auf einen Hash abbilden,
115
+/// der mit der übergebenen *difficulty* übereinstimmt.
116
+/// Falls ja, kommt eine `Solution` in der Option mit den Ergebnissen zurück.
117
+/// Falls nein, steht None im Optional
114 118
 pub fn verify_product(base: usize, number: usize, difficulty: &String) -> Option<Solution> {
115 119
     let sol = base * number;
116 120
     let input = sol.to_string();
@@ -128,11 +132,67 @@ pub fn verify_product(base: usize, number: usize, difficulty: &String) -> Option
128 132
     None
129 133
 }
130 134
 
135
+/// Sucht nach einem Hash für die angegebene Basis und die Schwierigkeit.
136
+/// Wenn `total` > 1 ist, dann hat jeder Aufruf mit einem anderen `start`-Wert (von 0 - total)
137
+/// eine disjunkte Zahlenmenge für die Suche zur Auswahl.
138
+fn search_hash(
139
+    hash: &String,
140
+    base: usize,
141
+    start: usize,
142
+    total: usize,
143
+    sync: bool,
144
+    found: Arc<AtomicBool>,
145
+    special: usize,
146
+    solution_tx: Sender<Solution>,
147
+    timing_tx: Sender<(Duration, usize)>,
148
+    measure: bool,
149
+) {
150
+    let max = <usize>::max_value();
151
+    let mut n = start;
152
+
153
+    let thread_start = get_time();
154
+    while n < max {
155
+
156
+        // Der special Parameter begrenzt die Anzahl der load()-Aufrufe auf jeden n.ten Loop.
157
+        if n % special == 0 && found.load(Relaxed) {
158
+            // Anderer Thread hat eine Lösung gefunden (sync ist aktiviert). Beende Suche.
159
+            break;
160
+        }
161
+
162
+        if let Some(solution) = verify_product(base, n, hash) {
163
+            if sync {
164
+                found.store(true, Relaxed);
165
+            }
166
+            // Sende gefundene Solution an den Consumer.
167
+            let _ = solution_tx.send(solution);
168
+            // Beende Suche.
169
+            break;
170
+        }
171
+        n += total;
172
+    }
173
+
174
+    // Falls measure aktiviert ist Sende Zeitdauer und Anzahl Loops an den Consumer.
175
+    if measure {
176
+        let thread_end = get_time();
177
+        let _ = timing_tx.send((thread_end - thread_start, (n / total)));
178
+    }
179
+}
180
+
181
+/// Teilt, wenn nötig, die Suche nach dem Hash auf mehrere Threads auf.
182
+/// Gibt ggf. die Solution (für die Tests) zurück.
183
+pub fn search_with_threads(
184
+    threads: usize,
185
+    diff_string: String,
186
+    with_base: usize,
187
+    time_measurement: bool,
188
+    verbosity: u64,
189
+    sync: Option<usize>,
190
+    wait: bool,
191
+) -> Option<Solution> {
131 192
 
132
-pub fn search_with_threads(threads:usize, diff_string:String, with_base:usize, time_measurement:bool, verbosity:u64, sync:Option<usize>, wait:bool){
133
-    let total_start = get_time();
134 193
     let diff = Arc::new(diff_string);
135 194
     let mut children = vec![];
195
+    let mut solution = None;
136 196
 
137 197
     let (solution_tx, solution_rx) = channel();
138 198
     let (timing_tx, timing_rx) = channel();
@@ -140,8 +200,15 @@ pub fn search_with_threads(threads:usize, diff_string:String, with_base:usize, t
140 200
     let found = Arc::new(AtomicBool::new(false));
141 201
     let m = time_measurement && verbosity > 0;
142 202
 
203
+    let total_start = get_time();
143 204
     if threads > 1 {
144 205
 
206
+        if verbosity > 0 {
207
+            println!("Searching with {} threads", threads);
208
+        }
209
+
210
+        // Erstellt Anzahl angeforderter Threads.
211
+        // Klont für jeden Thread die Referenz auf die gemeinsamen Variablen.
145 212
         for i in 0..threads {
146 213
             let diff = diff.clone();
147 214
             let solution_tx = solution_tx.clone();
@@ -150,6 +217,7 @@ pub fn search_with_threads(threads:usize, diff_string:String, with_base:usize, t
150 217
 
151 218
             children.push(thread::spawn(move || {
152 219
 
220
+                // Suche in jedem der Threads.
153 221
                 search_hash(
154 222
                     &diff,
155 223
                     with_base,
@@ -161,10 +229,15 @@ pub fn search_with_threads(threads:usize, diff_string:String, with_base:usize, t
161 229
                     solution_tx,
162 230
                     timing_tx,
163 231
                     m,
164
-                )
232
+                );
233
+
234
+                if verbosity > 1 {
235
+                    println!("[DEBUG] Thread {} exited", i);
236
+                }
165 237
             }));
166 238
         }
167 239
     } else {
240
+        // Suche auf dem Main-Thread.
168 241
         search_hash(
169 242
             &diff,
170 243
             with_base,
@@ -176,11 +249,20 @@ pub fn search_with_threads(threads:usize, diff_string:String, with_base:usize, t
176 249
             solution_tx,
177 250
             timing_tx,
178 251
             m,
179
-        )
252
+        );
253
+
254
+        if verbosity > 1 {
255
+            println!("[DEBUG] Finished search on main thread.");
256
+        }
180 257
     }
181 258
 
259
+    // Empfängt die Lösung von einem der Producer.
182 260
     match solution_rx.recv() {
183 261
         Ok(sol) => {
262
+            solution = Some(Solution {
263
+                number: sol.number,
264
+                hash: sol.hash.clone(),
265
+            });
184 266
             let total_end = get_time();
185 267
             println!("Number: {} --> hash: {}", sol.number, sol.hash);
186 268
             if time_measurement && verbosity == 0 {
@@ -200,20 +282,21 @@ pub fn search_with_threads(threads:usize, diff_string:String, with_base:usize, t
200 282
     for child in children {
201 283
 
202 284
         if time_measurement && verbosity > 0 {
203
-            match timing_rx.recv() {
204
-                Ok(stats) => {
205
-                    sum_time = sum_time + stats.0;
206
-                    sum_loops += stats.1;
207
-                }
208
-                Err(_) => {}
285
+            // Warte auf Zeitstatistik-Nachricht von jedem Thread auf dem zweiten MPSC Channel.
286
+            if let Ok(stats) = timing_rx.recv() {
287
+                // Addiere Werte dieses threads zu der Summe.
288
+                sum_time = sum_time + stats.0;
289
+                sum_loops += stats.1;
209 290
             }
210 291
         }
211 292
 
293
+        // Falls *wait* wahr ist, warte auf aktuellen thread (child)
212 294
         if wait {
213 295
             let _ = child.join();
214 296
         }
215 297
     }
216 298
 
299
+    // Gebe die Gesamtergebnisse der Threads aus.
217 300
     if time_measurement && verbosity > 0 {
218 301
         println!("Sum Loops in Producers:       {}", sum_loops);
219 302
         let s = sum_time.num_seconds();
@@ -221,43 +304,7 @@ pub fn search_with_threads(threads:usize, diff_string:String, with_base:usize, t
221 304
         let us = sum_time.num_microseconds().unwrap_or(ms * 1000);
222 305
         println!("Sum Duration in Producers:    {}s / {}ms / {}us", s, ms, us);
223 306
     }
224
-}
225
-
226
-fn search_hash(
227
-    hash: &String,
228
-    base: usize,
229
-    current: usize,
230
-    total: usize,
231
-    sync: bool,
232
-    found: Arc<AtomicBool>,
233
-    special: usize,
234
-    solution_tx: Sender<Solution>,
235
-    timing_tx: Sender<(Duration, usize)>,
236
-    measure: bool,
237
-) {
238
-    let max = <usize>::max_value();
239
-    let mut n = current;
240 307
 
241
-    let thread_start = get_time();
242
-    while n < max {
243
-
244
-        if n % special == 0 && found.load(Relaxed) {
245
-            break;
246
-        }
247
-
248
-        if let Some(solution) = verify_product(base, n, hash) {
249
-            if sync {
250
-                found.store(true, Relaxed);
251
-            }
252
-
253
-            let _ = solution_tx.send(solution);
254
-            break;
255
-        }
256
-        n += total;
257
-    }
258
-
259
-    if measure {
260
-        let thread_end = get_time();
261
-        let _ = timing_tx.send((thread_end - thread_start, n));
262
-    }
308
+    // Gebe die Option einer Solution zurück.
309
+    solution
263 310
 }

+ 6
- 7
hw8/task1/src/main.rs 查看文件

@@ -20,7 +20,11 @@ pub fn main() {
20 20
     let cpus = sys_info::cpu_num().unwrap_or(1).to_string();
21 21
     let threads = matches.value_of("threads").unwrap_or(&cpus);
22 22
     let sync = matches.is_present("sync");
23
-    let special = matches.value_of("special").unwrap_or("1").parse::<usize>().unwrap_or(1);
23
+    let special = matches
24
+        .value_of("special")
25
+        .unwrap_or("1")
26
+        .parse::<usize>()
27
+        .unwrap_or(1);
24 28
     let wait = matches.is_present("wait");
25 29
     let verbosity = matches.occurrences_of("verbose");
26 30
 
@@ -60,16 +64,12 @@ pub fn main() {
60 64
         (Ok(b), Ok(t)) => {
61 65
             println!("Please wait...");
62 66
 
63
-            if verbosity > 0 {
64
-                println!("Searching with {} threads", t);
65
-            }
66
-
67 67
             let mut sync_opt = None;
68 68
             if sync {
69 69
                 sync_opt = Some(special);
70 70
             }
71 71
 
72
-            search_with_threads(t,diff,b,time, verbosity,sync_opt,wait);
72
+            let _ = search_with_threads(t, diff, b, time, verbosity, sync_opt, wait);
73 73
 
74 74
         }
75 75
         (_, Err(_)) => {
@@ -82,4 +82,3 @@ pub fn main() {
82 82
         }
83 83
     };
84 84
 }
85
-

+ 24
- 8
hw8/task1/src/tests/mod.rs 查看文件

@@ -1,24 +1,40 @@
1 1
 #[cfg(test)]
2 2
 mod tests {
3
-    use *;
3
+    use ::*;
4
+
4 5
 
5 6
     #[test]
6
-    fn test_correct_diff() {
7
-        let hash = String::from("b6bea2a40ed1bd6d9999b2232072092f3df0e02c4b507aa3ad947367b9712345");
7
+    fn test_multithreaded_search() {
8 8
         assert_eq!(
9
-            verify_product(42,567621, &String::from("12345")),
10
-            Some(Solution{number:567621, hash:hash})
9
+            search_with_threads(4, String::from("12345"), 42, false, 0, None, false),
10
+            Some(Solution {
11
+                number: 567621,
12
+                hash: String::from(
13
+                    "b6bea2a40ed1bd6d9999b2232072092f3df0e02c4b507aa3ad947367b9712345",
14
+                ),
15
+            })
11 16
         )
12 17
     }
13 18
 
14 19
     #[test]
15
-    fn test_wrong_diff() {
20
+    fn test_correct_diff() {
21
+        let hash = String::from(
22
+            "b6bea2a40ed1bd6d9999b2232072092f3df0e02c4b507aa3ad947367b9712345",
23
+        );
16 24
         assert_eq!(
17
-            verify_product(42,13253224, &String::from("12345")),
18
-            None
25
+            verify_product(42, 567621, &String::from("12345")),
26
+            Some(Solution {
27
+                number: 567621,
28
+                hash: hash,
29
+            })
19 30
         )
20 31
     }
21 32
 
33
+    #[test]
34
+    fn test_wrong_diff() {
35
+        assert_eq!(verify_product(42, 13253224, &String::from("12345")), None)
36
+    }
37
+
22 38
     #[test]
23 39
     fn test_hashing() {
24 40
         assert_eq!(

Loading…
取消
儲存