|
@@ -1,7 +1,6 @@
|
|
|
//! randomx example that mines a dummy header using multiple threads
|
|
//! randomx example that mines a dummy header using multiple threads
|
|
|
|
|
|
|
|
use std::{
|
|
use std::{
|
|
|
- collections::VecDeque,
|
|
|
|
|
sync::{
|
|
sync::{
|
|
|
atomic::{AtomicBool, AtomicU64, Ordering},
|
|
atomic::{AtomicBool, AtomicU64, Ordering},
|
|
|
Arc,
|
|
Arc,
|
|
@@ -85,25 +84,35 @@ fn multi_thread_mine(threads: usize, header: &mut Header, target: &BigUint, inpu
|
|
|
let cache = RandomXCache::new(flags, &input[..]).unwrap();
|
|
let cache = RandomXCache::new(flags, &input[..]).unwrap();
|
|
|
let dataset_item_count = RandomXDataset::count().unwrap();
|
|
let dataset_item_count = RandomXDataset::count().unwrap();
|
|
|
let dataset = RandomXDataset::new(flags, cache, dataset_item_count).unwrap();
|
|
let dataset = RandomXDataset::new(flags, cache, dataset_item_count).unwrap();
|
|
|
- let mut subsets = VecDeque::with_capacity(threads);
|
|
|
|
|
|
|
|
|
|
// Multithreaded dataset init
|
|
// Multithreaded dataset init
|
|
|
|
|
+ let mut handles = Vec::with_capacity(threads);
|
|
|
let threads_u32 = threads as u32;
|
|
let threads_u32 = threads as u32;
|
|
|
|
|
+ let per_thread = dataset_item_count / threads_u32;
|
|
|
|
|
+ let remainder = dataset_item_count % threads_u32;
|
|
|
for t in 0..threads_u32 {
|
|
for t in 0..threads_u32 {
|
|
|
- println!("Initializing RandomX dataset for thread #{t}...");
|
|
|
|
|
- let ds_start = Instant::now();
|
|
|
|
|
- let a = (dataset_item_count * t) / threads_u32;
|
|
|
|
|
- let b = (dataset_item_count * (t + 1)) / threads_u32;
|
|
|
|
|
- subsets.push_back(dataset.subset_init(a, b - a));
|
|
|
|
|
- println!(
|
|
|
|
|
- "Initialized RandomX dataset for thread #{t} in {:?}",
|
|
|
|
|
- ds_start.elapsed()
|
|
|
|
|
- );
|
|
|
|
|
|
|
+ let dataset = dataset.clone();
|
|
|
|
|
+ let start_item = t * per_thread;
|
|
|
|
|
+ let count = per_thread + if t == threads_u32 - 1 { remainder } else { 0 };
|
|
|
|
|
+ handles.push(thread::spawn(move || {
|
|
|
|
|
+ println!("Initializing RandomX dataset for thread #{t}...");
|
|
|
|
|
+ let ds_start = Instant::now();
|
|
|
|
|
+ dataset.init(start_item, count);
|
|
|
|
|
+ println!(
|
|
|
|
|
+ "Initialized RandomX dataset for thread #{t} in {:?}",
|
|
|
|
|
+ ds_start.elapsed()
|
|
|
|
|
+ );
|
|
|
|
|
+ }));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Wait for threads to finish setup
|
|
|
|
|
+ for handle in handles {
|
|
|
|
|
+ let _ = handle.join();
|
|
|
}
|
|
}
|
|
|
println!("Setup time: {:?}", setup_start.elapsed());
|
|
println!("Setup time: {:?}", setup_start.elapsed());
|
|
|
|
|
|
|
|
println!("Initializing mining threads...");
|
|
println!("Initializing mining threads...");
|
|
|
- let mut handles = Vec::with_capacity(threads);
|
|
|
|
|
|
|
+ handles = Vec::with_capacity(threads);
|
|
|
let found_header = Arc::new(AtomicBool::new(false));
|
|
let found_header = Arc::new(AtomicBool::new(false));
|
|
|
let found_nonce = Arc::new(AtomicU64::new(0));
|
|
let found_nonce = Arc::new(AtomicU64::new(0));
|
|
|
let threads_u64 = threads as u64;
|
|
let threads_u64 = threads as u64;
|
|
@@ -119,7 +128,7 @@ fn multi_thread_mine(threads: usize, header: &mut Header, target: &BigUint, inpu
|
|
|
thread_header.nonce = t;
|
|
thread_header.nonce = t;
|
|
|
let found_header = Arc::clone(&found_header);
|
|
let found_header = Arc::clone(&found_header);
|
|
|
let found_nonce = Arc::clone(&found_nonce);
|
|
let found_nonce = Arc::clone(&found_nonce);
|
|
|
- let dataset = subsets.pop_front().unwrap();
|
|
|
|
|
|
|
+ let dataset = dataset.clone();
|
|
|
|
|
|
|
|
handles.push(thread::spawn(move || {
|
|
handles.push(thread::spawn(move || {
|
|
|
println!("Initializing RandomX VM #{t}...");
|
|
println!("Initializing RandomX VM #{t}...");
|