[ethash] remove manual unrolling (#11069)
* [ethash] remove unroll in calculate_dag_item * [ethash] add keccak bench * [ethash] remove unroll! completely * [ethash] specify required-features for benches * [ethcore/verification] specify required-features for benches * [CI] simplify cargo-check-benches step
This commit is contained in:
parent
2627288311
commit
fc22c58408
@ -100,9 +100,7 @@ cargo-check-benches:
|
|||||||
stage: test
|
stage: test
|
||||||
<<: *docker-cache-status
|
<<: *docker-cache-status
|
||||||
script:
|
script:
|
||||||
- time (cargo check --all --benches --exclude ethash --exclude verification --target $CARGO_TARGET --locked --verbose --color=always)
|
- time cargo check --all --benches --target $CARGO_TARGET --locked --verbose --color=always
|
||||||
- time (cd ethash; cargo check --benches --features bench --target $CARGO_TARGET --locked --verbose --color=always)
|
|
||||||
- time (cd ethcore/verification; cargo check --benches --features bench --target $CARGO_TARGET --locked --verbose --color=always)
|
|
||||||
- sccache -s
|
- sccache -s
|
||||||
|
|
||||||
cargo-audit:
|
cargo-audit:
|
||||||
@ -344,7 +342,7 @@ publish-release-awss3-nightly: &publish-release-awss3
|
|||||||
- linux-docker
|
- linux-docker
|
||||||
|
|
||||||
publish-release-awss3-manually:
|
publish-release-awss3-manually:
|
||||||
<<: *publish-release-awss3
|
<<: *publish-release-awss3
|
||||||
only: *releaseable_branches
|
only: *releaseable_branches
|
||||||
when: manual
|
when: manual
|
||||||
|
|
||||||
|
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -936,7 +936,6 @@ version = "1.12.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"common-types 0.1.0",
|
"common-types 0.1.0",
|
||||||
"criterion 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"criterion 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"ethereum-types 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"ethereum-types 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"keccak-hash 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"keccak-hash 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -6,7 +6,6 @@ authors = ["Parity Technologies <admin@parity.io>"]
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
common-types = { path = "../ethcore/types" }
|
common-types = { path = "../ethcore/types" }
|
||||||
crunchy = "0.1.0"
|
|
||||||
either = "1.0.0"
|
either = "1.0.0"
|
||||||
ethereum-types = "0.6.0"
|
ethereum-types = "0.6.0"
|
||||||
keccak-hash = "0.2.0"
|
keccak-hash = "0.2.0"
|
||||||
@ -29,7 +28,9 @@ bench = []
|
|||||||
[[bench]]
|
[[bench]]
|
||||||
name = "basic"
|
name = "basic"
|
||||||
harness = false
|
harness = false
|
||||||
|
required-features = ['bench']
|
||||||
|
|
||||||
[[bench]]
|
[[bench]]
|
||||||
name = "progpow"
|
name = "progpow"
|
||||||
harness = false
|
harness = false
|
||||||
|
required-features = ['bench']
|
||||||
|
@ -20,7 +20,7 @@ extern crate ethash;
|
|||||||
extern crate common_types;
|
extern crate common_types;
|
||||||
|
|
||||||
use criterion::Criterion;
|
use criterion::Criterion;
|
||||||
use ethash::NodeCacheBuilder;
|
use ethash::{NodeCacheBuilder, keccak};
|
||||||
use common_types::engines::OptimizeFor;
|
use common_types::engines::OptimizeFor;
|
||||||
|
|
||||||
const HASH: [u8; 32] = [
|
const HASH: [u8; 32] = [
|
||||||
@ -40,7 +40,8 @@ const NONCE: u64 = 0xd7b3ac70a301a249;
|
|||||||
criterion_group! {
|
criterion_group! {
|
||||||
name = basic;
|
name = basic;
|
||||||
config = dont_take_an_eternity_to_run();
|
config = dont_take_an_eternity_to_run();
|
||||||
targets = bench_light_compute_memmap,
|
targets = bench_keccak_512_inplace,
|
||||||
|
bench_light_compute_memmap,
|
||||||
bench_light_compute_memory,
|
bench_light_compute_memory,
|
||||||
bench_light_new_round_trip_memmap,
|
bench_light_new_round_trip_memmap,
|
||||||
bench_light_new_round_trip_memory,
|
bench_light_new_round_trip_memory,
|
||||||
@ -56,6 +57,13 @@ fn dont_take_an_eternity_to_run() -> Criterion {
|
|||||||
.sample_size(10)
|
.sample_size(10)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn bench_keccak_512_inplace(b: &mut Criterion) {
|
||||||
|
b.bench_function("bench_keccak_512_inplace", move |b| b.iter(|| {
|
||||||
|
let mut data = [4u8; 64];
|
||||||
|
keccak::keccak_512::inplace(&mut data);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
fn bench_light_compute_memmap(b: &mut Criterion) {
|
fn bench_light_compute_memmap(b: &mut Criterion) {
|
||||||
use std::env;
|
use std::env;
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ use memmap::MmapMut;
|
|||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use seed_compute::SeedHashCompute;
|
use seed_compute::SeedHashCompute;
|
||||||
|
|
||||||
use shared::{ETHASH_CACHE_ROUNDS, NODE_BYTES, NODE_DWORDS, Node, epoch, get_cache_size, to_hex};
|
use shared::{ETHASH_CACHE_ROUNDS, NODE_BYTES, Node, epoch, get_cache_size, to_hex};
|
||||||
|
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
@ -317,11 +317,6 @@ unsafe fn initialize_memory(memory: *mut Node, num_nodes: usize, ident: &H256) {
|
|||||||
// Now this is initialized, we can treat it as a slice.
|
// Now this is initialized, we can treat it as a slice.
|
||||||
let nodes: &mut [Node] = slice::from_raw_parts_mut(memory, num_nodes);
|
let nodes: &mut [Node] = slice::from_raw_parts_mut(memory, num_nodes);
|
||||||
|
|
||||||
// For `unroll!`, see below. If the literal in `unroll!` is not the same as the RHS here then
|
|
||||||
// these have got out of sync! Don't let this happen!
|
|
||||||
debug_assert_eq!(NODE_DWORDS, 8);
|
|
||||||
|
|
||||||
// This _should_ get unrolled by the compiler, since it's not using the loop variable.
|
|
||||||
for _ in 0..ETHASH_CACHE_ROUNDS {
|
for _ in 0..ETHASH_CACHE_ROUNDS {
|
||||||
for i in 0..num_nodes {
|
for i in 0..num_nodes {
|
||||||
let data_idx = (num_nodes - 1 + i) % num_nodes;
|
let data_idx = (num_nodes - 1 + i) % num_nodes;
|
||||||
@ -331,11 +326,8 @@ unsafe fn initialize_memory(memory: *mut Node, num_nodes: usize, ident: &H256) {
|
|||||||
let mut data: Node = nodes.get_unchecked(data_idx).clone();
|
let mut data: Node = nodes.get_unchecked(data_idx).clone();
|
||||||
let rhs: &Node = nodes.get_unchecked(idx);
|
let rhs: &Node = nodes.get_unchecked(idx);
|
||||||
|
|
||||||
unroll! {
|
for (a, b) in data.as_dwords_mut().iter_mut().zip(rhs.as_dwords()) {
|
||||||
for w in 0..8 {
|
*a ^= *b;
|
||||||
*data.as_dwords_mut().get_unchecked_mut(w) ^=
|
|
||||||
*rhs.as_dwords().get_unchecked(w);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
data
|
data
|
||||||
|
@ -239,24 +239,16 @@ fn hash_compute(light: &Light, full_size: usize, header_hash: &H256, nonce: u64)
|
|||||||
fnv_hash(first_val ^ i, mix_words[i as usize % MIX_WORDS]) % num_full_pages
|
fnv_hash(first_val ^ i, mix_words[i as usize % MIX_WORDS]) % num_full_pages
|
||||||
};
|
};
|
||||||
|
|
||||||
unroll! {
|
// MIX_NODES
|
||||||
// MIX_NODES
|
for n in 0..2 {
|
||||||
for n in 0..2 {
|
let tmp_node = calculate_dag_item(
|
||||||
let tmp_node = calculate_dag_item(
|
index * MIX_NODES as u32 + n as u32,
|
||||||
index * MIX_NODES as u32 + n as u32,
|
cache,
|
||||||
cache,
|
);
|
||||||
);
|
|
||||||
|
|
||||||
unroll! {
|
// NODE_WORDS
|
||||||
// NODE_WORDS
|
for (a, b) in mix[n].as_words_mut().iter_mut().zip(tmp_node.as_words()) {
|
||||||
for w in 0..16 {
|
*a = fnv_hash(*a, *b);
|
||||||
mix[n].as_words_mut()[w] =
|
|
||||||
fnv_hash(
|
|
||||||
mix[n].as_words()[w],
|
|
||||||
tmp_node.as_words()[w],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -277,16 +269,14 @@ fn hash_compute(light: &Light, full_size: usize, header_hash: &H256, nonce: u64)
|
|||||||
|
|
||||||
// Compress mix
|
// Compress mix
|
||||||
debug_assert_eq!(MIX_WORDS / 4, 8);
|
debug_assert_eq!(MIX_WORDS / 4, 8);
|
||||||
unroll! {
|
for i in 0..8 {
|
||||||
for i in 0..8 {
|
let w = i * 4;
|
||||||
let w = i * 4;
|
|
||||||
|
|
||||||
let mut reduction = mix_words[w + 0];
|
let mut reduction = mix_words[w + 0];
|
||||||
reduction = reduction.wrapping_mul(FNV_PRIME) ^ mix_words[w + 1];
|
reduction = reduction.wrapping_mul(FNV_PRIME) ^ mix_words[w + 1];
|
||||||
reduction = reduction.wrapping_mul(FNV_PRIME) ^ mix_words[w + 2];
|
reduction = reduction.wrapping_mul(FNV_PRIME) ^ mix_words[w + 2];
|
||||||
reduction = reduction.wrapping_mul(FNV_PRIME) ^ mix_words[w + 3];
|
reduction = reduction.wrapping_mul(FNV_PRIME) ^ mix_words[w + 3];
|
||||||
compress[i] = reduction;
|
compress[i] = reduction;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -312,7 +302,6 @@ fn hash_compute(light: &Light, full_size: usize, header_hash: &H256, nonce: u64)
|
|||||||
ProofOfWork { mix_hash: mix_hash, value: value }
|
ProofOfWork { mix_hash: mix_hash, value: value }
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Use the `simd` crate
|
|
||||||
pub fn calculate_dag_item(node_index: u32, cache: &[Node]) -> Node {
|
pub fn calculate_dag_item(node_index: u32, cache: &[Node]) -> Node {
|
||||||
let num_parent_nodes = cache.len();
|
let num_parent_nodes = cache.len();
|
||||||
let mut ret = cache[node_index as usize % num_parent_nodes].clone();
|
let mut ret = cache[node_index as usize % num_parent_nodes].clone();
|
||||||
@ -326,10 +315,8 @@ pub fn calculate_dag_item(node_index: u32, cache: &[Node]) -> Node {
|
|||||||
num_parent_nodes as u32;
|
num_parent_nodes as u32;
|
||||||
let parent = &cache[parent_index as usize];
|
let parent = &cache[parent_index as usize];
|
||||||
|
|
||||||
unroll! {
|
for (a, b) in ret.as_words_mut().iter_mut().zip(parent.as_words()) {
|
||||||
for w in 0..16 {
|
*a = fnv_hash(*a, *b);
|
||||||
ret.as_words_mut()[w] = fnv_hash(ret.as_words()[w], parent.as_words()[w]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,8 +21,6 @@ extern crate memmap;
|
|||||||
extern crate parking_lot;
|
extern crate parking_lot;
|
||||||
extern crate primal;
|
extern crate primal;
|
||||||
|
|
||||||
#[macro_use]
|
|
||||||
extern crate crunchy;
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate log;
|
extern crate log;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
@ -44,6 +42,9 @@ mod compute;
|
|||||||
|
|
||||||
mod seed_compute;
|
mod seed_compute;
|
||||||
mod cache;
|
mod cache;
|
||||||
|
#[cfg(feature = "bench")]
|
||||||
|
pub mod keccak;
|
||||||
|
#[cfg(not(feature = "bench"))]
|
||||||
mod keccak;
|
mod keccak;
|
||||||
mod shared;
|
mod shared;
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@ license = "GPL-3.0"
|
|||||||
[[bench]]
|
[[bench]]
|
||||||
name = "verification"
|
name = "verification"
|
||||||
harness = false
|
harness = false
|
||||||
|
required-features = ['bench']
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
blockchain = { package = "ethcore-blockchain", path = "../blockchain" }
|
blockchain = { package = "ethcore-blockchain", path = "../blockchain" }
|
||||||
|
Loading…
Reference in New Issue
Block a user