Use thread pools for rayon par_iter (#4473)
* Use thread pools for rayon par_iter * address review comments * cleanup
This commit is contained in:
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -2629,6 +2629,7 @@ dependencies = [
|
|||||||
"solana-storage-program 0.16.0",
|
"solana-storage-program 0.16.0",
|
||||||
"solana-vote-api 0.16.0",
|
"solana-vote-api 0.16.0",
|
||||||
"solana-vote-program 0.16.0",
|
"solana-vote-program 0.16.0",
|
||||||
|
"sys-info 0.5.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -3,6 +3,7 @@ use crate::blocktree::Blocktree;
|
|||||||
use crate::entry::{Entry, EntrySlice};
|
use crate::entry::{Entry, EntrySlice};
|
||||||
use crate::leader_schedule_cache::LeaderScheduleCache;
|
use crate::leader_schedule_cache::LeaderScheduleCache;
|
||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
|
use rayon::ThreadPool;
|
||||||
use solana_metrics::{datapoint, datapoint_error, inc_new_counter_debug};
|
use solana_metrics::{datapoint, datapoint_error, inc_new_counter_debug};
|
||||||
use solana_runtime::bank::Bank;
|
use solana_runtime::bank::Bank;
|
||||||
use solana_runtime::locked_accounts_results::LockedAccountsResults;
|
use solana_runtime::locked_accounts_results::LockedAccountsResults;
|
||||||
@ -15,6 +16,14 @@ use std::result;
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
|
|
||||||
|
pub const NUM_THREADS: u32 = 10;
|
||||||
|
use std::cell::RefCell;
|
||||||
|
|
||||||
|
thread_local!(static PAR_THREAD_POOL: RefCell<ThreadPool> = RefCell::new(rayon::ThreadPoolBuilder::new()
|
||||||
|
.num_threads(sys_info::cpu_num().unwrap_or(NUM_THREADS) as usize)
|
||||||
|
.build()
|
||||||
|
.unwrap()));
|
||||||
|
|
||||||
fn first_err(results: &[Result<()>]) -> Result<()> {
|
fn first_err(results: &[Result<()>]) -> Result<()> {
|
||||||
for r in results {
|
for r in results {
|
||||||
if r.is_err() {
|
if r.is_err() {
|
||||||
@ -29,7 +38,9 @@ fn par_execute_entries(
|
|||||||
entries: &[(&Entry, LockedAccountsResults<Transaction>)],
|
entries: &[(&Entry, LockedAccountsResults<Transaction>)],
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
inc_new_counter_debug!("bank-par_execute_entries-count", entries.len());
|
inc_new_counter_debug!("bank-par_execute_entries-count", entries.len());
|
||||||
let results: Vec<Result<()>> = entries
|
let results: Vec<Result<()>> = PAR_THREAD_POOL.with(|thread_pool| {
|
||||||
|
thread_pool.borrow().install(|| {
|
||||||
|
entries
|
||||||
.into_par_iter()
|
.into_par_iter()
|
||||||
.map(|(e, locked_accounts)| {
|
.map(|(e, locked_accounts)| {
|
||||||
let results = bank.load_execute_and_commit_transactions(
|
let results = bank.load_execute_and_commit_transactions(
|
||||||
@ -54,7 +65,9 @@ fn par_execute_entries(
|
|||||||
}
|
}
|
||||||
first_err.unwrap_or(Ok(()))
|
first_err.unwrap_or(Ok(()))
|
||||||
})
|
})
|
||||||
.collect();
|
.collect()
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
first_err(&results)
|
first_err(&results)
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ use crate::result::{Error, Result};
|
|||||||
use crate::service::Service;
|
use crate::service::Service;
|
||||||
use crate::staking_utils;
|
use crate::staking_utils;
|
||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
|
use rayon::ThreadPool;
|
||||||
use solana_metrics::{
|
use solana_metrics::{
|
||||||
datapoint, inc_new_counter_debug, inc_new_counter_error, inc_new_counter_info,
|
datapoint, inc_new_counter_debug, inc_new_counter_error, inc_new_counter_info,
|
||||||
inc_new_counter_warn,
|
inc_new_counter_warn,
|
||||||
@ -24,6 +25,8 @@ use std::sync::{Arc, RwLock};
|
|||||||
use std::thread::{self, Builder, JoinHandle};
|
use std::thread::{self, Builder, JoinHandle};
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
|
|
||||||
|
pub const NUM_THREADS: u32 = 10;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Clone)]
|
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||||
pub enum BroadcastStageReturnType {
|
pub enum BroadcastStageReturnType {
|
||||||
ChannelDisconnected,
|
ChannelDisconnected,
|
||||||
@ -40,6 +43,7 @@ struct Broadcast {
|
|||||||
id: Pubkey,
|
id: Pubkey,
|
||||||
coding_generator: CodingGenerator,
|
coding_generator: CodingGenerator,
|
||||||
stats: BroadcastStats,
|
stats: BroadcastStats,
|
||||||
|
thread_pool: ThreadPool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Broadcast {
|
impl Broadcast {
|
||||||
@ -96,14 +100,16 @@ impl Broadcast {
|
|||||||
|
|
||||||
let to_blobs_start = Instant::now();
|
let to_blobs_start = Instant::now();
|
||||||
|
|
||||||
let blobs: Vec<_> = ventries
|
let blobs: Vec<_> = self.thread_pool.install(|| {
|
||||||
|
ventries
|
||||||
.into_par_iter()
|
.into_par_iter()
|
||||||
.map(|p| {
|
.map(|p| {
|
||||||
let entries: Vec<_> = p.into_iter().map(|e| e.0).collect();
|
let entries: Vec<_> = p.into_iter().map(|e| e.0).collect();
|
||||||
entries.to_shared_blobs()
|
entries.to_shared_blobs()
|
||||||
})
|
})
|
||||||
.flatten()
|
.flatten()
|
||||||
.collect();
|
.collect()
|
||||||
|
});
|
||||||
|
|
||||||
let blob_index = blocktree
|
let blob_index = blocktree
|
||||||
.meta(bank.slot())
|
.meta(bank.slot())
|
||||||
@ -218,6 +224,10 @@ impl BroadcastStage {
|
|||||||
id: me.id,
|
id: me.id,
|
||||||
coding_generator,
|
coding_generator,
|
||||||
stats: BroadcastStats::default(),
|
stats: BroadcastStats::default(),
|
||||||
|
thread_pool: rayon::ThreadPoolBuilder::new()
|
||||||
|
.num_threads(sys_info::cpu_num().unwrap_or(NUM_THREADS) as usize)
|
||||||
|
.build()
|
||||||
|
.unwrap(),
|
||||||
};
|
};
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
use crate::packet::{Packet, Packets};
|
use crate::packet::{Packet, Packets};
|
||||||
use crate::result::Result;
|
use crate::result::Result;
|
||||||
use bincode::serialized_size;
|
use bincode::serialized_size;
|
||||||
|
use rayon::ThreadPool;
|
||||||
use solana_metrics::inc_new_counter_debug;
|
use solana_metrics::inc_new_counter_debug;
|
||||||
use solana_sdk::message::MessageHeader;
|
use solana_sdk::message::MessageHeader;
|
||||||
use solana_sdk::pubkey::Pubkey;
|
use solana_sdk::pubkey::Pubkey;
|
||||||
@ -16,6 +17,14 @@ use solana_sdk::signature::Signature;
|
|||||||
use solana_sdk::transaction::Transaction;
|
use solana_sdk::transaction::Transaction;
|
||||||
use std::mem::size_of;
|
use std::mem::size_of;
|
||||||
|
|
||||||
|
pub const NUM_THREADS: u32 = 10;
|
||||||
|
use std::cell::RefCell;
|
||||||
|
|
||||||
|
thread_local!(static PAR_THREAD_POOL: RefCell<ThreadPool> = RefCell::new(rayon::ThreadPoolBuilder::new()
|
||||||
|
.num_threads(sys_info::cpu_num().unwrap_or(NUM_THREADS) as usize)
|
||||||
|
.build()
|
||||||
|
.unwrap()));
|
||||||
|
|
||||||
type TxOffsets = (Vec<u32>, Vec<u32>, Vec<u32>, Vec<u32>, Vec<Vec<u32>>);
|
type TxOffsets = (Vec<u32>, Vec<u32>, Vec<u32>, Vec<u32>, Vec<Vec<u32>>);
|
||||||
|
|
||||||
#[cfg(feature = "cuda")]
|
#[cfg(feature = "cuda")]
|
||||||
@ -174,10 +183,14 @@ pub fn ed25519_verify_cpu(batches: &[Packets]) -> Vec<Vec<u8>> {
|
|||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
let count = batch_size(batches);
|
let count = batch_size(batches);
|
||||||
debug!("CPU ECDSA for {}", batch_size(batches));
|
debug!("CPU ECDSA for {}", batch_size(batches));
|
||||||
let rv = batches
|
let rv = PAR_THREAD_POOL.with(|thread_pool| {
|
||||||
|
thread_pool.borrow().install(|| {
|
||||||
|
batches
|
||||||
.into_par_iter()
|
.into_par_iter()
|
||||||
.map(|p| p.packets.par_iter().map(verify_packet).collect())
|
.map(|p| p.packets.par_iter().map(verify_packet).collect())
|
||||||
.collect();
|
.collect()
|
||||||
|
})
|
||||||
|
});
|
||||||
inc_new_counter_debug!("ed25519_verify_cpu", count);
|
inc_new_counter_debug!("ed25519_verify_cpu", count);
|
||||||
rv
|
rv
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,7 @@ solana-vote-program = { path = "../programs/vote_program", version = "0.16.0"
|
|||||||
solana-stake-program = { path = "../programs/stake_program", version = "0.16.0" }
|
solana-stake-program = { path = "../programs/stake_program", version = "0.16.0" }
|
||||||
solana-storage-program = { path = "../programs/storage_program", version = "0.16.0" }
|
solana-storage-program = { path = "../programs/storage_program", version = "0.16.0" }
|
||||||
solana-noop-program = { path = "../programs/noop_program", version = "0.16.0" }
|
solana-noop-program = { path = "../programs/noop_program", version = "0.16.0" }
|
||||||
|
sys-info = "0.5.7"
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
name = "solana_runtime"
|
name = "solana_runtime"
|
||||||
|
@ -24,15 +24,18 @@ use hashbrown::{HashMap, HashSet};
|
|||||||
use log::*;
|
use log::*;
|
||||||
use rand::{thread_rng, Rng};
|
use rand::{thread_rng, Rng};
|
||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
|
use rayon::ThreadPool;
|
||||||
use solana_sdk::account::Account;
|
use solana_sdk::account::Account;
|
||||||
use solana_sdk::pubkey::Pubkey;
|
use solana_sdk::pubkey::Pubkey;
|
||||||
use std::fs::{create_dir_all, remove_dir_all};
|
use std::fs::{create_dir_all, remove_dir_all};
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||||
use std::sync::{Arc, RwLock};
|
use std::sync::{Arc, RwLock};
|
||||||
|
use sys_info;
|
||||||
|
|
||||||
const ACCOUNT_DATA_FILE_SIZE: u64 = 64 * 1024 * 1024;
|
const ACCOUNT_DATA_FILE_SIZE: u64 = 64 * 1024 * 1024;
|
||||||
const ACCOUNT_DATA_FILE: &str = "data";
|
const ACCOUNT_DATA_FILE: &str = "data";
|
||||||
|
pub const NUM_THREADS: u32 = 10;
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct ErrorCounters {
|
pub struct ErrorCounters {
|
||||||
@ -166,7 +169,6 @@ impl AccountStorageEntry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// This structure handles the load/store of the accounts
|
// This structure handles the load/store of the accounts
|
||||||
#[derive(Default)]
|
|
||||||
pub struct AccountsDB {
|
pub struct AccountsDB {
|
||||||
/// Keeps tracks of index into AppendVec on a per fork basis
|
/// Keeps tracks of index into AppendVec on a per fork basis
|
||||||
pub accounts_index: RwLock<AccountsIndex<AccountInfo>>,
|
pub accounts_index: RwLock<AccountsIndex<AccountInfo>>,
|
||||||
@ -185,12 +187,32 @@ pub struct AccountsDB {
|
|||||||
|
|
||||||
/// Starting file size of appendvecs
|
/// Starting file size of appendvecs
|
||||||
file_size: u64,
|
file_size: u64,
|
||||||
|
|
||||||
|
/// Thread pool used for par_iter
|
||||||
|
thread_pool: ThreadPool,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_paths_vec(paths: &str) -> Vec<String> {
|
pub fn get_paths_vec(paths: &str) -> Vec<String> {
|
||||||
paths.split(',').map(ToString::to_string).collect()
|
paths.split(',').map(ToString::to_string).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for AccountsDB {
|
||||||
|
fn default() -> Self {
|
||||||
|
AccountsDB {
|
||||||
|
accounts_index: RwLock::new(AccountsIndex::default()),
|
||||||
|
storage: RwLock::new(HashMap::new()),
|
||||||
|
next_id: AtomicUsize::new(0),
|
||||||
|
write_version: AtomicUsize::new(0),
|
||||||
|
paths: Vec::default(),
|
||||||
|
file_size: u64::default(),
|
||||||
|
thread_pool: rayon::ThreadPoolBuilder::new()
|
||||||
|
.num_threads(2)
|
||||||
|
.build()
|
||||||
|
.unwrap(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl AccountsDB {
|
impl AccountsDB {
|
||||||
pub fn new_with_file_size(paths: &str, file_size: u64) -> Self {
|
pub fn new_with_file_size(paths: &str, file_size: u64) -> Self {
|
||||||
let paths = get_paths_vec(&paths);
|
let paths = get_paths_vec(&paths);
|
||||||
@ -201,6 +223,10 @@ impl AccountsDB {
|
|||||||
write_version: AtomicUsize::new(0),
|
write_version: AtomicUsize::new(0),
|
||||||
paths,
|
paths,
|
||||||
file_size,
|
file_size,
|
||||||
|
thread_pool: rayon::ThreadPoolBuilder::new()
|
||||||
|
.num_threads(sys_info::cpu_num().unwrap_or(NUM_THREADS) as usize)
|
||||||
|
.build()
|
||||||
|
.unwrap(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -242,6 +268,7 @@ impl AccountsDB {
|
|||||||
.filter(|store| store.fork_id == fork_id)
|
.filter(|store| store.fork_id == fork_id)
|
||||||
.cloned()
|
.cloned()
|
||||||
.collect();
|
.collect();
|
||||||
|
self.thread_pool.install(|| {
|
||||||
storage_maps
|
storage_maps
|
||||||
.into_par_iter()
|
.into_par_iter()
|
||||||
.map(|storage| {
|
.map(|storage| {
|
||||||
@ -253,6 +280,7 @@ impl AccountsDB {
|
|||||||
retval
|
retval
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn load(
|
pub fn load(
|
||||||
|
Reference in New Issue
Block a user