read-width experiment (gate 1): load classes W=4/16/64, per-load width mix, scratch RMW variant behind a generator flag; 20 packs; CPU verifier and acceptance mirror; emulator shims
Nothing changes for the default class: the pinned packs are byte-identical (tests/packs.rs), the v2 draw stream is untouched.
LoadClass {mix, load_slots, scratch}: fixed widths w16, w64, w64x4 (4 loads of 64 B), era mixes 50/35/15 and 25/50/25 drawn per load with one extra below(100) roll, and the scratch variant scr0/2/4/8 (persistent warps, 1 MiB per warp, tagged lazy fill, measurement only). A wide load reads the W-aligned address and folds every word: x = dst ^ w0; x = (rotl(x, 11) * 0x9e3779b1) ^ w[j]. Program ids carry the class. proto-opencl/host.c taken from opencl-rdna4 23810df (--memprobe, select read-back).
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
parent
5aa75166d8
commit
dc84789e34
253 changed files with 35043 additions and 95 deletions
|
|
@ -14,9 +14,9 @@
|
|||
//! costs about a millisecond on one core. The census (section 7.3) checked on 100,000 programs that the
|
||||
//! closed-form verdict agrees with the memory-hard one on all but 39 threshold-edge cases.
|
||||
|
||||
use crate::generator::{Instr, Op, Program, INSTR_COUNT, ITERATIONS, LANES};
|
||||
use crate::generator::{Instr, Op, Program, INSTR_COUNT, ITERATIONS, LANES, SCRATCH_SLOT_MASK};
|
||||
use crate::seed::{fnv1a64, SplitMix64};
|
||||
use crate::verify::{dataset_elem, splitmix32};
|
||||
use crate::verify::{dataset_elem, fold_words, splitmix32, ScratchModel};
|
||||
|
||||
/// Units (32-lane warps) the dynamic test interprets.
|
||||
pub const ACCEPT_UNITS: usize = 64;
|
||||
|
|
@ -33,6 +33,12 @@ pub const BIAS_TOLERANCE: u32 = 136;
|
|||
/// Distinct addresses per lane per evaluation, summed over 2,048 evaluations, must exceed this (mean above 120).
|
||||
pub const MIN_DISTINCT_SUM: u64 = 245_760;
|
||||
|
||||
/// The distinct-address bound for a program with `loads` loads per hash: the same 120 of 128 ratio, so
|
||||
/// [`MIN_DISTINCT_SUM`] for the lottery hash and `loads x 1,920` for the read-width classes with other counts.
|
||||
pub fn min_distinct_sum(loads: usize) -> u64 {
|
||||
loads as u64 * ACCEPT_HASHES as u64 * 120 / 128
|
||||
}
|
||||
|
||||
/// Why a candidate was rejected. The verdict (accept or reject) is what consensus depends on; the reason is the
|
||||
/// first failing test in the order of the module table.
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
|
|
@ -67,7 +73,7 @@ impl std::fmt::Display for Reject {
|
|||
Reject::Saturated { count } => write!(f, "(c) {count} of 16384 final register values saturated (limit 163)"),
|
||||
Reject::OutputBias { bit, ones } => write!(f, "(c) output bit {bit} set in {ones} of 2048 hashes"),
|
||||
Reject::DistinctAddresses { sum } => {
|
||||
write!(f, "(c) distinct addresses {sum} over 2048 hashes (mean {:.2}, needs above 120)", *sum as f64 / 2048.0)
|
||||
write!(f, "(c) distinct addresses {sum} over 2048 hashes (mean {:.2}, needs above 120 of 128 loads)", *sum as f64 / 2048.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -183,12 +189,28 @@ fn run_unit(p: &Program, unit: usize, base: u32, acc: &mut Acc, lane_addrs: &mut
|
|||
}
|
||||
let mut idx = [0u32; LANES];
|
||||
let mut nload = 0usize;
|
||||
let mut scratch = if p.has_scratch() { Some(ScratchModel::new()) } else { None };
|
||||
for it in 0..ITERATIONS {
|
||||
let sel = r[0];
|
||||
for (k, ins) in p.instrs.iter().enumerate() {
|
||||
let d = ins.dst as usize;
|
||||
let a = ins.src as usize;
|
||||
match ins.op {
|
||||
Op::Scratch => {
|
||||
// Variant 5: the slot stands in for the address (bit 31 set so it never aliases a dataset word).
|
||||
let m = scratch.as_mut().expect("a scratch op needs a scratch class");
|
||||
for lane in 0..LANES {
|
||||
idx[lane] = r[a][lane] & SCRATCH_SLOT_MASK;
|
||||
}
|
||||
if idx.iter().all(|&x| x == idx[0]) {
|
||||
return Err(Reject::LaneConstantSite { iteration: it as u8, instr: k as u8, unit: unit as u8 });
|
||||
}
|
||||
for lane in 0..LANES {
|
||||
r[d][lane] = m.rmw(&p.seed, base, lane, idx[lane], r[d][lane]);
|
||||
lane_addrs[lane * loads + nload] = 0x8000_0000 | idx[lane];
|
||||
}
|
||||
nload += 1;
|
||||
}
|
||||
Op::Add => {
|
||||
let (imm, imm2, bit) = (ins.imm, ins.imm2, ins.bit as u32);
|
||||
let src = r[a];
|
||||
|
|
@ -255,14 +277,26 @@ fn run_unit(p: &Program, unit: usize, base: u32, acc: &mut Acc, lane_addrs: &mut
|
|||
}
|
||||
}
|
||||
Op::Load => {
|
||||
// Read-width experiment: a load of `width` words reads from the aligned address and folds every
|
||||
// word (verify::fold_words); width 1 is the lottery hash's xor of one word.
|
||||
let width = ins.width as usize;
|
||||
let align = !(ins.width as u32 - 1);
|
||||
for lane in 0..LANES {
|
||||
idx[lane] = r[a][lane] & mask;
|
||||
idx[lane] = (r[a][lane] & mask) & align;
|
||||
}
|
||||
if idx.iter().all(|&x| x == idx[0]) {
|
||||
return Err(Reject::LaneConstantSite { iteration: it as u8, instr: k as u8, unit: unit as u8 });
|
||||
}
|
||||
for lane in 0..LANES {
|
||||
r[d][lane] ^= dataset_elem(idx[lane], d0, d1);
|
||||
if width == 1 {
|
||||
r[d][lane] ^= dataset_elem(idx[lane], d0, d1);
|
||||
} else {
|
||||
let mut w = [0u32; 16];
|
||||
for j in 0..width {
|
||||
w[j] = dataset_elem(idx[lane] + j as u32, d0, d1);
|
||||
}
|
||||
r[d][lane] = fold_words(r[d][lane], &w[..width]);
|
||||
}
|
||||
lane_addrs[lane * loads + nload] = idx[lane];
|
||||
}
|
||||
nload += 1;
|
||||
|
|
@ -333,7 +367,7 @@ pub fn check_dynamic(p: &Program) -> Result<AcceptReport, Reject> {
|
|||
}
|
||||
bias_max = bias_max.max(d);
|
||||
}
|
||||
if acc.distinct_sum <= MIN_DISTINCT_SUM {
|
||||
if acc.distinct_sum <= min_distinct_sum(loads) {
|
||||
return Err(Reject::DistinctAddresses { sum: acc.distinct_sum });
|
||||
}
|
||||
Ok(AcceptReport { distinct_sum: acc.distinct_sum, saturated: acc.saturated, bias_max })
|
||||
|
|
@ -348,9 +382,50 @@ pub fn check(p: &Program) -> Result<AcceptReport, Reject> {
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::generator::{candidate, generate, GeneratorConfig, generate_v1};
|
||||
use crate::generator::{candidate, candidate_class, generate, generate_class, GeneratorConfig, generate_v1, LoadClass};
|
||||
use crate::verify::{DatasetMode, DatasetSource};
|
||||
|
||||
#[test]
|
||||
fn distinct_bound_scales_with_the_load_count() {
|
||||
assert_eq!(min_distinct_sum(128), MIN_DISTINCT_SUM);
|
||||
assert_eq!(min_distinct_sum(32), 61_440);
|
||||
}
|
||||
|
||||
/// The read-width classes pass the rule at about the version 2 rate, and the instrumented interpreter agrees
|
||||
/// with `verify.rs` on every class (the fold is shared, the addresses are aligned the same way).
|
||||
#[test]
|
||||
fn classes_pass_and_match_verify() {
|
||||
for name in ["w16", "w64", "w64x4", "50,35,15", "25,50,25", "scr2", "scr8"] {
|
||||
let c = LoadClass::parse(name).unwrap();
|
||||
let p = generate_class("igneum-genesis", c);
|
||||
assert!(check(&p).is_ok(), "{name}");
|
||||
let mut rejected = 0;
|
||||
for i in 0..60u32 {
|
||||
let s = format!("igneum-rw-accept/{i}");
|
||||
let q = candidate_class(&s, s.as_bytes(), 0, c);
|
||||
if check(&q).is_err() {
|
||||
rejected += 1;
|
||||
}
|
||||
}
|
||||
assert!(rejected < 15, "{name}: {rejected} of 60 rejected");
|
||||
let ds = DatasetSource::from_key(p.seed, DatasetMode::ClosedForm, ACCEPT_DATASET_LOG2);
|
||||
let bases = accept_base_nonces(&p.seed);
|
||||
let loads = p.loads_per_hash();
|
||||
let mut acc = Acc { and_acc: [u32::MAX; 8], or_acc: [0; 8], saturated: 0, bit_ones: [0; 64], distinct_sum: 0 };
|
||||
let mut la = vec![0u32; LANES * loads];
|
||||
let mut ones = [0u32; 64];
|
||||
for (u, &b) in bases.iter().enumerate() {
|
||||
run_unit(&p, u, b, &mut acc, &mut la).unwrap();
|
||||
for h in crate::verify::hash_warp(&p, b, &ds) {
|
||||
for j in 0..64 {
|
||||
ones[j] += ((h >> j) & 1) as u32;
|
||||
}
|
||||
}
|
||||
}
|
||||
assert_eq!(acc.bit_ones, ones, "{name}: bit counts match the reference interpreter");
|
||||
}
|
||||
}
|
||||
|
||||
/// The instrumented interpreter agrees with `verify.rs` on the closed-form dataset keyed by the seed words.
|
||||
#[test]
|
||||
fn instrumented_interpreter_matches_verify() {
|
||||
|
|
|
|||
|
|
@ -9,13 +9,207 @@
|
|||
//! One deliberate difference from the Swift: `program_json` writes the cache line mask inside the `"item"` string
|
||||
//! as a bare `0x003fffff`. The Swift writes it quoted (`jhex`), which is not valid JSON.
|
||||
|
||||
use crate::generator::{Op, Program, GENERATOR_VERSION, INSTR_COUNT, ITERATIONS, LOAD_SLOTS};
|
||||
use crate::generator::{Instr, Op, Program, GENERATOR_VERSION, INSTR_COUNT, ITERATIONS, LOAD_SLOTS};
|
||||
use crate::memhard::{
|
||||
MixParams, CACHE_LINES_PER_SEGMENT, CACHE_LINE_MASK, CACHE_LOG2_WORDS, CACHE_SEGMENTS, CACHE_SEGMENT_LOG2_LINES,
|
||||
CACHE_TAG, CACHE_WORDS, CHACHA_ROUNDS, CHACHA_SIGMA, ITEM_ROUNDS,
|
||||
};
|
||||
use crate::seed::SplitMix64;
|
||||
use crate::verify::{DatasetMode, DatasetSource, Epoch};
|
||||
use crate::generator::{SCRATCH_BYTES_PER_WARP, SCRATCH_SLOTS, SCRATCH_SLOT_MASK, SCRATCH_WORDS_PER_LANE};
|
||||
use crate::verify::{DatasetMode, DatasetSource, Epoch, FOLD_MUL, FOLD_ROT};
|
||||
|
||||
/// Where the words of a wide load come from (read-width experiment).
|
||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||
enum WideSource {
|
||||
/// `dataset`/`ds`: vector loads from the stored dataset.
|
||||
Stored,
|
||||
/// the closed form per word (Metal inline shortcut kernel).
|
||||
InlineClosed,
|
||||
/// one `mh_item` derivation per load, words taken from it (Metal inline memory-hard kernel).
|
||||
InlineMemhard,
|
||||
}
|
||||
|
||||
/// One wide `load` as a single statement block (read-width experiment, 5 October 2026): `width` words from the
|
||||
/// address aligned down to `width` words, folded into `dst` as `verify::fold_words`. The emitted text is the
|
||||
/// same shape in the three dialects: the vector loads differ (`uint4` pointer on Metal and CUDA, `vload4` on
|
||||
/// OpenCL C 1.2). For `width == 1` the caller emits the lottery hash's one-word form instead.
|
||||
fn wide_load_stmt(dialect: CoreDialect, d: &str, a: &str, width: u8, src: WideSource, closed: Option<(u32, u32)>) -> String {
|
||||
debug_assert!(width == 4 || width == 16);
|
||||
let (u, mask, base_ptr) = match dialect {
|
||||
CoreDialect::Metal => ("uint", "MASK", "dataset"),
|
||||
CoreDialect::Cuda => ("uint32_t", "mask", "ds"),
|
||||
CoreDialect::OpenCl => ("uint", "mask", "ds"),
|
||||
};
|
||||
let vectors = width as usize / 4;
|
||||
let mut s = String::with_capacity(400);
|
||||
s.push_str(&format!("{{ {u} b_ = ({a} & {mask}) & ~{}u; ", width as u32 - 1));
|
||||
match src {
|
||||
WideSource::Stored => match dialect {
|
||||
CoreDialect::Metal => s.push_str(&format!("device const uint4* l_ = (device const uint4*)({base_ptr} + b_); ")),
|
||||
CoreDialect::Cuda => s.push_str(&format!("const uint4* l_ = (const uint4*)({base_ptr} + b_); ")),
|
||||
CoreDialect::OpenCl => {}
|
||||
},
|
||||
WideSource::InlineClosed => {}
|
||||
WideSource::InlineMemhard => s.push_str("uint s_[16]; mh_item(cache, b_ >> 4u, s_); "),
|
||||
}
|
||||
let word = |j: usize| -> String {
|
||||
match src {
|
||||
WideSource::Stored => format!("v{}_.{}", j / 4, ["x", "y", "z", "w"][j % 4]),
|
||||
WideSource::InlineClosed => {
|
||||
let (d0, d1) = closed.expect("closed-form words need d0, d1");
|
||||
format!("ds_elem(b_ + {j}u, {}, {})", hex(d0), hex(d1))
|
||||
}
|
||||
WideSource::InlineMemhard => format!("s_[(b_ & 15u) + {j}u]"),
|
||||
}
|
||||
};
|
||||
if src == WideSource::Stored {
|
||||
for v in 0..vectors {
|
||||
match dialect {
|
||||
CoreDialect::OpenCl => s.push_str(&format!("uint4 v{v}_ = vload4({v}u, {base_ptr} + b_); ")),
|
||||
_ => s.push_str(&format!("uint4 v{v}_ = l_[{v}]; ")),
|
||||
}
|
||||
}
|
||||
}
|
||||
s.push_str(&format!("{u} x_ = {d} ^ {}; ", word(0)));
|
||||
for j in 1..width as usize {
|
||||
s.push_str(&format!("x_ = (rotl_imm(x_, {FOLD_ROT}u) * {}) ^ {}; ", hex(FOLD_MUL), word(j)));
|
||||
}
|
||||
s.push_str(&format!("{d} = x_; }}"));
|
||||
s
|
||||
}
|
||||
|
||||
/// The load class lines of program.h (empty for the lottery hash, so the pinned packs do not change).
|
||||
fn class_header_lines(p: &Program) -> String {
|
||||
if p.class.is_v2() {
|
||||
return String::new();
|
||||
}
|
||||
let mut s = String::new();
|
||||
s.push_str("// Read-width experiment (5 October 2026, docs/plans/read-width.md): NOT the lottery hash. A load of W words reads
|
||||
");
|
||||
s.push_str("// the W-word-aligned address and folds every word into dst: x = dst ^ w[0]; x = (rotl(x, 11) * 0x9e3779b1) ^ w[j]; dst = x.
|
||||
");
|
||||
s.push_str(&format!("#define IGNEUM_LOAD_CLASS {}
|
||||
", jstr(&p.class.name())));
|
||||
s.push_str(&format!("#define IGNEUM_LOAD_SLOTS {}
|
||||
", p.class.load_slots));
|
||||
s.push_str(&format!("#define IGNEUM_LOAD_MIX {{ {}, {}, {} }}
|
||||
", p.class.mix[0], p.class.mix[1], p.class.mix[2]));
|
||||
let c = p.width_counts();
|
||||
s.push_str(&format!("#define IGNEUM_LOAD_WIDTH_COUNTS {{ {}, {}, {} }} // loads of 4, 16, 64 bytes per program
|
||||
", c[0], c[1], c[2]));
|
||||
s.push_str(&format!("#define IGNEUM_BYTES_PER_HASH {}
|
||||
", p.bytes_per_hash()));
|
||||
s.push_str(&format!("#define IGNEUM_FOLD_ROT {FOLD_ROT}
|
||||
"));
|
||||
s.push_str(&format!("#define IGNEUM_FOLD_MUL {}
|
||||
", hex(FOLD_MUL)));
|
||||
s
|
||||
}
|
||||
|
||||
/// The width of a load instruction's statement, for the emitters (1 for every non-load op).
|
||||
fn load_width(ins: &Instr) -> u8 {
|
||||
if ins.op == Op::Load {
|
||||
ins.width
|
||||
} else {
|
||||
1
|
||||
}
|
||||
}
|
||||
|
||||
/// Variant 5 prelude: `scr_fill(gbase, lane, slot, j)`, the fill word of a scratch slot (`verify::scratch_fill`),
|
||||
/// with the program's seed words as literals.
|
||||
fn scratch_prelude(p: &Program, dialect: CoreDialect) -> String {
|
||||
if !p.has_scratch() {
|
||||
return String::new();
|
||||
}
|
||||
let (u, fn_) = match dialect {
|
||||
CoreDialect::Metal => ("uint", "inline"),
|
||||
CoreDialect::Cuda => ("uint32_t", "__device__ __forceinline__"),
|
||||
CoreDialect::OpenCl => ("uint", "static inline"),
|
||||
};
|
||||
let mut s = String::new();
|
||||
s.push_str(&format!("// Variant 5 (read-width experiment, 5 October 2026, NOT the lottery hash): a 1 MiB scratch per warp, {} slots of
|
||||
", SCRATCH_SLOTS));
|
||||
s.push_str("// 16 bytes per lane, lane-major. A slot starts the unit as the fill words below (tagged lazily: a slot whose tag is not
|
||||
");
|
||||
s.push_str("// this unit's reads as its fill) and holds what the unit wrote afterwards. scr_fill mirrors verify::scratch_fill.
|
||||
");
|
||||
s.push_str(&format!(
|
||||
"{fn_} {u} scr_fill({u} gbase, {u} lane, {u} slot, {u} j) {{ {u} sw = (j == 0u) ? {} : ((j == 1u) ? {} : {}); return splitmix32(((gbase + lane) ^ sw) + slot * 0x9e3779b1u + (j + 1u) * 0x85ebca77u); }}
|
||||
",
|
||||
hex(p.seed[0]),
|
||||
hex(p.seed[1]),
|
||||
hex(p.seed[2])
|
||||
));
|
||||
s
|
||||
}
|
||||
|
||||
/// Variant 5: one scratch read-modify-write as a statement block. `arena`, `tag`, `gbase` and `lane` are in scope
|
||||
/// (the persistent prologue). Reads 16 bytes, folds the three data words into dst, rewrites the slot behind the tag.
|
||||
fn scratch_stmt(dialect: CoreDialect, d: &str, a: &str) -> String {
|
||||
let (u, load, store) = match dialect {
|
||||
CoreDialect::Metal => ("uint", "uint4 v_ = *(device const uint4*)(arena + s_ * 4u);", "*(device uint4*)(arena + s_ * 4u) = uint4(tag, x_ ^ w1_, rotl_imm(x_, 7u) ^ w2_, x_ + w0_);"),
|
||||
CoreDialect::Cuda => ("uint32_t", "uint4 v_ = *(const uint4*)(arena + s_ * 4u);", "*(uint4*)(arena + s_ * 4u) = make_uint4(tag, x_ ^ w1_, rotl_imm(x_, 7u) ^ w2_, x_ + w0_);"),
|
||||
CoreDialect::OpenCl => ("uint", "uint4 v_ = vload4(s_, arena);", "vstore4(IGNEUM_U4(tag, x_ ^ w1_, rotl_imm(x_, 7u) ^ w2_, x_ + w0_), s_, arena);"),
|
||||
};
|
||||
format!(
|
||||
"{{ {u} s_ = {a} & {}u; {load} {u} m_ = (v_.x == tag) ? 0xffffffffu : 0u; {u} w0_ = (v_.y & m_) | (scr_fill(gbase, lane, s_, 0u) & ~m_); {u} w1_ = (v_.z & m_) | (scr_fill(gbase, lane, s_, 1u) & ~m_); {u} w2_ = (v_.w & m_) | (scr_fill(gbase, lane, s_, 2u) & ~m_); {u} x_ = {d} ^ w0_; x_ = (rotl_imm(x_, {FOLD_ROT}u) * {k}) ^ w1_; x_ = (rotl_imm(x_, {FOLD_ROT}u) * {k}) ^ w2_; {d} = x_; {store} }}",
|
||||
SCRATCH_SLOT_MASK,
|
||||
k = hex(FOLD_MUL)
|
||||
)
|
||||
}
|
||||
|
||||
/// Variant 5: the persistent-warp prologue. The kernel is launched with N warps (the resident count, the host's
|
||||
/// choice); warp `w` owns arena `w` and runs the units `w, w + N, w + 2N, ...` of the launch. Inside the loop the
|
||||
/// lottery hash's text is unchanged: `gid` is the unit's first output index plus the lane. The host MUST launch
|
||||
/// `groups` as a multiple of N (a uniform trip count: the OpenCL local-memory exchange carries a barrier).
|
||||
fn persistent_prologue(dialect: CoreDialect) -> String {
|
||||
let (u, tid, nthreads, ptr) = match dialect {
|
||||
CoreDialect::Metal => ("uint", "tid", "nthreads", "device uint*"),
|
||||
CoreDialect::Cuda => ("uint32_t", "(blockIdx.x * blockDim.x + threadIdx.x)", "(gridDim.x * blockDim.x)", "uint32_t*"),
|
||||
CoreDialect::OpenCl => ("uint", "(uint)get_global_id(0)", "(uint)get_global_size(0)", "__global uint*"),
|
||||
};
|
||||
let mut s = String::new();
|
||||
s.push_str(&format!(" {u} lane = {tid} & 31u;
|
||||
"));
|
||||
s.push_str(&format!(" {u} warp_ = {tid} >> 5;
|
||||
"));
|
||||
s.push_str(&format!(" {u} nwarps_ = {nthreads} >> 5;
|
||||
"));
|
||||
s.push_str(&format!(" {ptr} arena = scratch + ((size_t)warp_ * 32u + lane) * {}u;
|
||||
", SCRATCH_WORDS_PER_LANE));
|
||||
s.push_str(&format!(" for ({u} g_ = warp_; g_ < groups; g_ += nwarps_) {{
|
||||
"));
|
||||
s.push_str(&format!(" {u} gid = g_ * 32u + lane;
|
||||
"));
|
||||
s.push_str(&format!(" {u} gbase = baseNonce + g_ * 32u;
|
||||
"));
|
||||
s.push_str(&format!(" {u} tag = salt + g_;
|
||||
"));
|
||||
s
|
||||
}
|
||||
|
||||
/// The scratch lines of program.h (variant 5).
|
||||
fn scratch_header_lines(p: &Program) -> String {
|
||||
if !p.has_scratch() {
|
||||
return String::new();
|
||||
}
|
||||
let mut s = String::new();
|
||||
s.push_str("// Variant 5: persistent warps, a 1 MiB scratch per launched warp (the host launches N warps and passes scratch,
|
||||
");
|
||||
s.push_str("// groups and salt as the last three kernel arguments; groups must be a multiple of N; the tag of a unit is salt + unit).
|
||||
");
|
||||
s.push_str("#define IGNEUM_PERSISTENT_WARPS 1
|
||||
");
|
||||
s.push_str(&format!("#define IGNEUM_SCRATCH_OPS {} // scratch read-modify-writes per program ({} per hash)
|
||||
", p.class.scratch_slots(), p.scratch_ops_per_hash()));
|
||||
s.push_str(&format!("#define IGNEUM_SCRATCH_SLOTS {SCRATCH_SLOTS}u
|
||||
"));
|
||||
s.push_str(&format!("#define IGNEUM_SCRATCH_WORDS_PER_LANE {SCRATCH_WORDS_PER_LANE}u
|
||||
"));
|
||||
s.push_str(&format!("#define IGNEUM_SCRATCH_BYTES_PER_WARP {SCRATCH_BYTES_PER_WARP}u
|
||||
"));
|
||||
s
|
||||
}
|
||||
|
||||
pub fn hex(v: u32) -> String {
|
||||
format!("0x{v:08x}u")
|
||||
|
|
@ -259,6 +453,7 @@ fn metal_program_impl(p: &Program, dataset_log2: u32, source: LoadSource, bound:
|
|||
s.push('\n');
|
||||
buffer0 = "device const uint* cache [[buffer(0)]]";
|
||||
}
|
||||
s.push_str(&scratch_prelude(p, CoreDialect::Metal));
|
||||
if bound {
|
||||
s.push_str("// Header-bound variant: the init words come from buffer 3 (bind.rs), not from SEEDW.\n");
|
||||
s.push_str(&format!("kernel void igneum_hash_bound({buffer0},\n"));
|
||||
|
|
@ -270,7 +465,17 @@ fn metal_program_impl(p: &Program, dataset_log2: u32, source: LoadSource, bound:
|
|||
if bound {
|
||||
s.push_str(" constant uint* initw [[buffer(3)]],\n");
|
||||
}
|
||||
s.push_str(" uint gid [[thread_position_in_grid]]) {\n");
|
||||
if p.has_scratch() {
|
||||
let b = if bound { 4 } else { 3 };
|
||||
s.push_str(&format!(" device uint* scratch [[buffer({b})]],\n"));
|
||||
s.push_str(&format!(" constant uint& groups [[buffer({})]],\n", b + 1));
|
||||
s.push_str(&format!(" constant uint& salt [[buffer({})]],\n", b + 2));
|
||||
s.push_str(" uint tid [[thread_position_in_grid]],\n");
|
||||
s.push_str(" uint nthreads [[threads_per_grid]]) {\n");
|
||||
s.push_str(&persistent_prologue(CoreDialect::Metal));
|
||||
} else {
|
||||
s.push_str(" uint gid [[thread_position_in_grid]]) {\n");
|
||||
}
|
||||
s.push_str(" uint nonce = baseNonce + gid;\n");
|
||||
s.push_str(" uint r0, r1, r2, r3, r4, r5, r6, r7;\n");
|
||||
if p.has_wide() {
|
||||
|
|
@ -319,8 +524,17 @@ fn metal_program_impl(p: &Program, dataset_log2: u32, source: LoadSource, bound:
|
|||
Op::Rotr => format!("{d} = rotr_var({d}, {a});"),
|
||||
Op::Mad => format!("{d} = {a} * {b} + {d};"),
|
||||
Op::Shfl => format!("{d} = {d} ^ simd_shuffle_xor({a}, (ushort){});", ins.mask),
|
||||
Op::Load if load_width(ins) > 1 => {
|
||||
let (src, closed) = match &source {
|
||||
LoadSource::Stored => (WideSource::Stored, None),
|
||||
LoadSource::InlineClosed(d0, d1) => (WideSource::InlineClosed, Some((*d0, *d1))),
|
||||
LoadSource::InlineMemhard(_) => (WideSource::InlineMemhard, None),
|
||||
};
|
||||
wide_load_stmt(CoreDialect::Metal, &d, &a, ins.width, src, closed)
|
||||
}
|
||||
Op::Load => format!("{d} = {d} ^ {};", fetch(word_index(&a, false))),
|
||||
Op::WLoad => format!("{d} = {d} ^ {};", fetch(word_index(&a, true))),
|
||||
Op::Scratch => scratch_stmt(CoreDialect::Metal, &d, &a),
|
||||
};
|
||||
s.push_str(&format!(" {line} // {k}\n"));
|
||||
}
|
||||
|
|
@ -328,6 +542,9 @@ fn metal_program_impl(p: &Program, dataset_log2: u32, source: LoadSource, bound:
|
|||
s.push_str(" uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u);\n");
|
||||
s.push_str(" uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u);\n");
|
||||
s.push_str(" out[gid] = ((ulong)hi << 32) | (ulong)lo;\n");
|
||||
if p.has_scratch() {
|
||||
s.push_str(" }\n");
|
||||
}
|
||||
s.push_str("}\n");
|
||||
s
|
||||
}
|
||||
|
|
@ -379,8 +596,10 @@ fn cuda_instr_lines(p: &Program) -> String {
|
|||
Op::Rotr => format!("{d} = rotr_var({d}, {a});"),
|
||||
Op::Mad => format!("{d} = {a} * {b} + {d};"),
|
||||
Op::Shfl => format!("{d} = {d} ^ __shfl_xor_sync(0xffffffffu, {a}, {});", ins.mask),
|
||||
Op::Load if load_width(ins) > 1 => wide_load_stmt(CoreDialect::Cuda, &d, &a, ins.width, WideSource::Stored, None),
|
||||
Op::Load => format!("{d} = {d} ^ ds[{a} & mask];"),
|
||||
Op::WLoad => format!("{d} = {d} ^ ds[(__shfl_sync(0xffffffffu, {a}, 0) & wmask) + lane];"),
|
||||
Op::Scratch => scratch_stmt(CoreDialect::Cuda, &d, &a),
|
||||
};
|
||||
s.push_str(&format!(" {line} // {k} {}\n", ins.op.name()));
|
||||
}
|
||||
|
|
@ -448,8 +667,14 @@ pub fn cuda_kernel(p: &Program, memhard: Option<&MixParams>) -> String {
|
|||
s.push_str("// One hash per thread. blockDim.x is a multiple of 32; lane = threadIdx.x & 31 and every\n");
|
||||
s.push_str("// __shfl_xor_sync stays inside the lane's own warp, exactly like simd_shuffle_xor inside a\n");
|
||||
s.push_str("// 32-wide Metal SIMD group. Control flow is uniform, so the full 0xffffffff member mask is valid.\n");
|
||||
s.push_str("__global__ void igneum_hash(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask) {\n");
|
||||
s.push_str(" uint32_t gid = blockIdx.x * blockDim.x + threadIdx.x;\n");
|
||||
s.push_str(&scratch_prelude(p, CoreDialect::Cuda));
|
||||
let scratch_args = if p.has_scratch() { ", uint32_t* scratch, uint32_t groups, uint32_t salt" } else { "" };
|
||||
s.push_str(&format!("__global__ void igneum_hash(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask{scratch_args}) {{\n"));
|
||||
if p.has_scratch() {
|
||||
s.push_str(&persistent_prologue(CoreDialect::Cuda));
|
||||
} else {
|
||||
s.push_str(" uint32_t gid = blockIdx.x * blockDim.x + threadIdx.x;\n");
|
||||
}
|
||||
s.push_str(" uint32_t nonce = baseNonce + gid;\n");
|
||||
s.push_str(" uint32_t r0, r1, r2, r3, r4, r5, r6, r7;\n");
|
||||
if p.has_wide() {
|
||||
|
|
@ -464,6 +689,9 @@ pub fn cuda_kernel(p: &Program, memhard: Option<&MixParams>) -> String {
|
|||
s.push_str(" uint32_t lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u);\n");
|
||||
s.push_str(" uint32_t hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u);\n");
|
||||
s.push_str(" out[gid] = ((uint64_t)hi << 32) | (uint64_t)lo;\n");
|
||||
if p.has_scratch() {
|
||||
s.push_str(" }\n");
|
||||
}
|
||||
s.push_str("}\n");
|
||||
s.push('\n');
|
||||
s.push_str("// Host-side launch wrappers. Declared in program.h, called from host.cu.\n");
|
||||
|
|
@ -494,16 +722,28 @@ pub fn cuda_kernel(p: &Program, memhard: Option<&MixParams>) -> String {
|
|||
s.push_str("}\n");
|
||||
s.push('\n');
|
||||
}
|
||||
s.push_str(
|
||||
"cudaError_t igneum_launch_hash(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask,\n",
|
||||
);
|
||||
s.push_str(" uint32_t nonces, uint32_t blockWarps) {\n");
|
||||
s.push_str(" if (blockWarps == 0u || blockWarps > 32u) return cudaErrorInvalidValue;\n");
|
||||
s.push_str(" uint32_t block = 32u * blockWarps;\n");
|
||||
s.push_str(" if (nonces == 0u || (nonces % block) != 0u) return cudaErrorInvalidValue;\n");
|
||||
s.push_str(" igneum_hash<<<nonces / block, block>>>(ds, out, baseNonce, mask);\n");
|
||||
s.push_str(" return cudaGetLastError();\n");
|
||||
s.push_str("}\n");
|
||||
if p.has_scratch() {
|
||||
s.push_str("// Variant 5: the wrapper launches `warps` persistent warps over `nonces / 32` units (host.cu does not use it).\n");
|
||||
s.push_str("cudaError_t igneum_launch_hash(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask,\n");
|
||||
s.push_str(" uint32_t nonces, uint32_t blockWarps, uint32_t* scratch, uint32_t warps, uint32_t salt) {\n");
|
||||
s.push_str(" if (blockWarps == 0u || blockWarps > 32u || warps == 0u || (warps % blockWarps) != 0u) return cudaErrorInvalidValue;\n");
|
||||
s.push_str(" uint32_t block = 32u * blockWarps;\n");
|
||||
s.push_str(" if (nonces == 0u || (nonces % (32u * warps)) != 0u) return cudaErrorInvalidValue;\n");
|
||||
s.push_str(" igneum_hash<<<warps / blockWarps, block>>>(ds, out, baseNonce, mask, scratch, nonces / 32u, salt);\n");
|
||||
s.push_str(" return cudaGetLastError();\n");
|
||||
s.push_str("}\n");
|
||||
} else {
|
||||
s.push_str(
|
||||
"cudaError_t igneum_launch_hash(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask,\n",
|
||||
);
|
||||
s.push_str(" uint32_t nonces, uint32_t blockWarps) {\n");
|
||||
s.push_str(" if (blockWarps == 0u || blockWarps > 32u) return cudaErrorInvalidValue;\n");
|
||||
s.push_str(" uint32_t block = 32u * blockWarps;\n");
|
||||
s.push_str(" if (nonces == 0u || (nonces % block) != 0u) return cudaErrorInvalidValue;\n");
|
||||
s.push_str(" igneum_hash<<<nonces / block, block>>>(ds, out, baseNonce, mask);\n");
|
||||
s.push_str(" return cudaGetLastError();\n");
|
||||
s.push_str("}\n");
|
||||
}
|
||||
s.push('\n');
|
||||
s.push_str("cudaError_t igneum_hash_info(int* numRegs, int* blocksPerSM, uint32_t blockWarps) {\n");
|
||||
s.push_str(" cudaFuncAttributes attr;\n");
|
||||
|
|
@ -548,8 +788,14 @@ pub fn cuda_kernel_bound(p: &Program, memhard: Option<&MixParams>) -> String {
|
|||
s.push_str("__device__ __forceinline__ uint32_t rotr_var(uint32_t x, uint32_t n) { n &= 31u; return (x >> n) | (x << ((32u - n) & 31u)); }\n");
|
||||
s.push('\n');
|
||||
let _ = memhard; // the bound kernel reads the stored dataset in both constructions
|
||||
s.push_str("__global__ void igneum_hash_bound(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask, IgneumInitWords iw) {\n");
|
||||
s.push_str(" uint32_t gid = blockIdx.x * blockDim.x + threadIdx.x;\n");
|
||||
s.push_str(&scratch_prelude(p, CoreDialect::Cuda));
|
||||
let scratch_args = if p.has_scratch() { ", uint32_t* scratch, uint32_t groups, uint32_t salt" } else { "" };
|
||||
s.push_str(&format!("__global__ void igneum_hash_bound(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask, IgneumInitWords iw{scratch_args}) {{\n"));
|
||||
if p.has_scratch() {
|
||||
s.push_str(&persistent_prologue(CoreDialect::Cuda));
|
||||
} else {
|
||||
s.push_str(" uint32_t gid = blockIdx.x * blockDim.x + threadIdx.x;\n");
|
||||
}
|
||||
s.push_str(" uint32_t nonce = baseNonce + gid;\n");
|
||||
s.push_str(" uint32_t r0, r1, r2, r3, r4, r5, r6, r7;\n");
|
||||
if p.has_wide() {
|
||||
|
|
@ -568,18 +814,33 @@ pub fn cuda_kernel_bound(p: &Program, memhard: Option<&MixParams>) -> String {
|
|||
s.push_str(" uint32_t lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u);\n");
|
||||
s.push_str(" uint32_t hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u);\n");
|
||||
s.push_str(" out[gid] = ((uint64_t)hi << 32) | (uint64_t)lo;\n");
|
||||
if p.has_scratch() {
|
||||
s.push_str(" }\n");
|
||||
}
|
||||
s.push_str("}\n");
|
||||
s.push('\n');
|
||||
s.push_str(
|
||||
"cudaError_t igneum_launch_hash_bound(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask,\n",
|
||||
);
|
||||
s.push_str(" IgneumInitWords iw, uint32_t nonces, uint32_t blockWarps) {\n");
|
||||
s.push_str(" if (blockWarps == 0u || blockWarps > 32u) return cudaErrorInvalidValue;\n");
|
||||
s.push_str(" uint32_t block = 32u * blockWarps;\n");
|
||||
s.push_str(" if (nonces == 0u || (nonces % block) != 0u) return cudaErrorInvalidValue;\n");
|
||||
s.push_str(" igneum_hash_bound<<<nonces / block, block>>>(ds, out, baseNonce, mask, iw);\n");
|
||||
s.push_str(" return cudaGetLastError();\n");
|
||||
s.push_str("}\n");
|
||||
if p.has_scratch() {
|
||||
s.push_str("// Variant 5: the wrapper launches `warps` persistent warps over `nonces / 32` units (host.cu does not use it).\n");
|
||||
s.push_str("cudaError_t igneum_launch_hash_bound(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask,\n");
|
||||
s.push_str(" IgneumInitWords iw, uint32_t nonces, uint32_t blockWarps, uint32_t* scratch, uint32_t warps, uint32_t salt) {\n");
|
||||
s.push_str(" if (blockWarps == 0u || blockWarps > 32u || warps == 0u || (warps % blockWarps) != 0u) return cudaErrorInvalidValue;\n");
|
||||
s.push_str(" uint32_t block = 32u * blockWarps;\n");
|
||||
s.push_str(" if (nonces == 0u || (nonces % (32u * warps)) != 0u) return cudaErrorInvalidValue;\n");
|
||||
s.push_str(" igneum_hash_bound<<<warps / blockWarps, block>>>(ds, out, baseNonce, mask, iw, scratch, nonces / 32u, salt);\n");
|
||||
s.push_str(" return cudaGetLastError();\n");
|
||||
s.push_str("}\n");
|
||||
} else {
|
||||
s.push_str(
|
||||
"cudaError_t igneum_launch_hash_bound(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask,\n",
|
||||
);
|
||||
s.push_str(" IgneumInitWords iw, uint32_t nonces, uint32_t blockWarps) {\n");
|
||||
s.push_str(" if (blockWarps == 0u || blockWarps > 32u) return cudaErrorInvalidValue;\n");
|
||||
s.push_str(" uint32_t block = 32u * blockWarps;\n");
|
||||
s.push_str(" if (nonces == 0u || (nonces % block) != 0u) return cudaErrorInvalidValue;\n");
|
||||
s.push_str(" igneum_hash_bound<<<nonces / block, block>>>(ds, out, baseNonce, mask, iw);\n");
|
||||
s.push_str(" return cudaGetLastError();\n");
|
||||
s.push_str("}\n");
|
||||
}
|
||||
s.push('\n');
|
||||
s.push_str("cudaError_t igneum_hash_bound_info(int* numRegs, int* blocksPerSM, uint32_t blockWarps) {\n");
|
||||
s.push_str(" cudaFuncAttributes attr;\n");
|
||||
|
|
@ -614,8 +875,10 @@ fn opencl_instr_lines(p: &Program) -> String {
|
|||
Op::Rotr => format!("{d} = rotr_var({d}, {a});"),
|
||||
Op::Mad => format!("{d} = {a} * {b} + {d};"),
|
||||
Op::Shfl => format!("{{ uint t_; IGNEUM_SHFL_XOR(t_, {a}, {}u); {d} = {d} ^ t_; }}", ins.mask),
|
||||
Op::Load if load_width(ins) > 1 => wide_load_stmt(CoreDialect::OpenCl, &d, &a, ins.width, WideSource::Stored, None),
|
||||
Op::Load => format!("{d} = {d} ^ ds[{a} & mask];"),
|
||||
Op::WLoad => format!("{{ uint t_; IGNEUM_BCAST0(t_, {a}); {d} = {d} ^ ds[(t_ & wmask) + lane]; }}"),
|
||||
Op::Scratch => scratch_stmt(CoreDialect::OpenCl, &d, &a),
|
||||
};
|
||||
s.push_str(&format!(" {line} // {k} {}\n", ins.op.name()));
|
||||
}
|
||||
|
|
@ -631,8 +894,13 @@ pub fn opencl_kernel_bound(p: &Program, memhard: Option<&MixParams>) -> String {
|
|||
s.push_str(
|
||||
"// Header-bound variant (bind.rs): the init words come from initw, not SEEDW. Same body as igneum_hash.\n",
|
||||
);
|
||||
s.push_str("IGNEUM_KERNEL_HASH void igneum_hash_bound(__global const uint* ds, __global ulong* out, uint baseNonce, uint mask, __global const uint* initw) {\n");
|
||||
s.push_str(" uint gid = (uint)get_global_id(0);\n");
|
||||
let scratch_args = if p.has_scratch() { ", __global uint* scratch, uint groups, uint salt" } else { "" };
|
||||
s.push_str(&format!("IGNEUM_KERNEL_HASH void igneum_hash_bound(__global const uint* ds, __global ulong* out, uint baseNonce, uint mask, __global const uint* initw{scratch_args}) {{\n"));
|
||||
if p.has_scratch() {
|
||||
s.push_str(&persistent_prologue(CoreDialect::OpenCl));
|
||||
} else {
|
||||
s.push_str(" uint gid = (uint)get_global_id(0);\n");
|
||||
}
|
||||
s.push_str(" uint lid = (uint)get_local_id(0);\n");
|
||||
s.push_str(" uint nonce = baseNonce + gid;\n");
|
||||
s.push_str(" uint r0, r1, r2, r3, r4, r5, r6, r7;\n");
|
||||
|
|
@ -659,6 +927,9 @@ pub fn opencl_kernel_bound(p: &Program, memhard: Option<&MixParams>) -> String {
|
|||
s.push_str(" uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u);\n");
|
||||
s.push_str(" uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u);\n");
|
||||
s.push_str(" out[gid] = ((ulong)hi << 32) | (ulong)lo;\n");
|
||||
if p.has_scratch() {
|
||||
s.push_str(" }\n");
|
||||
}
|
||||
s.push_str("}\n");
|
||||
s
|
||||
}
|
||||
|
|
@ -686,6 +957,9 @@ pub fn opencl_kernel(p: &Program, memhard: Option<&MixParams>) -> String {
|
|||
s.push_str("#ifdef cl_khr_subgroups\n#pragma OPENCL EXTENSION cl_khr_subgroups : enable\n#endif\n");
|
||||
s.push_str("#ifdef cl_khr_subgroup_shuffle\n#pragma OPENCL EXTENSION cl_khr_subgroup_shuffle : enable\n#endif\n");
|
||||
s.push_str("#elif IGNEUM_EXCHANGE == 2\n#pragma OPENCL EXTENSION cl_intel_subgroups : enable\n#endif\n");
|
||||
if p.has_scratch() {
|
||||
s.push_str("#define IGNEUM_U4(a, b, c, d) ((uint4)((a), (b), (c), (d)))\n");
|
||||
}
|
||||
s.push_str("#else\n");
|
||||
s.push_str("// Not an OpenCL compiler: proto-opencl/emu compiles this file as C++ and supplies the built-ins and these two macros.\n");
|
||||
s.push_str("#include \"emu_opencl.h\"\n#endif\n");
|
||||
|
|
@ -751,8 +1025,14 @@ pub fn opencl_kernel(p: &Program, memhard: Option<&MixParams>) -> String {
|
|||
s.push_str("// One hash per work-item. IGNEUM_GROUP is a multiple of 32; lane = lid & 31 and every exchange stays inside the\n");
|
||||
s.push_str("// lane's own aligned run of 32 work-items, exactly like simd_shuffle_xor inside a 32-wide Metal SIMD group and\n");
|
||||
s.push_str("// __shfl_xor_sync inside a CUDA warp. Control flow is uniform (no branches at all).\n");
|
||||
s.push_str("IGNEUM_KERNEL_HASH void igneum_hash(__global const uint* ds, __global ulong* out, uint baseNonce, uint mask) {\n");
|
||||
s.push_str(" uint gid = (uint)get_global_id(0);\n");
|
||||
s.push_str(&scratch_prelude(p, CoreDialect::OpenCl));
|
||||
let scratch_args = if p.has_scratch() { ", __global uint* scratch, uint groups, uint salt" } else { "" };
|
||||
s.push_str(&format!("IGNEUM_KERNEL_HASH void igneum_hash(__global const uint* ds, __global ulong* out, uint baseNonce, uint mask{scratch_args}) {{\n"));
|
||||
if p.has_scratch() {
|
||||
s.push_str(&persistent_prologue(CoreDialect::OpenCl));
|
||||
} else {
|
||||
s.push_str(" uint gid = (uint)get_global_id(0);\n");
|
||||
}
|
||||
s.push_str(" uint lid = (uint)get_local_id(0);\n");
|
||||
s.push_str(" uint nonce = baseNonce + gid;\n");
|
||||
s.push_str(" uint r0, r1, r2, r3, r4, r5, r6, r7;\n");
|
||||
|
|
@ -774,6 +1054,9 @@ pub fn opencl_kernel(p: &Program, memhard: Option<&MixParams>) -> String {
|
|||
s.push_str(" uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u);\n");
|
||||
s.push_str(" uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u);\n");
|
||||
s.push_str(" out[gid] = ((ulong)hi << 32) | (ulong)lo;\n");
|
||||
if p.has_scratch() {
|
||||
s.push_str(" }\n");
|
||||
}
|
||||
s.push_str("}\n");
|
||||
s.push('\n');
|
||||
s.push_str("#if IGNEUM_EXCHANGE != 0\n");
|
||||
|
|
@ -828,6 +1111,8 @@ pub fn program_header(p: &Program, day: &str, ds: &DatasetSource) -> String {
|
|||
s.push_str(&format!("#define IGNEUM_LOADS_PER_HASH {}\n", p.loads_per_hash()));
|
||||
s.push_str(&format!("#define IGNEUM_WIDE_LOADS_PER_HASH {}\n", p.wide_loads_per_hash()));
|
||||
s.push_str(&format!("#define IGNEUM_OP_MIX {}\n", jstr(&p.op_mix())));
|
||||
s.push_str(&class_header_lines(p));
|
||||
s.push_str(&scratch_header_lines(p));
|
||||
s.push_str("// 0 = closed-form dataset (ds_elem), 1 = memory-hard cache construction (MEMHARD.md, memhard.h)\n");
|
||||
s.push_str(&format!("#define IGNEUM_DATASET_MODE {}\n", if memhard.is_some() { 1 } else { 0 }));
|
||||
s.push('\n');
|
||||
|
|
@ -854,10 +1139,15 @@ pub fn program_header(p: &Program, day: &str, ds: &DatasetSource) -> String {
|
|||
s.push_str("// Defined in kernel.cu. Both launch on the default stream and return cudaGetLastError().\n");
|
||||
s.push_str("cudaError_t igneum_launch_fill(uint32_t* ds, uint32_t nWords, uint32_t d0, uint32_t d1);\n");
|
||||
}
|
||||
s.push_str(
|
||||
"cudaError_t igneum_launch_hash(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask,\n",
|
||||
);
|
||||
s.push_str(" uint32_t nonces, uint32_t blockWarps);\n");
|
||||
if p.has_scratch() {
|
||||
s.push_str("cudaError_t igneum_launch_hash(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask,\n");
|
||||
s.push_str(" uint32_t nonces, uint32_t blockWarps, uint32_t* scratch, uint32_t warps, uint32_t salt);\n");
|
||||
} else {
|
||||
s.push_str(
|
||||
"cudaError_t igneum_launch_hash(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask,\n",
|
||||
);
|
||||
s.push_str(" uint32_t nonces, uint32_t blockWarps);\n");
|
||||
}
|
||||
s.push_str("cudaError_t igneum_hash_info(int* numRegs, int* blocksPerSM, uint32_t blockWarps);\n");
|
||||
s.push_str("#endif\n");
|
||||
s
|
||||
|
|
@ -1004,6 +1294,19 @@ pub fn program_json(p: &Program, day: &str, ds: &DatasetSource) -> String {
|
|||
s.push_str(&format!(" \"iterations\": {ITERATIONS},\n"));
|
||||
s.push_str(&format!(" \"instruction_count\": {INSTR_COUNT},\n"));
|
||||
s.push_str(&format!(" \"loads_per_hash\": {},\n", p.loads_per_hash()));
|
||||
if !p.class.is_v2() {
|
||||
let c = p.width_counts();
|
||||
s.push_str(&format!(" \"load_class\": {},\n", jstr(&p.class.name())));
|
||||
s.push_str(&format!(" \"load_slots\": {},\n", p.class.load_slots));
|
||||
s.push_str(&format!(" \"load_mix_percent_4_16_64\": [{}, {}, {}],\n", p.class.mix[0], p.class.mix[1], p.class.mix[2]));
|
||||
s.push_str(&format!(" \"load_width_counts_4_16_64\": [{}, {}, {}],\n", c[0], c[1], c[2]));
|
||||
s.push_str(&format!(" \"bytes_per_hash\": {},\n", p.bytes_per_hash()));
|
||||
if p.has_scratch() {
|
||||
s.push_str(&format!(" \"scratch_ops_per_hash\": {},\n", p.scratch_ops_per_hash()));
|
||||
s.push_str(&format!(" \"scratch\": \"variant 5 (measurement only): persistent warps; a 1 MiB scratch per warp of {SCRATCH_SLOTS} 16-byte slots per lane (lane-major); slot = src & 0x{SCRATCH_SLOT_MASK:x}; a slot reads as its fill (scratch_fill(seed words, unit base nonce, lane, slot, j) = splitmix32(((base + lane) ^ seed[j]) + slot * 0x9e3779b1 + (j + 1) * 0x85ebca77), j in 0..2) until the unit writes it; read w0 w1 w2 (behind a per-unit tag on the GPU), x = fold(dst, w0, w1, w2), dst = x, rewrite (x ^ w1, rotl(x, 7) ^ w2, x + w0)\",\n"));
|
||||
}
|
||||
s.push_str(&format!(" \"wide_load\": \"read-width experiment (5 October 2026, docs/plans/read-width.md), NOT the lottery hash: a load of W words (width field, 4 or 16) reads dataset[b .. b + W) with b = (src & mask) & ~(W - 1) and folds every word into dst: x = dst ^ w[0]; for j in 1..W: x = (rotl(x, {FOLD_ROT}) * 0x{FOLD_MUL:08x}) ^ w[j]; dst = x; width 1 is the plain load; the width is drawn per instruction from the class mix with one extra below(100) draw after the nine of version 2, and the program id is FNV-1a 64 over 'igneum-program-rw/' || generator_le32 || seed words || attempt_le32 || mix[3] || load_slots\",\n"));
|
||||
}
|
||||
s.push_str(&format!(
|
||||
" \"op_mix\": {{{}}},\n",
|
||||
p.histogram().iter().map(|(n, c)| format!("{}: {c}", jstr(n))).collect::<Vec<_>>().join(", ")
|
||||
|
|
@ -1071,6 +1374,23 @@ pub fn program_json(p: &Program, day: &str, ds: &DatasetSource) -> String {
|
|||
s.push_str(" \"instructions\": [\n");
|
||||
let n = p.instrs.len();
|
||||
for (k, ins) in p.instrs.iter().enumerate() {
|
||||
if !p.class.is_v2() {
|
||||
s.push_str(&format!(
|
||||
" {{\"i\": {k}, \"op\": {}, \"dst\": {}, \"src\": {}, \"src2\": {}, \"imm\": {}, \"imm2\": {}, \"rot\": {}, \"bit\": {}, \"mask\": {}, \"width\": {}}}",
|
||||
jstr(ins.op.name()),
|
||||
ins.dst,
|
||||
ins.src,
|
||||
ins.src2,
|
||||
jhex(ins.imm),
|
||||
jhex(ins.imm2),
|
||||
ins.rot,
|
||||
ins.bit,
|
||||
ins.mask,
|
||||
ins.width
|
||||
));
|
||||
s.push_str(if k + 1 < n { ",\n" } else { "\n" });
|
||||
continue;
|
||||
}
|
||||
s.push_str(&format!(
|
||||
" {{\"i\": {k}, \"op\": {}, \"dst\": {}, \"src\": {}, \"src2\": {}, \"imm\": {}, \"imm2\": {}, \"rot\": {}, \"bit\": {}, \"mask\": {}}}",
|
||||
jstr(ins.op.name()),
|
||||
|
|
|
|||
|
|
@ -18,6 +18,13 @@
|
|||
//! The retired version 1 generator (op rolled per instruction with a 25 percent load weight, no acceptance) is
|
||||
//! kept as [`generate_v1`] for the census tool and the lever measurements of `proto-metal/MEMHARD.md`. Its
|
||||
//! programs are not the lottery hash and no pack or vector of version 1 is current.
|
||||
//!
|
||||
//! Read-width experiment (5 October 2026, gate 1, `docs/plans/read-width.md`; NOT the lottery hash, behind
|
||||
//! [`LoadClass`]): a program class whose `load` reads `W` bytes (4, 16 or 64: 1, 4 or 16 words, aligned to `W`)
|
||||
//! and folds every word into `dst` (`verify::fold_words`), with the width fixed per class or drawn per load from
|
||||
//! an era-fixed mix. The default class [`LoadClass::V2`] is the generator above, draw for draw and byte for byte;
|
||||
//! every other class takes one extra draw per instruction (the width roll), so its program stream differs from
|
||||
//! version 2 and its program id carries the class.
|
||||
|
||||
use crate::accept::{check, Reject};
|
||||
use crate::seed::{fnv1a64, program_rng, seed_words_from_bytes};
|
||||
|
|
@ -53,6 +60,9 @@ pub enum Op {
|
|||
Load,
|
||||
/// Warp-coalesced load (lever b of the version 1 generator). Never emitted by version 2.
|
||||
WLoad,
|
||||
/// Scratch read-modify-write (read-width experiment, variant 5, 5 October 2026): a 16-byte slot of the lane's
|
||||
/// own 32 KiB of the warp's 1 MiB scratch, read, folded into dst, rewritten. Never emitted by version 2.
|
||||
Scratch,
|
||||
}
|
||||
|
||||
impl Op {
|
||||
|
|
@ -71,6 +81,7 @@ impl Op {
|
|||
Op::Shfl => "shfl",
|
||||
Op::Load => "load",
|
||||
Op::WLoad => "wload",
|
||||
Op::Scratch => "scratch",
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -88,6 +99,7 @@ impl Op {
|
|||
"shfl" => Op::Shfl,
|
||||
"load" => Op::Load,
|
||||
"wload" => Op::WLoad,
|
||||
"scratch" => Op::Scratch,
|
||||
_ => return None,
|
||||
})
|
||||
}
|
||||
|
|
@ -95,11 +107,13 @@ impl Op {
|
|||
/// An injecting op: bijective in `dst` and bringing another register (or the dataset) in. The acceptance
|
||||
/// rule's part (b) requires one such write per register.
|
||||
pub fn injects(self) -> bool {
|
||||
matches!(self, Op::Add | Op::Sub | Op::Xor | Op::Mad | Op::Shfl | Op::Load | Op::WLoad)
|
||||
matches!(self, Op::Add | Op::Sub | Op::Xor | Op::Mad | Op::Shfl | Op::Load | Op::WLoad | Op::Scratch)
|
||||
}
|
||||
|
||||
/// A memory operation: the fresh-source rule, the acceptance tests and the load count treat the scratch
|
||||
/// read-modify-write as a load (it is one of the program's 128 memory operations).
|
||||
pub fn is_load(self) -> bool {
|
||||
matches!(self, Op::Load | Op::WLoad)
|
||||
matches!(self, Op::Load | Op::WLoad | Op::Scratch)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -124,6 +138,9 @@ pub struct Instr {
|
|||
pub bit: u8,
|
||||
/// Shuffle xor mask: 1, 2, 4, 8 or 16.
|
||||
pub mask: u8,
|
||||
/// Words read by a `load`: 1 (the lottery hash, 4 bytes), 4 or 16 (the read-width experiment). 1 on every
|
||||
/// other op.
|
||||
pub width: u8,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
|
|
@ -139,9 +156,144 @@ pub struct Program {
|
|||
pub generator: u32,
|
||||
/// Attempt index: 0 for the bare seed, `k` for the k-th re-derivation after rejections.
|
||||
pub attempt: u32,
|
||||
/// The load class: [`LoadClass::V2`] for the lottery hash, another for the read-width experiment.
|
||||
pub class: LoadClass,
|
||||
pub instrs: Vec<Instr>,
|
||||
}
|
||||
|
||||
/// The widths a `load` may read, in words: 4, 16 and 64 bytes.
|
||||
pub const WIDTH_WORDS: [u8; 3] = [1, 4, 16];
|
||||
|
||||
/// The load class of a program (read-width experiment, 5 October 2026). `mix` holds the percent weights of the
|
||||
/// three widths of [`WIDTH_WORDS`] (sum 100); `load_slots` the number of `load` instructions per program.
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct LoadClass {
|
||||
pub mix: [u8; 3],
|
||||
pub load_slots: u8,
|
||||
/// Variant 5: `Some(k)` gives the program a 1 MiB per-warp scratch (the kernels run persistent warps) and
|
||||
/// turns `k` of the load slots into scratch read-modify-writes. `None` for every other class.
|
||||
pub scratch: Option<u8>,
|
||||
}
|
||||
|
||||
/// Scratch geometry (variant 5): 2^11 slots of 16 bytes per lane (32 KiB), 32 lanes per warp (1 MiB), lane-major.
|
||||
pub const SCRATCH_SLOT_BITS: u32 = 11;
|
||||
pub const SCRATCH_SLOTS: usize = 1 << SCRATCH_SLOT_BITS;
|
||||
pub const SCRATCH_SLOT_MASK: u32 = SCRATCH_SLOTS as u32 - 1;
|
||||
pub const SCRATCH_WORDS_PER_LANE: usize = SCRATCH_SLOTS * 4;
|
||||
pub const SCRATCH_BYTES_PER_WARP: usize = SCRATCH_WORDS_PER_LANE * 4 * LANES;
|
||||
|
||||
impl LoadClass {
|
||||
/// Generator version 2 as adopted on 4 October 2026: 16 loads of one word. The lottery hash.
|
||||
pub const V2: LoadClass = LoadClass { mix: [100, 0, 0], load_slots: LOAD_SLOTS as u8, scratch: None };
|
||||
|
||||
/// A fixed width (1, 4 or 16 words) with `load_slots` loads per program.
|
||||
pub fn fixed(width_words: u8, load_slots: u8) -> LoadClass {
|
||||
let mut mix = [0u8; 3];
|
||||
let i = WIDTH_WORDS.iter().position(|&w| w == width_words).expect("width must be 1, 4 or 16 words");
|
||||
mix[i] = 100;
|
||||
LoadClass { mix, load_slots, scratch: None }
|
||||
}
|
||||
|
||||
/// Per-load width drawn from `mix` (percent for 4, 16, 64 bytes), 16 loads per program.
|
||||
pub fn mixed(mix: [u8; 3]) -> LoadClass {
|
||||
assert_eq!(mix.iter().map(|&m| m as u32).sum::<u32>(), 100, "the mix must sum to 100");
|
||||
LoadClass { mix, load_slots: LOAD_SLOTS as u8, scratch: None }
|
||||
}
|
||||
|
||||
/// Variant 5: version 2 widths, 16 memory operations of which `k` are scratch read-modify-writes.
|
||||
pub fn scratch(k: u8) -> LoadClass {
|
||||
assert!(k as usize <= LOAD_SLOTS);
|
||||
LoadClass { mix: [100, 0, 0], load_slots: LOAD_SLOTS as u8, scratch: Some(k) }
|
||||
}
|
||||
|
||||
/// Parse "p4,p16,p64" or one of the names of [`LoadClass::name`].
|
||||
pub fn parse(s: &str) -> Option<LoadClass> {
|
||||
if let Some(k) = s.strip_prefix("scr") {
|
||||
let k: u8 = k.parse().ok()?;
|
||||
if k as usize > LOAD_SLOTS {
|
||||
return None;
|
||||
}
|
||||
return Some(LoadClass::scratch(k));
|
||||
}
|
||||
let (mix_s, slots) = match s.split_once("x") {
|
||||
Some((m, n)) if !m.contains(',') => (m, n.parse::<u8>().ok()?),
|
||||
_ => (s, LOAD_SLOTS as u8),
|
||||
};
|
||||
let mix: [u8; 3] = match mix_s {
|
||||
"v2" => return Some(LoadClass::V2),
|
||||
"w4" => [100, 0, 0],
|
||||
"w16" => [0, 100, 0],
|
||||
"w64" => [0, 0, 100],
|
||||
m => {
|
||||
let v: Vec<u8> = m.split(',').map(|x| x.trim().parse::<u8>().ok()).collect::<Option<Vec<_>>>()?;
|
||||
if v.len() != 3 || v.iter().map(|&x| x as u32).sum::<u32>() != 100 {
|
||||
return None;
|
||||
}
|
||||
[v[0], v[1], v[2]]
|
||||
}
|
||||
};
|
||||
if slots == 0 || slots as usize >= INSTR_COUNT {
|
||||
return None;
|
||||
}
|
||||
Some(LoadClass { mix, load_slots: slots, scratch: None })
|
||||
}
|
||||
|
||||
/// Scratch read-modify-writes per program (0 without a scratch).
|
||||
pub fn scratch_slots(&self) -> usize {
|
||||
self.scratch.unwrap_or(0) as usize
|
||||
}
|
||||
|
||||
pub fn is_v2(&self) -> bool {
|
||||
*self == LoadClass::V2
|
||||
}
|
||||
|
||||
/// "v2", "w4", "w16", "w64", "w64x4", "mix50-35-15", "mix25-50-25x8", "scr4".
|
||||
pub fn name(&self) -> String {
|
||||
if self.is_v2() {
|
||||
return "v2".to_string();
|
||||
}
|
||||
if let Some(k) = self.scratch {
|
||||
return format!("scr{k}");
|
||||
}
|
||||
let base = match self.mix {
|
||||
[100, 0, 0] => "w4".to_string(),
|
||||
[0, 100, 0] => "w16".to_string(),
|
||||
[0, 0, 100] => "w64".to_string(),
|
||||
[a, b, c] => format!("mix{a}-{b}-{c}"),
|
||||
};
|
||||
if self.load_slots as usize == LOAD_SLOTS {
|
||||
base
|
||||
} else {
|
||||
format!("{base}x{}", self.load_slots)
|
||||
}
|
||||
}
|
||||
|
||||
/// The width in words of a load whose width roll (0..99) is `roll`: the first entry of the mix whose cumulative
|
||||
/// weight exceeds the roll.
|
||||
pub fn width_for_roll(&self, roll: u64) -> u8 {
|
||||
let mut acc = 0u64;
|
||||
for (i, &m) in self.mix.iter().enumerate() {
|
||||
acc += m as u64;
|
||||
if roll < acc {
|
||||
return WIDTH_WORDS[i];
|
||||
}
|
||||
}
|
||||
WIDTH_WORDS[2]
|
||||
}
|
||||
|
||||
/// Expected dataset bytes read per hash: dataset loads per hash times the mean width (scratch traffic apart).
|
||||
pub fn expected_bytes_per_hash(&self) -> f64 {
|
||||
let mean = self.mix.iter().zip(WIDTH_WORDS.iter()).map(|(&m, &w)| m as f64 / 100.0 * w as f64 * 4.0).sum::<f64>();
|
||||
(self.load_slots as usize - self.scratch_slots()) as f64 * ITERATIONS as f64 * mean
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for LoadClass {
|
||||
fn default() -> Self {
|
||||
LoadClass::V2
|
||||
}
|
||||
}
|
||||
|
||||
impl Program {
|
||||
pub fn loads_per_hash(&self) -> usize {
|
||||
self.instrs.iter().filter(|i| i.op.is_load()).count() * ITERATIONS
|
||||
|
|
@ -152,6 +304,27 @@ impl Program {
|
|||
pub fn has_wide(&self) -> bool {
|
||||
self.instrs.iter().any(|i| i.op == Op::WLoad)
|
||||
}
|
||||
/// Dataset bytes read per hash: 4 per one-word load, 16 and 64 for the wider loads of the experiment.
|
||||
pub fn bytes_per_hash(&self) -> usize {
|
||||
self.instrs.iter().filter(|i| i.op == Op::Load).map(|i| i.width as usize * 4).sum::<usize>() * ITERATIONS
|
||||
}
|
||||
/// Scratch read-modify-writes per hash (variant 5): each reads 16 bytes and writes 16 bytes.
|
||||
pub fn scratch_ops_per_hash(&self) -> usize {
|
||||
self.instrs.iter().filter(|i| i.op == Op::Scratch).count() * ITERATIONS
|
||||
}
|
||||
pub fn has_scratch(&self) -> bool {
|
||||
self.class.scratch.is_some()
|
||||
}
|
||||
/// Width histogram of the loads, in words: (1, 4, 16) counts.
|
||||
pub fn width_counts(&self) -> [usize; 3] {
|
||||
let mut c = [0usize; 3];
|
||||
for i in self.instrs.iter().filter(|i| i.op == Op::Load) {
|
||||
if let Some(k) = WIDTH_WORDS.iter().position(|&w| w == i.width) {
|
||||
c[k] += 1;
|
||||
}
|
||||
}
|
||||
c
|
||||
}
|
||||
/// Distinct dataset items a 32-lane warp touches per hash: 32 per plain load, 2 per wide load.
|
||||
pub fn items_per_warp(&self) -> usize {
|
||||
(self.loads_per_hash() - self.wide_loads_per_hash()) * 32 + self.wide_loads_per_hash() * 2
|
||||
|
|
@ -177,7 +350,11 @@ impl Program {
|
|||
/// || attempt_le32`. Written into every pack so a version 1 program, or another attempt of the same seed,
|
||||
/// can never be mistaken for this one.
|
||||
pub fn program_id(&self) -> u64 {
|
||||
program_id(self.generator, &self.seed, self.attempt)
|
||||
if self.class.is_v2() {
|
||||
program_id(self.generator, &self.seed, self.attempt)
|
||||
} else {
|
||||
program_id_class(self.generator, &self.seed, self.attempt, &self.class)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -192,6 +369,28 @@ pub fn program_id(generator: u32, seed: &[u32; 8], attempt: u32) -> u64 {
|
|||
fnv1a64(&b)
|
||||
}
|
||||
|
||||
/// Domain tag of the program id of a read-width class (never collides with [`PROGRAM_ID_TAG`]).
|
||||
pub const PROGRAM_ID_TAG_RW: &[u8] = b"igneum-program-rw/";
|
||||
|
||||
/// The program id of a non-default class: the tag, then the same fields as [`program_id`], then the three mix
|
||||
/// percentages and the slot count as bytes.
|
||||
pub fn program_id_class(generator: u32, seed: &[u32; 8], attempt: u32, class: &LoadClass) -> u64 {
|
||||
let mut b = Vec::with_capacity(PROGRAM_ID_TAG_RW.len() + 4 + 32 + 4 + 4);
|
||||
b.extend_from_slice(PROGRAM_ID_TAG_RW);
|
||||
b.extend_from_slice(&generator.to_le_bytes());
|
||||
for w in seed {
|
||||
b.extend_from_slice(&w.to_le_bytes());
|
||||
}
|
||||
b.extend_from_slice(&attempt.to_le_bytes());
|
||||
b.extend_from_slice(&class.mix);
|
||||
b.push(class.load_slots);
|
||||
if let Some(k) = class.scratch {
|
||||
b.extend_from_slice(b"scratch/");
|
||||
b.push(k);
|
||||
}
|
||||
fnv1a64(&b)
|
||||
}
|
||||
|
||||
/// Weights of the ten non-load families under version 2, in draw order. Sum 75. The load family has no
|
||||
/// weight: its count is fixed by [`LOAD_SLOTS`].
|
||||
pub const NONLOAD_WEIGHTS: [(Op, u64); 10] = [
|
||||
|
|
@ -237,20 +436,39 @@ pub fn attempt_words(seed_bytes: &[u8], attempt: u32) -> [u32; 8] {
|
|||
/// One version 2 candidate from its seed words, before the acceptance rule. Spec 01 section 1.4.3: 16 slot draws,
|
||||
/// then nine draws per instruction, 592 per program.
|
||||
pub fn candidate_from_words(seed_string: &str, seed_bytes: &[u8], seed: [u32; 8], attempt: u32) -> Program {
|
||||
candidate_from_words_class(seed_string, seed_bytes, seed, attempt, LoadClass::V2)
|
||||
}
|
||||
|
||||
/// [`candidate_from_words`] for a load class. For [`LoadClass::V2`] this is the version 2 draw stream exactly;
|
||||
/// for any other class the slot count is the class's and every instruction takes a tenth draw, `below(100)`,
|
||||
/// the width roll (used only on a load slot, drawn on every slot so the stream stays uniform).
|
||||
pub fn candidate_from_words_class(
|
||||
seed_string: &str,
|
||||
seed_bytes: &[u8],
|
||||
seed: [u32; 8],
|
||||
attempt: u32,
|
||||
class: LoadClass,
|
||||
) -> Program {
|
||||
let mut rng = program_rng(&seed);
|
||||
// (1) Load slots: a uniform 16-subset of 1..63 by partial Fisher-Yates. Instruction 0 is never a load.
|
||||
let slots = class.load_slots as usize;
|
||||
// (1) Load slots: a uniform subset of 1..63 by partial Fisher-Yates. Instruction 0 is never a load.
|
||||
let mut p: [u8; INSTR_COUNT - 1] = [0; INSTR_COUNT - 1];
|
||||
for (i, slot) in p.iter_mut().enumerate() {
|
||||
*slot = (i + 1) as u8;
|
||||
}
|
||||
for i in 0..LOAD_SLOTS {
|
||||
for i in 0..slots {
|
||||
let j = i + rng.below((INSTR_COUNT - 1 - i) as u64) as usize;
|
||||
p.swap(i, j);
|
||||
}
|
||||
let mut is_load = [false; INSTR_COUNT];
|
||||
for &slot in &p[..LOAD_SLOTS] {
|
||||
for &slot in &p[..slots] {
|
||||
is_load[slot as usize] = true;
|
||||
}
|
||||
// Variant 5: the first k drawn load slots (a uniform k-subset, the draw order is random) are scratch ops.
|
||||
let mut is_scratch = [false; INSTR_COUNT];
|
||||
for &slot in &p[..class.scratch_slots()] {
|
||||
is_scratch[slot as usize] = true;
|
||||
}
|
||||
// (2) The instructions. `fresh[r]`: r was written by an earlier instruction and no load has read it since.
|
||||
let mut fresh = [false; 8];
|
||||
let mut instrs = Vec::with_capacity(INSTR_COUNT);
|
||||
|
|
@ -265,10 +483,10 @@ pub fn candidate_from_words(seed_string: &str, seed_bytes: &[u8], seed: [u32; 8]
|
|||
roll -= w;
|
||||
}
|
||||
if is_load[k] {
|
||||
op = Op::Load;
|
||||
op = if is_scratch[k] { Op::Scratch } else { Op::Load };
|
||||
}
|
||||
let dst = rng.below(8);
|
||||
let src = if op == Op::Load {
|
||||
let src = if op.is_load() {
|
||||
let mut eligible = [0u64; 8];
|
||||
let mut n = 0usize;
|
||||
for r in 0..8u64 {
|
||||
|
|
@ -301,11 +519,13 @@ pub fn candidate_from_words(seed_string: &str, seed_bytes: &[u8], seed: [u32; 8]
|
|||
let rot = 1 + rng.below(31) as u32;
|
||||
let bit = rng.below(32);
|
||||
let mask = 1u8 << rng.below(5);
|
||||
if op == Op::Load {
|
||||
let width = if class.is_v2() { 1 } else { class.width_for_roll(rng.below(100)) };
|
||||
let width = if op == Op::Load { width } else { 1 };
|
||||
if op.is_load() {
|
||||
fresh[src as usize] = false;
|
||||
}
|
||||
fresh[dst as usize] = true;
|
||||
instrs.push(Instr { op, dst: dst as u8, src: src as u8, src2: b as u8, imm, imm2, rot, bit: bit as u8, mask });
|
||||
instrs.push(Instr { op, dst: dst as u8, src: src as u8, src2: b as u8, imm, imm2, rot, bit: bit as u8, mask, width });
|
||||
}
|
||||
Program {
|
||||
seed_string: seed_string.to_string(),
|
||||
|
|
@ -313,6 +533,7 @@ pub fn candidate_from_words(seed_string: &str, seed_bytes: &[u8], seed: [u32; 8]
|
|||
seed,
|
||||
generator: GENERATOR_VERSION,
|
||||
attempt,
|
||||
class,
|
||||
instrs,
|
||||
}
|
||||
}
|
||||
|
|
@ -322,6 +543,11 @@ pub fn candidate(seed_string: &str, seed_bytes: &[u8], attempt: u32) -> Program
|
|||
candidate_from_words(seed_string, seed_bytes, attempt_words(seed_bytes, attempt), attempt)
|
||||
}
|
||||
|
||||
/// [`candidate`] for a load class.
|
||||
pub fn candidate_class(seed_string: &str, seed_bytes: &[u8], attempt: u32, class: LoadClass) -> Program {
|
||||
candidate_from_words_class(seed_string, seed_bytes, attempt_words(seed_bytes, attempt), attempt, class)
|
||||
}
|
||||
|
||||
/// Why no program could be derived from a seed.
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct Exhausted {
|
||||
|
|
@ -342,9 +568,14 @@ impl std::error::Error for Exhausted {}
|
|||
/// This is what the chain calls (`Epoch::from_seed_bytes`) with the 32-byte epoch seed, and what the packs call
|
||||
/// with the UTF-8 of a seed string.
|
||||
pub fn try_generate_from_seed_bytes(seed_string: &str, seed_bytes: &[u8]) -> Result<Program, Exhausted> {
|
||||
try_generate_class(seed_string, seed_bytes, LoadClass::V2)
|
||||
}
|
||||
|
||||
/// [`try_generate_from_seed_bytes`] for a load class.
|
||||
pub fn try_generate_class(seed_string: &str, seed_bytes: &[u8], class: LoadClass) -> Result<Program, Exhausted> {
|
||||
let mut last = None;
|
||||
for attempt in 0..MAX_ATTEMPTS {
|
||||
let p = candidate(seed_string, seed_bytes, attempt);
|
||||
let p = candidate_class(seed_string, seed_bytes, attempt, class);
|
||||
match check(&p) {
|
||||
Ok(_) => return Ok(p),
|
||||
Err(r) => last = Some(r),
|
||||
|
|
@ -358,16 +589,31 @@ pub fn generate_from_seed_bytes(seed_string: &str, seed_bytes: &[u8]) -> Program
|
|||
try_generate_from_seed_bytes(seed_string, seed_bytes).unwrap_or_else(|e| panic!("{e}"))
|
||||
}
|
||||
|
||||
/// [`generate_from_seed_bytes`] for a load class.
|
||||
pub fn generate_from_seed_bytes_class(seed_string: &str, seed_bytes: &[u8], class: LoadClass) -> Program {
|
||||
try_generate_class(seed_string, seed_bytes, class).unwrap_or_else(|e| panic!("{e}"))
|
||||
}
|
||||
|
||||
/// The program of a seed string (its UTF-8 bytes are the program seed).
|
||||
pub fn generate(seed_string: &str) -> Program {
|
||||
generate_from_seed_bytes(seed_string, seed_string.as_bytes())
|
||||
}
|
||||
|
||||
/// [`generate`] for a load class.
|
||||
pub fn generate_class(seed_string: &str, class: LoadClass) -> Program {
|
||||
generate_from_seed_bytes_class(seed_string, seed_string.as_bytes(), class)
|
||||
}
|
||||
|
||||
/// Every candidate of a seed up to and including the accepted one, with each rejection. For reports and tests.
|
||||
pub fn attempts(seed_string: &str, seed_bytes: &[u8]) -> Vec<(Program, Result<(), Reject>)> {
|
||||
attempts_class(seed_string, seed_bytes, LoadClass::V2)
|
||||
}
|
||||
|
||||
/// [`attempts`] for a load class.
|
||||
pub fn attempts_class(seed_string: &str, seed_bytes: &[u8], class: LoadClass) -> Vec<(Program, Result<(), Reject>)> {
|
||||
let mut out = Vec::new();
|
||||
for attempt in 0..MAX_ATTEMPTS {
|
||||
let p = candidate(seed_string, seed_bytes, attempt);
|
||||
let p = candidate_class(seed_string, seed_bytes, attempt, class);
|
||||
let verdict = check(&p).map(|_| ());
|
||||
let accepted = verdict.is_ok();
|
||||
out.push((p, verdict));
|
||||
|
|
@ -455,7 +701,7 @@ pub fn generate_v1_from_words(seed_string: &str, seed: [u32; 8], cfg: &Generator
|
|||
if op == Op::Load && bit * 100 < cfg.wide_frac * 32 {
|
||||
op = Op::WLoad;
|
||||
}
|
||||
instrs.push(Instr { op, dst: dst as u8, src: a as u8, src2: b as u8, imm, imm2, rot, bit: bit as u8, mask });
|
||||
instrs.push(Instr { op, dst: dst as u8, src: a as u8, src2: b as u8, imm, imm2, rot, bit: bit as u8, mask, width: 1 });
|
||||
}
|
||||
Program {
|
||||
seed_string: seed_string.to_string(),
|
||||
|
|
@ -463,6 +709,7 @@ pub fn generate_v1_from_words(seed_string: &str, seed: [u32; 8], cfg: &Generator
|
|||
seed,
|
||||
generator: 1,
|
||||
attempt: 0,
|
||||
class: LoadClass::V2,
|
||||
instrs,
|
||||
}
|
||||
}
|
||||
|
|
@ -565,6 +812,81 @@ mod tests {
|
|||
assert_ne!(program_id(2, &p.seed, 0), program_id(2, &p.seed, 1));
|
||||
}
|
||||
|
||||
/// The read-width classes (5 October 2026): the default class is the version 2 stream exactly; a class
|
||||
/// program has its slot count, widths from its mix only, and an id that separates it from version 2 and from
|
||||
/// the other classes.
|
||||
#[test]
|
||||
fn load_classes() {
|
||||
let v2 = candidate("igneum-genesis", b"igneum-genesis", 0);
|
||||
let same = candidate_class("igneum-genesis", b"igneum-genesis", 0, LoadClass::V2);
|
||||
assert_eq!(v2, same);
|
||||
assert!(v2.instrs.iter().all(|i| i.width == 1));
|
||||
assert_eq!(v2.bytes_per_hash(), 512);
|
||||
assert_eq!(LoadClass::parse("w16"), Some(LoadClass::fixed(4, 16)));
|
||||
assert_eq!(LoadClass::parse("w64x4"), Some(LoadClass::fixed(16, 4)));
|
||||
assert_eq!(LoadClass::parse("50,35,15"), Some(LoadClass::mixed([50, 35, 15])));
|
||||
assert_eq!(LoadClass::parse("v2"), Some(LoadClass::V2));
|
||||
assert_eq!(LoadClass::parse("50,35,10"), None);
|
||||
assert_eq!(LoadClass::fixed(16, 4).name(), "w64x4");
|
||||
assert_eq!(LoadClass::mixed([25, 50, 25]).name(), "mix25-50-25");
|
||||
// W = 4 with 16 slots IS the lottery hash: the w4 name parses to the default class
|
||||
assert_eq!(LoadClass::fixed(1, 16), LoadClass::V2);
|
||||
assert_eq!(LoadClass::parse("w4"), Some(LoadClass::V2));
|
||||
assert_eq!(LoadClass::fixed(1, 16).name(), "v2");
|
||||
assert_eq!(LoadClass::fixed(1, 8).name(), "w4x8");
|
||||
assert!((LoadClass::mixed([50, 35, 15]).expected_bytes_per_hash() - 2201.6).abs() < 1e-6);
|
||||
assert!((LoadClass::fixed(16, 4).expected_bytes_per_hash() - 2048.0).abs() < 1e-9);
|
||||
let mut ids = std::collections::HashSet::new();
|
||||
ids.insert(v2.program_id());
|
||||
for (name, slots, widths) in [("w4x8", 8, vec![1u8]), ("w16", 16, vec![4]), ("w64", 16, vec![16]), ("w64x4", 4, vec![16]), ("50,35,15", 16, vec![1, 4, 16]), ("25,50,25", 16, vec![1, 4, 16])] {
|
||||
let c = LoadClass::parse(name).unwrap();
|
||||
let p = candidate_class("igneum-genesis", b"igneum-genesis", 0, c);
|
||||
assert_eq!(p.class, c);
|
||||
assert_eq!(p.instrs.len(), INSTR_COUNT);
|
||||
assert_eq!(p.loads_per_hash(), 8 * slots);
|
||||
assert_ne!(p.instrs[0].op, Op::Load);
|
||||
for ins in &p.instrs {
|
||||
if ins.op == Op::Load {
|
||||
assert!(widths.contains(&ins.width), "{name}: width {}", ins.width);
|
||||
} else {
|
||||
assert_eq!(ins.width, 1);
|
||||
}
|
||||
}
|
||||
assert!(ids.insert(p.program_id()), "{name}: program id collides");
|
||||
}
|
||||
// variant 5: k scratch ops among the 16 memory operations, the rest one-word loads
|
||||
for k in [0u8, 2, 4, 8] {
|
||||
let c = LoadClass::parse(&format!("scr{k}")).unwrap();
|
||||
assert_eq!(c, LoadClass::scratch(k));
|
||||
assert_eq!(c.name(), format!("scr{k}"));
|
||||
let p = candidate_class("igneum-genesis", b"igneum-genesis", 0, c);
|
||||
assert_eq!(p.loads_per_hash(), 128);
|
||||
assert_eq!(p.scratch_ops_per_hash(), 8 * k as usize);
|
||||
assert_eq!(p.bytes_per_hash(), (16 - k as usize) * 8 * 4);
|
||||
assert!(p.instrs.iter().all(|i| i.width == 1));
|
||||
assert!(ids.insert(p.program_id()), "scr{k}: program id collides");
|
||||
}
|
||||
assert!(!LoadClass::scratch(0).is_v2());
|
||||
// a class with the version 2 widths but another slot count takes the extra roll: a different stream
|
||||
let w4x8 = candidate_class("igneum-genesis", b"igneum-genesis", 0, LoadClass::fixed(1, 8));
|
||||
assert_ne!(w4x8.instrs, v2.instrs);
|
||||
// the mix draws every width over a population
|
||||
let mut counts = [0usize; 3];
|
||||
for i in 0..200u32 {
|
||||
let s = format!("igneum-rw-mix/{i}");
|
||||
let p = candidate_class(&s, s.as_bytes(), 0, LoadClass::mixed([50, 35, 15]));
|
||||
let c = p.width_counts();
|
||||
for k in 0..3 {
|
||||
counts[k] += c[k];
|
||||
}
|
||||
}
|
||||
let total = (counts[0] + counts[1] + counts[2]) as f64;
|
||||
assert_eq!(total as usize, 200 * 16);
|
||||
assert!((counts[0] as f64 / total - 0.50).abs() < 0.05, "{counts:?}");
|
||||
assert!((counts[1] as f64 / total - 0.35).abs() < 0.05, "{counts:?}");
|
||||
assert!((counts[2] as f64 / total - 0.15).abs() < 0.05, "{counts:?}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn generate_returns_an_accepted_program() {
|
||||
let p = generate("igneum-genesis");
|
||||
|
|
|
|||
|
|
@ -7,8 +7,12 @@
|
|||
//! [--epoch-hex <64 hex> --day-hex <hex>] byte seeds instead of strings (Epoch::from_seed_bytes)
|
||||
//! igneum-pow accept --seed <s> [--epoch-hex <64 hex>] every candidate of the seed with its verdict (spec 01 section 1.4.6)
|
||||
//! igneum-pow show --seed <s> [--epoch-hex <64 hex>] the accepted program, one instruction per line
|
||||
//!
|
||||
//! Read-width experiment (5 October 2026, docs/plans/read-width.md): `--class v2|w4|w16|w64|w64x4|p4,p16,p64[xN]`
|
||||
//! on every command selects the load class (default v2, the lottery hash). Nothing in a v2 run changes.
|
||||
|
||||
use igneum_pow::emit::export_pack;
|
||||
use igneum_pow::generator::LoadClass;
|
||||
use igneum_pow::memhard::Cache;
|
||||
use igneum_pow::seed::day_key;
|
||||
use igneum_pow::verify::{DatasetMode, Epoch, DEFAULT_DATASET_LOG2};
|
||||
|
|
@ -26,6 +30,7 @@ struct Args {
|
|||
prehash: String,
|
||||
epoch_hex: Option<String>,
|
||||
day_hex: Option<String>,
|
||||
class: LoadClass,
|
||||
}
|
||||
|
||||
fn usage() -> ! {
|
||||
|
|
@ -36,7 +41,8 @@ fn usage() -> ! {
|
|||
\x20 hash --nonce <n> print the 64-bit hash of one nonce (pack form, init words = seed words)\n\
|
||||
\x20 hash-bound --prehash <64 hex> --nonce <u64> print the header-bound hash (bind.rs) of one 64-bit nonce\n\
|
||||
\x20 accept every candidate of the seed (or --epoch-hex) with its acceptance verdict\n\
|
||||
\x20 show the accepted program, one instruction per line"
|
||||
\x20 show the accepted program, one instruction per line\n\
|
||||
\x20 --class C load class (read-width experiment): v2 (default), w4, w16, w64, w64x4, or p4,p16,p64[xN]"
|
||||
);
|
||||
std::process::exit(2)
|
||||
}
|
||||
|
|
@ -54,6 +60,7 @@ fn parse() -> Args {
|
|||
prehash: "00".repeat(32),
|
||||
epoch_hex: None,
|
||||
day_hex: None,
|
||||
class: LoadClass::V2,
|
||||
};
|
||||
let mut it = std::env::args().skip(1);
|
||||
a.cmd = it.next().unwrap_or_else(|| usage());
|
||||
|
|
@ -70,6 +77,7 @@ fn parse() -> Args {
|
|||
"--prehash" => a.prehash = val(),
|
||||
"--epoch-hex" => a.epoch_hex = Some(val()),
|
||||
"--day-hex" => a.day_hex = Some(val()),
|
||||
"--class" => a.class = LoadClass::parse(&val()).unwrap_or_else(|| usage()),
|
||||
_ => usage(),
|
||||
}
|
||||
}
|
||||
|
|
@ -85,7 +93,7 @@ fn main() {
|
|||
"accept" => accept(&a),
|
||||
"show" => show(&a),
|
||||
"hash" => {
|
||||
let e = Epoch::new(&a.seed, &a.day, mode, a.dataset_log2);
|
||||
let e = Epoch::new_class(&a.seed, &a.day, mode, a.dataset_log2, a.class);
|
||||
println!("{:016x}", e.hash(a.nonce as u32));
|
||||
}
|
||||
"hash-bound" => {
|
||||
|
|
@ -96,9 +104,9 @@ fn main() {
|
|||
(Some(eh), Some(dh)) => {
|
||||
let eb = igneum_pow::bind::unhex(eh).unwrap_or_else(|| usage());
|
||||
let db = igneum_pow::bind::unhex(dh).unwrap_or_else(|| usage());
|
||||
Epoch::from_seed_bytes(&eb, &db, "cli")
|
||||
Epoch::from_seed_bytes_class(&eb, &db, "cli", a.class)
|
||||
}
|
||||
_ => Epoch::new(&a.seed, &a.day, mode, a.dataset_log2),
|
||||
_ => Epoch::new_class(&a.seed, &a.day, mode, a.dataset_log2, a.class),
|
||||
};
|
||||
let init = igneum_pow::bind::block_init_words(&prehash, a.nonce);
|
||||
println!("init words {}", init.iter().map(|w| format!("{w:08x}")).collect::<Vec<_>>().join(" "));
|
||||
|
|
@ -125,11 +133,14 @@ fn bench(a: &Args, mode: DatasetMode) {
|
|||
drop(c);
|
||||
}
|
||||
let t0 = Instant::now();
|
||||
let e = Epoch::new(&a.seed, &a.day, mode, a.dataset_log2);
|
||||
let e = Epoch::new_class(&a.seed, &a.day, mode, a.dataset_log2, a.class);
|
||||
let build_ms = t0.elapsed().as_secs_f64() * 1e3;
|
||||
println!(
|
||||
"program: {} loads/hash, {} items/warp, op mix {}; epoch built in {build_ms:.1} ms",
|
||||
"program: class {}, {} loads/hash, {} bytes/hash, widths (1,4,16 words) {:?}, {} items/warp, op mix {}; epoch built in {build_ms:.1} ms",
|
||||
e.program.class.name(),
|
||||
e.program.loads_per_hash(),
|
||||
e.program.bytes_per_hash(),
|
||||
e.program.width_counts(),
|
||||
e.program.items_per_warp(),
|
||||
e.program.op_mix()
|
||||
);
|
||||
|
|
@ -162,9 +173,9 @@ fn export(a: &Args, mode: DatasetMode) {
|
|||
(Some(eh), Some(dh)) => {
|
||||
let eb = igneum_pow::bind::unhex(eh).unwrap_or_else(|| usage());
|
||||
let db = igneum_pow::bind::unhex(dh).unwrap_or_else(|| usage());
|
||||
(Epoch::from_seed_bytes(&eb, &db, &format!("igneum-epoch/{eh}/day/{dh}")), format!("bytes:{dh}"))
|
||||
(Epoch::from_seed_bytes_class(&eb, &db, &format!("igneum-epoch/{eh}/day/{dh}"), a.class), format!("bytes:{dh}"))
|
||||
}
|
||||
_ => (Epoch::new(&a.seed, &a.day, mode, a.dataset_log2), a.day.clone()),
|
||||
_ => (Epoch::new_class(&a.seed, &a.day, mode, a.dataset_log2, a.class), a.day.clone()),
|
||||
};
|
||||
let build_ms = t0.elapsed().as_secs_f64() * 1e3;
|
||||
println!("igneum-pow export {out}");
|
||||
|
|
@ -179,7 +190,7 @@ fn export(a: &Args, mode: DatasetMode) {
|
|||
e.program.program_id(),
|
||||
e.program.loads_per_hash()
|
||||
);
|
||||
println!("op mix: {}", e.program.op_mix());
|
||||
println!("op mix: {}; class {}, {} bytes/hash, widths (1,4,16 words) {:?}", e.program.op_mix(), e.program.class.name(), e.program.bytes_per_hash(), e.program.width_counts());
|
||||
let source = format!("igneum-pow (Rust) CPU interpreter, generator v{}, {} dataset", e.program.generator, e.dataset.mode().name());
|
||||
let pack = export_pack(&e, &day_label, &source);
|
||||
let dir = std::path::Path::new(&out);
|
||||
|
|
@ -209,7 +220,7 @@ fn seed_bytes_of(a: &Args) -> (String, Vec<u8>) {
|
|||
fn accept(a: &Args) {
|
||||
let (label, bytes) = seed_bytes_of(a);
|
||||
let t0 = Instant::now();
|
||||
let tries = igneum_pow::generator::attempts(&label, &bytes);
|
||||
let tries = igneum_pow::generator::attempts_class(&label, &bytes, a.class);
|
||||
let ms = t0.elapsed().as_secs_f64() * 1e3;
|
||||
for (p, verdict) in &tries {
|
||||
match verdict {
|
||||
|
|
@ -233,19 +244,20 @@ fn accept(a: &Args) {
|
|||
|
||||
fn show(a: &Args) {
|
||||
let (label, bytes) = seed_bytes_of(a);
|
||||
let p = igneum_pow::generator::generate_from_seed_bytes(&label, &bytes);
|
||||
let p = igneum_pow::generator::generate_from_seed_bytes_class(&label, &bytes, a.class);
|
||||
println!(
|
||||
"seed \"{}\" generator v{} attempt {} program id {:016x} seed words {}",
|
||||
"seed \"{}\" generator v{} class {} attempt {} program id {:016x} seed words {}",
|
||||
p.seed_string,
|
||||
p.generator,
|
||||
p.class.name(),
|
||||
p.attempt,
|
||||
p.program_id(),
|
||||
p.seed.iter().map(|w| format!("{w:08x}")).collect::<Vec<_>>().join(" ")
|
||||
);
|
||||
println!("op mix {} loads/hash {}", p.op_mix(), p.loads_per_hash());
|
||||
println!("op mix {} loads/hash {} bytes/hash {}", p.op_mix(), p.loads_per_hash(), p.bytes_per_hash());
|
||||
for (k, i) in p.instrs.iter().enumerate() {
|
||||
println!(
|
||||
"{k:2}: {:5} dst={} src={} src2={} imm={:#010x} imm2={:#010x} rot={} bit={} mask={}",
|
||||
"{k:2}: {:5} dst={} src={} src2={} imm={:#010x} imm2={:#010x} rot={} bit={} mask={}{}",
|
||||
i.op.name(),
|
||||
i.dst,
|
||||
i.src,
|
||||
|
|
@ -254,7 +266,8 @@ fn show(a: &Args) {
|
|||
i.imm2,
|
||||
i.rot,
|
||||
i.bit,
|
||||
i.mask
|
||||
i.mask,
|
||||
if i.op == igneum_pow::generator::Op::Load && i.width > 1 { format!(" width={}B", i.width as u32 * 4) } else { String::new() }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -269,6 +269,34 @@ impl MemhardCpu {
|
|||
}
|
||||
u
|
||||
}
|
||||
/// `out[k][j] = dataset[base[k] + j]` for `j < width` (read-width experiment): `base[k]` is aligned to `width`
|
||||
/// words, so every lane's words lie in one item, derived once per distinct item. Returns the distinct items.
|
||||
pub fn fetch_wide(&self, base: &[u32], width: usize, out: &mut [[u32; 16]]) -> usize {
|
||||
let n = base.len();
|
||||
assert!(n <= FETCH_MAX && out.len() >= n && width <= 16);
|
||||
let mut uniq = [0u32; FETCH_MAX];
|
||||
let mut slot = [0u8; FETCH_MAX];
|
||||
let mut u = 0usize;
|
||||
for k in 0..n {
|
||||
let t = base[k] >> 4;
|
||||
let j = match uniq[..u].iter().position(|&x| x == t) {
|
||||
Some(j) => j,
|
||||
None => {
|
||||
uniq[u] = t;
|
||||
u += 1;
|
||||
u - 1
|
||||
}
|
||||
};
|
||||
slot[k] = j as u8;
|
||||
}
|
||||
let mut items = [[0u32; 16]; FETCH_MAX];
|
||||
derive_items(&uniq[..u], &self.params, &self.cache, &mut items);
|
||||
for k in 0..n {
|
||||
let o = (base[k] & 15) as usize;
|
||||
out[k][..width].copy_from_slice(&items[slot[k] as usize][o..o + width]);
|
||||
}
|
||||
u
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
|
|||
|
|
@ -1,10 +1,91 @@
|
|||
//! The CPU reference interpreter for one 32-lane warp (`cpuWarpTraced` in the Swift) and the API the node
|
||||
//! calls. Dataset words come from the memory-hard cache (default) or from the closed form (old packs).
|
||||
|
||||
use crate::generator::{generate, Instr, Op, Program, ITERATIONS, LANES};
|
||||
use crate::generator::{
|
||||
generate, generate_class, Instr, LoadClass, Op, Program, ITERATIONS, LANES, SCRATCH_SLOTS, SCRATCH_SLOT_MASK,
|
||||
};
|
||||
use crate::memhard::MemhardCpu;
|
||||
use crate::seed::day_key;
|
||||
|
||||
/// Read-width experiment (5 October 2026): a `load` of `W` words folds every word into `dst`:
|
||||
/// `x = dst XOR w[0]; for j in 1..W: x = (rotl(x, FOLD_ROT) * FOLD_MUL) XOR w[j]; dst = x`. For `W = 1` this is the
|
||||
/// lottery hash's `dst XOR dataset[...]`. The fold is state-dependent (the rotate-multiply sits between the words),
|
||||
/// so no function of the line alone replaces it: two different lines give two different maps of `dst`, and a
|
||||
/// dataset of folded lines cannot be stored in place of the dataset (see `docs/plans/read-width.md`).
|
||||
pub const FOLD_ROT: u32 = 11;
|
||||
pub const FOLD_MUL: u32 = 0x9E3779B1;
|
||||
|
||||
/// The fold of `words` into `dst` (at least one word).
|
||||
#[inline(always)]
|
||||
pub fn fold_words(dst: u32, words: &[u32]) -> u32 {
|
||||
let mut x = dst ^ words[0];
|
||||
for &w in &words[1..] {
|
||||
x = x.rotate_left(FOLD_ROT).wrapping_mul(FOLD_MUL) ^ w;
|
||||
}
|
||||
x
|
||||
}
|
||||
|
||||
/// Variant 5 (scratch): the fill value of word `j` (0..2) of slot `slot` of lane `lane` of the unit at base nonce
|
||||
/// `base`, under program seed words `seed`. The scratch of a unit starts as these values; a slot written during
|
||||
/// the unit's hash holds what was written. Mirrored as `scr_fill` in every emitted kernel.
|
||||
#[inline(always)]
|
||||
pub fn scratch_fill(seed: &[u32; 8], base: u32, lane: u32, slot: u32, j: u32) -> u32 {
|
||||
splitmix32(
|
||||
(base.wrapping_add(lane) ^ seed[j as usize])
|
||||
.wrapping_add(slot.wrapping_mul(0x9E3779B1))
|
||||
.wrapping_add((j + 1).wrapping_mul(0x85EBCA77)),
|
||||
)
|
||||
}
|
||||
|
||||
/// Variant 5: the 16-byte slot after a read-modify-write that read `w` and folded to `x`: `(x ^ w1, rotl(x, 7) ^ w2,
|
||||
/// x + w0)` behind the slot's tag.
|
||||
#[inline(always)]
|
||||
pub fn scratch_rewrite(x: u32, w: &[u32; 3]) -> [u32; 3] {
|
||||
[x ^ w[1], x.rotate_left(7) ^ w[2], x.wrapping_add(w[0])]
|
||||
}
|
||||
|
||||
/// The CPU model of one unit's scratch (variant 5): per lane, the written slots and their words. Unwritten slots
|
||||
/// read as [`scratch_fill`]. A unit touches at most `scratch ops x 32` slots, so the model is small whatever the
|
||||
/// nominal 1 MiB; a GPU keeps the real 1 MiB per resident warp with a per-unit tag per slot.
|
||||
pub struct ScratchModel {
|
||||
written: Vec<bool>,
|
||||
data: Vec<[u32; 3]>,
|
||||
pub reads: usize,
|
||||
pub writes: usize,
|
||||
}
|
||||
|
||||
impl ScratchModel {
|
||||
pub fn new() -> Self {
|
||||
Self { written: vec![false; LANES * SCRATCH_SLOTS], data: vec![[0; 3]; LANES * SCRATCH_SLOTS], reads: 0, writes: 0 }
|
||||
}
|
||||
/// Read slot `slot` of `lane`, then rewrite it from the fold result `x`. Returns the three words read.
|
||||
#[inline]
|
||||
pub fn rmw(&mut self, seed: &[u32; 8], base: u32, lane: usize, slot: u32, dst: u32) -> u32 {
|
||||
let i = lane * SCRATCH_SLOTS + slot as usize;
|
||||
let w = if self.written[i] {
|
||||
self.data[i]
|
||||
} else {
|
||||
[
|
||||
scratch_fill(seed, base, lane as u32, slot, 0),
|
||||
scratch_fill(seed, base, lane as u32, slot, 1),
|
||||
scratch_fill(seed, base, lane as u32, slot, 2),
|
||||
]
|
||||
};
|
||||
let x = fold_words(dst, &w);
|
||||
self.data[i] = scratch_rewrite(x, &w);
|
||||
self.written[i] = true;
|
||||
self.reads += 1;
|
||||
self.writes += 1;
|
||||
x
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for ScratchModel {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
/// Dataset element, closed form of (day words, index). The original prototype's six-operation element.
|
||||
#[inline(always)]
|
||||
pub fn dataset_elem(i: u32, d0: u32, d1: u32) -> u32 {
|
||||
|
|
@ -121,6 +202,23 @@ impl DatasetSource {
|
|||
Dataset::MemoryHard(m) => m.fetch(idx, out),
|
||||
}
|
||||
}
|
||||
|
||||
/// `out[k][j] = dataset[base[k] + j]` for `j < width`; bases are masked and aligned to `width` words
|
||||
/// (`width` 4 or 16, so a lane's words lie in one item). Returns items derived (0 for the closed form).
|
||||
#[inline]
|
||||
fn fetch_wide(&self, base: &[u32; LANES], width: usize, out: &mut [[u32; 16]; LANES]) -> usize {
|
||||
match &self.dataset {
|
||||
Dataset::ClosedForm { d0, d1 } => {
|
||||
for k in 0..LANES {
|
||||
for j in 0..width {
|
||||
out[k][j] = dataset_elem(base[k] + j as u32, *d0, *d1);
|
||||
}
|
||||
}
|
||||
0
|
||||
}
|
||||
Dataset::MemoryHard(m) => m.fetch_wide(base, width, out),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The result of interpreting one warp.
|
||||
|
|
@ -160,10 +258,19 @@ pub fn interpret_warp_init(program: &Program, seed: &[u32; 8], base_nonce: u32,
|
|||
let mut items_derived = 0usize;
|
||||
let mut idx = [0u32; LANES];
|
||||
let mut val = [0u32; LANES];
|
||||
let mut scratch = if program.has_scratch() { Some(ScratchModel::new()) } else { None };
|
||||
for _ in 0..ITERATIONS {
|
||||
let sel = r[0];
|
||||
for ins in &program.instrs {
|
||||
step(ins, &mut r, &sel, mask, ds, &mut idx, &mut val, &mut items_derived);
|
||||
if ins.op == Op::Scratch {
|
||||
let m = scratch.as_mut().expect("a scratch op needs a scratch class");
|
||||
let (d, a) = (ins.dst as usize, ins.src as usize);
|
||||
for lane in 0..LANES {
|
||||
let slot = r[a][lane] & SCRATCH_SLOT_MASK;
|
||||
r[d][lane] = m.rmw(&program.seed, base_nonce, lane, slot, r[d][lane]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let mut hashes = [0u64; LANES];
|
||||
|
|
@ -255,7 +362,7 @@ fn step(
|
|||
r[d][lane] ^= src[lane ^ m];
|
||||
}
|
||||
}
|
||||
Op::Load => {
|
||||
Op::Load if ins.width == 1 => {
|
||||
for lane in 0..LANES {
|
||||
idx[lane] = r[a][lane] & mask;
|
||||
}
|
||||
|
|
@ -264,6 +371,22 @@ fn step(
|
|||
r[d][lane] ^= val[lane];
|
||||
}
|
||||
}
|
||||
Op::Load => {
|
||||
// Read-width experiment: `width` words from the aligned address, every word folded into dst.
|
||||
let width = ins.width as usize;
|
||||
let align = !(ins.width as u32 - 1);
|
||||
for lane in 0..LANES {
|
||||
idx[lane] = (r[a][lane] & mask) & align;
|
||||
}
|
||||
let mut vals = [[0u32; 16]; LANES];
|
||||
*items_derived += ds.fetch_wide(idx, width, &mut vals);
|
||||
for lane in 0..LANES {
|
||||
r[d][lane] = fold_words(r[d][lane], &vals[lane][..width]);
|
||||
}
|
||||
}
|
||||
Op::Scratch => {
|
||||
// handled by the caller (interpret_warp_init), which owns the unit's scratch model
|
||||
}
|
||||
Op::WLoad => {
|
||||
// Lane 0's register, masked, aligned down to 32 words; lane l reads word base + l.
|
||||
let base = (r[a][0] & mask) & !31;
|
||||
|
|
@ -299,6 +422,11 @@ impl Epoch {
|
|||
Self { program: generate(seed), dataset: DatasetSource::new(day, mode, dataset_log2) }
|
||||
}
|
||||
|
||||
/// [`Epoch::new`] with a load class (read-width experiment).
|
||||
pub fn new_class(seed: &str, day: &str, mode: DatasetMode, dataset_log2: u32, class: LoadClass) -> Self {
|
||||
Self { program: generate_class(seed, class), dataset: DatasetSource::new(day, mode, dataset_log2) }
|
||||
}
|
||||
|
||||
/// The production shape: memory-hard, 1 GiB dataset.
|
||||
pub fn memory_hard(seed: &str, day: &str) -> Self {
|
||||
Self::new(seed, day, DatasetMode::MemoryHard, DEFAULT_DATASET_LOG2)
|
||||
|
|
@ -309,7 +437,12 @@ impl Epoch {
|
|||
/// `seed_words_from_bytes(day_bytes)` (`bind::day_bytes`). Memory-hard, 1 GiB dataset. `label` is only
|
||||
/// recorded in emitted packs.
|
||||
pub fn from_seed_bytes(epoch_seed: &[u8], day_bytes: &[u8], label: &str) -> Self {
|
||||
let program = crate::generator::generate_from_seed_bytes(label, epoch_seed);
|
||||
Self::from_seed_bytes_class(epoch_seed, day_bytes, label, LoadClass::V2)
|
||||
}
|
||||
|
||||
/// [`Epoch::from_seed_bytes`] with a load class (read-width experiment).
|
||||
pub fn from_seed_bytes_class(epoch_seed: &[u8], day_bytes: &[u8], label: &str, class: LoadClass) -> Self {
|
||||
let program = crate::generator::generate_from_seed_bytes_class(label, epoch_seed, class);
|
||||
let key = crate::seed::seed_words_from_bytes(day_bytes);
|
||||
let mut dataset = DatasetSource::from_key(key, DatasetMode::MemoryHard, DEFAULT_DATASET_LOG2);
|
||||
dataset.key_bytes = day_bytes.to_vec();
|
||||
|
|
@ -356,6 +489,80 @@ mod tests {
|
|||
assert_eq!(ds.word(0x0fffffff), 0xf78c84a4);
|
||||
}
|
||||
|
||||
/// Read-width experiment: the fold for one word is a plain xor; a wide fetch hands each lane the words the
|
||||
/// scalar path would; two distinct lines give two distinct maps of dst (one point suffices as a smoke check).
|
||||
#[test]
|
||||
fn fold_and_wide_fetch() {
|
||||
assert_eq!(fold_words(0x1234_5678, &[0xdead_beef]), 0x1234_5678 ^ 0xdead_beef);
|
||||
let w = [1u32, 2, 3, 4];
|
||||
let x = fold_words(7, &w);
|
||||
let mut y: u32 = 7 ^ 1;
|
||||
for &v in &w[1..] {
|
||||
y = y.rotate_left(FOLD_ROT).wrapping_mul(FOLD_MUL) ^ v;
|
||||
}
|
||||
assert_eq!(x, y);
|
||||
assert_ne!(fold_words(7, &[1, 2, 3, 4]), fold_words(7, &[1, 2, 3, 5]));
|
||||
let ds = DatasetSource::new("2026-10-03", DatasetMode::MemoryHard, 20);
|
||||
let mut base = [0u32; LANES];
|
||||
for (k, b) in base.iter_mut().enumerate() {
|
||||
*b = ((k as u32 * 0x9E37_79B1) & ds.mask) & !15;
|
||||
}
|
||||
let mut out = [[0u32; 16]; LANES];
|
||||
let items = ds.fetch_wide(&base, 16, &mut out);
|
||||
assert!(items >= 1 && items <= LANES);
|
||||
for k in 0..LANES {
|
||||
for j in 0..16 {
|
||||
assert_eq!(out[k][j], ds.word(base[k] + j as u32), "lane {k} word {j}");
|
||||
}
|
||||
}
|
||||
let mut base4 = base;
|
||||
for b in base4.iter_mut() {
|
||||
*b += 8;
|
||||
}
|
||||
let items4 = ds.fetch_wide(&base4, 4, &mut out);
|
||||
assert_eq!(items4, items);
|
||||
for k in 0..LANES {
|
||||
for j in 0..4 {
|
||||
assert_eq!(out[k][j], ds.word(base4[k] + j as u32));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A wide-load program interprets identically on the closed form and through the memory-hard path's fold
|
||||
/// (the same fold code), and a mixed-class epoch builds and hashes.
|
||||
/// Variant 5: a fill word is deterministic, a rewrite changes the slot, and a second read of a written slot
|
||||
/// returns the rewrite, not the fill.
|
||||
#[test]
|
||||
fn scratch_model() {
|
||||
let seed = [1u32, 2, 3, 4, 5, 6, 7, 8];
|
||||
assert_eq!(scratch_fill(&seed, 32, 3, 100, 1), scratch_fill(&seed, 32, 3, 100, 1));
|
||||
assert_ne!(scratch_fill(&seed, 32, 3, 100, 1), scratch_fill(&seed, 32, 3, 100, 2));
|
||||
assert_ne!(scratch_fill(&seed, 32, 3, 100, 1), scratch_fill(&seed, 64, 3, 100, 1));
|
||||
let mut m = ScratchModel::new();
|
||||
let w = [scratch_fill(&seed, 32, 3, 100, 0), scratch_fill(&seed, 32, 3, 100, 1), scratch_fill(&seed, 32, 3, 100, 2)];
|
||||
let x = m.rmw(&seed, 32, 3, 100, 0xabcd);
|
||||
assert_eq!(x, fold_words(0xabcd, &w));
|
||||
let x2 = m.rmw(&seed, 32, 3, 100, 0xabcd);
|
||||
assert_eq!(x2, fold_words(0xabcd, &scratch_rewrite(x, &w)));
|
||||
assert_eq!(m.reads, 2);
|
||||
let e = Epoch::new_class("igneum-genesis", "2026-10-03", DatasetMode::ClosedForm, 20, LoadClass::scratch(4));
|
||||
assert_eq!(e.program.scratch_ops_per_hash(), 32);
|
||||
assert_eq!(e.hash_warp(0), e.hash_warp(0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn wide_class_epochs_hash() {
|
||||
for name in ["w16", "w64x4", "50,35,15"] {
|
||||
let c = LoadClass::parse(name).unwrap();
|
||||
let e = Epoch::new_class("igneum-genesis", "2026-10-03", DatasetMode::ClosedForm, 20, c);
|
||||
assert_eq!(e.program.class, c);
|
||||
let a = e.hash_warp(0);
|
||||
let b = e.hash_warp(0);
|
||||
assert_eq!(a, b);
|
||||
assert_ne!(a[0], a[1]);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn closed_form_genesis_vector_lane0() {
|
||||
// Generator v2 vectors (4 October 2026), proto-cuda/packs/igneum-genesis/vectors.json.
|
||||
|
|
|
|||
|
|
@ -20,6 +20,9 @@
|
|||
#define __forceinline__ inline
|
||||
|
||||
struct uint3 { unsigned x, y, z; };
|
||||
// uint4 and make_uint4 (read-width experiment, 5 October 2026): the wide loads and the scratch slots are 16-byte vectors.
|
||||
struct uint4 { unsigned x, y, z, w; };
|
||||
static inline uint4 make_uint4(unsigned x, unsigned y, unsigned z, unsigned w) { uint4 v; v.x = x; v.y = y; v.z = z; v.w = w; return v; }
|
||||
struct dim3 { unsigned x, y, z; dim3(unsigned x_ = 1, unsigned y_ = 1, unsigned z_ = 1) : x(x_), y(y_), z(z_) {} };
|
||||
extern thread_local uint3 threadIdx;
|
||||
extern thread_local uint3 blockIdx;
|
||||
|
|
|
|||
278
proto-cuda/packs-readwidth/mixA-0/kernel.cl
Normal file
278
proto-cuda/packs-readwidth/mixA-0/kernel.cl
Normal file
|
|
@ -0,0 +1,278 @@
|
|||
// Generated by igneum-pow export (generator v2) for seed "igneum-readwidth/A/0". Do not edit by hand.
|
||||
// OpenCL C twin of the Metal kernel for the same seed (see proto-opencl/README.md, WAVEFRONT.md and program.metal).
|
||||
// Built from source at runtime by proto-opencl/host.c, which passes these defines:
|
||||
// IGNEUM_GROUP work-group size of igneum_hash, a multiple of 32 (default 32: one work-group = one 32-lane unit)
|
||||
// IGNEUM_EXCHANGE 0 = local-memory exchange with a barrier (any device, any wave width; the default)
|
||||
// 1 = sub_group_shuffle_xor (cl_khr_subgroup_shuffle), only with IGNEUM_GROUP 32 and a sub-group size of exactly 32
|
||||
// 2 = intel_sub_group_shuffle_xor (cl_intel_subgroups), same condition
|
||||
// The verification unit is always 32 lanes. A 64-wide hardware wave (AMD GCN/CDNA, RDNA in wave64) runs two units;
|
||||
// the exchange masks are 1, 2, 4, 8, 16, so every partner lane lies inside the lane's own aligned run of 32.
|
||||
#ifndef IGNEUM_GROUP
|
||||
#define IGNEUM_GROUP 32
|
||||
#endif
|
||||
#ifndef IGNEUM_EXCHANGE
|
||||
#define IGNEUM_EXCHANGE 0
|
||||
#endif
|
||||
#ifdef __OPENCL_VERSION__
|
||||
#define IGNEUM_KERNEL_HASH __kernel __attribute__((reqd_work_group_size(IGNEUM_GROUP, 1, 1)))
|
||||
#define IGNEUM_LOCAL_WORDS(name, n) __local uint name[n]
|
||||
#if IGNEUM_EXCHANGE == 1
|
||||
#ifdef cl_khr_subgroups
|
||||
#pragma OPENCL EXTENSION cl_khr_subgroups : enable
|
||||
#endif
|
||||
#ifdef cl_khr_subgroup_shuffle
|
||||
#pragma OPENCL EXTENSION cl_khr_subgroup_shuffle : enable
|
||||
#endif
|
||||
#elif IGNEUM_EXCHANGE == 2
|
||||
#pragma OPENCL EXTENSION cl_intel_subgroups : enable
|
||||
#endif
|
||||
#else
|
||||
// Not an OpenCL compiler: proto-opencl/emu compiles this file as C++ and supplies the built-ins and these two macros.
|
||||
#include "emu_opencl.h"
|
||||
#endif
|
||||
|
||||
#if IGNEUM_EXCHANGE == 1
|
||||
#define IGNEUM_SHFL_XOR(dst, a, m) dst = sub_group_shuffle_xor((a), (uint)(m))
|
||||
#define IGNEUM_BCAST0(dst, a) dst = sub_group_broadcast((a), 0u)
|
||||
#elif IGNEUM_EXCHANGE == 2
|
||||
#define IGNEUM_SHFL_XOR(dst, a, m) dst = intel_sub_group_shuffle_xor((a), (uint)(m))
|
||||
#define IGNEUM_BCAST0(dst, a) dst = sub_group_broadcast((a), 0u)
|
||||
#else
|
||||
// Local-memory exchange. Two buffers of IGNEUM_GROUP words alternate (xk counts exchanges), so one barrier per
|
||||
// exchange is enough: a lane can only overwrite buffer b at exchange k+2 after passing barrier k+1, and every lane
|
||||
// reaches barrier k+1 only after its read of buffer b at exchange k. The partner lid ^ m stays inside the lane's
|
||||
// aligned run of 32 because m < 32. Control flow is uniform, so every work-item reaches every barrier.
|
||||
#define IGNEUM_SHFL_XOR(dst, a, m) { xch[(xk & 1u) * IGNEUM_GROUP + lid] = (a); barrier(CLK_LOCAL_MEM_FENCE); dst = xch[(xk & 1u) * IGNEUM_GROUP + (lid ^ (uint)(m))]; xk += 1u; }
|
||||
#define IGNEUM_BCAST0(dst, a) { xch[(xk & 1u) * IGNEUM_GROUP + lid] = (a); barrier(CLK_LOCAL_MEM_FENCE); dst = xch[(xk & 1u) * IGNEUM_GROUP + (lid & ~31u)]; xk += 1u; }
|
||||
#endif
|
||||
|
||||
static inline uint splitmix32(uint x) {
|
||||
x ^= x >> 16; x *= 0x7feb352du;
|
||||
x ^= x >> 15; x *= 0x846ca68bu;
|
||||
x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
// n is a literal in 1..31 at every call site. OpenCL rotate() rotates left by n modulo 32.
|
||||
static inline uint rotl_imm(uint x, uint n) { return rotate(x, n); }
|
||||
// Right rotation by n modulo 32 as a left rotation by (32 - n) modulo 32; n == 0 gives x.
|
||||
static inline uint rotr_var(uint x, uint n) { return rotate(x, (0u - n) & 31u); }
|
||||
static inline uint ds_elem(uint i, uint d0, uint d1) {
|
||||
uint x = i ^ d0;
|
||||
x *= 0x9E3779B1u; x ^= x >> 15;
|
||||
x += d1;
|
||||
x *= 0x85EBCA77u; x ^= x >> 13;
|
||||
x *= 0xC2B2AE3Du; x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
|
||||
// Memory-hard dataset core (MEMHARD.md). Cache: 2^26 words in 2^16 segments of 64 chained ChaCha12 lines.
|
||||
// Item: 8 rounds of seed-parameterised mixer + one 64-byte cache read, then a final mixer. All parameters are literals.
|
||||
#define MH_CACHE_LINE_MASK 0x003fffffu
|
||||
#define MH_SEGMENT_LINES 64u
|
||||
#define MH_QR(a, b, c, d, r1, r2, r3, r4) { a += b; d ^= a; d = mh_rotl(d, r1); c += d; b ^= c; b = mh_rotl(b, r2); a += b; d ^= a; d = mh_rotl(d, r3); c += d; b ^= c; b = mh_rotl(b, r4); }
|
||||
static inline uint mh_rotl(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 at every call site
|
||||
|
||||
// y = ChaCha12 core(x) + x
|
||||
static inline void mh_chacha_block(const uint* x, uint* y) {
|
||||
for (uint i = 0u; i < 16u; ++i) y[i] = x[i];
|
||||
for (uint r = 0u; r < 6u; ++r) {
|
||||
MH_QR(y[0], y[4], y[8], y[12], 16u, 12u, 8u, 7u) MH_QR(y[1], y[5], y[9], y[13], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[2], y[6], y[10], y[14], 16u, 12u, 8u, 7u) MH_QR(y[3], y[7], y[11], y[15], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[0], y[5], y[10], y[15], 16u, 12u, 8u, 7u) MH_QR(y[1], y[6], y[11], y[12], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[2], y[7], y[8], y[13], 16u, 12u, 8u, 7u) MH_QR(y[3], y[4], y[9], y[14], 16u, 12u, 8u, 7u)
|
||||
}
|
||||
for (uint i = 0u; i < 16u; ++i) y[i] += x[i];
|
||||
}
|
||||
|
||||
// One cache segment: 64 chained lines written at cache[seg * 1024]. in_j = prev ^ (sigma || K || seg || j || tag), prev_0 = 0.
|
||||
static inline void mh_cache_segment(__global uint* cache, uint seg) {
|
||||
uint prev[16]; uint x[16]; uint y[16];
|
||||
for (uint i = 0u; i < 16u; ++i) prev[i] = 0u;
|
||||
for (uint j = 0u; j < MH_SEGMENT_LINES; ++j) {
|
||||
x[0] = 0x61707865u ^ prev[0]; x[1] = 0x3320646eu ^ prev[1]; x[2] = 0x79622d32u ^ prev[2]; x[3] = 0x6b206574u ^ prev[3];
|
||||
x[4] = 0x3067619fu ^ prev[4];
|
||||
x[5] = 0x3c269176u ^ prev[5];
|
||||
x[6] = 0x84a03b03u ^ prev[6];
|
||||
x[7] = 0xf8c63294u ^ prev[7];
|
||||
x[8] = 0xff977c5bu ^ prev[8];
|
||||
x[9] = 0xe60def3eu ^ prev[9];
|
||||
x[10] = 0x63630141u ^ prev[10];
|
||||
x[11] = 0xb8fbcb58u ^ prev[11];
|
||||
x[12] = seg ^ prev[12]; x[13] = j ^ prev[13]; x[14] = 0x49676e65u ^ prev[14]; x[15] = 0x756d4d48u ^ prev[15];
|
||||
mh_chacha_block(x, y);
|
||||
__global uint* line = cache + ((seg * MH_SEGMENT_LINES + j) * 16u);
|
||||
for (uint i = 0u; i < 16u; ++i) { line[i] = y[i]; prev[i] = y[i]; }
|
||||
}
|
||||
}
|
||||
|
||||
// M_r: per word (s ^ (RC + rk)) * MUL, then a column round and a diagonal round with the seed-drawn rotations.
|
||||
static inline void mh_mixer(uint* s, uint rk) {
|
||||
s[0] = (s[0] ^ (0xbab68293u + rk)) * 0x42146205u;
|
||||
s[1] = (s[1] ^ (0xcc162340u + rk)) * 0x52cbe0fbu;
|
||||
s[2] = (s[2] ^ (0x6ce151ccu + rk)) * 0x7ecf4a03u;
|
||||
s[3] = (s[3] ^ (0xe62b8997u + rk)) * 0x6728907fu;
|
||||
s[4] = (s[4] ^ (0xc9c80297u + rk)) * 0xd81d9751u;
|
||||
s[5] = (s[5] ^ (0xf74a1654u + rk)) * 0x132952c3u;
|
||||
s[6] = (s[6] ^ (0x3d704af5u + rk)) * 0xf60de277u;
|
||||
s[7] = (s[7] ^ (0x3cf522b7u + rk)) * 0x05358035u;
|
||||
s[8] = (s[8] ^ (0x2b9cac04u + rk)) * 0xbaf6499du;
|
||||
s[9] = (s[9] ^ (0xa880ac10u + rk)) * 0xe4db9667u;
|
||||
s[10] = (s[10] ^ (0x13e5dd1du + rk)) * 0x3e98f45du;
|
||||
s[11] = (s[11] ^ (0x6fc3e233u + rk)) * 0xd0004eddu;
|
||||
s[12] = (s[12] ^ (0x2d83eeacu + rk)) * 0x2691630du;
|
||||
s[13] = (s[13] ^ (0x9006e8bfu + rk)) * 0x9beb3bcfu;
|
||||
s[14] = (s[14] ^ (0x2c4b5362u + rk)) * 0xab310379u;
|
||||
s[15] = (s[15] ^ (0x31b49ee2u + rk)) * 0x99cfb423u;
|
||||
MH_QR(s[0], s[4], s[8], s[12], 20u, 20u, 19u, 4u) MH_QR(s[1], s[5], s[9], s[13], 20u, 20u, 19u, 4u)
|
||||
MH_QR(s[2], s[6], s[10], s[14], 20u, 20u, 19u, 4u) MH_QR(s[3], s[7], s[11], s[15], 20u, 20u, 19u, 4u)
|
||||
MH_QR(s[0], s[5], s[10], s[15], 26u, 3u, 3u, 27u) MH_QR(s[1], s[6], s[11], s[12], 26u, 3u, 3u, 27u)
|
||||
MH_QR(s[2], s[7], s[8], s[13], 26u, 3u, 3u, 27u) MH_QR(s[3], s[4], s[9], s[14], 26u, 3u, 3u, 27u)
|
||||
}
|
||||
|
||||
// Item t: 16 words. s = (K, t * MUL[i] + RC[i]); 8 rounds of mixer + cache line s[0] & mask; final mixer.
|
||||
static inline void mh_item(__global const uint* cache, uint t, uint* s) {
|
||||
s[0] = 0x3067619fu;
|
||||
s[1] = 0x3c269176u;
|
||||
s[2] = 0x84a03b03u;
|
||||
s[3] = 0xf8c63294u;
|
||||
s[4] = 0xff977c5bu;
|
||||
s[5] = 0xe60def3eu;
|
||||
s[6] = 0x63630141u;
|
||||
s[7] = 0xb8fbcb58u;
|
||||
s[8] = t * 0x42146205u + 0xbab68293u;
|
||||
s[9] = t * 0x52cbe0fbu + 0xcc162340u;
|
||||
s[10] = t * 0x7ecf4a03u + 0x6ce151ccu;
|
||||
s[11] = t * 0x6728907fu + 0xe62b8997u;
|
||||
s[12] = t * 0xd81d9751u + 0xc9c80297u;
|
||||
s[13] = t * 0x132952c3u + 0xf74a1654u;
|
||||
s[14] = t * 0xf60de277u + 0x3d704af5u;
|
||||
s[15] = t * 0x05358035u + 0x3cf522b7u;
|
||||
for (uint r = 0u; r < 8u; ++r) {
|
||||
mh_mixer(s, 0x9E3779B9u * (r + 1u));
|
||||
__global const uint* line = cache + ((s[0] & MH_CACHE_LINE_MASK) * 16u);
|
||||
for (uint i = 0u; i < 16u; ++i) s[i] ^= line[i];
|
||||
}
|
||||
mh_mixer(s, 0x9E3779B9u * 9u);
|
||||
}
|
||||
// dataset[w] without the dataset: derive item w >> 4 and take word w & 15.
|
||||
static inline uint mh_word(__global const uint* cache, uint w) { uint s[16]; mh_item(cache, w >> 4u, s); return s[w & 15u]; }
|
||||
|
||||
// Memory-hard dataset (MEMHARD.md). One work-item per cache segment; one work-item per 64-byte dataset item.
|
||||
// The same constants as memhard.h in this pack (one emitter, three dialects).
|
||||
__kernel void igneum_cache_fill(__global uint* cache, uint nSegments) {
|
||||
uint seg = (uint)get_global_id(0);
|
||||
if (seg < nSegments) mh_cache_segment(cache, seg);
|
||||
}
|
||||
__kernel void igneum_build(__global uint* ds, __global const uint* cache, uint nItems) {
|
||||
uint t = (uint)get_global_id(0);
|
||||
if (t < nItems) {
|
||||
uint s[16];
|
||||
mh_item(cache, t, s);
|
||||
__global uint* d = ds + ((ulong)t * 16u);
|
||||
for (uint i = 0u; i < 16u; ++i) d[i] = s[i];
|
||||
}
|
||||
}
|
||||
|
||||
// One hash per work-item. IGNEUM_GROUP is a multiple of 32; lane = lid & 31 and every exchange stays inside the
|
||||
// lane's own aligned run of 32 work-items, exactly like simd_shuffle_xor inside a 32-wide Metal SIMD group and
|
||||
// __shfl_xor_sync inside a CUDA warp. Control flow is uniform (no branches at all).
|
||||
IGNEUM_KERNEL_HASH void igneum_hash(__global const uint* ds, __global ulong* out, uint baseNonce, uint mask) {
|
||||
uint gid = (uint)get_global_id(0);
|
||||
uint lid = (uint)get_local_id(0);
|
||||
uint nonce = baseNonce + gid;
|
||||
uint r0, r1, r2, r3, r4, r5, r6, r7;
|
||||
#if IGNEUM_EXCHANGE == 0
|
||||
IGNEUM_LOCAL_WORDS(xch, 2 * IGNEUM_GROUP);
|
||||
uint xk = 0u;
|
||||
#else
|
||||
(void)lid;
|
||||
#endif
|
||||
{ uint x = nonce ^ 0xaa5a3f6eu; x += 0x9e3779b9u; x = splitmix32(x); r0 = x ^ 0x5c0410c3u; } // SEEDW[0], 0x9e3779b9u * 1u, SEEDW[1]
|
||||
{ uint x = nonce ^ 0x5c0410c3u; x += 0x3c6ef372u; x = splitmix32(x); r1 = x ^ 0x9d994375u; } // SEEDW[1], 0x9e3779b9u * 2u, SEEDW[2]
|
||||
{ uint x = nonce ^ 0x9d994375u; x += 0xdaa66d2bu; x = splitmix32(x); r2 = x ^ 0xd8d53386u; } // SEEDW[2], 0x9e3779b9u * 3u, SEEDW[3]
|
||||
{ uint x = nonce ^ 0xd8d53386u; x += 0x78dde6e4u; x = splitmix32(x); r3 = x ^ 0x2c956ee2u; } // SEEDW[3], 0x9e3779b9u * 4u, SEEDW[4]
|
||||
{ uint x = nonce ^ 0x2c956ee2u; x += 0x1715609du; x = splitmix32(x); r4 = x ^ 0xe313c2f9u; } // SEEDW[4], 0x9e3779b9u * 5u, SEEDW[5]
|
||||
{ uint x = nonce ^ 0xe313c2f9u; x += 0xb54cda56u; x = splitmix32(x); r5 = x ^ 0x495ace1bu; } // SEEDW[5], 0x9e3779b9u * 6u, SEEDW[6]
|
||||
{ uint x = nonce ^ 0x495ace1bu; x += 0x5384540fu; x = splitmix32(x); r6 = x ^ 0x8238bb25u; } // SEEDW[6], 0x9e3779b9u * 7u, SEEDW[7]
|
||||
{ uint x = nonce ^ 0x8238bb25u; x += 0xf1bbcdc8u; x = splitmix32(x); r7 = x ^ 0xaa5a3f6eu; } // SEEDW[7], 0x9e3779b9u * 8u, SEEDW[0]
|
||||
|
||||
for (uint it = 0u; it < 8u; ++it) {
|
||||
uint sel = r0;
|
||||
r2 = r2 + r7 + ((((sel >> 30u) & 1u) != 0u) ? 0xb788d5f8u : 0x92d00116u); // 0 add
|
||||
r3 = mul_hi(r3, r2); // 1 mulhi
|
||||
r6 = r6 ^ ds[r3 & mask]; // 2 load
|
||||
r0 = r0 ^ ds[r6 & mask]; // 3 load
|
||||
r5 = r5 * r2; // 4 mul
|
||||
r7 = r7 + r2 + ((((sel >> 20u) & 1u) != 0u) ? 0x9a773a55u : 0xd5f6f389u); // 5 add
|
||||
{ uint b_ = (r5 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r6 = x_; } // 6 load
|
||||
r5 = r5 ^ ds[r6 & mask]; // 7 load
|
||||
{ uint b_ = (r2 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r1 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r1 = x_; } // 8 load
|
||||
r4 = r4 * r5; // 9 mul
|
||||
{ uint b_ = (r0 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r2 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r2 = x_; } // 10 load
|
||||
r3 = r3 ^ ds[r2 & mask]; // 11 load
|
||||
r4 = r4 ^ r0; // 12 xor
|
||||
r7 = r7 ^ ds[r3 & mask]; // 13 load
|
||||
r7 = r7 ^ r1; // 14 xor
|
||||
r4 = r1 * r4 + r4; // 15 mad
|
||||
r3 = r0 * r4 + r3; // 16 mad
|
||||
r4 = r6 * r2 + r4; // 17 mad
|
||||
r0 = rotr_var(r0, r2); // 18 rotr
|
||||
r5 = rotr_var(r5, r6); // 19 rotr
|
||||
r4 = r4 ^ ds[r1 & mask]; // 20 load
|
||||
r2 = r2 ^ ds[r4 & mask]; // 21 load
|
||||
r1 = rotl_imm(r1, 14u); // 22 rotl
|
||||
r7 = r7 - r1; // 23 sub
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r6, 2u); r2 = r2 ^ t_; } // 24 shfl
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r4, 16u); r1 = r1 ^ t_; } // 25 shfl
|
||||
r6 = r6 ^ ds[r0 & mask]; // 26 load
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r6, 1u); r0 = r0 ^ t_; } // 27 shfl
|
||||
r0 = r0 + r2 + ((((sel >> 25u) & 1u) != 0u) ? 0xc6311db1u : 0x1a3cecfbu); // 28 add
|
||||
r5 = mul_hi(r5, r7); // 29 mulhi
|
||||
r0 = r1 * r7 + r0; // 30 mad
|
||||
r5 = rotl_imm(r5, 23u); // 31 rotl
|
||||
r0 = r0 + r2 + ((((sel >> 28u) & 1u) != 0u) ? 0xf1282553u : 0x7aa05e39u); // 32 add
|
||||
r1 = r1 ^ r6; // 33 xor
|
||||
r0 = r0 - r1; // 34 sub
|
||||
r1 = r1 ^ ds[r6 & mask]; // 35 load
|
||||
r1 = rotl_imm(r1, 7u); // 36 rotl
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r4, 8u); r0 = r0 ^ t_; } // 37 shfl
|
||||
r3 = r3 + r5 + ((((sel >> 13u) & 1u) != 0u) ? 0x70173cfdu : 0x4a9bf1a8u); // 38 add
|
||||
r3 = mul_hi(r3, r4); // 39 mulhi
|
||||
r3 = r3 + r6 + ((((sel >> 8u) & 1u) != 0u) ? 0x2596fd35u : 0x26b3e1a7u); // 40 add
|
||||
r3 = r3 - r7; // 41 sub
|
||||
r0 = r0 - r4; // 42 sub
|
||||
r5 = rotr_var(r5, r7); // 43 rotr
|
||||
r3 = r4 * r1 + r3; // 44 mad
|
||||
r4 = r4 ^ ds[r2 & mask]; // 45 load
|
||||
r2 = mul_hi(r2, r5); // 46 mulhi
|
||||
r3 = r3 ^ ds[r5 & mask]; // 47 load
|
||||
r5 = mul_hi(r5, r6); // 48 mulhi
|
||||
r5 = r5 + r7 + ((((sel >> 22u) & 1u) != 0u) ? 0x724f77b9u : 0x9f31d23cu); // 49 add
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r7, 1u); r2 = r2 ^ t_; } // 50 shfl
|
||||
r1 = r1 * r5; // 51 mul
|
||||
r1 = r1 * r6; // 52 mul
|
||||
{ uint b_ = (r1 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r6 = x_; } // 53 load
|
||||
r7 = r7 ^ r2; // 54 xor
|
||||
r2 = r2 - r1; // 55 sub
|
||||
r7 = r7 ^ r3; // 56 xor
|
||||
r3 = rotl_imm(r3, 2u); // 57 rotl
|
||||
r6 = mul_hi(r6, r4); // 58 mulhi
|
||||
r4 = rotr_var(r4, r5); // 59 rotr
|
||||
r3 = mul_hi(r3, r1); // 60 mulhi
|
||||
r3 = r3 ^ r6; // 61 xor
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r1, 16u); r5 = r5 ^ t_; } // 62 shfl
|
||||
r1 = r1 ^ ds[r6 & mask]; // 63 load
|
||||
}
|
||||
uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u);
|
||||
uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u);
|
||||
out[gid] = ((ulong)hi << 32) | (ulong)lo;
|
||||
}
|
||||
|
||||
#if IGNEUM_EXCHANGE != 0
|
||||
// Reports the sub-group size this device uses for a work-group of IGNEUM_GROUP items. host.c runs it only when the
|
||||
// per-kernel query (clGetKernelSubGroupInfoKHR on igneum_hash) is unavailable; that query is preferred because a
|
||||
// compiler may pick a different wave width per kernel (RDNA: wave32 or wave64). See WAVEFRONT.md.
|
||||
IGNEUM_KERNEL_HASH void igneum_probe_subgroup(__global uint* out) {
|
||||
if (get_local_id(0) == 0u) { out[0] = get_sub_group_size(); out[1] = get_num_sub_groups(); }
|
||||
}
|
||||
#endif
|
||||
164
proto-cuda/packs-readwidth/mixA-0/kernel.cu
Normal file
164
proto-cuda/packs-readwidth/mixA-0/kernel.cu
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
// Generated by igneum-pow export (generator v2) for seed "igneum-readwidth/A/0". Do not edit by hand.
|
||||
// Bit-exact twin of the Metal kernel for the same seed (see proto-cuda/CHECKLIST.md and program.metal).
|
||||
// Compiled ahead of time by nvcc together with proto-cuda/host.cu. No NVRTC.
|
||||
#include <cuda_runtime.h>
|
||||
#include <cstdint>
|
||||
#include "program.h"
|
||||
#include "memhard.h"
|
||||
|
||||
__device__ __forceinline__ uint32_t splitmix32(uint32_t x) {
|
||||
x ^= x >> 16; x *= 0x7feb352du;
|
||||
x ^= x >> 15; x *= 0x846ca68bu;
|
||||
x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
// n is a literal in 1..31 at every call site, so both shift amounts are in 1..31.
|
||||
__device__ __forceinline__ uint32_t rotl_imm(uint32_t x, uint32_t n) { return (x << n) | (x >> (32u - n)); }
|
||||
// n is masked to 0..31; the second shift amount is masked too, so n == 0 gives x.
|
||||
__device__ __forceinline__ uint32_t rotr_var(uint32_t x, uint32_t n) { n &= 31u; return (x >> n) | (x << ((32u - n) & 31u)); }
|
||||
__device__ __forceinline__ uint32_t ds_elem(uint32_t i, uint32_t d0, uint32_t d1) {
|
||||
uint32_t x = i ^ d0;
|
||||
x *= 0x9E3779B1u; x ^= x >> 15;
|
||||
x += d1;
|
||||
x *= 0x85EBCA77u; x ^= x >> 13;
|
||||
x *= 0xC2B2AE3Du; x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
|
||||
// Memory-hard dataset (MEMHARD.md). One thread per cache segment; one thread per 64-byte dataset item.
|
||||
// The core functions (mh_cache_segment, mh_item) are in memhard.h and are also compiled for the host.
|
||||
__global__ void igneum_cache_fill(uint32_t* cache, uint32_t nSegments) {
|
||||
uint32_t seg = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
if (seg < nSegments) mh_cache_segment(cache, seg);
|
||||
}
|
||||
__global__ void igneum_build(uint32_t* ds, const uint32_t* cache, uint32_t nItems) {
|
||||
uint32_t t = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
if (t < nItems) {
|
||||
uint32_t s[16];
|
||||
mh_item(cache, t, s);
|
||||
uint32_t* d = ds + (size_t)t * 16u;
|
||||
for (uint32_t i = 0u; i < 16u; ++i) d[i] = s[i];
|
||||
}
|
||||
}
|
||||
|
||||
// One hash per thread. blockDim.x is a multiple of 32; lane = threadIdx.x & 31 and every
|
||||
// __shfl_xor_sync stays inside the lane's own warp, exactly like simd_shuffle_xor inside a
|
||||
// 32-wide Metal SIMD group. Control flow is uniform, so the full 0xffffffff member mask is valid.
|
||||
__global__ void igneum_hash(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask) {
|
||||
uint32_t gid = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
uint32_t nonce = baseNonce + gid;
|
||||
uint32_t r0, r1, r2, r3, r4, r5, r6, r7;
|
||||
{ uint32_t x = nonce ^ 0xaa5a3f6eu; x += 0x9e3779b9u; x = splitmix32(x); r0 = x ^ 0x5c0410c3u; } // SEEDW[0], 0x9e3779b9u * 1u, SEEDW[1]
|
||||
{ uint32_t x = nonce ^ 0x5c0410c3u; x += 0x3c6ef372u; x = splitmix32(x); r1 = x ^ 0x9d994375u; } // SEEDW[1], 0x9e3779b9u * 2u, SEEDW[2]
|
||||
{ uint32_t x = nonce ^ 0x9d994375u; x += 0xdaa66d2bu; x = splitmix32(x); r2 = x ^ 0xd8d53386u; } // SEEDW[2], 0x9e3779b9u * 3u, SEEDW[3]
|
||||
{ uint32_t x = nonce ^ 0xd8d53386u; x += 0x78dde6e4u; x = splitmix32(x); r3 = x ^ 0x2c956ee2u; } // SEEDW[3], 0x9e3779b9u * 4u, SEEDW[4]
|
||||
{ uint32_t x = nonce ^ 0x2c956ee2u; x += 0x1715609du; x = splitmix32(x); r4 = x ^ 0xe313c2f9u; } // SEEDW[4], 0x9e3779b9u * 5u, SEEDW[5]
|
||||
{ uint32_t x = nonce ^ 0xe313c2f9u; x += 0xb54cda56u; x = splitmix32(x); r5 = x ^ 0x495ace1bu; } // SEEDW[5], 0x9e3779b9u * 6u, SEEDW[6]
|
||||
{ uint32_t x = nonce ^ 0x495ace1bu; x += 0x5384540fu; x = splitmix32(x); r6 = x ^ 0x8238bb25u; } // SEEDW[6], 0x9e3779b9u * 7u, SEEDW[7]
|
||||
{ uint32_t x = nonce ^ 0x8238bb25u; x += 0xf1bbcdc8u; x = splitmix32(x); r7 = x ^ 0xaa5a3f6eu; } // SEEDW[7], 0x9e3779b9u * 8u, SEEDW[0]
|
||||
|
||||
for (uint32_t it = 0u; it < 8u; ++it) {
|
||||
uint32_t sel = r0;
|
||||
r2 = r2 + r7 + ((((sel >> 30u) & 1u) != 0u) ? 0xb788d5f8u : 0x92d00116u); // 0 add
|
||||
r3 = __umulhi(r3, r2); // 1 mulhi
|
||||
r6 = r6 ^ ds[r3 & mask]; // 2 load
|
||||
r0 = r0 ^ ds[r6 & mask]; // 3 load
|
||||
r5 = r5 * r2; // 4 mul
|
||||
r7 = r7 + r2 + ((((sel >> 20u) & 1u) != 0u) ? 0x9a773a55u : 0xd5f6f389u); // 5 add
|
||||
{ uint32_t b_ = (r5 & mask) & ~15u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint32_t x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r6 = x_; } // 6 load
|
||||
r5 = r5 ^ ds[r6 & mask]; // 7 load
|
||||
{ uint32_t b_ = (r2 & mask) & ~3u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint32_t x_ = r1 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r1 = x_; } // 8 load
|
||||
r4 = r4 * r5; // 9 mul
|
||||
{ uint32_t b_ = (r0 & mask) & ~3u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint32_t x_ = r2 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r2 = x_; } // 10 load
|
||||
r3 = r3 ^ ds[r2 & mask]; // 11 load
|
||||
r4 = r4 ^ r0; // 12 xor
|
||||
r7 = r7 ^ ds[r3 & mask]; // 13 load
|
||||
r7 = r7 ^ r1; // 14 xor
|
||||
r4 = r1 * r4 + r4; // 15 mad
|
||||
r3 = r0 * r4 + r3; // 16 mad
|
||||
r4 = r6 * r2 + r4; // 17 mad
|
||||
r0 = rotr_var(r0, r2); // 18 rotr
|
||||
r5 = rotr_var(r5, r6); // 19 rotr
|
||||
r4 = r4 ^ ds[r1 & mask]; // 20 load
|
||||
r2 = r2 ^ ds[r4 & mask]; // 21 load
|
||||
r1 = rotl_imm(r1, 14u); // 22 rotl
|
||||
r7 = r7 - r1; // 23 sub
|
||||
r2 = r2 ^ __shfl_xor_sync(0xffffffffu, r6, 2); // 24 shfl
|
||||
r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r4, 16); // 25 shfl
|
||||
r6 = r6 ^ ds[r0 & mask]; // 26 load
|
||||
r0 = r0 ^ __shfl_xor_sync(0xffffffffu, r6, 1); // 27 shfl
|
||||
r0 = r0 + r2 + ((((sel >> 25u) & 1u) != 0u) ? 0xc6311db1u : 0x1a3cecfbu); // 28 add
|
||||
r5 = __umulhi(r5, r7); // 29 mulhi
|
||||
r0 = r1 * r7 + r0; // 30 mad
|
||||
r5 = rotl_imm(r5, 23u); // 31 rotl
|
||||
r0 = r0 + r2 + ((((sel >> 28u) & 1u) != 0u) ? 0xf1282553u : 0x7aa05e39u); // 32 add
|
||||
r1 = r1 ^ r6; // 33 xor
|
||||
r0 = r0 - r1; // 34 sub
|
||||
r1 = r1 ^ ds[r6 & mask]; // 35 load
|
||||
r1 = rotl_imm(r1, 7u); // 36 rotl
|
||||
r0 = r0 ^ __shfl_xor_sync(0xffffffffu, r4, 8); // 37 shfl
|
||||
r3 = r3 + r5 + ((((sel >> 13u) & 1u) != 0u) ? 0x70173cfdu : 0x4a9bf1a8u); // 38 add
|
||||
r3 = __umulhi(r3, r4); // 39 mulhi
|
||||
r3 = r3 + r6 + ((((sel >> 8u) & 1u) != 0u) ? 0x2596fd35u : 0x26b3e1a7u); // 40 add
|
||||
r3 = r3 - r7; // 41 sub
|
||||
r0 = r0 - r4; // 42 sub
|
||||
r5 = rotr_var(r5, r7); // 43 rotr
|
||||
r3 = r4 * r1 + r3; // 44 mad
|
||||
r4 = r4 ^ ds[r2 & mask]; // 45 load
|
||||
r2 = __umulhi(r2, r5); // 46 mulhi
|
||||
r3 = r3 ^ ds[r5 & mask]; // 47 load
|
||||
r5 = __umulhi(r5, r6); // 48 mulhi
|
||||
r5 = r5 + r7 + ((((sel >> 22u) & 1u) != 0u) ? 0x724f77b9u : 0x9f31d23cu); // 49 add
|
||||
r2 = r2 ^ __shfl_xor_sync(0xffffffffu, r7, 1); // 50 shfl
|
||||
r1 = r1 * r5; // 51 mul
|
||||
r1 = r1 * r6; // 52 mul
|
||||
{ uint32_t b_ = (r1 & mask) & ~15u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint32_t x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r6 = x_; } // 53 load
|
||||
r7 = r7 ^ r2; // 54 xor
|
||||
r2 = r2 - r1; // 55 sub
|
||||
r7 = r7 ^ r3; // 56 xor
|
||||
r3 = rotl_imm(r3, 2u); // 57 rotl
|
||||
r6 = __umulhi(r6, r4); // 58 mulhi
|
||||
r4 = rotr_var(r4, r5); // 59 rotr
|
||||
r3 = __umulhi(r3, r1); // 60 mulhi
|
||||
r3 = r3 ^ r6; // 61 xor
|
||||
r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r1, 16); // 62 shfl
|
||||
r1 = r1 ^ ds[r6 & mask]; // 63 load
|
||||
}
|
||||
uint32_t lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u);
|
||||
uint32_t hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u);
|
||||
out[gid] = ((uint64_t)hi << 32) | (uint64_t)lo;
|
||||
}
|
||||
|
||||
// Host-side launch wrappers. Declared in program.h, called from host.cu.
|
||||
cudaError_t igneum_launch_cache_fill(uint32_t* cache, uint32_t nSegments) {
|
||||
if (nSegments == 0u) return cudaErrorInvalidValue;
|
||||
uint32_t block = 256u;
|
||||
uint32_t grid = (nSegments + block - 1u) / block;
|
||||
igneum_cache_fill<<<grid, block>>>(cache, nSegments);
|
||||
return cudaGetLastError();
|
||||
}
|
||||
|
||||
cudaError_t igneum_launch_build(uint32_t* ds, const uint32_t* cache, uint32_t nItems) {
|
||||
if (nItems == 0u) return cudaErrorInvalidValue;
|
||||
uint32_t block = 256u;
|
||||
uint32_t grid = (nItems + block - 1u) / block;
|
||||
igneum_build<<<grid, block>>>(ds, cache, nItems);
|
||||
return cudaGetLastError();
|
||||
}
|
||||
|
||||
cudaError_t igneum_launch_hash(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask,
|
||||
uint32_t nonces, uint32_t blockWarps) {
|
||||
if (blockWarps == 0u || blockWarps > 32u) return cudaErrorInvalidValue;
|
||||
uint32_t block = 32u * blockWarps;
|
||||
if (nonces == 0u || (nonces % block) != 0u) return cudaErrorInvalidValue;
|
||||
igneum_hash<<<nonces / block, block>>>(ds, out, baseNonce, mask);
|
||||
return cudaGetLastError();
|
||||
}
|
||||
|
||||
cudaError_t igneum_hash_info(int* numRegs, int* blocksPerSM, uint32_t blockWarps) {
|
||||
cudaFuncAttributes attr;
|
||||
cudaError_t e = cudaFuncGetAttributes(&attr, igneum_hash);
|
||||
if (e != cudaSuccess) return e;
|
||||
*numRegs = attr.numRegs;
|
||||
return cudaOccupancyMaxActiveBlocksPerMultiprocessor(blocksPerSM, igneum_hash, (int)(32u * blockWarps), 0);
|
||||
}
|
||||
372
proto-cuda/packs-readwidth/mixA-0/kernel_bound.cl
Normal file
372
proto-cuda/packs-readwidth/mixA-0/kernel_bound.cl
Normal file
|
|
@ -0,0 +1,372 @@
|
|||
// Generated by igneum-pow export (generator v2) for seed "igneum-readwidth/A/0". Do not edit by hand.
|
||||
// OpenCL C twin of the Metal kernel for the same seed (see proto-opencl/README.md, WAVEFRONT.md and program.metal).
|
||||
// Built from source at runtime by proto-opencl/host.c, which passes these defines:
|
||||
// IGNEUM_GROUP work-group size of igneum_hash, a multiple of 32 (default 32: one work-group = one 32-lane unit)
|
||||
// IGNEUM_EXCHANGE 0 = local-memory exchange with a barrier (any device, any wave width; the default)
|
||||
// 1 = sub_group_shuffle_xor (cl_khr_subgroup_shuffle), only with IGNEUM_GROUP 32 and a sub-group size of exactly 32
|
||||
// 2 = intel_sub_group_shuffle_xor (cl_intel_subgroups), same condition
|
||||
// The verification unit is always 32 lanes. A 64-wide hardware wave (AMD GCN/CDNA, RDNA in wave64) runs two units;
|
||||
// the exchange masks are 1, 2, 4, 8, 16, so every partner lane lies inside the lane's own aligned run of 32.
|
||||
#ifndef IGNEUM_GROUP
|
||||
#define IGNEUM_GROUP 32
|
||||
#endif
|
||||
#ifndef IGNEUM_EXCHANGE
|
||||
#define IGNEUM_EXCHANGE 0
|
||||
#endif
|
||||
#ifdef __OPENCL_VERSION__
|
||||
#define IGNEUM_KERNEL_HASH __kernel __attribute__((reqd_work_group_size(IGNEUM_GROUP, 1, 1)))
|
||||
#define IGNEUM_LOCAL_WORDS(name, n) __local uint name[n]
|
||||
#if IGNEUM_EXCHANGE == 1
|
||||
#ifdef cl_khr_subgroups
|
||||
#pragma OPENCL EXTENSION cl_khr_subgroups : enable
|
||||
#endif
|
||||
#ifdef cl_khr_subgroup_shuffle
|
||||
#pragma OPENCL EXTENSION cl_khr_subgroup_shuffle : enable
|
||||
#endif
|
||||
#elif IGNEUM_EXCHANGE == 2
|
||||
#pragma OPENCL EXTENSION cl_intel_subgroups : enable
|
||||
#endif
|
||||
#else
|
||||
// Not an OpenCL compiler: proto-opencl/emu compiles this file as C++ and supplies the built-ins and these two macros.
|
||||
#include "emu_opencl.h"
|
||||
#endif
|
||||
|
||||
#if IGNEUM_EXCHANGE == 1
|
||||
#define IGNEUM_SHFL_XOR(dst, a, m) dst = sub_group_shuffle_xor((a), (uint)(m))
|
||||
#define IGNEUM_BCAST0(dst, a) dst = sub_group_broadcast((a), 0u)
|
||||
#elif IGNEUM_EXCHANGE == 2
|
||||
#define IGNEUM_SHFL_XOR(dst, a, m) dst = intel_sub_group_shuffle_xor((a), (uint)(m))
|
||||
#define IGNEUM_BCAST0(dst, a) dst = sub_group_broadcast((a), 0u)
|
||||
#else
|
||||
// Local-memory exchange. Two buffers of IGNEUM_GROUP words alternate (xk counts exchanges), so one barrier per
|
||||
// exchange is enough: a lane can only overwrite buffer b at exchange k+2 after passing barrier k+1, and every lane
|
||||
// reaches barrier k+1 only after its read of buffer b at exchange k. The partner lid ^ m stays inside the lane's
|
||||
// aligned run of 32 because m < 32. Control flow is uniform, so every work-item reaches every barrier.
|
||||
#define IGNEUM_SHFL_XOR(dst, a, m) { xch[(xk & 1u) * IGNEUM_GROUP + lid] = (a); barrier(CLK_LOCAL_MEM_FENCE); dst = xch[(xk & 1u) * IGNEUM_GROUP + (lid ^ (uint)(m))]; xk += 1u; }
|
||||
#define IGNEUM_BCAST0(dst, a) { xch[(xk & 1u) * IGNEUM_GROUP + lid] = (a); barrier(CLK_LOCAL_MEM_FENCE); dst = xch[(xk & 1u) * IGNEUM_GROUP + (lid & ~31u)]; xk += 1u; }
|
||||
#endif
|
||||
|
||||
static inline uint splitmix32(uint x) {
|
||||
x ^= x >> 16; x *= 0x7feb352du;
|
||||
x ^= x >> 15; x *= 0x846ca68bu;
|
||||
x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
// n is a literal in 1..31 at every call site. OpenCL rotate() rotates left by n modulo 32.
|
||||
static inline uint rotl_imm(uint x, uint n) { return rotate(x, n); }
|
||||
// Right rotation by n modulo 32 as a left rotation by (32 - n) modulo 32; n == 0 gives x.
|
||||
static inline uint rotr_var(uint x, uint n) { return rotate(x, (0u - n) & 31u); }
|
||||
static inline uint ds_elem(uint i, uint d0, uint d1) {
|
||||
uint x = i ^ d0;
|
||||
x *= 0x9E3779B1u; x ^= x >> 15;
|
||||
x += d1;
|
||||
x *= 0x85EBCA77u; x ^= x >> 13;
|
||||
x *= 0xC2B2AE3Du; x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
|
||||
// Memory-hard dataset core (MEMHARD.md). Cache: 2^26 words in 2^16 segments of 64 chained ChaCha12 lines.
|
||||
// Item: 8 rounds of seed-parameterised mixer + one 64-byte cache read, then a final mixer. All parameters are literals.
|
||||
#define MH_CACHE_LINE_MASK 0x003fffffu
|
||||
#define MH_SEGMENT_LINES 64u
|
||||
#define MH_QR(a, b, c, d, r1, r2, r3, r4) { a += b; d ^= a; d = mh_rotl(d, r1); c += d; b ^= c; b = mh_rotl(b, r2); a += b; d ^= a; d = mh_rotl(d, r3); c += d; b ^= c; b = mh_rotl(b, r4); }
|
||||
static inline uint mh_rotl(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 at every call site
|
||||
|
||||
// y = ChaCha12 core(x) + x
|
||||
static inline void mh_chacha_block(const uint* x, uint* y) {
|
||||
for (uint i = 0u; i < 16u; ++i) y[i] = x[i];
|
||||
for (uint r = 0u; r < 6u; ++r) {
|
||||
MH_QR(y[0], y[4], y[8], y[12], 16u, 12u, 8u, 7u) MH_QR(y[1], y[5], y[9], y[13], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[2], y[6], y[10], y[14], 16u, 12u, 8u, 7u) MH_QR(y[3], y[7], y[11], y[15], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[0], y[5], y[10], y[15], 16u, 12u, 8u, 7u) MH_QR(y[1], y[6], y[11], y[12], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[2], y[7], y[8], y[13], 16u, 12u, 8u, 7u) MH_QR(y[3], y[4], y[9], y[14], 16u, 12u, 8u, 7u)
|
||||
}
|
||||
for (uint i = 0u; i < 16u; ++i) y[i] += x[i];
|
||||
}
|
||||
|
||||
// One cache segment: 64 chained lines written at cache[seg * 1024]. in_j = prev ^ (sigma || K || seg || j || tag), prev_0 = 0.
|
||||
static inline void mh_cache_segment(__global uint* cache, uint seg) {
|
||||
uint prev[16]; uint x[16]; uint y[16];
|
||||
for (uint i = 0u; i < 16u; ++i) prev[i] = 0u;
|
||||
for (uint j = 0u; j < MH_SEGMENT_LINES; ++j) {
|
||||
x[0] = 0x61707865u ^ prev[0]; x[1] = 0x3320646eu ^ prev[1]; x[2] = 0x79622d32u ^ prev[2]; x[3] = 0x6b206574u ^ prev[3];
|
||||
x[4] = 0x3067619fu ^ prev[4];
|
||||
x[5] = 0x3c269176u ^ prev[5];
|
||||
x[6] = 0x84a03b03u ^ prev[6];
|
||||
x[7] = 0xf8c63294u ^ prev[7];
|
||||
x[8] = 0xff977c5bu ^ prev[8];
|
||||
x[9] = 0xe60def3eu ^ prev[9];
|
||||
x[10] = 0x63630141u ^ prev[10];
|
||||
x[11] = 0xb8fbcb58u ^ prev[11];
|
||||
x[12] = seg ^ prev[12]; x[13] = j ^ prev[13]; x[14] = 0x49676e65u ^ prev[14]; x[15] = 0x756d4d48u ^ prev[15];
|
||||
mh_chacha_block(x, y);
|
||||
__global uint* line = cache + ((seg * MH_SEGMENT_LINES + j) * 16u);
|
||||
for (uint i = 0u; i < 16u; ++i) { line[i] = y[i]; prev[i] = y[i]; }
|
||||
}
|
||||
}
|
||||
|
||||
// M_r: per word (s ^ (RC + rk)) * MUL, then a column round and a diagonal round with the seed-drawn rotations.
|
||||
static inline void mh_mixer(uint* s, uint rk) {
|
||||
s[0] = (s[0] ^ (0xbab68293u + rk)) * 0x42146205u;
|
||||
s[1] = (s[1] ^ (0xcc162340u + rk)) * 0x52cbe0fbu;
|
||||
s[2] = (s[2] ^ (0x6ce151ccu + rk)) * 0x7ecf4a03u;
|
||||
s[3] = (s[3] ^ (0xe62b8997u + rk)) * 0x6728907fu;
|
||||
s[4] = (s[4] ^ (0xc9c80297u + rk)) * 0xd81d9751u;
|
||||
s[5] = (s[5] ^ (0xf74a1654u + rk)) * 0x132952c3u;
|
||||
s[6] = (s[6] ^ (0x3d704af5u + rk)) * 0xf60de277u;
|
||||
s[7] = (s[7] ^ (0x3cf522b7u + rk)) * 0x05358035u;
|
||||
s[8] = (s[8] ^ (0x2b9cac04u + rk)) * 0xbaf6499du;
|
||||
s[9] = (s[9] ^ (0xa880ac10u + rk)) * 0xe4db9667u;
|
||||
s[10] = (s[10] ^ (0x13e5dd1du + rk)) * 0x3e98f45du;
|
||||
s[11] = (s[11] ^ (0x6fc3e233u + rk)) * 0xd0004eddu;
|
||||
s[12] = (s[12] ^ (0x2d83eeacu + rk)) * 0x2691630du;
|
||||
s[13] = (s[13] ^ (0x9006e8bfu + rk)) * 0x9beb3bcfu;
|
||||
s[14] = (s[14] ^ (0x2c4b5362u + rk)) * 0xab310379u;
|
||||
s[15] = (s[15] ^ (0x31b49ee2u + rk)) * 0x99cfb423u;
|
||||
MH_QR(s[0], s[4], s[8], s[12], 20u, 20u, 19u, 4u) MH_QR(s[1], s[5], s[9], s[13], 20u, 20u, 19u, 4u)
|
||||
MH_QR(s[2], s[6], s[10], s[14], 20u, 20u, 19u, 4u) MH_QR(s[3], s[7], s[11], s[15], 20u, 20u, 19u, 4u)
|
||||
MH_QR(s[0], s[5], s[10], s[15], 26u, 3u, 3u, 27u) MH_QR(s[1], s[6], s[11], s[12], 26u, 3u, 3u, 27u)
|
||||
MH_QR(s[2], s[7], s[8], s[13], 26u, 3u, 3u, 27u) MH_QR(s[3], s[4], s[9], s[14], 26u, 3u, 3u, 27u)
|
||||
}
|
||||
|
||||
// Item t: 16 words. s = (K, t * MUL[i] + RC[i]); 8 rounds of mixer + cache line s[0] & mask; final mixer.
|
||||
static inline void mh_item(__global const uint* cache, uint t, uint* s) {
|
||||
s[0] = 0x3067619fu;
|
||||
s[1] = 0x3c269176u;
|
||||
s[2] = 0x84a03b03u;
|
||||
s[3] = 0xf8c63294u;
|
||||
s[4] = 0xff977c5bu;
|
||||
s[5] = 0xe60def3eu;
|
||||
s[6] = 0x63630141u;
|
||||
s[7] = 0xb8fbcb58u;
|
||||
s[8] = t * 0x42146205u + 0xbab68293u;
|
||||
s[9] = t * 0x52cbe0fbu + 0xcc162340u;
|
||||
s[10] = t * 0x7ecf4a03u + 0x6ce151ccu;
|
||||
s[11] = t * 0x6728907fu + 0xe62b8997u;
|
||||
s[12] = t * 0xd81d9751u + 0xc9c80297u;
|
||||
s[13] = t * 0x132952c3u + 0xf74a1654u;
|
||||
s[14] = t * 0xf60de277u + 0x3d704af5u;
|
||||
s[15] = t * 0x05358035u + 0x3cf522b7u;
|
||||
for (uint r = 0u; r < 8u; ++r) {
|
||||
mh_mixer(s, 0x9E3779B9u * (r + 1u));
|
||||
__global const uint* line = cache + ((s[0] & MH_CACHE_LINE_MASK) * 16u);
|
||||
for (uint i = 0u; i < 16u; ++i) s[i] ^= line[i];
|
||||
}
|
||||
mh_mixer(s, 0x9E3779B9u * 9u);
|
||||
}
|
||||
// dataset[w] without the dataset: derive item w >> 4 and take word w & 15.
|
||||
static inline uint mh_word(__global const uint* cache, uint w) { uint s[16]; mh_item(cache, w >> 4u, s); return s[w & 15u]; }
|
||||
|
||||
// Memory-hard dataset (MEMHARD.md). One work-item per cache segment; one work-item per 64-byte dataset item.
|
||||
// The same constants as memhard.h in this pack (one emitter, three dialects).
|
||||
__kernel void igneum_cache_fill(__global uint* cache, uint nSegments) {
|
||||
uint seg = (uint)get_global_id(0);
|
||||
if (seg < nSegments) mh_cache_segment(cache, seg);
|
||||
}
|
||||
__kernel void igneum_build(__global uint* ds, __global const uint* cache, uint nItems) {
|
||||
uint t = (uint)get_global_id(0);
|
||||
if (t < nItems) {
|
||||
uint s[16];
|
||||
mh_item(cache, t, s);
|
||||
__global uint* d = ds + ((ulong)t * 16u);
|
||||
for (uint i = 0u; i < 16u; ++i) d[i] = s[i];
|
||||
}
|
||||
}
|
||||
|
||||
// One hash per work-item. IGNEUM_GROUP is a multiple of 32; lane = lid & 31 and every exchange stays inside the
|
||||
// lane's own aligned run of 32 work-items, exactly like simd_shuffle_xor inside a 32-wide Metal SIMD group and
|
||||
// __shfl_xor_sync inside a CUDA warp. Control flow is uniform (no branches at all).
|
||||
IGNEUM_KERNEL_HASH void igneum_hash(__global const uint* ds, __global ulong* out, uint baseNonce, uint mask) {
|
||||
uint gid = (uint)get_global_id(0);
|
||||
uint lid = (uint)get_local_id(0);
|
||||
uint nonce = baseNonce + gid;
|
||||
uint r0, r1, r2, r3, r4, r5, r6, r7;
|
||||
#if IGNEUM_EXCHANGE == 0
|
||||
IGNEUM_LOCAL_WORDS(xch, 2 * IGNEUM_GROUP);
|
||||
uint xk = 0u;
|
||||
#else
|
||||
(void)lid;
|
||||
#endif
|
||||
{ uint x = nonce ^ 0xaa5a3f6eu; x += 0x9e3779b9u; x = splitmix32(x); r0 = x ^ 0x5c0410c3u; } // SEEDW[0], 0x9e3779b9u * 1u, SEEDW[1]
|
||||
{ uint x = nonce ^ 0x5c0410c3u; x += 0x3c6ef372u; x = splitmix32(x); r1 = x ^ 0x9d994375u; } // SEEDW[1], 0x9e3779b9u * 2u, SEEDW[2]
|
||||
{ uint x = nonce ^ 0x9d994375u; x += 0xdaa66d2bu; x = splitmix32(x); r2 = x ^ 0xd8d53386u; } // SEEDW[2], 0x9e3779b9u * 3u, SEEDW[3]
|
||||
{ uint x = nonce ^ 0xd8d53386u; x += 0x78dde6e4u; x = splitmix32(x); r3 = x ^ 0x2c956ee2u; } // SEEDW[3], 0x9e3779b9u * 4u, SEEDW[4]
|
||||
{ uint x = nonce ^ 0x2c956ee2u; x += 0x1715609du; x = splitmix32(x); r4 = x ^ 0xe313c2f9u; } // SEEDW[4], 0x9e3779b9u * 5u, SEEDW[5]
|
||||
{ uint x = nonce ^ 0xe313c2f9u; x += 0xb54cda56u; x = splitmix32(x); r5 = x ^ 0x495ace1bu; } // SEEDW[5], 0x9e3779b9u * 6u, SEEDW[6]
|
||||
{ uint x = nonce ^ 0x495ace1bu; x += 0x5384540fu; x = splitmix32(x); r6 = x ^ 0x8238bb25u; } // SEEDW[6], 0x9e3779b9u * 7u, SEEDW[7]
|
||||
{ uint x = nonce ^ 0x8238bb25u; x += 0xf1bbcdc8u; x = splitmix32(x); r7 = x ^ 0xaa5a3f6eu; } // SEEDW[7], 0x9e3779b9u * 8u, SEEDW[0]
|
||||
|
||||
for (uint it = 0u; it < 8u; ++it) {
|
||||
uint sel = r0;
|
||||
r2 = r2 + r7 + ((((sel >> 30u) & 1u) != 0u) ? 0xb788d5f8u : 0x92d00116u); // 0 add
|
||||
r3 = mul_hi(r3, r2); // 1 mulhi
|
||||
r6 = r6 ^ ds[r3 & mask]; // 2 load
|
||||
r0 = r0 ^ ds[r6 & mask]; // 3 load
|
||||
r5 = r5 * r2; // 4 mul
|
||||
r7 = r7 + r2 + ((((sel >> 20u) & 1u) != 0u) ? 0x9a773a55u : 0xd5f6f389u); // 5 add
|
||||
{ uint b_ = (r5 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r6 = x_; } // 6 load
|
||||
r5 = r5 ^ ds[r6 & mask]; // 7 load
|
||||
{ uint b_ = (r2 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r1 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r1 = x_; } // 8 load
|
||||
r4 = r4 * r5; // 9 mul
|
||||
{ uint b_ = (r0 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r2 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r2 = x_; } // 10 load
|
||||
r3 = r3 ^ ds[r2 & mask]; // 11 load
|
||||
r4 = r4 ^ r0; // 12 xor
|
||||
r7 = r7 ^ ds[r3 & mask]; // 13 load
|
||||
r7 = r7 ^ r1; // 14 xor
|
||||
r4 = r1 * r4 + r4; // 15 mad
|
||||
r3 = r0 * r4 + r3; // 16 mad
|
||||
r4 = r6 * r2 + r4; // 17 mad
|
||||
r0 = rotr_var(r0, r2); // 18 rotr
|
||||
r5 = rotr_var(r5, r6); // 19 rotr
|
||||
r4 = r4 ^ ds[r1 & mask]; // 20 load
|
||||
r2 = r2 ^ ds[r4 & mask]; // 21 load
|
||||
r1 = rotl_imm(r1, 14u); // 22 rotl
|
||||
r7 = r7 - r1; // 23 sub
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r6, 2u); r2 = r2 ^ t_; } // 24 shfl
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r4, 16u); r1 = r1 ^ t_; } // 25 shfl
|
||||
r6 = r6 ^ ds[r0 & mask]; // 26 load
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r6, 1u); r0 = r0 ^ t_; } // 27 shfl
|
||||
r0 = r0 + r2 + ((((sel >> 25u) & 1u) != 0u) ? 0xc6311db1u : 0x1a3cecfbu); // 28 add
|
||||
r5 = mul_hi(r5, r7); // 29 mulhi
|
||||
r0 = r1 * r7 + r0; // 30 mad
|
||||
r5 = rotl_imm(r5, 23u); // 31 rotl
|
||||
r0 = r0 + r2 + ((((sel >> 28u) & 1u) != 0u) ? 0xf1282553u : 0x7aa05e39u); // 32 add
|
||||
r1 = r1 ^ r6; // 33 xor
|
||||
r0 = r0 - r1; // 34 sub
|
||||
r1 = r1 ^ ds[r6 & mask]; // 35 load
|
||||
r1 = rotl_imm(r1, 7u); // 36 rotl
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r4, 8u); r0 = r0 ^ t_; } // 37 shfl
|
||||
r3 = r3 + r5 + ((((sel >> 13u) & 1u) != 0u) ? 0x70173cfdu : 0x4a9bf1a8u); // 38 add
|
||||
r3 = mul_hi(r3, r4); // 39 mulhi
|
||||
r3 = r3 + r6 + ((((sel >> 8u) & 1u) != 0u) ? 0x2596fd35u : 0x26b3e1a7u); // 40 add
|
||||
r3 = r3 - r7; // 41 sub
|
||||
r0 = r0 - r4; // 42 sub
|
||||
r5 = rotr_var(r5, r7); // 43 rotr
|
||||
r3 = r4 * r1 + r3; // 44 mad
|
||||
r4 = r4 ^ ds[r2 & mask]; // 45 load
|
||||
r2 = mul_hi(r2, r5); // 46 mulhi
|
||||
r3 = r3 ^ ds[r5 & mask]; // 47 load
|
||||
r5 = mul_hi(r5, r6); // 48 mulhi
|
||||
r5 = r5 + r7 + ((((sel >> 22u) & 1u) != 0u) ? 0x724f77b9u : 0x9f31d23cu); // 49 add
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r7, 1u); r2 = r2 ^ t_; } // 50 shfl
|
||||
r1 = r1 * r5; // 51 mul
|
||||
r1 = r1 * r6; // 52 mul
|
||||
{ uint b_ = (r1 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r6 = x_; } // 53 load
|
||||
r7 = r7 ^ r2; // 54 xor
|
||||
r2 = r2 - r1; // 55 sub
|
||||
r7 = r7 ^ r3; // 56 xor
|
||||
r3 = rotl_imm(r3, 2u); // 57 rotl
|
||||
r6 = mul_hi(r6, r4); // 58 mulhi
|
||||
r4 = rotr_var(r4, r5); // 59 rotr
|
||||
r3 = mul_hi(r3, r1); // 60 mulhi
|
||||
r3 = r3 ^ r6; // 61 xor
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r1, 16u); r5 = r5 ^ t_; } // 62 shfl
|
||||
r1 = r1 ^ ds[r6 & mask]; // 63 load
|
||||
}
|
||||
uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u);
|
||||
uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u);
|
||||
out[gid] = ((ulong)hi << 32) | (ulong)lo;
|
||||
}
|
||||
|
||||
#if IGNEUM_EXCHANGE != 0
|
||||
// Reports the sub-group size this device uses for a work-group of IGNEUM_GROUP items. host.c runs it only when the
|
||||
// per-kernel query (clGetKernelSubGroupInfoKHR on igneum_hash) is unavailable; that query is preferred because a
|
||||
// compiler may pick a different wave width per kernel (RDNA: wave32 or wave64). See WAVEFRONT.md.
|
||||
IGNEUM_KERNEL_HASH void igneum_probe_subgroup(__global uint* out) {
|
||||
if (get_local_id(0) == 0u) { out[0] = get_sub_group_size(); out[1] = get_num_sub_groups(); }
|
||||
}
|
||||
#endif
|
||||
|
||||
// Header-bound variant (bind.rs): the init words come from initw, not SEEDW. Same body as igneum_hash.
|
||||
IGNEUM_KERNEL_HASH void igneum_hash_bound(__global const uint* ds, __global ulong* out, uint baseNonce, uint mask, __global const uint* initw) {
|
||||
uint gid = (uint)get_global_id(0);
|
||||
uint lid = (uint)get_local_id(0);
|
||||
uint nonce = baseNonce + gid;
|
||||
uint r0, r1, r2, r3, r4, r5, r6, r7;
|
||||
uint iw0 = initw[0], iw1 = initw[1], iw2 = initw[2], iw3 = initw[3], iw4 = initw[4], iw5 = initw[5], iw6 = initw[6], iw7 = initw[7];
|
||||
#if IGNEUM_EXCHANGE == 0
|
||||
IGNEUM_LOCAL_WORDS(xch, 2 * IGNEUM_GROUP);
|
||||
uint xk = 0u;
|
||||
#else
|
||||
(void)lid;
|
||||
#endif
|
||||
{ uint x = nonce ^ iw0; x += 0x9e3779b9u * 1u; x = splitmix32(x); r0 = x ^ iw1; }
|
||||
{ uint x = nonce ^ iw1; x += 0x9e3779b9u * 2u; x = splitmix32(x); r1 = x ^ iw2; }
|
||||
{ uint x = nonce ^ iw2; x += 0x9e3779b9u * 3u; x = splitmix32(x); r2 = x ^ iw3; }
|
||||
{ uint x = nonce ^ iw3; x += 0x9e3779b9u * 4u; x = splitmix32(x); r3 = x ^ iw4; }
|
||||
{ uint x = nonce ^ iw4; x += 0x9e3779b9u * 5u; x = splitmix32(x); r4 = x ^ iw5; }
|
||||
{ uint x = nonce ^ iw5; x += 0x9e3779b9u * 6u; x = splitmix32(x); r5 = x ^ iw6; }
|
||||
{ uint x = nonce ^ iw6; x += 0x9e3779b9u * 7u; x = splitmix32(x); r6 = x ^ iw7; }
|
||||
{ uint x = nonce ^ iw7; x += 0x9e3779b9u * 8u; x = splitmix32(x); r7 = x ^ iw0; }
|
||||
|
||||
for (uint it = 0u; it < 8u; ++it) {
|
||||
uint sel = r0;
|
||||
r2 = r2 + r7 + ((((sel >> 30u) & 1u) != 0u) ? 0xb788d5f8u : 0x92d00116u); // 0 add
|
||||
r3 = mul_hi(r3, r2); // 1 mulhi
|
||||
r6 = r6 ^ ds[r3 & mask]; // 2 load
|
||||
r0 = r0 ^ ds[r6 & mask]; // 3 load
|
||||
r5 = r5 * r2; // 4 mul
|
||||
r7 = r7 + r2 + ((((sel >> 20u) & 1u) != 0u) ? 0x9a773a55u : 0xd5f6f389u); // 5 add
|
||||
{ uint b_ = (r5 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r6 = x_; } // 6 load
|
||||
r5 = r5 ^ ds[r6 & mask]; // 7 load
|
||||
{ uint b_ = (r2 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r1 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r1 = x_; } // 8 load
|
||||
r4 = r4 * r5; // 9 mul
|
||||
{ uint b_ = (r0 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r2 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r2 = x_; } // 10 load
|
||||
r3 = r3 ^ ds[r2 & mask]; // 11 load
|
||||
r4 = r4 ^ r0; // 12 xor
|
||||
r7 = r7 ^ ds[r3 & mask]; // 13 load
|
||||
r7 = r7 ^ r1; // 14 xor
|
||||
r4 = r1 * r4 + r4; // 15 mad
|
||||
r3 = r0 * r4 + r3; // 16 mad
|
||||
r4 = r6 * r2 + r4; // 17 mad
|
||||
r0 = rotr_var(r0, r2); // 18 rotr
|
||||
r5 = rotr_var(r5, r6); // 19 rotr
|
||||
r4 = r4 ^ ds[r1 & mask]; // 20 load
|
||||
r2 = r2 ^ ds[r4 & mask]; // 21 load
|
||||
r1 = rotl_imm(r1, 14u); // 22 rotl
|
||||
r7 = r7 - r1; // 23 sub
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r6, 2u); r2 = r2 ^ t_; } // 24 shfl
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r4, 16u); r1 = r1 ^ t_; } // 25 shfl
|
||||
r6 = r6 ^ ds[r0 & mask]; // 26 load
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r6, 1u); r0 = r0 ^ t_; } // 27 shfl
|
||||
r0 = r0 + r2 + ((((sel >> 25u) & 1u) != 0u) ? 0xc6311db1u : 0x1a3cecfbu); // 28 add
|
||||
r5 = mul_hi(r5, r7); // 29 mulhi
|
||||
r0 = r1 * r7 + r0; // 30 mad
|
||||
r5 = rotl_imm(r5, 23u); // 31 rotl
|
||||
r0 = r0 + r2 + ((((sel >> 28u) & 1u) != 0u) ? 0xf1282553u : 0x7aa05e39u); // 32 add
|
||||
r1 = r1 ^ r6; // 33 xor
|
||||
r0 = r0 - r1; // 34 sub
|
||||
r1 = r1 ^ ds[r6 & mask]; // 35 load
|
||||
r1 = rotl_imm(r1, 7u); // 36 rotl
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r4, 8u); r0 = r0 ^ t_; } // 37 shfl
|
||||
r3 = r3 + r5 + ((((sel >> 13u) & 1u) != 0u) ? 0x70173cfdu : 0x4a9bf1a8u); // 38 add
|
||||
r3 = mul_hi(r3, r4); // 39 mulhi
|
||||
r3 = r3 + r6 + ((((sel >> 8u) & 1u) != 0u) ? 0x2596fd35u : 0x26b3e1a7u); // 40 add
|
||||
r3 = r3 - r7; // 41 sub
|
||||
r0 = r0 - r4; // 42 sub
|
||||
r5 = rotr_var(r5, r7); // 43 rotr
|
||||
r3 = r4 * r1 + r3; // 44 mad
|
||||
r4 = r4 ^ ds[r2 & mask]; // 45 load
|
||||
r2 = mul_hi(r2, r5); // 46 mulhi
|
||||
r3 = r3 ^ ds[r5 & mask]; // 47 load
|
||||
r5 = mul_hi(r5, r6); // 48 mulhi
|
||||
r5 = r5 + r7 + ((((sel >> 22u) & 1u) != 0u) ? 0x724f77b9u : 0x9f31d23cu); // 49 add
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r7, 1u); r2 = r2 ^ t_; } // 50 shfl
|
||||
r1 = r1 * r5; // 51 mul
|
||||
r1 = r1 * r6; // 52 mul
|
||||
{ uint b_ = (r1 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r6 = x_; } // 53 load
|
||||
r7 = r7 ^ r2; // 54 xor
|
||||
r2 = r2 - r1; // 55 sub
|
||||
r7 = r7 ^ r3; // 56 xor
|
||||
r3 = rotl_imm(r3, 2u); // 57 rotl
|
||||
r6 = mul_hi(r6, r4); // 58 mulhi
|
||||
r4 = rotr_var(r4, r5); // 59 rotr
|
||||
r3 = mul_hi(r3, r1); // 60 mulhi
|
||||
r3 = r3 ^ r6; // 61 xor
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r1, 16u); r5 = r5 ^ t_; } // 62 shfl
|
||||
r1 = r1 ^ ds[r6 & mask]; // 63 load
|
||||
}
|
||||
uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u);
|
||||
uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u);
|
||||
out[gid] = ((ulong)hi << 32) | (ulong)lo;
|
||||
}
|
||||
123
proto-cuda/packs-readwidth/mixA-0/kernel_bound.cu
Normal file
123
proto-cuda/packs-readwidth/mixA-0/kernel_bound.cu
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
// Generated by igneum-pow export (generator v2) for seed "igneum-readwidth/A/0". Do not edit by hand.
|
||||
// Header-bound twin of igneum_hash in kernel.cu: the init words come from a kernel argument, not SEEDW.
|
||||
// Host declarations (also in program_bound.h if present):
|
||||
// struct IgneumInitWords { uint32_t w[8]; };
|
||||
// cudaError_t igneum_launch_hash_bound(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask,
|
||||
// IgneumInitWords iw, uint32_t nonces, uint32_t blockWarps);
|
||||
// cudaError_t igneum_hash_bound_info(int* numRegs, int* blocksPerSM, uint32_t blockWarps);
|
||||
#include <cuda_runtime.h>
|
||||
#include <cstdint>
|
||||
#include "program.h"
|
||||
|
||||
struct IgneumInitWords { uint32_t w[8]; };
|
||||
|
||||
__device__ __forceinline__ uint32_t splitmix32(uint32_t x) {
|
||||
x ^= x >> 16; x *= 0x7feb352du;
|
||||
x ^= x >> 15; x *= 0x846ca68bu;
|
||||
x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
__device__ __forceinline__ uint32_t rotl_imm(uint32_t x, uint32_t n) { return (x << n) | (x >> (32u - n)); }
|
||||
__device__ __forceinline__ uint32_t rotr_var(uint32_t x, uint32_t n) { n &= 31u; return (x >> n) | (x << ((32u - n) & 31u)); }
|
||||
|
||||
__global__ void igneum_hash_bound(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask, IgneumInitWords iw) {
|
||||
uint32_t gid = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
uint32_t nonce = baseNonce + gid;
|
||||
uint32_t r0, r1, r2, r3, r4, r5, r6, r7;
|
||||
{ uint32_t x = nonce ^ iw.w[0]; x += 0x9e3779b9u * 1u; x = splitmix32(x); r0 = x ^ iw.w[1]; }
|
||||
{ uint32_t x = nonce ^ iw.w[1]; x += 0x9e3779b9u * 2u; x = splitmix32(x); r1 = x ^ iw.w[2]; }
|
||||
{ uint32_t x = nonce ^ iw.w[2]; x += 0x9e3779b9u * 3u; x = splitmix32(x); r2 = x ^ iw.w[3]; }
|
||||
{ uint32_t x = nonce ^ iw.w[3]; x += 0x9e3779b9u * 4u; x = splitmix32(x); r3 = x ^ iw.w[4]; }
|
||||
{ uint32_t x = nonce ^ iw.w[4]; x += 0x9e3779b9u * 5u; x = splitmix32(x); r4 = x ^ iw.w[5]; }
|
||||
{ uint32_t x = nonce ^ iw.w[5]; x += 0x9e3779b9u * 6u; x = splitmix32(x); r5 = x ^ iw.w[6]; }
|
||||
{ uint32_t x = nonce ^ iw.w[6]; x += 0x9e3779b9u * 7u; x = splitmix32(x); r6 = x ^ iw.w[7]; }
|
||||
{ uint32_t x = nonce ^ iw.w[7]; x += 0x9e3779b9u * 8u; x = splitmix32(x); r7 = x ^ iw.w[0]; }
|
||||
|
||||
for (uint32_t it = 0u; it < 8u; ++it) {
|
||||
uint32_t sel = r0;
|
||||
r2 = r2 + r7 + ((((sel >> 30u) & 1u) != 0u) ? 0xb788d5f8u : 0x92d00116u); // 0 add
|
||||
r3 = __umulhi(r3, r2); // 1 mulhi
|
||||
r6 = r6 ^ ds[r3 & mask]; // 2 load
|
||||
r0 = r0 ^ ds[r6 & mask]; // 3 load
|
||||
r5 = r5 * r2; // 4 mul
|
||||
r7 = r7 + r2 + ((((sel >> 20u) & 1u) != 0u) ? 0x9a773a55u : 0xd5f6f389u); // 5 add
|
||||
{ uint32_t b_ = (r5 & mask) & ~15u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint32_t x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r6 = x_; } // 6 load
|
||||
r5 = r5 ^ ds[r6 & mask]; // 7 load
|
||||
{ uint32_t b_ = (r2 & mask) & ~3u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint32_t x_ = r1 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r1 = x_; } // 8 load
|
||||
r4 = r4 * r5; // 9 mul
|
||||
{ uint32_t b_ = (r0 & mask) & ~3u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint32_t x_ = r2 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r2 = x_; } // 10 load
|
||||
r3 = r3 ^ ds[r2 & mask]; // 11 load
|
||||
r4 = r4 ^ r0; // 12 xor
|
||||
r7 = r7 ^ ds[r3 & mask]; // 13 load
|
||||
r7 = r7 ^ r1; // 14 xor
|
||||
r4 = r1 * r4 + r4; // 15 mad
|
||||
r3 = r0 * r4 + r3; // 16 mad
|
||||
r4 = r6 * r2 + r4; // 17 mad
|
||||
r0 = rotr_var(r0, r2); // 18 rotr
|
||||
r5 = rotr_var(r5, r6); // 19 rotr
|
||||
r4 = r4 ^ ds[r1 & mask]; // 20 load
|
||||
r2 = r2 ^ ds[r4 & mask]; // 21 load
|
||||
r1 = rotl_imm(r1, 14u); // 22 rotl
|
||||
r7 = r7 - r1; // 23 sub
|
||||
r2 = r2 ^ __shfl_xor_sync(0xffffffffu, r6, 2); // 24 shfl
|
||||
r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r4, 16); // 25 shfl
|
||||
r6 = r6 ^ ds[r0 & mask]; // 26 load
|
||||
r0 = r0 ^ __shfl_xor_sync(0xffffffffu, r6, 1); // 27 shfl
|
||||
r0 = r0 + r2 + ((((sel >> 25u) & 1u) != 0u) ? 0xc6311db1u : 0x1a3cecfbu); // 28 add
|
||||
r5 = __umulhi(r5, r7); // 29 mulhi
|
||||
r0 = r1 * r7 + r0; // 30 mad
|
||||
r5 = rotl_imm(r5, 23u); // 31 rotl
|
||||
r0 = r0 + r2 + ((((sel >> 28u) & 1u) != 0u) ? 0xf1282553u : 0x7aa05e39u); // 32 add
|
||||
r1 = r1 ^ r6; // 33 xor
|
||||
r0 = r0 - r1; // 34 sub
|
||||
r1 = r1 ^ ds[r6 & mask]; // 35 load
|
||||
r1 = rotl_imm(r1, 7u); // 36 rotl
|
||||
r0 = r0 ^ __shfl_xor_sync(0xffffffffu, r4, 8); // 37 shfl
|
||||
r3 = r3 + r5 + ((((sel >> 13u) & 1u) != 0u) ? 0x70173cfdu : 0x4a9bf1a8u); // 38 add
|
||||
r3 = __umulhi(r3, r4); // 39 mulhi
|
||||
r3 = r3 + r6 + ((((sel >> 8u) & 1u) != 0u) ? 0x2596fd35u : 0x26b3e1a7u); // 40 add
|
||||
r3 = r3 - r7; // 41 sub
|
||||
r0 = r0 - r4; // 42 sub
|
||||
r5 = rotr_var(r5, r7); // 43 rotr
|
||||
r3 = r4 * r1 + r3; // 44 mad
|
||||
r4 = r4 ^ ds[r2 & mask]; // 45 load
|
||||
r2 = __umulhi(r2, r5); // 46 mulhi
|
||||
r3 = r3 ^ ds[r5 & mask]; // 47 load
|
||||
r5 = __umulhi(r5, r6); // 48 mulhi
|
||||
r5 = r5 + r7 + ((((sel >> 22u) & 1u) != 0u) ? 0x724f77b9u : 0x9f31d23cu); // 49 add
|
||||
r2 = r2 ^ __shfl_xor_sync(0xffffffffu, r7, 1); // 50 shfl
|
||||
r1 = r1 * r5; // 51 mul
|
||||
r1 = r1 * r6; // 52 mul
|
||||
{ uint32_t b_ = (r1 & mask) & ~15u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint32_t x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r6 = x_; } // 53 load
|
||||
r7 = r7 ^ r2; // 54 xor
|
||||
r2 = r2 - r1; // 55 sub
|
||||
r7 = r7 ^ r3; // 56 xor
|
||||
r3 = rotl_imm(r3, 2u); // 57 rotl
|
||||
r6 = __umulhi(r6, r4); // 58 mulhi
|
||||
r4 = rotr_var(r4, r5); // 59 rotr
|
||||
r3 = __umulhi(r3, r1); // 60 mulhi
|
||||
r3 = r3 ^ r6; // 61 xor
|
||||
r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r1, 16); // 62 shfl
|
||||
r1 = r1 ^ ds[r6 & mask]; // 63 load
|
||||
}
|
||||
uint32_t lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u);
|
||||
uint32_t hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u);
|
||||
out[gid] = ((uint64_t)hi << 32) | (uint64_t)lo;
|
||||
}
|
||||
|
||||
cudaError_t igneum_launch_hash_bound(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask,
|
||||
IgneumInitWords iw, uint32_t nonces, uint32_t blockWarps) {
|
||||
if (blockWarps == 0u || blockWarps > 32u) return cudaErrorInvalidValue;
|
||||
uint32_t block = 32u * blockWarps;
|
||||
if (nonces == 0u || (nonces % block) != 0u) return cudaErrorInvalidValue;
|
||||
igneum_hash_bound<<<nonces / block, block>>>(ds, out, baseNonce, mask, iw);
|
||||
return cudaGetLastError();
|
||||
}
|
||||
|
||||
cudaError_t igneum_hash_bound_info(int* numRegs, int* blocksPerSM, uint32_t blockWarps) {
|
||||
cudaFuncAttributes attr;
|
||||
cudaError_t e = cudaFuncGetAttributes(&attr, igneum_hash_bound);
|
||||
if (e != cudaSuccess) return e;
|
||||
*numRegs = attr.numRegs;
|
||||
return cudaOccupancyMaxActiveBlocksPerMultiprocessor(blocksPerSM, igneum_hash_bound, (int)(32u * blockWarps), 0);
|
||||
}
|
||||
108
proto-cuda/packs-readwidth/mixA-0/memhard.h
Normal file
108
proto-cuda/packs-readwidth/mixA-0/memhard.h
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
// Generated by igneum-pow export (generator v2) for seed "igneum-readwidth/A/0". Do not edit by hand.
|
||||
// Memory-hard dataset core, the same text that the Mac's Metal kernels and CPU verifier were checked against.
|
||||
// Included by kernel.cu (device), host.cu (host reference) and proto-opencl/host.c (C99 host reference).
|
||||
// See proto-metal/MEMHARD.md for the construction. kernel.cl carries the same text in OpenCL C.
|
||||
#pragma once
|
||||
#ifdef __cplusplus
|
||||
#include <cstdint>
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
#if defined(__CUDACC__)
|
||||
#define IGNEUM_HD __host__ __device__ __forceinline__
|
||||
#elif defined(_MSC_VER) && !defined(__cplusplus)
|
||||
#define IGNEUM_HD static __inline
|
||||
#else
|
||||
#define IGNEUM_HD static inline
|
||||
#endif
|
||||
// Memory-hard dataset core (MEMHARD.md). Cache: 2^26 words in 2^16 segments of 64 chained ChaCha12 lines.
|
||||
// Item: 8 rounds of seed-parameterised mixer + one 64-byte cache read, then a final mixer. All parameters are literals.
|
||||
#define MH_CACHE_LINE_MASK 0x003fffffu
|
||||
#define MH_SEGMENT_LINES 64u
|
||||
#define MH_QR(a, b, c, d, r1, r2, r3, r4) { a += b; d ^= a; d = mh_rotl(d, r1); c += d; b ^= c; b = mh_rotl(b, r2); a += b; d ^= a; d = mh_rotl(d, r3); c += d; b ^= c; b = mh_rotl(b, r4); }
|
||||
IGNEUM_HD uint32_t mh_rotl(uint32_t x, uint32_t n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 at every call site
|
||||
|
||||
// y = ChaCha12 core(x) + x
|
||||
IGNEUM_HD void mh_chacha_block(const uint32_t* x, uint32_t* y) {
|
||||
for (uint32_t i = 0u; i < 16u; ++i) y[i] = x[i];
|
||||
for (uint32_t r = 0u; r < 6u; ++r) {
|
||||
MH_QR(y[0], y[4], y[8], y[12], 16u, 12u, 8u, 7u) MH_QR(y[1], y[5], y[9], y[13], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[2], y[6], y[10], y[14], 16u, 12u, 8u, 7u) MH_QR(y[3], y[7], y[11], y[15], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[0], y[5], y[10], y[15], 16u, 12u, 8u, 7u) MH_QR(y[1], y[6], y[11], y[12], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[2], y[7], y[8], y[13], 16u, 12u, 8u, 7u) MH_QR(y[3], y[4], y[9], y[14], 16u, 12u, 8u, 7u)
|
||||
}
|
||||
for (uint32_t i = 0u; i < 16u; ++i) y[i] += x[i];
|
||||
}
|
||||
|
||||
// One cache segment: 64 chained lines written at cache[seg * 1024]. in_j = prev ^ (sigma || K || seg || j || tag), prev_0 = 0.
|
||||
IGNEUM_HD void mh_cache_segment(uint32_t* cache, uint32_t seg) {
|
||||
uint32_t prev[16]; uint32_t x[16]; uint32_t y[16];
|
||||
for (uint32_t i = 0u; i < 16u; ++i) prev[i] = 0u;
|
||||
for (uint32_t j = 0u; j < MH_SEGMENT_LINES; ++j) {
|
||||
x[0] = 0x61707865u ^ prev[0]; x[1] = 0x3320646eu ^ prev[1]; x[2] = 0x79622d32u ^ prev[2]; x[3] = 0x6b206574u ^ prev[3];
|
||||
x[4] = 0x3067619fu ^ prev[4];
|
||||
x[5] = 0x3c269176u ^ prev[5];
|
||||
x[6] = 0x84a03b03u ^ prev[6];
|
||||
x[7] = 0xf8c63294u ^ prev[7];
|
||||
x[8] = 0xff977c5bu ^ prev[8];
|
||||
x[9] = 0xe60def3eu ^ prev[9];
|
||||
x[10] = 0x63630141u ^ prev[10];
|
||||
x[11] = 0xb8fbcb58u ^ prev[11];
|
||||
x[12] = seg ^ prev[12]; x[13] = j ^ prev[13]; x[14] = 0x49676e65u ^ prev[14]; x[15] = 0x756d4d48u ^ prev[15];
|
||||
mh_chacha_block(x, y);
|
||||
uint32_t* line = cache + ((seg * MH_SEGMENT_LINES + j) * 16u);
|
||||
for (uint32_t i = 0u; i < 16u; ++i) { line[i] = y[i]; prev[i] = y[i]; }
|
||||
}
|
||||
}
|
||||
|
||||
// M_r: per word (s ^ (RC + rk)) * MUL, then a column round and a diagonal round with the seed-drawn rotations.
|
||||
IGNEUM_HD void mh_mixer(uint32_t* s, uint32_t rk) {
|
||||
s[0] = (s[0] ^ (0xbab68293u + rk)) * 0x42146205u;
|
||||
s[1] = (s[1] ^ (0xcc162340u + rk)) * 0x52cbe0fbu;
|
||||
s[2] = (s[2] ^ (0x6ce151ccu + rk)) * 0x7ecf4a03u;
|
||||
s[3] = (s[3] ^ (0xe62b8997u + rk)) * 0x6728907fu;
|
||||
s[4] = (s[4] ^ (0xc9c80297u + rk)) * 0xd81d9751u;
|
||||
s[5] = (s[5] ^ (0xf74a1654u + rk)) * 0x132952c3u;
|
||||
s[6] = (s[6] ^ (0x3d704af5u + rk)) * 0xf60de277u;
|
||||
s[7] = (s[7] ^ (0x3cf522b7u + rk)) * 0x05358035u;
|
||||
s[8] = (s[8] ^ (0x2b9cac04u + rk)) * 0xbaf6499du;
|
||||
s[9] = (s[9] ^ (0xa880ac10u + rk)) * 0xe4db9667u;
|
||||
s[10] = (s[10] ^ (0x13e5dd1du + rk)) * 0x3e98f45du;
|
||||
s[11] = (s[11] ^ (0x6fc3e233u + rk)) * 0xd0004eddu;
|
||||
s[12] = (s[12] ^ (0x2d83eeacu + rk)) * 0x2691630du;
|
||||
s[13] = (s[13] ^ (0x9006e8bfu + rk)) * 0x9beb3bcfu;
|
||||
s[14] = (s[14] ^ (0x2c4b5362u + rk)) * 0xab310379u;
|
||||
s[15] = (s[15] ^ (0x31b49ee2u + rk)) * 0x99cfb423u;
|
||||
MH_QR(s[0], s[4], s[8], s[12], 20u, 20u, 19u, 4u) MH_QR(s[1], s[5], s[9], s[13], 20u, 20u, 19u, 4u)
|
||||
MH_QR(s[2], s[6], s[10], s[14], 20u, 20u, 19u, 4u) MH_QR(s[3], s[7], s[11], s[15], 20u, 20u, 19u, 4u)
|
||||
MH_QR(s[0], s[5], s[10], s[15], 26u, 3u, 3u, 27u) MH_QR(s[1], s[6], s[11], s[12], 26u, 3u, 3u, 27u)
|
||||
MH_QR(s[2], s[7], s[8], s[13], 26u, 3u, 3u, 27u) MH_QR(s[3], s[4], s[9], s[14], 26u, 3u, 3u, 27u)
|
||||
}
|
||||
|
||||
// Item t: 16 words. s = (K, t * MUL[i] + RC[i]); 8 rounds of mixer + cache line s[0] & mask; final mixer.
|
||||
IGNEUM_HD void mh_item(const uint32_t* cache, uint32_t t, uint32_t* s) {
|
||||
s[0] = 0x3067619fu;
|
||||
s[1] = 0x3c269176u;
|
||||
s[2] = 0x84a03b03u;
|
||||
s[3] = 0xf8c63294u;
|
||||
s[4] = 0xff977c5bu;
|
||||
s[5] = 0xe60def3eu;
|
||||
s[6] = 0x63630141u;
|
||||
s[7] = 0xb8fbcb58u;
|
||||
s[8] = t * 0x42146205u + 0xbab68293u;
|
||||
s[9] = t * 0x52cbe0fbu + 0xcc162340u;
|
||||
s[10] = t * 0x7ecf4a03u + 0x6ce151ccu;
|
||||
s[11] = t * 0x6728907fu + 0xe62b8997u;
|
||||
s[12] = t * 0xd81d9751u + 0xc9c80297u;
|
||||
s[13] = t * 0x132952c3u + 0xf74a1654u;
|
||||
s[14] = t * 0xf60de277u + 0x3d704af5u;
|
||||
s[15] = t * 0x05358035u + 0x3cf522b7u;
|
||||
for (uint32_t r = 0u; r < 8u; ++r) {
|
||||
mh_mixer(s, 0x9E3779B9u * (r + 1u));
|
||||
const uint32_t* line = cache + ((s[0] & MH_CACHE_LINE_MASK) * 16u);
|
||||
for (uint32_t i = 0u; i < 16u; ++i) s[i] ^= line[i];
|
||||
}
|
||||
mh_mixer(s, 0x9E3779B9u * 9u);
|
||||
}
|
||||
// dataset[w] without the dataset: derive item w >> 4 and take word w & 15.
|
||||
IGNEUM_HD uint32_t mh_word(const uint32_t* cache, uint32_t w) { uint32_t s[16]; mh_item(cache, w >> 4u, s); return s[w & 15u]; }
|
||||
106
proto-cuda/packs-readwidth/mixA-0/memhard.metal
Normal file
106
proto-cuda/packs-readwidth/mixA-0/memhard.metal
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
#include <metal_stdlib>
|
||||
using namespace metal;
|
||||
// Memory-hard dataset core (MEMHARD.md). Cache: 2^26 words in 2^16 segments of 64 chained ChaCha12 lines.
|
||||
// Item: 8 rounds of seed-parameterised mixer + one 64-byte cache read, then a final mixer. All parameters are literals.
|
||||
#define MH_CACHE_LINE_MASK 0x003fffffu
|
||||
#define MH_SEGMENT_LINES 64u
|
||||
#define MH_QR(a, b, c, d, r1, r2, r3, r4) { a += b; d ^= a; d = mh_rotl(d, r1); c += d; b ^= c; b = mh_rotl(b, r2); a += b; d ^= a; d = mh_rotl(d, r3); c += d; b ^= c; b = mh_rotl(b, r4); }
|
||||
inline uint mh_rotl(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 at every call site
|
||||
|
||||
// y = ChaCha12 core(x) + x
|
||||
inline void mh_chacha_block(const thread uint* x, thread uint* y) {
|
||||
for (uint i = 0u; i < 16u; ++i) y[i] = x[i];
|
||||
for (uint r = 0u; r < 6u; ++r) {
|
||||
MH_QR(y[0], y[4], y[8], y[12], 16u, 12u, 8u, 7u) MH_QR(y[1], y[5], y[9], y[13], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[2], y[6], y[10], y[14], 16u, 12u, 8u, 7u) MH_QR(y[3], y[7], y[11], y[15], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[0], y[5], y[10], y[15], 16u, 12u, 8u, 7u) MH_QR(y[1], y[6], y[11], y[12], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[2], y[7], y[8], y[13], 16u, 12u, 8u, 7u) MH_QR(y[3], y[4], y[9], y[14], 16u, 12u, 8u, 7u)
|
||||
}
|
||||
for (uint i = 0u; i < 16u; ++i) y[i] += x[i];
|
||||
}
|
||||
|
||||
// One cache segment: 64 chained lines written at cache[seg * 1024]. in_j = prev ^ (sigma || K || seg || j || tag), prev_0 = 0.
|
||||
inline void mh_cache_segment(device uint* cache, uint seg) {
|
||||
uint prev[16]; uint x[16]; uint y[16];
|
||||
for (uint i = 0u; i < 16u; ++i) prev[i] = 0u;
|
||||
for (uint j = 0u; j < MH_SEGMENT_LINES; ++j) {
|
||||
x[0] = 0x61707865u ^ prev[0]; x[1] = 0x3320646eu ^ prev[1]; x[2] = 0x79622d32u ^ prev[2]; x[3] = 0x6b206574u ^ prev[3];
|
||||
x[4] = 0x3067619fu ^ prev[4];
|
||||
x[5] = 0x3c269176u ^ prev[5];
|
||||
x[6] = 0x84a03b03u ^ prev[6];
|
||||
x[7] = 0xf8c63294u ^ prev[7];
|
||||
x[8] = 0xff977c5bu ^ prev[8];
|
||||
x[9] = 0xe60def3eu ^ prev[9];
|
||||
x[10] = 0x63630141u ^ prev[10];
|
||||
x[11] = 0xb8fbcb58u ^ prev[11];
|
||||
x[12] = seg ^ prev[12]; x[13] = j ^ prev[13]; x[14] = 0x49676e65u ^ prev[14]; x[15] = 0x756d4d48u ^ prev[15];
|
||||
mh_chacha_block(x, y);
|
||||
device uint* line = cache + ((seg * MH_SEGMENT_LINES + j) * 16u);
|
||||
for (uint i = 0u; i < 16u; ++i) { line[i] = y[i]; prev[i] = y[i]; }
|
||||
}
|
||||
}
|
||||
|
||||
// M_r: per word (s ^ (RC + rk)) * MUL, then a column round and a diagonal round with the seed-drawn rotations.
|
||||
inline void mh_mixer(thread uint* s, uint rk) {
|
||||
s[0] = (s[0] ^ (0xbab68293u + rk)) * 0x42146205u;
|
||||
s[1] = (s[1] ^ (0xcc162340u + rk)) * 0x52cbe0fbu;
|
||||
s[2] = (s[2] ^ (0x6ce151ccu + rk)) * 0x7ecf4a03u;
|
||||
s[3] = (s[3] ^ (0xe62b8997u + rk)) * 0x6728907fu;
|
||||
s[4] = (s[4] ^ (0xc9c80297u + rk)) * 0xd81d9751u;
|
||||
s[5] = (s[5] ^ (0xf74a1654u + rk)) * 0x132952c3u;
|
||||
s[6] = (s[6] ^ (0x3d704af5u + rk)) * 0xf60de277u;
|
||||
s[7] = (s[7] ^ (0x3cf522b7u + rk)) * 0x05358035u;
|
||||
s[8] = (s[8] ^ (0x2b9cac04u + rk)) * 0xbaf6499du;
|
||||
s[9] = (s[9] ^ (0xa880ac10u + rk)) * 0xe4db9667u;
|
||||
s[10] = (s[10] ^ (0x13e5dd1du + rk)) * 0x3e98f45du;
|
||||
s[11] = (s[11] ^ (0x6fc3e233u + rk)) * 0xd0004eddu;
|
||||
s[12] = (s[12] ^ (0x2d83eeacu + rk)) * 0x2691630du;
|
||||
s[13] = (s[13] ^ (0x9006e8bfu + rk)) * 0x9beb3bcfu;
|
||||
s[14] = (s[14] ^ (0x2c4b5362u + rk)) * 0xab310379u;
|
||||
s[15] = (s[15] ^ (0x31b49ee2u + rk)) * 0x99cfb423u;
|
||||
MH_QR(s[0], s[4], s[8], s[12], 20u, 20u, 19u, 4u) MH_QR(s[1], s[5], s[9], s[13], 20u, 20u, 19u, 4u)
|
||||
MH_QR(s[2], s[6], s[10], s[14], 20u, 20u, 19u, 4u) MH_QR(s[3], s[7], s[11], s[15], 20u, 20u, 19u, 4u)
|
||||
MH_QR(s[0], s[5], s[10], s[15], 26u, 3u, 3u, 27u) MH_QR(s[1], s[6], s[11], s[12], 26u, 3u, 3u, 27u)
|
||||
MH_QR(s[2], s[7], s[8], s[13], 26u, 3u, 3u, 27u) MH_QR(s[3], s[4], s[9], s[14], 26u, 3u, 3u, 27u)
|
||||
}
|
||||
|
||||
// Item t: 16 words. s = (K, t * MUL[i] + RC[i]); 8 rounds of mixer + cache line s[0] & mask; final mixer.
|
||||
inline void mh_item(device const uint* cache, uint t, thread uint* s) {
|
||||
s[0] = 0x3067619fu;
|
||||
s[1] = 0x3c269176u;
|
||||
s[2] = 0x84a03b03u;
|
||||
s[3] = 0xf8c63294u;
|
||||
s[4] = 0xff977c5bu;
|
||||
s[5] = 0xe60def3eu;
|
||||
s[6] = 0x63630141u;
|
||||
s[7] = 0xb8fbcb58u;
|
||||
s[8] = t * 0x42146205u + 0xbab68293u;
|
||||
s[9] = t * 0x52cbe0fbu + 0xcc162340u;
|
||||
s[10] = t * 0x7ecf4a03u + 0x6ce151ccu;
|
||||
s[11] = t * 0x6728907fu + 0xe62b8997u;
|
||||
s[12] = t * 0xd81d9751u + 0xc9c80297u;
|
||||
s[13] = t * 0x132952c3u + 0xf74a1654u;
|
||||
s[14] = t * 0xf60de277u + 0x3d704af5u;
|
||||
s[15] = t * 0x05358035u + 0x3cf522b7u;
|
||||
for (uint r = 0u; r < 8u; ++r) {
|
||||
mh_mixer(s, 0x9E3779B9u * (r + 1u));
|
||||
device const uint* line = cache + ((s[0] & MH_CACHE_LINE_MASK) * 16u);
|
||||
for (uint i = 0u; i < 16u; ++i) s[i] ^= line[i];
|
||||
}
|
||||
mh_mixer(s, 0x9E3779B9u * 9u);
|
||||
}
|
||||
// dataset[w] without the dataset: derive item w >> 4 and take word w & 15.
|
||||
inline uint mh_word(device const uint* cache, uint w) { uint s[16]; mh_item(cache, w >> 4u, s); return s[w & 15u]; }
|
||||
|
||||
// One thread per segment (2^16 threads).
|
||||
kernel void igneum_cache_fill(device uint* cache [[buffer(0)]], uint gid [[thread_position_in_grid]]) {
|
||||
mh_cache_segment(cache, gid);
|
||||
}
|
||||
// One thread per 64-byte item (dataset words / 16 threads).
|
||||
kernel void igneum_build(device const uint* cache [[buffer(0)]], device uint* dataset [[buffer(1)]],
|
||||
uint gid [[thread_position_in_grid]]) {
|
||||
uint s[16];
|
||||
mh_item(cache, gid, s);
|
||||
device uint* d = dataset + gid * 16u;
|
||||
for (uint i = 0u; i < 16u; ++i) d[i] = s[i];
|
||||
}
|
||||
60
proto-cuda/packs-readwidth/mixA-0/program.h
Normal file
60
proto-cuda/packs-readwidth/mixA-0/program.h
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
// Generated by igneum-pow export (generator v2) for seed "igneum-readwidth/A/0". Do not edit by hand.
|
||||
// Program metadata for host.cu plus the launch wrappers defined in kernel.cu.
|
||||
// Also included by proto-opencl/host.c (C99), which defines IGNEUM_NO_CUDA first and reads only the macros.
|
||||
#pragma once
|
||||
#ifdef __cplusplus
|
||||
#include <cstdint>
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
#ifndef IGNEUM_NO_CUDA
|
||||
#include <cuda_runtime.h>
|
||||
#endif
|
||||
|
||||
#define IGNEUM_SEED_STRING "igneum-readwidth/A/0"
|
||||
#define IGNEUM_SEED_BYTES_HEX "69676e65756d2d7265616477696474682f412f30"
|
||||
#define IGNEUM_GENERATOR 2
|
||||
#define IGNEUM_PROGRAM_ATTEMPT 0
|
||||
#define IGNEUM_PROGRAM_ID 0xd30baa94fa82322eull
|
||||
#define IGNEUM_DAY_STRING "2026-10-03"
|
||||
#define IGNEUM_DAY_BYTES_HEX "6461792f323032362d31302d3033"
|
||||
#define IGNEUM_DAY0 0x3067619fu
|
||||
#define IGNEUM_DAY1 0x3c269176u
|
||||
#define IGNEUM_DATASET_LOG2 28
|
||||
#define IGNEUM_MASK 0x0fffffffu
|
||||
#define IGNEUM_LANES 32
|
||||
#define IGNEUM_ITERATIONS 8
|
||||
#define IGNEUM_INSTR_COUNT 64
|
||||
#define IGNEUM_LOADS_PER_HASH 128
|
||||
#define IGNEUM_WIDE_LOADS_PER_HASH 0
|
||||
#define IGNEUM_OP_MIX "load=16 add=7 mulhi=7 shfl=6 xor=6 mad=5 sub=5 mul=4 rotl=4 rotr=4"
|
||||
// Read-width experiment (5 October 2026, docs/plans/read-width.md): NOT the lottery hash. A load of W words reads
|
||||
// the W-word-aligned address and folds every word into dst: x = dst ^ w[0]; x = (rotl(x, 11) * 0x9e3779b1) ^ w[j]; dst = x.
|
||||
#define IGNEUM_LOAD_CLASS "mix50-35-15"
|
||||
#define IGNEUM_LOAD_SLOTS 16
|
||||
#define IGNEUM_LOAD_MIX { 50, 35, 15 }
|
||||
#define IGNEUM_LOAD_WIDTH_COUNTS { 12, 2, 2 } // loads of 4, 16, 64 bytes per program
|
||||
#define IGNEUM_BYTES_PER_HASH 1664
|
||||
#define IGNEUM_FOLD_ROT 11
|
||||
#define IGNEUM_FOLD_MUL 0x9e3779b1u
|
||||
// 0 = closed-form dataset (ds_elem), 1 = memory-hard cache construction (MEMHARD.md, memhard.h)
|
||||
#define IGNEUM_DATASET_MODE 1
|
||||
|
||||
#define IGNEUM_SEEDW_INIT { 0xaa5a3f6eu, 0x5c0410c3u, 0x9d994375u, 0xd8d53386u, 0x2c956ee2u, 0xe313c2f9u, 0x495ace1bu, 0x8238bb25u }
|
||||
#define IGNEUM_KEY_INIT { 0x3067619fu, 0x3c269176u, 0x84a03b03u, 0xf8c63294u, 0xff977c5bu, 0xe60def3eu, 0x63630141u, 0xb8fbcb58u }
|
||||
#define IGNEUM_CACHE_LOG2_WORDS 26
|
||||
#define IGNEUM_CACHE_SEGMENT_LOG2_LINES 6
|
||||
#define IGNEUM_CACHE_SEGMENTS 65536u
|
||||
#define IGNEUM_ITEM_ROUNDS 8
|
||||
#define IGNEUM_MIX_ROT_INIT { 20u, 20u, 19u, 4u, 26u, 3u, 3u, 27u }
|
||||
#define IGNEUM_MIX_MUL_INIT { 0x42146205u, 0x52cbe0fbu, 0x7ecf4a03u, 0x6728907fu, 0xd81d9751u, 0x132952c3u, 0xf60de277u, 0x05358035u, 0xbaf6499du, 0xe4db9667u, 0x3e98f45du, 0xd0004eddu, 0x2691630du, 0x9beb3bcfu, 0xab310379u, 0x99cfb423u }
|
||||
#define IGNEUM_MIX_RC_INIT { 0xbab68293u, 0xcc162340u, 0x6ce151ccu, 0xe62b8997u, 0xc9c80297u, 0xf74a1654u, 0x3d704af5u, 0x3cf522b7u, 0x2b9cac04u, 0xa880ac10u, 0x13e5dd1du, 0x6fc3e233u, 0x2d83eeacu, 0x9006e8bfu, 0x2c4b5362u, 0x31b49ee2u }
|
||||
|
||||
#ifndef IGNEUM_NO_CUDA
|
||||
// Defined in kernel.cu. All launch on the default stream and return cudaGetLastError().
|
||||
cudaError_t igneum_launch_cache_fill(uint32_t* cache, uint32_t nSegments);
|
||||
cudaError_t igneum_launch_build(uint32_t* ds, const uint32_t* cache, uint32_t nItems);
|
||||
cudaError_t igneum_launch_hash(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask,
|
||||
uint32_t nonces, uint32_t blockWarps);
|
||||
cudaError_t igneum_hash_info(int* numRegs, int* blocksPerSM, uint32_t blockWarps);
|
||||
#endif
|
||||
127
proto-cuda/packs-readwidth/mixA-0/program.json
Normal file
127
proto-cuda/packs-readwidth/mixA-0/program.json
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
{
|
||||
"format": "igneum-program-pack-3",
|
||||
"generator": 2,
|
||||
"attempt": 0,
|
||||
"program_id": "0xd30baa94fa82322e",
|
||||
"program_id_derivation": "FNV-1a 64 over 'igneum-program/' || generator_le32 || seed_words as little-endian bytes || attempt_le32",
|
||||
"dataset_mode": "memory-hard",
|
||||
"seed": "igneum-readwidth/A/0",
|
||||
"seed_bytes": "69676e65756d2d7265616477696474682f412f30",
|
||||
"seed_words": ["0xaa5a3f6e", "0x5c0410c3", "0x9d994375", "0xd8d53386", "0x2c956ee2", "0xe313c2f9", "0x495ace1b", "0x8238bb25"],
|
||||
"seed_derivation": "seed_words = FNV-1a 64 over seed_bytes (attempt 0) or seed_bytes || attempt_le32 (attempt k >= 1), basis ^ (salt * 0x9E3779B97F4A7C15) for salt 0..3, then h ^= h>>33; h *= 0xff51afd7ed558ccd; h ^= h>>33; words[2*salt] = low 32, words[2*salt+1] = high 32",
|
||||
"generator_rule": "version 2: exactly 16 load slots drawn first from instructions 1..63 (partial Fisher-Yates), the other 48 ops from the ten non-load weights (sum 75); a load's source is drawn from the registers other than dst written by an earlier instruction and not read by a load since; the candidate must pass the acceptance rule of spec 01 section 1.4.6 (static: no cyclically stale load source, every register has an injecting write; dynamic: 64 units on the seed-keyed closed-form dataset with no constant register bit, no lane-constant load site, under 164 saturated final values, every output bit within 136 of 1024, distinct addresses above 245760), else the next attempt of the seed is tried",
|
||||
"lanes": 32,
|
||||
"registers": 8,
|
||||
"iterations": 8,
|
||||
"instruction_count": 64,
|
||||
"loads_per_hash": 128,
|
||||
"load_class": "mix50-35-15",
|
||||
"load_slots": 16,
|
||||
"load_mix_percent_4_16_64": [50, 35, 15],
|
||||
"load_width_counts_4_16_64": [12, 2, 2],
|
||||
"bytes_per_hash": 1664,
|
||||
"wide_load": "read-width experiment (5 October 2026, docs/plans/read-width.md), NOT the lottery hash: a load of W words (width field, 4 or 16) reads dataset[b .. b + W) with b = (src & mask) & ~(W - 1) and folds every word into dst: x = dst ^ w[0]; for j in 1..W: x = (rotl(x, 11) * 0x9e3779b1) ^ w[j]; dst = x; width 1 is the plain load; the width is drawn per instruction from the class mix with one extra below(100) draw after the nine of version 2, and the program id is FNV-1a 64 over 'igneum-program-rw/' || generator_le32 || seed words || attempt_le32 || mix[3] || load_slots",
|
||||
"op_mix": {"load": 16, "add": 7, "mulhi": 7, "shfl": 6, "xor": 6, "mad": 5, "sub": 5, "mul": 4, "rotl": 4, "rotr": 4},
|
||||
"register_init": "for i in 0..7: x = nonce ^ seed_words[i]; x += 0x9e3779b9 * (i+1) (mod 2^32); x = splitmix32(x); r[i] = x ^ seed_words[(i+1) & 7]",
|
||||
"splitmix32": "x ^= x>>16; x *= 0x7feb352d; x ^= x>>15; x *= 0x846ca68b; x ^= x>>16",
|
||||
"iteration": "sel = r0 sampled once at the top of each iteration, then all instructions in order",
|
||||
"output": "lo = r0 ^ rotl(r1,7) ^ rotl(r2,14) ^ rotl(r3,21); hi = r4 ^ rotl(r5,9) ^ rotl(r6,18) ^ rotl(r7,27); out = (hi << 32) | lo",
|
||||
"op_semantics": {
|
||||
"add": "dst = dst + src + (bit `bit` of sel ? imm2 : imm)",
|
||||
"sub": "dst = dst - src",
|
||||
"mul": "dst = dst * src (low 32)",
|
||||
"mulhi": "dst = high 32 bits of dst * src",
|
||||
"xor": "dst = dst ^ src",
|
||||
"or": "dst = dst | src",
|
||||
"rotl": "dst = rotl(dst, rot), rot in 1..31",
|
||||
"rotr": "dst = rotr(dst, src & 31)",
|
||||
"mad": "dst = src * src2 + dst",
|
||||
"shfl": "dst = dst ^ (src of lane (lane ^ mask)), mask in {1,2,4,8,16}, within the 32-lane warp",
|
||||
"load": "dst = dst ^ dataset[src & dataset.mask]",
|
||||
"wload": "base = (src of lane 0 & dataset.mask) & ~31; dst = dst ^ dataset[base + lane] (warp-coalesced 128-byte load, lever b, only when --wide-frac > 0)"
|
||||
},
|
||||
"dataset": {
|
||||
"log2_words": 28,
|
||||
"bytes": 1073741824,
|
||||
"mask": "0x0fffffff",
|
||||
"day": "2026-10-03",
|
||||
"day_bytes": "6461792f323032362d31302d3033",
|
||||
"day_words_from": "seed_words_from_bytes(day_bytes)",
|
||||
"d0": "0x3067619f",
|
||||
"d1": "0x3c269176",
|
||||
"mode": "memory-hard",
|
||||
"spec": "proto-metal/MEMHARD.md",
|
||||
"key": ["0x3067619f", "0x3c269176", "0x84a03b03", "0xf8c63294", "0xff977c5b", "0xe60def3e", "0x63630141", "0xb8fbcb58"],
|
||||
"key_derivation": "the 8 words of seed_words_from_bytes(day_bytes); d0, d1 are key[0], key[1]",
|
||||
"cache": {"log2_words": 26, "bytes": 268435456, "line_words": 16, "segment_lines": 64, "segments": 65536, "block": "ChaCha12 core + feed-forward, rotations 16 12 8 7", "sigma": ["0x61707865", "0x3320646e", "0x79622d32", "0x6b206574"], "tag": ["0x49676e65", "0x756d4d48"], "chain": "in_j = prev_line ^ (sigma[0..3] || key[0..7] || seg || j || tag[0..1]); line_j = block(in_j); prev_0 = 0"},
|
||||
"mixer": {"draw": "SplitMix64 seeded with key[0] | key[1] << 32: rot[0..7] = 1 + next() % 31, mul[0..15] = low32(next()) | 1, rc[0..15] = low32(next())", "rot": [20, 20, 19, 4, 26, 3, 3, 27], "mul": ["0x42146205", "0x52cbe0fb", "0x7ecf4a03", "0x6728907f", "0xd81d9751", "0x132952c3", "0xf60de277", "0x05358035", "0xbaf6499d", "0xe4db9667", "0x3e98f45d", "0xd0004edd", "0x2691630d", "0x9beb3bcf", "0xab310379", "0x99cfb423"], "rc": ["0xbab68293", "0xcc162340", "0x6ce151cc", "0xe62b8997", "0xc9c80297", "0xf74a1654", "0x3d704af5", "0x3cf522b7", "0x2b9cac04", "0xa880ac10", "0x13e5dd1d", "0x6fc3e233", "0x2d83eeac", "0x9006e8bf", "0x2c4b5362", "0x31b49ee2"], "round": "for i in 0..15: s[i] = (s[i] ^ (rc[i] + (r+1) * 0x9E3779B9)) * mul[i]; then quarter rounds on columns (0,4,8,12) (1,5,9,13) (2,6,10,14) (3,7,11,15) with rot[0..3] and diagonals (0,5,10,15) (1,6,11,12) (2,7,8,13) (3,4,9,14) with rot[4..7]", "quarter_round": "a += b; d ^= a; d = rotl(d, r1); c += d; b ^= c; b = rotl(b, r2); a += b; d ^= a; d = rotl(d, r3); c += d; b ^= c; b = rotl(b, r4)"},
|
||||
"item": "s[0..7] = key; s[8+i] = t * mul[i] + rc[i] for i in 0..7; for r in 0..7: s = M_r(s); line = s[0] & 0x003fffff; s[i] ^= cache[line * 16 + i]; then s = M_8(s); item(t) = s",
|
||||
"word": "dataset[w] = item(w >> 4)[w & 15]"
|
||||
},
|
||||
"instructions": [
|
||||
{"i": 0, "op": "add", "dst": 2, "src": 7, "src2": 2, "imm": "0x92d00116", "imm2": "0xb788d5f8", "rot": 18, "bit": 30, "mask": 16, "width": 1},
|
||||
{"i": 1, "op": "mulhi", "dst": 3, "src": 2, "src2": 2, "imm": "0xda7cdbf6", "imm2": "0xb722360d", "rot": 28, "bit": 18, "mask": 2, "width": 1},
|
||||
{"i": 2, "op": "load", "dst": 6, "src": 3, "src2": 3, "imm": "0x4c76905d", "imm2": "0x8700b920", "rot": 20, "bit": 19, "mask": 16, "width": 1},
|
||||
{"i": 3, "op": "load", "dst": 0, "src": 6, "src2": 5, "imm": "0xc88bd196", "imm2": "0x0bec95ee", "rot": 27, "bit": 2, "mask": 1, "width": 1},
|
||||
{"i": 4, "op": "mul", "dst": 5, "src": 2, "src2": 0, "imm": "0x7ed20556", "imm2": "0x3cb2440a", "rot": 19, "bit": 8, "mask": 8, "width": 1},
|
||||
{"i": 5, "op": "add", "dst": 7, "src": 2, "src2": 5, "imm": "0xd5f6f389", "imm2": "0x9a773a55", "rot": 29, "bit": 20, "mask": 2, "width": 1},
|
||||
{"i": 6, "op": "load", "dst": 6, "src": 5, "src2": 7, "imm": "0xd9894991", "imm2": "0xf41ba497", "rot": 14, "bit": 9, "mask": 4, "width": 16},
|
||||
{"i": 7, "op": "load", "dst": 5, "src": 6, "src2": 0, "imm": "0xab148320", "imm2": "0x83097251", "rot": 31, "bit": 6, "mask": 16, "width": 1},
|
||||
{"i": 8, "op": "load", "dst": 1, "src": 2, "src2": 0, "imm": "0x9f83b9b8", "imm2": "0x5b9a1ccc", "rot": 17, "bit": 28, "mask": 1, "width": 4},
|
||||
{"i": 9, "op": "mul", "dst": 4, "src": 5, "src2": 1, "imm": "0x70d7287a", "imm2": "0x803900fa", "rot": 26, "bit": 24, "mask": 4, "width": 1},
|
||||
{"i": 10, "op": "load", "dst": 2, "src": 0, "src2": 1, "imm": "0xf15303dd", "imm2": "0x4725246d", "rot": 4, "bit": 10, "mask": 2, "width": 4},
|
||||
{"i": 11, "op": "load", "dst": 3, "src": 2, "src2": 6, "imm": "0xd6d526e4", "imm2": "0x0af56645", "rot": 19, "bit": 18, "mask": 4, "width": 1},
|
||||
{"i": 12, "op": "xor", "dst": 4, "src": 0, "src2": 5, "imm": "0xa08eca24", "imm2": "0x21fe64a3", "rot": 29, "bit": 29, "mask": 8, "width": 1},
|
||||
{"i": 13, "op": "load", "dst": 7, "src": 3, "src2": 2, "imm": "0x0f32a107", "imm2": "0x92e66063", "rot": 24, "bit": 22, "mask": 8, "width": 1},
|
||||
{"i": 14, "op": "xor", "dst": 7, "src": 1, "src2": 2, "imm": "0x9eec6af9", "imm2": "0x21dc3f6f", "rot": 28, "bit": 18, "mask": 4, "width": 1},
|
||||
{"i": 15, "op": "mad", "dst": 4, "src": 1, "src2": 4, "imm": "0xfa6381a2", "imm2": "0x2409fa4f", "rot": 18, "bit": 31, "mask": 4, "width": 1},
|
||||
{"i": 16, "op": "mad", "dst": 3, "src": 0, "src2": 4, "imm": "0x52a02e74", "imm2": "0xcdd43c2d", "rot": 9, "bit": 12, "mask": 2, "width": 1},
|
||||
{"i": 17, "op": "mad", "dst": 4, "src": 6, "src2": 2, "imm": "0x60e472f6", "imm2": "0xe8623e17", "rot": 5, "bit": 30, "mask": 4, "width": 1},
|
||||
{"i": 18, "op": "rotr", "dst": 0, "src": 2, "src2": 1, "imm": "0x08cbdd3e", "imm2": "0x3ab8f3a3", "rot": 27, "bit": 2, "mask": 8, "width": 1},
|
||||
{"i": 19, "op": "rotr", "dst": 5, "src": 6, "src2": 6, "imm": "0x09d41964", "imm2": "0x98709424", "rot": 28, "bit": 2, "mask": 2, "width": 1},
|
||||
{"i": 20, "op": "load", "dst": 4, "src": 1, "src2": 3, "imm": "0x3831d4c0", "imm2": "0xb095fd4b", "rot": 28, "bit": 18, "mask": 2, "width": 1},
|
||||
{"i": 21, "op": "load", "dst": 2, "src": 4, "src2": 0, "imm": "0x61f00f86", "imm2": "0x2bd27add", "rot": 1, "bit": 5, "mask": 2, "width": 1},
|
||||
{"i": 22, "op": "rotl", "dst": 1, "src": 5, "src2": 6, "imm": "0xe8785677", "imm2": "0xafeefe07", "rot": 14, "bit": 20, "mask": 2, "width": 1},
|
||||
{"i": 23, "op": "sub", "dst": 7, "src": 1, "src2": 3, "imm": "0x06c22ebe", "imm2": "0x486a522e", "rot": 19, "bit": 17, "mask": 2, "width": 1},
|
||||
{"i": 24, "op": "shfl", "dst": 2, "src": 6, "src2": 5, "imm": "0xf684e748", "imm2": "0xd67fa827", "rot": 31, "bit": 24, "mask": 2, "width": 1},
|
||||
{"i": 25, "op": "shfl", "dst": 1, "src": 4, "src2": 1, "imm": "0x712a551f", "imm2": "0xf6b8ff0b", "rot": 7, "bit": 7, "mask": 16, "width": 1},
|
||||
{"i": 26, "op": "load", "dst": 6, "src": 0, "src2": 6, "imm": "0xcc4fcce5", "imm2": "0xd121fe63", "rot": 31, "bit": 20, "mask": 1, "width": 1},
|
||||
{"i": 27, "op": "shfl", "dst": 0, "src": 6, "src2": 6, "imm": "0x1a31bcef", "imm2": "0x0152fc58", "rot": 19, "bit": 31, "mask": 1, "width": 1},
|
||||
{"i": 28, "op": "add", "dst": 0, "src": 2, "src2": 6, "imm": "0x1a3cecfb", "imm2": "0xc6311db1", "rot": 25, "bit": 25, "mask": 16, "width": 1},
|
||||
{"i": 29, "op": "mulhi", "dst": 5, "src": 7, "src2": 7, "imm": "0x7eda9d10", "imm2": "0x74eacbd7", "rot": 8, "bit": 20, "mask": 1, "width": 1},
|
||||
{"i": 30, "op": "mad", "dst": 0, "src": 1, "src2": 7, "imm": "0xf1992097", "imm2": "0xcc9bf87e", "rot": 14, "bit": 0, "mask": 16, "width": 1},
|
||||
{"i": 31, "op": "rotl", "dst": 5, "src": 1, "src2": 6, "imm": "0xf7adfcf5", "imm2": "0x16693ac6", "rot": 23, "bit": 10, "mask": 4, "width": 1},
|
||||
{"i": 32, "op": "add", "dst": 0, "src": 2, "src2": 7, "imm": "0x7aa05e39", "imm2": "0xf1282553", "rot": 21, "bit": 28, "mask": 4, "width": 1},
|
||||
{"i": 33, "op": "xor", "dst": 1, "src": 6, "src2": 4, "imm": "0xa773d935", "imm2": "0x38d34547", "rot": 8, "bit": 16, "mask": 8, "width": 1},
|
||||
{"i": 34, "op": "sub", "dst": 0, "src": 1, "src2": 4, "imm": "0x20af644a", "imm2": "0x28e75a4d", "rot": 7, "bit": 28, "mask": 8, "width": 1},
|
||||
{"i": 35, "op": "load", "dst": 1, "src": 6, "src2": 2, "imm": "0x6fb47122", "imm2": "0x562f2b23", "rot": 9, "bit": 23, "mask": 8, "width": 1},
|
||||
{"i": 36, "op": "rotl", "dst": 1, "src": 6, "src2": 3, "imm": "0xafd08d8b", "imm2": "0xa7f3e93d", "rot": 7, "bit": 30, "mask": 16, "width": 1},
|
||||
{"i": 37, "op": "shfl", "dst": 0, "src": 4, "src2": 0, "imm": "0x84fda071", "imm2": "0x3ec80cba", "rot": 25, "bit": 11, "mask": 8, "width": 1},
|
||||
{"i": 38, "op": "add", "dst": 3, "src": 5, "src2": 1, "imm": "0x4a9bf1a8", "imm2": "0x70173cfd", "rot": 15, "bit": 13, "mask": 2, "width": 1},
|
||||
{"i": 39, "op": "mulhi", "dst": 3, "src": 4, "src2": 3, "imm": "0x2ea4e0bd", "imm2": "0x1431b05f", "rot": 6, "bit": 22, "mask": 1, "width": 1},
|
||||
{"i": 40, "op": "add", "dst": 3, "src": 6, "src2": 3, "imm": "0x26b3e1a7", "imm2": "0x2596fd35", "rot": 4, "bit": 8, "mask": 1, "width": 1},
|
||||
{"i": 41, "op": "sub", "dst": 3, "src": 7, "src2": 5, "imm": "0x50df0069", "imm2": "0xba092804", "rot": 28, "bit": 31, "mask": 8, "width": 1},
|
||||
{"i": 42, "op": "sub", "dst": 0, "src": 4, "src2": 1, "imm": "0x22b4b65e", "imm2": "0x567989de", "rot": 3, "bit": 2, "mask": 16, "width": 1},
|
||||
{"i": 43, "op": "rotr", "dst": 5, "src": 7, "src2": 6, "imm": "0xeebb6e92", "imm2": "0xdb303272", "rot": 7, "bit": 26, "mask": 16, "width": 1},
|
||||
{"i": 44, "op": "mad", "dst": 3, "src": 4, "src2": 1, "imm": "0x17907041", "imm2": "0x2665fc2a", "rot": 24, "bit": 10, "mask": 8, "width": 1},
|
||||
{"i": 45, "op": "load", "dst": 4, "src": 2, "src2": 0, "imm": "0xf85e047a", "imm2": "0x514751b2", "rot": 21, "bit": 3, "mask": 16, "width": 1},
|
||||
{"i": 46, "op": "mulhi", "dst": 2, "src": 5, "src2": 6, "imm": "0x79ee74b0", "imm2": "0x71d32fd1", "rot": 26, "bit": 5, "mask": 2, "width": 1},
|
||||
{"i": 47, "op": "load", "dst": 3, "src": 5, "src2": 6, "imm": "0x73fa2964", "imm2": "0x25d08887", "rot": 22, "bit": 22, "mask": 4, "width": 1},
|
||||
{"i": 48, "op": "mulhi", "dst": 5, "src": 6, "src2": 3, "imm": "0xb686c1c8", "imm2": "0x31b980fa", "rot": 26, "bit": 20, "mask": 8, "width": 1},
|
||||
{"i": 49, "op": "add", "dst": 5, "src": 7, "src2": 0, "imm": "0x9f31d23c", "imm2": "0x724f77b9", "rot": 9, "bit": 22, "mask": 4, "width": 1},
|
||||
{"i": 50, "op": "shfl", "dst": 2, "src": 7, "src2": 6, "imm": "0x0793dd9f", "imm2": "0xbed3bbbb", "rot": 31, "bit": 23, "mask": 1, "width": 1},
|
||||
{"i": 51, "op": "mul", "dst": 1, "src": 5, "src2": 7, "imm": "0x713cb7a1", "imm2": "0x9e06cef8", "rot": 20, "bit": 2, "mask": 1, "width": 1},
|
||||
{"i": 52, "op": "mul", "dst": 1, "src": 6, "src2": 5, "imm": "0x57dcbb02", "imm2": "0xf262ce05", "rot": 11, "bit": 17, "mask": 4, "width": 1},
|
||||
{"i": 53, "op": "load", "dst": 6, "src": 1, "src2": 2, "imm": "0x6a4caa97", "imm2": "0x26d85624", "rot": 22, "bit": 28, "mask": 2, "width": 16},
|
||||
{"i": 54, "op": "xor", "dst": 7, "src": 2, "src2": 5, "imm": "0x2cb21c3f", "imm2": "0x53fa6b79", "rot": 2, "bit": 17, "mask": 4, "width": 1},
|
||||
{"i": 55, "op": "sub", "dst": 2, "src": 1, "src2": 5, "imm": "0x19c7d010", "imm2": "0xd7f64a4b", "rot": 28, "bit": 30, "mask": 4, "width": 1},
|
||||
{"i": 56, "op": "xor", "dst": 7, "src": 3, "src2": 2, "imm": "0xecabf384", "imm2": "0x0587918d", "rot": 25, "bit": 5, "mask": 8, "width": 1},
|
||||
{"i": 57, "op": "rotl", "dst": 3, "src": 6, "src2": 0, "imm": "0x5dba32f7", "imm2": "0x3228574b", "rot": 2, "bit": 20, "mask": 4, "width": 1},
|
||||
{"i": 58, "op": "mulhi", "dst": 6, "src": 4, "src2": 5, "imm": "0x558cb969", "imm2": "0xb0531a17", "rot": 2, "bit": 17, "mask": 2, "width": 1},
|
||||
{"i": 59, "op": "rotr", "dst": 4, "src": 5, "src2": 2, "imm": "0x8384814a", "imm2": "0xad7ee308", "rot": 7, "bit": 2, "mask": 16, "width": 1},
|
||||
{"i": 60, "op": "mulhi", "dst": 3, "src": 1, "src2": 7, "imm": "0x86193717", "imm2": "0x3daece51", "rot": 10, "bit": 12, "mask": 4, "width": 1},
|
||||
{"i": 61, "op": "xor", "dst": 3, "src": 6, "src2": 7, "imm": "0x83dada1b", "imm2": "0xc9f04198", "rot": 24, "bit": 22, "mask": 2, "width": 1},
|
||||
{"i": 62, "op": "shfl", "dst": 5, "src": 1, "src2": 0, "imm": "0x21dc46bb", "imm2": "0xe2eb5f1e", "rot": 19, "bit": 19, "mask": 16, "width": 1},
|
||||
{"i": 63, "op": "load", "dst": 1, "src": 6, "src2": 5, "imm": "0x5a37a588", "imm2": "0xcb1e1122", "rot": 13, "bit": 1, "mask": 1, "width": 1}
|
||||
]
|
||||
}
|
||||
109
proto-cuda/packs-readwidth/mixA-0/program.metal
Normal file
109
proto-cuda/packs-readwidth/mixA-0/program.metal
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
#include <metal_stdlib>
|
||||
using namespace metal;
|
||||
|
||||
#define MASK 0x0fffffffu
|
||||
constant uint SEEDW[8] = { 0xaa5a3f6eu, 0x5c0410c3u, 0x9d994375u, 0xd8d53386u, 0x2c956ee2u, 0xe313c2f9u, 0x495ace1bu, 0x8238bb25u };
|
||||
|
||||
inline uint splitmix32(uint x) {
|
||||
x ^= x >> 16; x *= 0x7feb352du;
|
||||
x ^= x >> 15; x *= 0x846ca68bu;
|
||||
x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
inline uint rotl_imm(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31
|
||||
inline uint rotr_var(uint x, uint n) { n &= 31u; return (x >> n) | (x << ((32u - n) & 31u)); }
|
||||
inline uint ds_elem(uint i, uint d0, uint d1) {
|
||||
uint x = i ^ d0;
|
||||
x *= 0x9E3779B1u; x ^= x >> 15;
|
||||
x += d1;
|
||||
x *= 0x85EBCA77u; x ^= x >> 13;
|
||||
x *= 0xC2B2AE3Du; x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
|
||||
kernel void igneum_hash(device const uint* dataset [[buffer(0)]],
|
||||
device ulong* out [[buffer(1)]],
|
||||
constant uint& baseNonce [[buffer(2)]],
|
||||
uint gid [[thread_position_in_grid]]) {
|
||||
uint nonce = baseNonce + gid;
|
||||
uint r0, r1, r2, r3, r4, r5, r6, r7;
|
||||
{ uint x = nonce ^ SEEDW[0]; x += 0x9e3779b9u * 1u; x = splitmix32(x); r0 = x ^ SEEDW[1]; }
|
||||
{ uint x = nonce ^ SEEDW[1]; x += 0x9e3779b9u * 2u; x = splitmix32(x); r1 = x ^ SEEDW[2]; }
|
||||
{ uint x = nonce ^ SEEDW[2]; x += 0x9e3779b9u * 3u; x = splitmix32(x); r2 = x ^ SEEDW[3]; }
|
||||
{ uint x = nonce ^ SEEDW[3]; x += 0x9e3779b9u * 4u; x = splitmix32(x); r3 = x ^ SEEDW[4]; }
|
||||
{ uint x = nonce ^ SEEDW[4]; x += 0x9e3779b9u * 5u; x = splitmix32(x); r4 = x ^ SEEDW[5]; }
|
||||
{ uint x = nonce ^ SEEDW[5]; x += 0x9e3779b9u * 6u; x = splitmix32(x); r5 = x ^ SEEDW[6]; }
|
||||
{ uint x = nonce ^ SEEDW[6]; x += 0x9e3779b9u * 7u; x = splitmix32(x); r6 = x ^ SEEDW[7]; }
|
||||
{ uint x = nonce ^ SEEDW[7]; x += 0x9e3779b9u * 8u; x = splitmix32(x); r7 = x ^ SEEDW[0]; }
|
||||
|
||||
for (uint it = 0u; it < 8u; ++it) {
|
||||
uint sel = r0;
|
||||
r2 = r2 + r7 + select(0x92d00116u, 0xb788d5f8u, ((sel >> 30u) & 1u) != 0u); // 0
|
||||
r3 = mulhi(r3, r2); // 1
|
||||
r6 = r6 ^ dataset[r3 & MASK]; // 2
|
||||
r0 = r0 ^ dataset[r6 & MASK]; // 3
|
||||
r5 = r5 * r2; // 4
|
||||
r7 = r7 + r2 + select(0xd5f6f389u, 0x9a773a55u, ((sel >> 20u) & 1u) != 0u); // 5
|
||||
{ uint b_ = (r5 & MASK) & ~15u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r6 = x_; } // 6
|
||||
r5 = r5 ^ dataset[r6 & MASK]; // 7
|
||||
{ uint b_ = (r2 & MASK) & ~3u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint x_ = r1 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r1 = x_; } // 8
|
||||
r4 = r4 * r5; // 9
|
||||
{ uint b_ = (r0 & MASK) & ~3u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint x_ = r2 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r2 = x_; } // 10
|
||||
r3 = r3 ^ dataset[r2 & MASK]; // 11
|
||||
r4 = r4 ^ r0; // 12
|
||||
r7 = r7 ^ dataset[r3 & MASK]; // 13
|
||||
r7 = r7 ^ r1; // 14
|
||||
r4 = r1 * r4 + r4; // 15
|
||||
r3 = r0 * r4 + r3; // 16
|
||||
r4 = r6 * r2 + r4; // 17
|
||||
r0 = rotr_var(r0, r2); // 18
|
||||
r5 = rotr_var(r5, r6); // 19
|
||||
r4 = r4 ^ dataset[r1 & MASK]; // 20
|
||||
r2 = r2 ^ dataset[r4 & MASK]; // 21
|
||||
r1 = rotl_imm(r1, 14u); // 22
|
||||
r7 = r7 - r1; // 23
|
||||
r2 = r2 ^ simd_shuffle_xor(r6, (ushort)2); // 24
|
||||
r1 = r1 ^ simd_shuffle_xor(r4, (ushort)16); // 25
|
||||
r6 = r6 ^ dataset[r0 & MASK]; // 26
|
||||
r0 = r0 ^ simd_shuffle_xor(r6, (ushort)1); // 27
|
||||
r0 = r0 + r2 + select(0x1a3cecfbu, 0xc6311db1u, ((sel >> 25u) & 1u) != 0u); // 28
|
||||
r5 = mulhi(r5, r7); // 29
|
||||
r0 = r1 * r7 + r0; // 30
|
||||
r5 = rotl_imm(r5, 23u); // 31
|
||||
r0 = r0 + r2 + select(0x7aa05e39u, 0xf1282553u, ((sel >> 28u) & 1u) != 0u); // 32
|
||||
r1 = r1 ^ r6; // 33
|
||||
r0 = r0 - r1; // 34
|
||||
r1 = r1 ^ dataset[r6 & MASK]; // 35
|
||||
r1 = rotl_imm(r1, 7u); // 36
|
||||
r0 = r0 ^ simd_shuffle_xor(r4, (ushort)8); // 37
|
||||
r3 = r3 + r5 + select(0x4a9bf1a8u, 0x70173cfdu, ((sel >> 13u) & 1u) != 0u); // 38
|
||||
r3 = mulhi(r3, r4); // 39
|
||||
r3 = r3 + r6 + select(0x26b3e1a7u, 0x2596fd35u, ((sel >> 8u) & 1u) != 0u); // 40
|
||||
r3 = r3 - r7; // 41
|
||||
r0 = r0 - r4; // 42
|
||||
r5 = rotr_var(r5, r7); // 43
|
||||
r3 = r4 * r1 + r3; // 44
|
||||
r4 = r4 ^ dataset[r2 & MASK]; // 45
|
||||
r2 = mulhi(r2, r5); // 46
|
||||
r3 = r3 ^ dataset[r5 & MASK]; // 47
|
||||
r5 = mulhi(r5, r6); // 48
|
||||
r5 = r5 + r7 + select(0x9f31d23cu, 0x724f77b9u, ((sel >> 22u) & 1u) != 0u); // 49
|
||||
r2 = r2 ^ simd_shuffle_xor(r7, (ushort)1); // 50
|
||||
r1 = r1 * r5; // 51
|
||||
r1 = r1 * r6; // 52
|
||||
{ uint b_ = (r1 & MASK) & ~15u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r6 = x_; } // 53
|
||||
r7 = r7 ^ r2; // 54
|
||||
r2 = r2 - r1; // 55
|
||||
r7 = r7 ^ r3; // 56
|
||||
r3 = rotl_imm(r3, 2u); // 57
|
||||
r6 = mulhi(r6, r4); // 58
|
||||
r4 = rotr_var(r4, r5); // 59
|
||||
r3 = mulhi(r3, r1); // 60
|
||||
r3 = r3 ^ r6; // 61
|
||||
r5 = r5 ^ simd_shuffle_xor(r1, (ushort)16); // 62
|
||||
r1 = r1 ^ dataset[r6 & MASK]; // 63
|
||||
}
|
||||
uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u);
|
||||
uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u);
|
||||
out[gid] = ((ulong)hi << 32) | (ulong)lo;
|
||||
}
|
||||
111
proto-cuda/packs-readwidth/mixA-0/program_bound.metal
Normal file
111
proto-cuda/packs-readwidth/mixA-0/program_bound.metal
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
#include <metal_stdlib>
|
||||
using namespace metal;
|
||||
|
||||
#define MASK 0x0fffffffu
|
||||
constant uint SEEDW[8] = { 0xaa5a3f6eu, 0x5c0410c3u, 0x9d994375u, 0xd8d53386u, 0x2c956ee2u, 0xe313c2f9u, 0x495ace1bu, 0x8238bb25u };
|
||||
|
||||
inline uint splitmix32(uint x) {
|
||||
x ^= x >> 16; x *= 0x7feb352du;
|
||||
x ^= x >> 15; x *= 0x846ca68bu;
|
||||
x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
inline uint rotl_imm(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31
|
||||
inline uint rotr_var(uint x, uint n) { n &= 31u; return (x >> n) | (x << ((32u - n) & 31u)); }
|
||||
inline uint ds_elem(uint i, uint d0, uint d1) {
|
||||
uint x = i ^ d0;
|
||||
x *= 0x9E3779B1u; x ^= x >> 15;
|
||||
x += d1;
|
||||
x *= 0x85EBCA77u; x ^= x >> 13;
|
||||
x *= 0xC2B2AE3Du; x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
|
||||
// Header-bound variant: the init words come from buffer 3 (bind.rs), not from SEEDW.
|
||||
kernel void igneum_hash_bound(device const uint* dataset [[buffer(0)]],
|
||||
device ulong* out [[buffer(1)]],
|
||||
constant uint& baseNonce [[buffer(2)]],
|
||||
constant uint* initw [[buffer(3)]],
|
||||
uint gid [[thread_position_in_grid]]) {
|
||||
uint nonce = baseNonce + gid;
|
||||
uint r0, r1, r2, r3, r4, r5, r6, r7;
|
||||
{ uint x = nonce ^ initw[0]; x += 0x9e3779b9u * 1u; x = splitmix32(x); r0 = x ^ initw[1]; }
|
||||
{ uint x = nonce ^ initw[1]; x += 0x9e3779b9u * 2u; x = splitmix32(x); r1 = x ^ initw[2]; }
|
||||
{ uint x = nonce ^ initw[2]; x += 0x9e3779b9u * 3u; x = splitmix32(x); r2 = x ^ initw[3]; }
|
||||
{ uint x = nonce ^ initw[3]; x += 0x9e3779b9u * 4u; x = splitmix32(x); r3 = x ^ initw[4]; }
|
||||
{ uint x = nonce ^ initw[4]; x += 0x9e3779b9u * 5u; x = splitmix32(x); r4 = x ^ initw[5]; }
|
||||
{ uint x = nonce ^ initw[5]; x += 0x9e3779b9u * 6u; x = splitmix32(x); r5 = x ^ initw[6]; }
|
||||
{ uint x = nonce ^ initw[6]; x += 0x9e3779b9u * 7u; x = splitmix32(x); r6 = x ^ initw[7]; }
|
||||
{ uint x = nonce ^ initw[7]; x += 0x9e3779b9u * 8u; x = splitmix32(x); r7 = x ^ initw[0]; }
|
||||
|
||||
for (uint it = 0u; it < 8u; ++it) {
|
||||
uint sel = r0;
|
||||
r2 = r2 + r7 + select(0x92d00116u, 0xb788d5f8u, ((sel >> 30u) & 1u) != 0u); // 0
|
||||
r3 = mulhi(r3, r2); // 1
|
||||
r6 = r6 ^ dataset[r3 & MASK]; // 2
|
||||
r0 = r0 ^ dataset[r6 & MASK]; // 3
|
||||
r5 = r5 * r2; // 4
|
||||
r7 = r7 + r2 + select(0xd5f6f389u, 0x9a773a55u, ((sel >> 20u) & 1u) != 0u); // 5
|
||||
{ uint b_ = (r5 & MASK) & ~15u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r6 = x_; } // 6
|
||||
r5 = r5 ^ dataset[r6 & MASK]; // 7
|
||||
{ uint b_ = (r2 & MASK) & ~3u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint x_ = r1 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r1 = x_; } // 8
|
||||
r4 = r4 * r5; // 9
|
||||
{ uint b_ = (r0 & MASK) & ~3u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint x_ = r2 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r2 = x_; } // 10
|
||||
r3 = r3 ^ dataset[r2 & MASK]; // 11
|
||||
r4 = r4 ^ r0; // 12
|
||||
r7 = r7 ^ dataset[r3 & MASK]; // 13
|
||||
r7 = r7 ^ r1; // 14
|
||||
r4 = r1 * r4 + r4; // 15
|
||||
r3 = r0 * r4 + r3; // 16
|
||||
r4 = r6 * r2 + r4; // 17
|
||||
r0 = rotr_var(r0, r2); // 18
|
||||
r5 = rotr_var(r5, r6); // 19
|
||||
r4 = r4 ^ dataset[r1 & MASK]; // 20
|
||||
r2 = r2 ^ dataset[r4 & MASK]; // 21
|
||||
r1 = rotl_imm(r1, 14u); // 22
|
||||
r7 = r7 - r1; // 23
|
||||
r2 = r2 ^ simd_shuffle_xor(r6, (ushort)2); // 24
|
||||
r1 = r1 ^ simd_shuffle_xor(r4, (ushort)16); // 25
|
||||
r6 = r6 ^ dataset[r0 & MASK]; // 26
|
||||
r0 = r0 ^ simd_shuffle_xor(r6, (ushort)1); // 27
|
||||
r0 = r0 + r2 + select(0x1a3cecfbu, 0xc6311db1u, ((sel >> 25u) & 1u) != 0u); // 28
|
||||
r5 = mulhi(r5, r7); // 29
|
||||
r0 = r1 * r7 + r0; // 30
|
||||
r5 = rotl_imm(r5, 23u); // 31
|
||||
r0 = r0 + r2 + select(0x7aa05e39u, 0xf1282553u, ((sel >> 28u) & 1u) != 0u); // 32
|
||||
r1 = r1 ^ r6; // 33
|
||||
r0 = r0 - r1; // 34
|
||||
r1 = r1 ^ dataset[r6 & MASK]; // 35
|
||||
r1 = rotl_imm(r1, 7u); // 36
|
||||
r0 = r0 ^ simd_shuffle_xor(r4, (ushort)8); // 37
|
||||
r3 = r3 + r5 + select(0x4a9bf1a8u, 0x70173cfdu, ((sel >> 13u) & 1u) != 0u); // 38
|
||||
r3 = mulhi(r3, r4); // 39
|
||||
r3 = r3 + r6 + select(0x26b3e1a7u, 0x2596fd35u, ((sel >> 8u) & 1u) != 0u); // 40
|
||||
r3 = r3 - r7; // 41
|
||||
r0 = r0 - r4; // 42
|
||||
r5 = rotr_var(r5, r7); // 43
|
||||
r3 = r4 * r1 + r3; // 44
|
||||
r4 = r4 ^ dataset[r2 & MASK]; // 45
|
||||
r2 = mulhi(r2, r5); // 46
|
||||
r3 = r3 ^ dataset[r5 & MASK]; // 47
|
||||
r5 = mulhi(r5, r6); // 48
|
||||
r5 = r5 + r7 + select(0x9f31d23cu, 0x724f77b9u, ((sel >> 22u) & 1u) != 0u); // 49
|
||||
r2 = r2 ^ simd_shuffle_xor(r7, (ushort)1); // 50
|
||||
r1 = r1 * r5; // 51
|
||||
r1 = r1 * r6; // 52
|
||||
{ uint b_ = (r1 & MASK) & ~15u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r6 = x_; } // 53
|
||||
r7 = r7 ^ r2; // 54
|
||||
r2 = r2 - r1; // 55
|
||||
r7 = r7 ^ r3; // 56
|
||||
r3 = rotl_imm(r3, 2u); // 57
|
||||
r6 = mulhi(r6, r4); // 58
|
||||
r4 = rotr_var(r4, r5); // 59
|
||||
r3 = mulhi(r3, r1); // 60
|
||||
r3 = r3 ^ r6; // 61
|
||||
r5 = r5 ^ simd_shuffle_xor(r1, (ushort)16); // 62
|
||||
r1 = r1 ^ dataset[r6 & MASK]; // 63
|
||||
}
|
||||
uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u);
|
||||
uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u);
|
||||
out[gid] = ((ulong)hi << 32) | (ulong)lo;
|
||||
}
|
||||
57
proto-cuda/packs-readwidth/mixA-0/vectors.h
Normal file
57
proto-cuda/packs-readwidth/mixA-0/vectors.h
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
// Generated by igneum-pow export (generator v2) for seed "igneum-readwidth/A/0". Do not edit by hand.
|
||||
// Expected outputs: igneum-pow (Rust) CPU interpreter, generator v2, memory-hard dataset
|
||||
#pragma once
|
||||
#ifdef __cplusplus
|
||||
#include <cstdint>
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
#define IGNEUM_VEC_WARPS 3
|
||||
static const uint32_t IGNEUM_VEC_BASE[IGNEUM_VEC_WARPS] = { 0u, 4096u, 1000000u };
|
||||
static const uint64_t IGNEUM_VEC_OUT[IGNEUM_VEC_WARPS][32] = {
|
||||
{ // base nonce 0
|
||||
0xc02af7d21c32b6e2ull, 0xf9676c7b81e42590ull, 0x3b5b2f433e291756ull, 0x2307064009985ab7ull, 0xf1f2d84aa86f1f5aull, 0xa7ed219296c204beull, 0xf8105c9692ac08e7ull, 0x04377ca8373b8e1full,
|
||||
0x2f76672aa0a6104dull, 0xac85110c18a8edc8ull, 0x3b4c20d7d3c22e52ull, 0x365c221488fa37e4ull, 0x989dab8f749cd976ull, 0x37f6690cc11dd5a7ull, 0x6159da4241e04ae2ull, 0x3c19bfdcd7821055ull,
|
||||
0x5b48a58c99800f4full, 0x991018ff7b067a45ull, 0xf281167cb9c28ef2ull, 0xe9497f5c0207892dull, 0xac1ccf9060f7c78bull, 0xf6f4282e68ceff58ull, 0xfa2694f87cf04ef6ull, 0x62d01632e98c6a11ull,
|
||||
0x63a875eb903ee9afull, 0x680ad026ac9e5e1full, 0x63d80718c2e2912bull, 0x377a3c901dadb9f5ull, 0xb2c39a01420d0806ull, 0x5ce44109e5c38357ull, 0x8532912b848b1f5bull, 0x76141c17aa59c5f6ull
|
||||
},
|
||||
{ // base nonce 4096
|
||||
0x30301278872d1766ull, 0xfd009372bb888e00ull, 0xb93e45944b9cb923ull, 0xe74cb4f099ac3ea9ull, 0x3cd9b2381d1cde3cull, 0xb69bddb5df734350ull, 0xbccc2d57615b8465ull, 0xa30bbff25bf3d723ull,
|
||||
0x66ca1a4c82d500d0ull, 0xbb60ed823f1bee84ull, 0x6312dd68c839352full, 0xf15a1a4e9b902225ull, 0xcf315f5496b73b41ull, 0x5e6aa39724dbe6caull, 0x3a4be831dca92fd7ull, 0xbd5f1ae9b2892322ull,
|
||||
0x69582160f1bdf99cull, 0xcc41242a8f4776a2ull, 0x377a337ca9a5f44aull, 0x12e453c8c831a462ull, 0xfe278d9da6dcaf29ull, 0xfddd6db8998a7f00ull, 0x6f9d4db889ef7e98ull, 0x278294842317978dull,
|
||||
0xe4bab477a44177b0ull, 0x52c1ea0d495c960dull, 0xf1504ce7e9c0d818ull, 0x15673b7d791269d7ull, 0x18828b1a6fd35583ull, 0xa6d769abd44e3827ull, 0x82b838f1172afc66ull, 0x5b18a4842a119defull
|
||||
},
|
||||
{ // base nonce 1000000
|
||||
0xfd55a3c4be548e4eull, 0x00f110e15155ab33ull, 0x374d6799a6b45a35ull, 0x27f9962d27ae0515ull, 0xd0ffb5d4c0f1dd83ull, 0x718d962e2ec9d7e7ull, 0xe07c572ca8705952ull, 0x99db60352bae63b7ull,
|
||||
0x065808eaebc7f7c8ull, 0x0072533c9ddc9f30ull, 0x7b11d0becd7297edull, 0xcf4b94c52549288aull, 0x0e8d98977c965c26ull, 0x890c6664b01fb638ull, 0x4d0a4b30a326dca6ull, 0x948a02536dca9925ull,
|
||||
0x1d9b3442fd4c3e0aull, 0x8b555804a68adabbull, 0x4942826f941b2089ull, 0x967b94a90c51196eull, 0xea8cf4b416d1878cull, 0xbefa6e39bfc1860aull, 0x53cbf72fe366ef94ull, 0xbfe204292b3f8b03ull,
|
||||
0xe269bfe9953bcf03ull, 0x24a758d6174e0da3ull, 0x25f57ab508d87895ull, 0xe45ec6208eb56f7dull, 0x47c891dda3f102c6ull, 0x088698d191e8dc33ull, 0xc1c4cd437ae11388ull, 0xa17c529d1a26c64dull
|
||||
}
|
||||
};
|
||||
|
||||
// Dataset self-test: dataset[0..15] and dataset[IGNEUM_MASK] (268435455).
|
||||
static const uint32_t IGNEUM_DS_HEAD[16] = {
|
||||
0xffc3cd94u, 0x5920ccd8u, 0x392f44bbu, 0x5e57f67au, 0x2f2bc2a9u, 0x620b0e36u, 0xbdc09014u, 0x436654bfu,
|
||||
0x311e0b48u, 0x1abd93adu, 0x59cc7ce8u, 0xee5247b2u, 0x86171fe8u, 0x6d874751u, 0xc9f7728fu, 0x7c2a435du
|
||||
};
|
||||
static const uint32_t IGNEUM_DS_LAST_INDEX = 268435455u;
|
||||
static const uint32_t IGNEUM_DS_LAST = 0xa33ada72u;
|
||||
// 64 sampled dataset words (index, value) computed on the Mac.
|
||||
#define IGNEUM_DS_SAMPLES 64
|
||||
static const uint32_t IGNEUM_DS_SAMPLE_INDEX[IGNEUM_DS_SAMPLES] = {
|
||||
59471966u, 217795994u, 208353206u, 42483309u, 172547758u, 148076330u, 183853158u, 214389424u, 267488061u, 169781097u, 184093494u, 153880993u, 84977930u, 46426879u, 3093825u, 225364072u, 44593546u, 260713159u, 168250303u, 52384140u, 223401610u, 45554030u, 95410555u, 175039924u, 79171087u, 267580473u, 24168642u, 37981670u, 171551130u, 195559979u, 204611762u, 140997658u, 138925853u, 86637313u, 20736778u, 219665210u, 160430336u, 264654675u, 8013395u, 228945585u, 213884386u, 104419827u, 44185464u, 142737231u, 99284897u, 132475900u, 61861762u, 132056166u, 262388043u, 91878046u, 117353561u, 124768597u, 71352993u, 190698941u, 46055428u, 55281366u, 165145231u, 106810753u, 171985651u, 232085256u, 159510492u, 40072060u, 209107596u, 39023794u
|
||||
};
|
||||
static const uint32_t IGNEUM_DS_SAMPLE_VALUE[IGNEUM_DS_SAMPLES] = {
|
||||
0xe8b73d94u, 0x337028b5u, 0xafe148c9u, 0xab99f7aeu, 0x434ea619u, 0xd85cb880u, 0x54764c7fu, 0x82c7e420u, 0xedf4cb9eu, 0x9884c959u, 0x223ee793u, 0x3a9ccf69u, 0x81da4fd2u, 0xd6ce8cb9u, 0xe3922dcau, 0x3e7e6bdeu, 0x382a3acau, 0x567e7f7fu, 0x25a0f084u, 0xbfeef128u, 0xe338abfbu, 0x7c3b5280u, 0x909bc5f1u, 0xd8b74b9cu, 0x8e31a22eu, 0x26b5f1d8u, 0x79122c00u, 0xcafc3340u, 0xd5e02ea3u, 0x1aee1afdu, 0xdb090d9au, 0xb049f435u, 0x4954d8bau, 0x03797ba0u, 0x196eefbdu, 0xd153412au, 0xbe5d2c4bu, 0xdaa14f0eu, 0x8e61ed07u, 0x9e9a64c6u, 0x2e29ff36u, 0x392a8589u, 0xb56a5912u, 0xfa6e8b57u, 0xd1a737cbu, 0xb0fa841au, 0xbe1c341fu, 0xe25be0f1u, 0xe937f543u, 0xebab2248u, 0x8e1b607au, 0x202a2fedu, 0x95e2819cu, 0x9c9652d4u, 0x32fedef0u, 0xdecfff82u, 0xcb5d43e5u, 0xb735806au, 0x8905939cu, 0xfbf8472du, 0xada74e5du, 0x7ebdeeeau, 0x0119f2b3u, 0xa9a376b8u
|
||||
};
|
||||
// Cache self-test (memory-hard mode): cache[0..15], the last 16 words, and FNV-1a 64 over all 2^26 words.
|
||||
static const uint32_t IGNEUM_CACHE_HEAD[16] = {
|
||||
0x355a86d2u, 0x7957db1cu, 0xd21772afu, 0x6fc1e09bu, 0xd55ce61du, 0x6e6a278bu, 0xd3f543ceu, 0x223d8e82u,
|
||||
0x143ab337u, 0x2e9f05bdu, 0x2eb389bfu, 0x0c6e449eu, 0x5cfa4222u, 0xba6560feu, 0x8e3e1aa4u, 0xdbcc1d53u
|
||||
};
|
||||
static const uint32_t IGNEUM_CACHE_LAST[16] = {
|
||||
0x41190d91u, 0xbd277957u, 0x22ddbb49u, 0x6986f207u, 0xdf69a4d6u, 0x26401a3au, 0x818230fbu, 0xc417122du,
|
||||
0x3597b211u, 0xb553ce55u, 0xcf39cc0du, 0x3b7fc43au, 0x3fd43b00u, 0x67e1c80eu, 0xffa7ea7du, 0xca2960abu
|
||||
};
|
||||
static const uint64_t IGNEUM_CACHE_FNV64 = 0x48c4f5bf24166b2eull;
|
||||
36
proto-cuda/packs-readwidth/mixA-0/vectors.json
Normal file
36
proto-cuda/packs-readwidth/mixA-0/vectors.json
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
{
|
||||
"seed": "igneum-readwidth/A/0",
|
||||
"day": "2026-10-03",
|
||||
"dataset_mode": "memory-hard",
|
||||
"dataset_log2_words": 28,
|
||||
"mask": "0x0fffffff",
|
||||
"lanes": 32,
|
||||
"source": "igneum-pow (Rust) CPU interpreter, generator v2, memory-hard dataset",
|
||||
"warps": [
|
||||
{"base_nonce": 0, "expected": [
|
||||
"0xc02af7d21c32b6e2", "0xf9676c7b81e42590", "0x3b5b2f433e291756", "0x2307064009985ab7", "0xf1f2d84aa86f1f5a", "0xa7ed219296c204be", "0xf8105c9692ac08e7", "0x04377ca8373b8e1f",
|
||||
"0x2f76672aa0a6104d", "0xac85110c18a8edc8", "0x3b4c20d7d3c22e52", "0x365c221488fa37e4", "0x989dab8f749cd976", "0x37f6690cc11dd5a7", "0x6159da4241e04ae2", "0x3c19bfdcd7821055",
|
||||
"0x5b48a58c99800f4f", "0x991018ff7b067a45", "0xf281167cb9c28ef2", "0xe9497f5c0207892d", "0xac1ccf9060f7c78b", "0xf6f4282e68ceff58", "0xfa2694f87cf04ef6", "0x62d01632e98c6a11",
|
||||
"0x63a875eb903ee9af", "0x680ad026ac9e5e1f", "0x63d80718c2e2912b", "0x377a3c901dadb9f5", "0xb2c39a01420d0806", "0x5ce44109e5c38357", "0x8532912b848b1f5b", "0x76141c17aa59c5f6"
|
||||
]},
|
||||
{"base_nonce": 4096, "expected": [
|
||||
"0x30301278872d1766", "0xfd009372bb888e00", "0xb93e45944b9cb923", "0xe74cb4f099ac3ea9", "0x3cd9b2381d1cde3c", "0xb69bddb5df734350", "0xbccc2d57615b8465", "0xa30bbff25bf3d723",
|
||||
"0x66ca1a4c82d500d0", "0xbb60ed823f1bee84", "0x6312dd68c839352f", "0xf15a1a4e9b902225", "0xcf315f5496b73b41", "0x5e6aa39724dbe6ca", "0x3a4be831dca92fd7", "0xbd5f1ae9b2892322",
|
||||
"0x69582160f1bdf99c", "0xcc41242a8f4776a2", "0x377a337ca9a5f44a", "0x12e453c8c831a462", "0xfe278d9da6dcaf29", "0xfddd6db8998a7f00", "0x6f9d4db889ef7e98", "0x278294842317978d",
|
||||
"0xe4bab477a44177b0", "0x52c1ea0d495c960d", "0xf1504ce7e9c0d818", "0x15673b7d791269d7", "0x18828b1a6fd35583", "0xa6d769abd44e3827", "0x82b838f1172afc66", "0x5b18a4842a119def"
|
||||
]},
|
||||
{"base_nonce": 1000000, "expected": [
|
||||
"0xfd55a3c4be548e4e", "0x00f110e15155ab33", "0x374d6799a6b45a35", "0x27f9962d27ae0515", "0xd0ffb5d4c0f1dd83", "0x718d962e2ec9d7e7", "0xe07c572ca8705952", "0x99db60352bae63b7",
|
||||
"0x065808eaebc7f7c8", "0x0072533c9ddc9f30", "0x7b11d0becd7297ed", "0xcf4b94c52549288a", "0x0e8d98977c965c26", "0x890c6664b01fb638", "0x4d0a4b30a326dca6", "0x948a02536dca9925",
|
||||
"0x1d9b3442fd4c3e0a", "0x8b555804a68adabb", "0x4942826f941b2089", "0x967b94a90c51196e", "0xea8cf4b416d1878c", "0xbefa6e39bfc1860a", "0x53cbf72fe366ef94", "0xbfe204292b3f8b03",
|
||||
"0xe269bfe9953bcf03", "0x24a758d6174e0da3", "0x25f57ab508d87895", "0xe45ec6208eb56f7d", "0x47c891dda3f102c6", "0x088698d191e8dc33", "0xc1c4cd437ae11388", "0xa17c529d1a26c64d"
|
||||
]}
|
||||
],
|
||||
"dataset_head": ["0xffc3cd94", "0x5920ccd8", "0x392f44bb", "0x5e57f67a", "0x2f2bc2a9", "0x620b0e36", "0xbdc09014", "0x436654bf", "0x311e0b48", "0x1abd93ad", "0x59cc7ce8", "0xee5247b2", "0x86171fe8", "0x6d874751", "0xc9f7728f", "0x7c2a435d"],
|
||||
"dataset_last_index": 268435455,
|
||||
"dataset_last": "0xa33ada72",
|
||||
"dataset_samples": [{"index": 59471966, "value": "0xe8b73d94"}, {"index": 217795994, "value": "0x337028b5"}, {"index": 208353206, "value": "0xafe148c9"}, {"index": 42483309, "value": "0xab99f7ae"}, {"index": 172547758, "value": "0x434ea619"}, {"index": 148076330, "value": "0xd85cb880"}, {"index": 183853158, "value": "0x54764c7f"}, {"index": 214389424, "value": "0x82c7e420"}, {"index": 267488061, "value": "0xedf4cb9e"}, {"index": 169781097, "value": "0x9884c959"}, {"index": 184093494, "value": "0x223ee793"}, {"index": 153880993, "value": "0x3a9ccf69"}, {"index": 84977930, "value": "0x81da4fd2"}, {"index": 46426879, "value": "0xd6ce8cb9"}, {"index": 3093825, "value": "0xe3922dca"}, {"index": 225364072, "value": "0x3e7e6bde"}, {"index": 44593546, "value": "0x382a3aca"}, {"index": 260713159, "value": "0x567e7f7f"}, {"index": 168250303, "value": "0x25a0f084"}, {"index": 52384140, "value": "0xbfeef128"}, {"index": 223401610, "value": "0xe338abfb"}, {"index": 45554030, "value": "0x7c3b5280"}, {"index": 95410555, "value": "0x909bc5f1"}, {"index": 175039924, "value": "0xd8b74b9c"}, {"index": 79171087, "value": "0x8e31a22e"}, {"index": 267580473, "value": "0x26b5f1d8"}, {"index": 24168642, "value": "0x79122c00"}, {"index": 37981670, "value": "0xcafc3340"}, {"index": 171551130, "value": "0xd5e02ea3"}, {"index": 195559979, "value": "0x1aee1afd"}, {"index": 204611762, "value": "0xdb090d9a"}, {"index": 140997658, "value": "0xb049f435"}, {"index": 138925853, "value": "0x4954d8ba"}, {"index": 86637313, "value": "0x03797ba0"}, {"index": 20736778, "value": "0x196eefbd"}, {"index": 219665210, "value": "0xd153412a"}, {"index": 160430336, "value": "0xbe5d2c4b"}, {"index": 264654675, "value": "0xdaa14f0e"}, {"index": 8013395, "value": "0x8e61ed07"}, {"index": 228945585, "value": "0x9e9a64c6"}, {"index": 213884386, "value": "0x2e29ff36"}, {"index": 104419827, "value": "0x392a8589"}, {"index": 44185464, "value": "0xb56a5912"}, {"index": 142737231, "value": "0xfa6e8b57"}, {"index": 99284897, "value": "0xd1a737cb"}, {"index": 132475900, "value": "0xb0fa841a"}, {"index": 61861762, "value": "0xbe1c341f"}, {"index": 132056166, "value": "0xe25be0f1"}, {"index": 262388043, "value": "0xe937f543"}, {"index": 91878046, "value": "0xebab2248"}, {"index": 117353561, "value": "0x8e1b607a"}, {"index": 124768597, "value": "0x202a2fed"}, {"index": 71352993, "value": "0x95e2819c"}, {"index": 190698941, "value": "0x9c9652d4"}, {"index": 46055428, "value": "0x32fedef0"}, {"index": 55281366, "value": "0xdecfff82"}, {"index": 165145231, "value": "0xcb5d43e5"}, {"index": 106810753, "value": "0xb735806a"}, {"index": 171985651, "value": "0x8905939c"}, {"index": 232085256, "value": "0xfbf8472d"}, {"index": 159510492, "value": "0xada74e5d"}, {"index": 40072060, "value": "0x7ebdeeea"}, {"index": 209107596, "value": "0x0119f2b3"}, {"index": 39023794, "value": "0xa9a376b8"}],
|
||||
"cache_head": ["0x355a86d2", "0x7957db1c", "0xd21772af", "0x6fc1e09b", "0xd55ce61d", "0x6e6a278b", "0xd3f543ce", "0x223d8e82", "0x143ab337", "0x2e9f05bd", "0x2eb389bf", "0x0c6e449e", "0x5cfa4222", "0xba6560fe", "0x8e3e1aa4", "0xdbcc1d53"],
|
||||
"cache_last_line": ["0x41190d91", "0xbd277957", "0x22ddbb49", "0x6986f207", "0xdf69a4d6", "0x26401a3a", "0x818230fb", "0xc417122d", "0x3597b211", "0xb553ce55", "0xcf39cc0d", "0x3b7fc43a", "0x3fd43b00", "0x67e1c80e", "0xffa7ea7d", "0xca2960ab"],
|
||||
"cache_fnv1a64": "0x48c4f5bf24166b2e"
|
||||
}
|
||||
278
proto-cuda/packs-readwidth/mixA-1/kernel.cl
Normal file
278
proto-cuda/packs-readwidth/mixA-1/kernel.cl
Normal file
|
|
@ -0,0 +1,278 @@
|
|||
// Generated by igneum-pow export (generator v2) for seed "igneum-readwidth/A/1". Do not edit by hand.
|
||||
// OpenCL C twin of the Metal kernel for the same seed (see proto-opencl/README.md, WAVEFRONT.md and program.metal).
|
||||
// Built from source at runtime by proto-opencl/host.c, which passes these defines:
|
||||
// IGNEUM_GROUP work-group size of igneum_hash, a multiple of 32 (default 32: one work-group = one 32-lane unit)
|
||||
// IGNEUM_EXCHANGE 0 = local-memory exchange with a barrier (any device, any wave width; the default)
|
||||
// 1 = sub_group_shuffle_xor (cl_khr_subgroup_shuffle), only with IGNEUM_GROUP 32 and a sub-group size of exactly 32
|
||||
// 2 = intel_sub_group_shuffle_xor (cl_intel_subgroups), same condition
|
||||
// The verification unit is always 32 lanes. A 64-wide hardware wave (AMD GCN/CDNA, RDNA in wave64) runs two units;
|
||||
// the exchange masks are 1, 2, 4, 8, 16, so every partner lane lies inside the lane's own aligned run of 32.
|
||||
#ifndef IGNEUM_GROUP
|
||||
#define IGNEUM_GROUP 32
|
||||
#endif
|
||||
#ifndef IGNEUM_EXCHANGE
|
||||
#define IGNEUM_EXCHANGE 0
|
||||
#endif
|
||||
#ifdef __OPENCL_VERSION__
|
||||
#define IGNEUM_KERNEL_HASH __kernel __attribute__((reqd_work_group_size(IGNEUM_GROUP, 1, 1)))
|
||||
#define IGNEUM_LOCAL_WORDS(name, n) __local uint name[n]
|
||||
#if IGNEUM_EXCHANGE == 1
|
||||
#ifdef cl_khr_subgroups
|
||||
#pragma OPENCL EXTENSION cl_khr_subgroups : enable
|
||||
#endif
|
||||
#ifdef cl_khr_subgroup_shuffle
|
||||
#pragma OPENCL EXTENSION cl_khr_subgroup_shuffle : enable
|
||||
#endif
|
||||
#elif IGNEUM_EXCHANGE == 2
|
||||
#pragma OPENCL EXTENSION cl_intel_subgroups : enable
|
||||
#endif
|
||||
#else
|
||||
// Not an OpenCL compiler: proto-opencl/emu compiles this file as C++ and supplies the built-ins and these two macros.
|
||||
#include "emu_opencl.h"
|
||||
#endif
|
||||
|
||||
#if IGNEUM_EXCHANGE == 1
|
||||
#define IGNEUM_SHFL_XOR(dst, a, m) dst = sub_group_shuffle_xor((a), (uint)(m))
|
||||
#define IGNEUM_BCAST0(dst, a) dst = sub_group_broadcast((a), 0u)
|
||||
#elif IGNEUM_EXCHANGE == 2
|
||||
#define IGNEUM_SHFL_XOR(dst, a, m) dst = intel_sub_group_shuffle_xor((a), (uint)(m))
|
||||
#define IGNEUM_BCAST0(dst, a) dst = sub_group_broadcast((a), 0u)
|
||||
#else
|
||||
// Local-memory exchange. Two buffers of IGNEUM_GROUP words alternate (xk counts exchanges), so one barrier per
|
||||
// exchange is enough: a lane can only overwrite buffer b at exchange k+2 after passing barrier k+1, and every lane
|
||||
// reaches barrier k+1 only after its read of buffer b at exchange k. The partner lid ^ m stays inside the lane's
|
||||
// aligned run of 32 because m < 32. Control flow is uniform, so every work-item reaches every barrier.
|
||||
#define IGNEUM_SHFL_XOR(dst, a, m) { xch[(xk & 1u) * IGNEUM_GROUP + lid] = (a); barrier(CLK_LOCAL_MEM_FENCE); dst = xch[(xk & 1u) * IGNEUM_GROUP + (lid ^ (uint)(m))]; xk += 1u; }
|
||||
#define IGNEUM_BCAST0(dst, a) { xch[(xk & 1u) * IGNEUM_GROUP + lid] = (a); barrier(CLK_LOCAL_MEM_FENCE); dst = xch[(xk & 1u) * IGNEUM_GROUP + (lid & ~31u)]; xk += 1u; }
|
||||
#endif
|
||||
|
||||
static inline uint splitmix32(uint x) {
|
||||
x ^= x >> 16; x *= 0x7feb352du;
|
||||
x ^= x >> 15; x *= 0x846ca68bu;
|
||||
x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
// n is a literal in 1..31 at every call site. OpenCL rotate() rotates left by n modulo 32.
|
||||
static inline uint rotl_imm(uint x, uint n) { return rotate(x, n); }
|
||||
// Right rotation by n modulo 32 as a left rotation by (32 - n) modulo 32; n == 0 gives x.
|
||||
static inline uint rotr_var(uint x, uint n) { return rotate(x, (0u - n) & 31u); }
|
||||
static inline uint ds_elem(uint i, uint d0, uint d1) {
|
||||
uint x = i ^ d0;
|
||||
x *= 0x9E3779B1u; x ^= x >> 15;
|
||||
x += d1;
|
||||
x *= 0x85EBCA77u; x ^= x >> 13;
|
||||
x *= 0xC2B2AE3Du; x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
|
||||
// Memory-hard dataset core (MEMHARD.md). Cache: 2^26 words in 2^16 segments of 64 chained ChaCha12 lines.
|
||||
// Item: 8 rounds of seed-parameterised mixer + one 64-byte cache read, then a final mixer. All parameters are literals.
|
||||
#define MH_CACHE_LINE_MASK 0x003fffffu
|
||||
#define MH_SEGMENT_LINES 64u
|
||||
#define MH_QR(a, b, c, d, r1, r2, r3, r4) { a += b; d ^= a; d = mh_rotl(d, r1); c += d; b ^= c; b = mh_rotl(b, r2); a += b; d ^= a; d = mh_rotl(d, r3); c += d; b ^= c; b = mh_rotl(b, r4); }
|
||||
static inline uint mh_rotl(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 at every call site
|
||||
|
||||
// y = ChaCha12 core(x) + x
|
||||
static inline void mh_chacha_block(const uint* x, uint* y) {
|
||||
for (uint i = 0u; i < 16u; ++i) y[i] = x[i];
|
||||
for (uint r = 0u; r < 6u; ++r) {
|
||||
MH_QR(y[0], y[4], y[8], y[12], 16u, 12u, 8u, 7u) MH_QR(y[1], y[5], y[9], y[13], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[2], y[6], y[10], y[14], 16u, 12u, 8u, 7u) MH_QR(y[3], y[7], y[11], y[15], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[0], y[5], y[10], y[15], 16u, 12u, 8u, 7u) MH_QR(y[1], y[6], y[11], y[12], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[2], y[7], y[8], y[13], 16u, 12u, 8u, 7u) MH_QR(y[3], y[4], y[9], y[14], 16u, 12u, 8u, 7u)
|
||||
}
|
||||
for (uint i = 0u; i < 16u; ++i) y[i] += x[i];
|
||||
}
|
||||
|
||||
// One cache segment: 64 chained lines written at cache[seg * 1024]. in_j = prev ^ (sigma || K || seg || j || tag), prev_0 = 0.
|
||||
static inline void mh_cache_segment(__global uint* cache, uint seg) {
|
||||
uint prev[16]; uint x[16]; uint y[16];
|
||||
for (uint i = 0u; i < 16u; ++i) prev[i] = 0u;
|
||||
for (uint j = 0u; j < MH_SEGMENT_LINES; ++j) {
|
||||
x[0] = 0x61707865u ^ prev[0]; x[1] = 0x3320646eu ^ prev[1]; x[2] = 0x79622d32u ^ prev[2]; x[3] = 0x6b206574u ^ prev[3];
|
||||
x[4] = 0x3067619fu ^ prev[4];
|
||||
x[5] = 0x3c269176u ^ prev[5];
|
||||
x[6] = 0x84a03b03u ^ prev[6];
|
||||
x[7] = 0xf8c63294u ^ prev[7];
|
||||
x[8] = 0xff977c5bu ^ prev[8];
|
||||
x[9] = 0xe60def3eu ^ prev[9];
|
||||
x[10] = 0x63630141u ^ prev[10];
|
||||
x[11] = 0xb8fbcb58u ^ prev[11];
|
||||
x[12] = seg ^ prev[12]; x[13] = j ^ prev[13]; x[14] = 0x49676e65u ^ prev[14]; x[15] = 0x756d4d48u ^ prev[15];
|
||||
mh_chacha_block(x, y);
|
||||
__global uint* line = cache + ((seg * MH_SEGMENT_LINES + j) * 16u);
|
||||
for (uint i = 0u; i < 16u; ++i) { line[i] = y[i]; prev[i] = y[i]; }
|
||||
}
|
||||
}
|
||||
|
||||
// M_r: per word (s ^ (RC + rk)) * MUL, then a column round and a diagonal round with the seed-drawn rotations.
|
||||
static inline void mh_mixer(uint* s, uint rk) {
|
||||
s[0] = (s[0] ^ (0xbab68293u + rk)) * 0x42146205u;
|
||||
s[1] = (s[1] ^ (0xcc162340u + rk)) * 0x52cbe0fbu;
|
||||
s[2] = (s[2] ^ (0x6ce151ccu + rk)) * 0x7ecf4a03u;
|
||||
s[3] = (s[3] ^ (0xe62b8997u + rk)) * 0x6728907fu;
|
||||
s[4] = (s[4] ^ (0xc9c80297u + rk)) * 0xd81d9751u;
|
||||
s[5] = (s[5] ^ (0xf74a1654u + rk)) * 0x132952c3u;
|
||||
s[6] = (s[6] ^ (0x3d704af5u + rk)) * 0xf60de277u;
|
||||
s[7] = (s[7] ^ (0x3cf522b7u + rk)) * 0x05358035u;
|
||||
s[8] = (s[8] ^ (0x2b9cac04u + rk)) * 0xbaf6499du;
|
||||
s[9] = (s[9] ^ (0xa880ac10u + rk)) * 0xe4db9667u;
|
||||
s[10] = (s[10] ^ (0x13e5dd1du + rk)) * 0x3e98f45du;
|
||||
s[11] = (s[11] ^ (0x6fc3e233u + rk)) * 0xd0004eddu;
|
||||
s[12] = (s[12] ^ (0x2d83eeacu + rk)) * 0x2691630du;
|
||||
s[13] = (s[13] ^ (0x9006e8bfu + rk)) * 0x9beb3bcfu;
|
||||
s[14] = (s[14] ^ (0x2c4b5362u + rk)) * 0xab310379u;
|
||||
s[15] = (s[15] ^ (0x31b49ee2u + rk)) * 0x99cfb423u;
|
||||
MH_QR(s[0], s[4], s[8], s[12], 20u, 20u, 19u, 4u) MH_QR(s[1], s[5], s[9], s[13], 20u, 20u, 19u, 4u)
|
||||
MH_QR(s[2], s[6], s[10], s[14], 20u, 20u, 19u, 4u) MH_QR(s[3], s[7], s[11], s[15], 20u, 20u, 19u, 4u)
|
||||
MH_QR(s[0], s[5], s[10], s[15], 26u, 3u, 3u, 27u) MH_QR(s[1], s[6], s[11], s[12], 26u, 3u, 3u, 27u)
|
||||
MH_QR(s[2], s[7], s[8], s[13], 26u, 3u, 3u, 27u) MH_QR(s[3], s[4], s[9], s[14], 26u, 3u, 3u, 27u)
|
||||
}
|
||||
|
||||
// Item t: 16 words. s = (K, t * MUL[i] + RC[i]); 8 rounds of mixer + cache line s[0] & mask; final mixer.
|
||||
static inline void mh_item(__global const uint* cache, uint t, uint* s) {
|
||||
s[0] = 0x3067619fu;
|
||||
s[1] = 0x3c269176u;
|
||||
s[2] = 0x84a03b03u;
|
||||
s[3] = 0xf8c63294u;
|
||||
s[4] = 0xff977c5bu;
|
||||
s[5] = 0xe60def3eu;
|
||||
s[6] = 0x63630141u;
|
||||
s[7] = 0xb8fbcb58u;
|
||||
s[8] = t * 0x42146205u + 0xbab68293u;
|
||||
s[9] = t * 0x52cbe0fbu + 0xcc162340u;
|
||||
s[10] = t * 0x7ecf4a03u + 0x6ce151ccu;
|
||||
s[11] = t * 0x6728907fu + 0xe62b8997u;
|
||||
s[12] = t * 0xd81d9751u + 0xc9c80297u;
|
||||
s[13] = t * 0x132952c3u + 0xf74a1654u;
|
||||
s[14] = t * 0xf60de277u + 0x3d704af5u;
|
||||
s[15] = t * 0x05358035u + 0x3cf522b7u;
|
||||
for (uint r = 0u; r < 8u; ++r) {
|
||||
mh_mixer(s, 0x9E3779B9u * (r + 1u));
|
||||
__global const uint* line = cache + ((s[0] & MH_CACHE_LINE_MASK) * 16u);
|
||||
for (uint i = 0u; i < 16u; ++i) s[i] ^= line[i];
|
||||
}
|
||||
mh_mixer(s, 0x9E3779B9u * 9u);
|
||||
}
|
||||
// dataset[w] without the dataset: derive item w >> 4 and take word w & 15.
|
||||
static inline uint mh_word(__global const uint* cache, uint w) { uint s[16]; mh_item(cache, w >> 4u, s); return s[w & 15u]; }
|
||||
|
||||
// Memory-hard dataset (MEMHARD.md). One work-item per cache segment; one work-item per 64-byte dataset item.
|
||||
// The same constants as memhard.h in this pack (one emitter, three dialects).
|
||||
__kernel void igneum_cache_fill(__global uint* cache, uint nSegments) {
|
||||
uint seg = (uint)get_global_id(0);
|
||||
if (seg < nSegments) mh_cache_segment(cache, seg);
|
||||
}
|
||||
__kernel void igneum_build(__global uint* ds, __global const uint* cache, uint nItems) {
|
||||
uint t = (uint)get_global_id(0);
|
||||
if (t < nItems) {
|
||||
uint s[16];
|
||||
mh_item(cache, t, s);
|
||||
__global uint* d = ds + ((ulong)t * 16u);
|
||||
for (uint i = 0u; i < 16u; ++i) d[i] = s[i];
|
||||
}
|
||||
}
|
||||
|
||||
// One hash per work-item. IGNEUM_GROUP is a multiple of 32; lane = lid & 31 and every exchange stays inside the
|
||||
// lane's own aligned run of 32 work-items, exactly like simd_shuffle_xor inside a 32-wide Metal SIMD group and
|
||||
// __shfl_xor_sync inside a CUDA warp. Control flow is uniform (no branches at all).
|
||||
IGNEUM_KERNEL_HASH void igneum_hash(__global const uint* ds, __global ulong* out, uint baseNonce, uint mask) {
|
||||
uint gid = (uint)get_global_id(0);
|
||||
uint lid = (uint)get_local_id(0);
|
||||
uint nonce = baseNonce + gid;
|
||||
uint r0, r1, r2, r3, r4, r5, r6, r7;
|
||||
#if IGNEUM_EXCHANGE == 0
|
||||
IGNEUM_LOCAL_WORDS(xch, 2 * IGNEUM_GROUP);
|
||||
uint xk = 0u;
|
||||
#else
|
||||
(void)lid;
|
||||
#endif
|
||||
{ uint x = nonce ^ 0xa7198abfu; x += 0x9e3779b9u; x = splitmix32(x); r0 = x ^ 0x6cd0f8cfu; } // SEEDW[0], 0x9e3779b9u * 1u, SEEDW[1]
|
||||
{ uint x = nonce ^ 0x6cd0f8cfu; x += 0x3c6ef372u; x = splitmix32(x); r1 = x ^ 0xe4ef8ebfu; } // SEEDW[1], 0x9e3779b9u * 2u, SEEDW[2]
|
||||
{ uint x = nonce ^ 0xe4ef8ebfu; x += 0xdaa66d2bu; x = splitmix32(x); r2 = x ^ 0x03ee1e65u; } // SEEDW[2], 0x9e3779b9u * 3u, SEEDW[3]
|
||||
{ uint x = nonce ^ 0x03ee1e65u; x += 0x78dde6e4u; x = splitmix32(x); r3 = x ^ 0xcfcfc5c0u; } // SEEDW[3], 0x9e3779b9u * 4u, SEEDW[4]
|
||||
{ uint x = nonce ^ 0xcfcfc5c0u; x += 0x1715609du; x = splitmix32(x); r4 = x ^ 0x82e9e19bu; } // SEEDW[4], 0x9e3779b9u * 5u, SEEDW[5]
|
||||
{ uint x = nonce ^ 0x82e9e19bu; x += 0xb54cda56u; x = splitmix32(x); r5 = x ^ 0x5d7a8a2fu; } // SEEDW[5], 0x9e3779b9u * 6u, SEEDW[6]
|
||||
{ uint x = nonce ^ 0x5d7a8a2fu; x += 0x5384540fu; x = splitmix32(x); r6 = x ^ 0xfafccd93u; } // SEEDW[6], 0x9e3779b9u * 7u, SEEDW[7]
|
||||
{ uint x = nonce ^ 0xfafccd93u; x += 0xf1bbcdc8u; x = splitmix32(x); r7 = x ^ 0xa7198abfu; } // SEEDW[7], 0x9e3779b9u * 8u, SEEDW[0]
|
||||
|
||||
for (uint it = 0u; it < 8u; ++it) {
|
||||
uint sel = r0;
|
||||
r4 = r4 + r3 + ((((sel >> 8u) & 1u) != 0u) ? 0x5b2d5fe3u : 0x4a4c6caau); // 0 add
|
||||
r7 = r7 | r6; // 1 or
|
||||
r2 = r2 * r7; // 2 mul
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r1, 2u); r5 = r5 ^ t_; } // 3 shfl
|
||||
r4 = r4 ^ r6; // 4 xor
|
||||
r0 = r0 ^ ds[r4 & mask]; // 5 load
|
||||
r3 = rotl_imm(r3, 17u); // 6 rotl
|
||||
r1 = r1 + r4 + ((((sel >> 27u) & 1u) != 0u) ? 0x83aa2c52u : 0xaeb38cc5u); // 7 add
|
||||
r1 = rotl_imm(r1, 31u); // 8 rotl
|
||||
r4 = r4 ^ r7; // 9 xor
|
||||
{ uint b_ = (r0 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r6 = x_; } // 10 load
|
||||
{ uint b_ = (r6 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r0 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r0 = x_; } // 11 load
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r2, 1u); r5 = r5 ^ t_; } // 12 shfl
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r4, 2u); r1 = r1 ^ t_; } // 13 shfl
|
||||
r5 = r5 * r7; // 14 mul
|
||||
r3 = r3 ^ r0; // 15 xor
|
||||
r5 = r5 * r4; // 16 mul
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r0, 4u); r2 = r2 ^ t_; } // 17 shfl
|
||||
r4 = r4 + r1 + ((((sel >> 31u) & 1u) != 0u) ? 0xfb36bddau : 0x87d3a998u); // 18 add
|
||||
r0 = r0 + r1 + ((((sel >> 22u) & 1u) != 0u) ? 0xf2ef7076u : 0x88921092u); // 19 add
|
||||
r6 = r6 + r1 + ((((sel >> 3u) & 1u) != 0u) ? 0xe42e69c6u : 0x35e06b74u); // 20 add
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r5, 8u); r2 = r2 ^ t_; } // 21 shfl
|
||||
r3 = r3 + r6 + ((((sel >> 3u) & 1u) != 0u) ? 0xb45d9671u : 0x74df5734u); // 22 add
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r4, 8u); r5 = r5 ^ t_; } // 23 shfl
|
||||
r4 = r4 ^ ds[r2 & mask]; // 24 load
|
||||
r2 = r2 ^ r1; // 25 xor
|
||||
r7 = r7 * r6; // 26 mul
|
||||
{ uint b_ = (r3 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r2 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r2 = x_; } // 27 load
|
||||
r3 = rotl_imm(r3, 29u); // 28 rotl
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r0, 8u); r3 = r3 ^ t_; } // 29 shfl
|
||||
r1 = r1 ^ ds[r4 & mask]; // 30 load
|
||||
r4 = r4 - r6; // 31 sub
|
||||
r2 = r2 * r4; // 32 mul
|
||||
r4 = r3 * r3 + r4; // 33 mad
|
||||
r0 = r0 + r6 + ((((sel >> 15u) & 1u) != 0u) ? 0x97d2762du : 0x19318d72u); // 34 add
|
||||
r7 = r7 + r1 + ((((sel >> 19u) & 1u) != 0u) ? 0x79830eadu : 0x26b63296u); // 35 add
|
||||
r7 = r7 ^ ds[r2 & mask]; // 36 load
|
||||
r0 = rotr_var(r0, r7); // 37 rotr
|
||||
r2 = r2 + r7 + ((((sel >> 28u) & 1u) != 0u) ? 0x23c8dec4u : 0xb228dc81u); // 38 add
|
||||
r0 = r0 ^ ds[r5 & mask]; // 39 load
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r5, 2u); r7 = r7 ^ t_; } // 40 shfl
|
||||
r5 = r0 * r1 + r5; // 41 mad
|
||||
r2 = r2 ^ r3; // 42 xor
|
||||
r7 = r7 ^ ds[r0 & mask]; // 43 load
|
||||
{ uint b_ = (r5 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r0 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r0 = x_; } // 44 load
|
||||
r2 = r2 + r7 + ((((sel >> 22u) & 1u) != 0u) ? 0x5a3a7fe1u : 0xcc64df8eu); // 45 add
|
||||
r0 = rotr_var(r0, r5); // 46 rotr
|
||||
r3 = rotr_var(r3, r7); // 47 rotr
|
||||
r2 = r7 * r6 + r2; // 48 mad
|
||||
r6 = r3 * r5 + r6; // 49 mad
|
||||
r1 = r1 ^ ds[r6 & mask]; // 50 load
|
||||
r7 = r7 ^ ds[r1 & mask]; // 51 load
|
||||
r3 = r3 + r4 + ((((sel >> 6u) & 1u) != 0u) ? 0xcba22643u : 0x7a646d78u); // 52 add
|
||||
r4 = r4 ^ r0; // 53 xor
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r7, 4u); r3 = r3 ^ t_; } // 54 shfl
|
||||
r0 = rotr_var(r0, r1); // 55 rotr
|
||||
r5 = r5 ^ r3; // 56 xor
|
||||
r1 = r1 + r0 + ((((sel >> 8u) & 1u) != 0u) ? 0x1834af00u : 0x6f26b909u); // 57 add
|
||||
r6 = r6 ^ ds[r4 & mask]; // 58 load
|
||||
{ uint b_ = (r7 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r1 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r1 = x_; } // 59 load
|
||||
r1 = r1 ^ ds[r0 & mask]; // 60 load
|
||||
r4 = r4 ^ r7; // 61 xor
|
||||
r6 = r2 * r1 + r6; // 62 mad
|
||||
{ uint b_ = (r2 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r3 = x_; } // 63 load
|
||||
}
|
||||
uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u);
|
||||
uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u);
|
||||
out[gid] = ((ulong)hi << 32) | (ulong)lo;
|
||||
}
|
||||
|
||||
#if IGNEUM_EXCHANGE != 0
|
||||
// Reports the sub-group size this device uses for a work-group of IGNEUM_GROUP items. host.c runs it only when the
|
||||
// per-kernel query (clGetKernelSubGroupInfoKHR on igneum_hash) is unavailable; that query is preferred because a
|
||||
// compiler may pick a different wave width per kernel (RDNA: wave32 or wave64). See WAVEFRONT.md.
|
||||
IGNEUM_KERNEL_HASH void igneum_probe_subgroup(__global uint* out) {
|
||||
if (get_local_id(0) == 0u) { out[0] = get_sub_group_size(); out[1] = get_num_sub_groups(); }
|
||||
}
|
||||
#endif
|
||||
164
proto-cuda/packs-readwidth/mixA-1/kernel.cu
Normal file
164
proto-cuda/packs-readwidth/mixA-1/kernel.cu
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
// Generated by igneum-pow export (generator v2) for seed "igneum-readwidth/A/1". Do not edit by hand.
|
||||
// Bit-exact twin of the Metal kernel for the same seed (see proto-cuda/CHECKLIST.md and program.metal).
|
||||
// Compiled ahead of time by nvcc together with proto-cuda/host.cu. No NVRTC.
|
||||
#include <cuda_runtime.h>
|
||||
#include <cstdint>
|
||||
#include "program.h"
|
||||
#include "memhard.h"
|
||||
|
||||
__device__ __forceinline__ uint32_t splitmix32(uint32_t x) {
|
||||
x ^= x >> 16; x *= 0x7feb352du;
|
||||
x ^= x >> 15; x *= 0x846ca68bu;
|
||||
x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
// n is a literal in 1..31 at every call site, so both shift amounts are in 1..31.
|
||||
__device__ __forceinline__ uint32_t rotl_imm(uint32_t x, uint32_t n) { return (x << n) | (x >> (32u - n)); }
|
||||
// n is masked to 0..31; the second shift amount is masked too, so n == 0 gives x.
|
||||
__device__ __forceinline__ uint32_t rotr_var(uint32_t x, uint32_t n) { n &= 31u; return (x >> n) | (x << ((32u - n) & 31u)); }
|
||||
__device__ __forceinline__ uint32_t ds_elem(uint32_t i, uint32_t d0, uint32_t d1) {
|
||||
uint32_t x = i ^ d0;
|
||||
x *= 0x9E3779B1u; x ^= x >> 15;
|
||||
x += d1;
|
||||
x *= 0x85EBCA77u; x ^= x >> 13;
|
||||
x *= 0xC2B2AE3Du; x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
|
||||
// Memory-hard dataset (MEMHARD.md). One thread per cache segment; one thread per 64-byte dataset item.
|
||||
// The core functions (mh_cache_segment, mh_item) are in memhard.h and are also compiled for the host.
|
||||
__global__ void igneum_cache_fill(uint32_t* cache, uint32_t nSegments) {
|
||||
uint32_t seg = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
if (seg < nSegments) mh_cache_segment(cache, seg);
|
||||
}
|
||||
__global__ void igneum_build(uint32_t* ds, const uint32_t* cache, uint32_t nItems) {
|
||||
uint32_t t = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
if (t < nItems) {
|
||||
uint32_t s[16];
|
||||
mh_item(cache, t, s);
|
||||
uint32_t* d = ds + (size_t)t * 16u;
|
||||
for (uint32_t i = 0u; i < 16u; ++i) d[i] = s[i];
|
||||
}
|
||||
}
|
||||
|
||||
// One hash per thread. blockDim.x is a multiple of 32; lane = threadIdx.x & 31 and every
|
||||
// __shfl_xor_sync stays inside the lane's own warp, exactly like simd_shuffle_xor inside a
|
||||
// 32-wide Metal SIMD group. Control flow is uniform, so the full 0xffffffff member mask is valid.
|
||||
__global__ void igneum_hash(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask) {
|
||||
uint32_t gid = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
uint32_t nonce = baseNonce + gid;
|
||||
uint32_t r0, r1, r2, r3, r4, r5, r6, r7;
|
||||
{ uint32_t x = nonce ^ 0xa7198abfu; x += 0x9e3779b9u; x = splitmix32(x); r0 = x ^ 0x6cd0f8cfu; } // SEEDW[0], 0x9e3779b9u * 1u, SEEDW[1]
|
||||
{ uint32_t x = nonce ^ 0x6cd0f8cfu; x += 0x3c6ef372u; x = splitmix32(x); r1 = x ^ 0xe4ef8ebfu; } // SEEDW[1], 0x9e3779b9u * 2u, SEEDW[2]
|
||||
{ uint32_t x = nonce ^ 0xe4ef8ebfu; x += 0xdaa66d2bu; x = splitmix32(x); r2 = x ^ 0x03ee1e65u; } // SEEDW[2], 0x9e3779b9u * 3u, SEEDW[3]
|
||||
{ uint32_t x = nonce ^ 0x03ee1e65u; x += 0x78dde6e4u; x = splitmix32(x); r3 = x ^ 0xcfcfc5c0u; } // SEEDW[3], 0x9e3779b9u * 4u, SEEDW[4]
|
||||
{ uint32_t x = nonce ^ 0xcfcfc5c0u; x += 0x1715609du; x = splitmix32(x); r4 = x ^ 0x82e9e19bu; } // SEEDW[4], 0x9e3779b9u * 5u, SEEDW[5]
|
||||
{ uint32_t x = nonce ^ 0x82e9e19bu; x += 0xb54cda56u; x = splitmix32(x); r5 = x ^ 0x5d7a8a2fu; } // SEEDW[5], 0x9e3779b9u * 6u, SEEDW[6]
|
||||
{ uint32_t x = nonce ^ 0x5d7a8a2fu; x += 0x5384540fu; x = splitmix32(x); r6 = x ^ 0xfafccd93u; } // SEEDW[6], 0x9e3779b9u * 7u, SEEDW[7]
|
||||
{ uint32_t x = nonce ^ 0xfafccd93u; x += 0xf1bbcdc8u; x = splitmix32(x); r7 = x ^ 0xa7198abfu; } // SEEDW[7], 0x9e3779b9u * 8u, SEEDW[0]
|
||||
|
||||
for (uint32_t it = 0u; it < 8u; ++it) {
|
||||
uint32_t sel = r0;
|
||||
r4 = r4 + r3 + ((((sel >> 8u) & 1u) != 0u) ? 0x5b2d5fe3u : 0x4a4c6caau); // 0 add
|
||||
r7 = r7 | r6; // 1 or
|
||||
r2 = r2 * r7; // 2 mul
|
||||
r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r1, 2); // 3 shfl
|
||||
r4 = r4 ^ r6; // 4 xor
|
||||
r0 = r0 ^ ds[r4 & mask]; // 5 load
|
||||
r3 = rotl_imm(r3, 17u); // 6 rotl
|
||||
r1 = r1 + r4 + ((((sel >> 27u) & 1u) != 0u) ? 0x83aa2c52u : 0xaeb38cc5u); // 7 add
|
||||
r1 = rotl_imm(r1, 31u); // 8 rotl
|
||||
r4 = r4 ^ r7; // 9 xor
|
||||
{ uint32_t b_ = (r0 & mask) & ~3u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint32_t x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r6 = x_; } // 10 load
|
||||
{ uint32_t b_ = (r6 & mask) & ~3u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint32_t x_ = r0 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r0 = x_; } // 11 load
|
||||
r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r2, 1); // 12 shfl
|
||||
r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r4, 2); // 13 shfl
|
||||
r5 = r5 * r7; // 14 mul
|
||||
r3 = r3 ^ r0; // 15 xor
|
||||
r5 = r5 * r4; // 16 mul
|
||||
r2 = r2 ^ __shfl_xor_sync(0xffffffffu, r0, 4); // 17 shfl
|
||||
r4 = r4 + r1 + ((((sel >> 31u) & 1u) != 0u) ? 0xfb36bddau : 0x87d3a998u); // 18 add
|
||||
r0 = r0 + r1 + ((((sel >> 22u) & 1u) != 0u) ? 0xf2ef7076u : 0x88921092u); // 19 add
|
||||
r6 = r6 + r1 + ((((sel >> 3u) & 1u) != 0u) ? 0xe42e69c6u : 0x35e06b74u); // 20 add
|
||||
r2 = r2 ^ __shfl_xor_sync(0xffffffffu, r5, 8); // 21 shfl
|
||||
r3 = r3 + r6 + ((((sel >> 3u) & 1u) != 0u) ? 0xb45d9671u : 0x74df5734u); // 22 add
|
||||
r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r4, 8); // 23 shfl
|
||||
r4 = r4 ^ ds[r2 & mask]; // 24 load
|
||||
r2 = r2 ^ r1; // 25 xor
|
||||
r7 = r7 * r6; // 26 mul
|
||||
{ uint32_t b_ = (r3 & mask) & ~15u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint32_t x_ = r2 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r2 = x_; } // 27 load
|
||||
r3 = rotl_imm(r3, 29u); // 28 rotl
|
||||
r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r0, 8); // 29 shfl
|
||||
r1 = r1 ^ ds[r4 & mask]; // 30 load
|
||||
r4 = r4 - r6; // 31 sub
|
||||
r2 = r2 * r4; // 32 mul
|
||||
r4 = r3 * r3 + r4; // 33 mad
|
||||
r0 = r0 + r6 + ((((sel >> 15u) & 1u) != 0u) ? 0x97d2762du : 0x19318d72u); // 34 add
|
||||
r7 = r7 + r1 + ((((sel >> 19u) & 1u) != 0u) ? 0x79830eadu : 0x26b63296u); // 35 add
|
||||
r7 = r7 ^ ds[r2 & mask]; // 36 load
|
||||
r0 = rotr_var(r0, r7); // 37 rotr
|
||||
r2 = r2 + r7 + ((((sel >> 28u) & 1u) != 0u) ? 0x23c8dec4u : 0xb228dc81u); // 38 add
|
||||
r0 = r0 ^ ds[r5 & mask]; // 39 load
|
||||
r7 = r7 ^ __shfl_xor_sync(0xffffffffu, r5, 2); // 40 shfl
|
||||
r5 = r0 * r1 + r5; // 41 mad
|
||||
r2 = r2 ^ r3; // 42 xor
|
||||
r7 = r7 ^ ds[r0 & mask]; // 43 load
|
||||
{ uint32_t b_ = (r5 & mask) & ~3u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint32_t x_ = r0 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r0 = x_; } // 44 load
|
||||
r2 = r2 + r7 + ((((sel >> 22u) & 1u) != 0u) ? 0x5a3a7fe1u : 0xcc64df8eu); // 45 add
|
||||
r0 = rotr_var(r0, r5); // 46 rotr
|
||||
r3 = rotr_var(r3, r7); // 47 rotr
|
||||
r2 = r7 * r6 + r2; // 48 mad
|
||||
r6 = r3 * r5 + r6; // 49 mad
|
||||
r1 = r1 ^ ds[r6 & mask]; // 50 load
|
||||
r7 = r7 ^ ds[r1 & mask]; // 51 load
|
||||
r3 = r3 + r4 + ((((sel >> 6u) & 1u) != 0u) ? 0xcba22643u : 0x7a646d78u); // 52 add
|
||||
r4 = r4 ^ r0; // 53 xor
|
||||
r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r7, 4); // 54 shfl
|
||||
r0 = rotr_var(r0, r1); // 55 rotr
|
||||
r5 = r5 ^ r3; // 56 xor
|
||||
r1 = r1 + r0 + ((((sel >> 8u) & 1u) != 0u) ? 0x1834af00u : 0x6f26b909u); // 57 add
|
||||
r6 = r6 ^ ds[r4 & mask]; // 58 load
|
||||
{ uint32_t b_ = (r7 & mask) & ~15u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint32_t x_ = r1 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r1 = x_; } // 59 load
|
||||
r1 = r1 ^ ds[r0 & mask]; // 60 load
|
||||
r4 = r4 ^ r7; // 61 xor
|
||||
r6 = r2 * r1 + r6; // 62 mad
|
||||
{ uint32_t b_ = (r2 & mask) & ~3u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint32_t x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r3 = x_; } // 63 load
|
||||
}
|
||||
uint32_t lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u);
|
||||
uint32_t hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u);
|
||||
out[gid] = ((uint64_t)hi << 32) | (uint64_t)lo;
|
||||
}
|
||||
|
||||
// Host-side launch wrappers. Declared in program.h, called from host.cu.
|
||||
cudaError_t igneum_launch_cache_fill(uint32_t* cache, uint32_t nSegments) {
|
||||
if (nSegments == 0u) return cudaErrorInvalidValue;
|
||||
uint32_t block = 256u;
|
||||
uint32_t grid = (nSegments + block - 1u) / block;
|
||||
igneum_cache_fill<<<grid, block>>>(cache, nSegments);
|
||||
return cudaGetLastError();
|
||||
}
|
||||
|
||||
cudaError_t igneum_launch_build(uint32_t* ds, const uint32_t* cache, uint32_t nItems) {
|
||||
if (nItems == 0u) return cudaErrorInvalidValue;
|
||||
uint32_t block = 256u;
|
||||
uint32_t grid = (nItems + block - 1u) / block;
|
||||
igneum_build<<<grid, block>>>(ds, cache, nItems);
|
||||
return cudaGetLastError();
|
||||
}
|
||||
|
||||
cudaError_t igneum_launch_hash(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask,
|
||||
uint32_t nonces, uint32_t blockWarps) {
|
||||
if (blockWarps == 0u || blockWarps > 32u) return cudaErrorInvalidValue;
|
||||
uint32_t block = 32u * blockWarps;
|
||||
if (nonces == 0u || (nonces % block) != 0u) return cudaErrorInvalidValue;
|
||||
igneum_hash<<<nonces / block, block>>>(ds, out, baseNonce, mask);
|
||||
return cudaGetLastError();
|
||||
}
|
||||
|
||||
cudaError_t igneum_hash_info(int* numRegs, int* blocksPerSM, uint32_t blockWarps) {
|
||||
cudaFuncAttributes attr;
|
||||
cudaError_t e = cudaFuncGetAttributes(&attr, igneum_hash);
|
||||
if (e != cudaSuccess) return e;
|
||||
*numRegs = attr.numRegs;
|
||||
return cudaOccupancyMaxActiveBlocksPerMultiprocessor(blocksPerSM, igneum_hash, (int)(32u * blockWarps), 0);
|
||||
}
|
||||
372
proto-cuda/packs-readwidth/mixA-1/kernel_bound.cl
Normal file
372
proto-cuda/packs-readwidth/mixA-1/kernel_bound.cl
Normal file
|
|
@ -0,0 +1,372 @@
|
|||
// Generated by igneum-pow export (generator v2) for seed "igneum-readwidth/A/1". Do not edit by hand.
|
||||
// OpenCL C twin of the Metal kernel for the same seed (see proto-opencl/README.md, WAVEFRONT.md and program.metal).
|
||||
// Built from source at runtime by proto-opencl/host.c, which passes these defines:
|
||||
// IGNEUM_GROUP work-group size of igneum_hash, a multiple of 32 (default 32: one work-group = one 32-lane unit)
|
||||
// IGNEUM_EXCHANGE 0 = local-memory exchange with a barrier (any device, any wave width; the default)
|
||||
// 1 = sub_group_shuffle_xor (cl_khr_subgroup_shuffle), only with IGNEUM_GROUP 32 and a sub-group size of exactly 32
|
||||
// 2 = intel_sub_group_shuffle_xor (cl_intel_subgroups), same condition
|
||||
// The verification unit is always 32 lanes. A 64-wide hardware wave (AMD GCN/CDNA, RDNA in wave64) runs two units;
|
||||
// the exchange masks are 1, 2, 4, 8, 16, so every partner lane lies inside the lane's own aligned run of 32.
|
||||
#ifndef IGNEUM_GROUP
|
||||
#define IGNEUM_GROUP 32
|
||||
#endif
|
||||
#ifndef IGNEUM_EXCHANGE
|
||||
#define IGNEUM_EXCHANGE 0
|
||||
#endif
|
||||
#ifdef __OPENCL_VERSION__
|
||||
#define IGNEUM_KERNEL_HASH __kernel __attribute__((reqd_work_group_size(IGNEUM_GROUP, 1, 1)))
|
||||
#define IGNEUM_LOCAL_WORDS(name, n) __local uint name[n]
|
||||
#if IGNEUM_EXCHANGE == 1
|
||||
#ifdef cl_khr_subgroups
|
||||
#pragma OPENCL EXTENSION cl_khr_subgroups : enable
|
||||
#endif
|
||||
#ifdef cl_khr_subgroup_shuffle
|
||||
#pragma OPENCL EXTENSION cl_khr_subgroup_shuffle : enable
|
||||
#endif
|
||||
#elif IGNEUM_EXCHANGE == 2
|
||||
#pragma OPENCL EXTENSION cl_intel_subgroups : enable
|
||||
#endif
|
||||
#else
|
||||
// Not an OpenCL compiler: proto-opencl/emu compiles this file as C++ and supplies the built-ins and these two macros.
|
||||
#include "emu_opencl.h"
|
||||
#endif
|
||||
|
||||
#if IGNEUM_EXCHANGE == 1
|
||||
#define IGNEUM_SHFL_XOR(dst, a, m) dst = sub_group_shuffle_xor((a), (uint)(m))
|
||||
#define IGNEUM_BCAST0(dst, a) dst = sub_group_broadcast((a), 0u)
|
||||
#elif IGNEUM_EXCHANGE == 2
|
||||
#define IGNEUM_SHFL_XOR(dst, a, m) dst = intel_sub_group_shuffle_xor((a), (uint)(m))
|
||||
#define IGNEUM_BCAST0(dst, a) dst = sub_group_broadcast((a), 0u)
|
||||
#else
|
||||
// Local-memory exchange. Two buffers of IGNEUM_GROUP words alternate (xk counts exchanges), so one barrier per
|
||||
// exchange is enough: a lane can only overwrite buffer b at exchange k+2 after passing barrier k+1, and every lane
|
||||
// reaches barrier k+1 only after its read of buffer b at exchange k. The partner lid ^ m stays inside the lane's
|
||||
// aligned run of 32 because m < 32. Control flow is uniform, so every work-item reaches every barrier.
|
||||
#define IGNEUM_SHFL_XOR(dst, a, m) { xch[(xk & 1u) * IGNEUM_GROUP + lid] = (a); barrier(CLK_LOCAL_MEM_FENCE); dst = xch[(xk & 1u) * IGNEUM_GROUP + (lid ^ (uint)(m))]; xk += 1u; }
|
||||
#define IGNEUM_BCAST0(dst, a) { xch[(xk & 1u) * IGNEUM_GROUP + lid] = (a); barrier(CLK_LOCAL_MEM_FENCE); dst = xch[(xk & 1u) * IGNEUM_GROUP + (lid & ~31u)]; xk += 1u; }
|
||||
#endif
|
||||
|
||||
static inline uint splitmix32(uint x) {
|
||||
x ^= x >> 16; x *= 0x7feb352du;
|
||||
x ^= x >> 15; x *= 0x846ca68bu;
|
||||
x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
// n is a literal in 1..31 at every call site. OpenCL rotate() rotates left by n modulo 32.
|
||||
static inline uint rotl_imm(uint x, uint n) { return rotate(x, n); }
|
||||
// Right rotation by n modulo 32 as a left rotation by (32 - n) modulo 32; n == 0 gives x.
|
||||
static inline uint rotr_var(uint x, uint n) { return rotate(x, (0u - n) & 31u); }
|
||||
static inline uint ds_elem(uint i, uint d0, uint d1) {
|
||||
uint x = i ^ d0;
|
||||
x *= 0x9E3779B1u; x ^= x >> 15;
|
||||
x += d1;
|
||||
x *= 0x85EBCA77u; x ^= x >> 13;
|
||||
x *= 0xC2B2AE3Du; x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
|
||||
// Memory-hard dataset core (MEMHARD.md). Cache: 2^26 words in 2^16 segments of 64 chained ChaCha12 lines.
|
||||
// Item: 8 rounds of seed-parameterised mixer + one 64-byte cache read, then a final mixer. All parameters are literals.
|
||||
#define MH_CACHE_LINE_MASK 0x003fffffu
|
||||
#define MH_SEGMENT_LINES 64u
|
||||
#define MH_QR(a, b, c, d, r1, r2, r3, r4) { a += b; d ^= a; d = mh_rotl(d, r1); c += d; b ^= c; b = mh_rotl(b, r2); a += b; d ^= a; d = mh_rotl(d, r3); c += d; b ^= c; b = mh_rotl(b, r4); }
|
||||
static inline uint mh_rotl(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 at every call site
|
||||
|
||||
// y = ChaCha12 core(x) + x
|
||||
static inline void mh_chacha_block(const uint* x, uint* y) {
|
||||
for (uint i = 0u; i < 16u; ++i) y[i] = x[i];
|
||||
for (uint r = 0u; r < 6u; ++r) {
|
||||
MH_QR(y[0], y[4], y[8], y[12], 16u, 12u, 8u, 7u) MH_QR(y[1], y[5], y[9], y[13], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[2], y[6], y[10], y[14], 16u, 12u, 8u, 7u) MH_QR(y[3], y[7], y[11], y[15], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[0], y[5], y[10], y[15], 16u, 12u, 8u, 7u) MH_QR(y[1], y[6], y[11], y[12], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[2], y[7], y[8], y[13], 16u, 12u, 8u, 7u) MH_QR(y[3], y[4], y[9], y[14], 16u, 12u, 8u, 7u)
|
||||
}
|
||||
for (uint i = 0u; i < 16u; ++i) y[i] += x[i];
|
||||
}
|
||||
|
||||
// One cache segment: 64 chained lines written at cache[seg * 1024]. in_j = prev ^ (sigma || K || seg || j || tag), prev_0 = 0.
|
||||
static inline void mh_cache_segment(__global uint* cache, uint seg) {
|
||||
uint prev[16]; uint x[16]; uint y[16];
|
||||
for (uint i = 0u; i < 16u; ++i) prev[i] = 0u;
|
||||
for (uint j = 0u; j < MH_SEGMENT_LINES; ++j) {
|
||||
x[0] = 0x61707865u ^ prev[0]; x[1] = 0x3320646eu ^ prev[1]; x[2] = 0x79622d32u ^ prev[2]; x[3] = 0x6b206574u ^ prev[3];
|
||||
x[4] = 0x3067619fu ^ prev[4];
|
||||
x[5] = 0x3c269176u ^ prev[5];
|
||||
x[6] = 0x84a03b03u ^ prev[6];
|
||||
x[7] = 0xf8c63294u ^ prev[7];
|
||||
x[8] = 0xff977c5bu ^ prev[8];
|
||||
x[9] = 0xe60def3eu ^ prev[9];
|
||||
x[10] = 0x63630141u ^ prev[10];
|
||||
x[11] = 0xb8fbcb58u ^ prev[11];
|
||||
x[12] = seg ^ prev[12]; x[13] = j ^ prev[13]; x[14] = 0x49676e65u ^ prev[14]; x[15] = 0x756d4d48u ^ prev[15];
|
||||
mh_chacha_block(x, y);
|
||||
__global uint* line = cache + ((seg * MH_SEGMENT_LINES + j) * 16u);
|
||||
for (uint i = 0u; i < 16u; ++i) { line[i] = y[i]; prev[i] = y[i]; }
|
||||
}
|
||||
}
|
||||
|
||||
// M_r: per word (s ^ (RC + rk)) * MUL, then a column round and a diagonal round with the seed-drawn rotations.
|
||||
static inline void mh_mixer(uint* s, uint rk) {
|
||||
s[0] = (s[0] ^ (0xbab68293u + rk)) * 0x42146205u;
|
||||
s[1] = (s[1] ^ (0xcc162340u + rk)) * 0x52cbe0fbu;
|
||||
s[2] = (s[2] ^ (0x6ce151ccu + rk)) * 0x7ecf4a03u;
|
||||
s[3] = (s[3] ^ (0xe62b8997u + rk)) * 0x6728907fu;
|
||||
s[4] = (s[4] ^ (0xc9c80297u + rk)) * 0xd81d9751u;
|
||||
s[5] = (s[5] ^ (0xf74a1654u + rk)) * 0x132952c3u;
|
||||
s[6] = (s[6] ^ (0x3d704af5u + rk)) * 0xf60de277u;
|
||||
s[7] = (s[7] ^ (0x3cf522b7u + rk)) * 0x05358035u;
|
||||
s[8] = (s[8] ^ (0x2b9cac04u + rk)) * 0xbaf6499du;
|
||||
s[9] = (s[9] ^ (0xa880ac10u + rk)) * 0xe4db9667u;
|
||||
s[10] = (s[10] ^ (0x13e5dd1du + rk)) * 0x3e98f45du;
|
||||
s[11] = (s[11] ^ (0x6fc3e233u + rk)) * 0xd0004eddu;
|
||||
s[12] = (s[12] ^ (0x2d83eeacu + rk)) * 0x2691630du;
|
||||
s[13] = (s[13] ^ (0x9006e8bfu + rk)) * 0x9beb3bcfu;
|
||||
s[14] = (s[14] ^ (0x2c4b5362u + rk)) * 0xab310379u;
|
||||
s[15] = (s[15] ^ (0x31b49ee2u + rk)) * 0x99cfb423u;
|
||||
MH_QR(s[0], s[4], s[8], s[12], 20u, 20u, 19u, 4u) MH_QR(s[1], s[5], s[9], s[13], 20u, 20u, 19u, 4u)
|
||||
MH_QR(s[2], s[6], s[10], s[14], 20u, 20u, 19u, 4u) MH_QR(s[3], s[7], s[11], s[15], 20u, 20u, 19u, 4u)
|
||||
MH_QR(s[0], s[5], s[10], s[15], 26u, 3u, 3u, 27u) MH_QR(s[1], s[6], s[11], s[12], 26u, 3u, 3u, 27u)
|
||||
MH_QR(s[2], s[7], s[8], s[13], 26u, 3u, 3u, 27u) MH_QR(s[3], s[4], s[9], s[14], 26u, 3u, 3u, 27u)
|
||||
}
|
||||
|
||||
// Item t: 16 words. s = (K, t * MUL[i] + RC[i]); 8 rounds of mixer + cache line s[0] & mask; final mixer.
|
||||
static inline void mh_item(__global const uint* cache, uint t, uint* s) {
|
||||
s[0] = 0x3067619fu;
|
||||
s[1] = 0x3c269176u;
|
||||
s[2] = 0x84a03b03u;
|
||||
s[3] = 0xf8c63294u;
|
||||
s[4] = 0xff977c5bu;
|
||||
s[5] = 0xe60def3eu;
|
||||
s[6] = 0x63630141u;
|
||||
s[7] = 0xb8fbcb58u;
|
||||
s[8] = t * 0x42146205u + 0xbab68293u;
|
||||
s[9] = t * 0x52cbe0fbu + 0xcc162340u;
|
||||
s[10] = t * 0x7ecf4a03u + 0x6ce151ccu;
|
||||
s[11] = t * 0x6728907fu + 0xe62b8997u;
|
||||
s[12] = t * 0xd81d9751u + 0xc9c80297u;
|
||||
s[13] = t * 0x132952c3u + 0xf74a1654u;
|
||||
s[14] = t * 0xf60de277u + 0x3d704af5u;
|
||||
s[15] = t * 0x05358035u + 0x3cf522b7u;
|
||||
for (uint r = 0u; r < 8u; ++r) {
|
||||
mh_mixer(s, 0x9E3779B9u * (r + 1u));
|
||||
__global const uint* line = cache + ((s[0] & MH_CACHE_LINE_MASK) * 16u);
|
||||
for (uint i = 0u; i < 16u; ++i) s[i] ^= line[i];
|
||||
}
|
||||
mh_mixer(s, 0x9E3779B9u * 9u);
|
||||
}
|
||||
// dataset[w] without the dataset: derive item w >> 4 and take word w & 15.
|
||||
static inline uint mh_word(__global const uint* cache, uint w) { uint s[16]; mh_item(cache, w >> 4u, s); return s[w & 15u]; }
|
||||
|
||||
// Memory-hard dataset (MEMHARD.md). One work-item per cache segment; one work-item per 64-byte dataset item.
|
||||
// The same constants as memhard.h in this pack (one emitter, three dialects).
|
||||
__kernel void igneum_cache_fill(__global uint* cache, uint nSegments) {
|
||||
uint seg = (uint)get_global_id(0);
|
||||
if (seg < nSegments) mh_cache_segment(cache, seg);
|
||||
}
|
||||
__kernel void igneum_build(__global uint* ds, __global const uint* cache, uint nItems) {
|
||||
uint t = (uint)get_global_id(0);
|
||||
if (t < nItems) {
|
||||
uint s[16];
|
||||
mh_item(cache, t, s);
|
||||
__global uint* d = ds + ((ulong)t * 16u);
|
||||
for (uint i = 0u; i < 16u; ++i) d[i] = s[i];
|
||||
}
|
||||
}
|
||||
|
||||
// One hash per work-item. IGNEUM_GROUP is a multiple of 32; lane = lid & 31 and every exchange stays inside the
|
||||
// lane's own aligned run of 32 work-items, exactly like simd_shuffle_xor inside a 32-wide Metal SIMD group and
|
||||
// __shfl_xor_sync inside a CUDA warp. Control flow is uniform (no branches at all).
|
||||
IGNEUM_KERNEL_HASH void igneum_hash(__global const uint* ds, __global ulong* out, uint baseNonce, uint mask) {
|
||||
uint gid = (uint)get_global_id(0);
|
||||
uint lid = (uint)get_local_id(0);
|
||||
uint nonce = baseNonce + gid;
|
||||
uint r0, r1, r2, r3, r4, r5, r6, r7;
|
||||
#if IGNEUM_EXCHANGE == 0
|
||||
IGNEUM_LOCAL_WORDS(xch, 2 * IGNEUM_GROUP);
|
||||
uint xk = 0u;
|
||||
#else
|
||||
(void)lid;
|
||||
#endif
|
||||
{ uint x = nonce ^ 0xa7198abfu; x += 0x9e3779b9u; x = splitmix32(x); r0 = x ^ 0x6cd0f8cfu; } // SEEDW[0], 0x9e3779b9u * 1u, SEEDW[1]
|
||||
{ uint x = nonce ^ 0x6cd0f8cfu; x += 0x3c6ef372u; x = splitmix32(x); r1 = x ^ 0xe4ef8ebfu; } // SEEDW[1], 0x9e3779b9u * 2u, SEEDW[2]
|
||||
{ uint x = nonce ^ 0xe4ef8ebfu; x += 0xdaa66d2bu; x = splitmix32(x); r2 = x ^ 0x03ee1e65u; } // SEEDW[2], 0x9e3779b9u * 3u, SEEDW[3]
|
||||
{ uint x = nonce ^ 0x03ee1e65u; x += 0x78dde6e4u; x = splitmix32(x); r3 = x ^ 0xcfcfc5c0u; } // SEEDW[3], 0x9e3779b9u * 4u, SEEDW[4]
|
||||
{ uint x = nonce ^ 0xcfcfc5c0u; x += 0x1715609du; x = splitmix32(x); r4 = x ^ 0x82e9e19bu; } // SEEDW[4], 0x9e3779b9u * 5u, SEEDW[5]
|
||||
{ uint x = nonce ^ 0x82e9e19bu; x += 0xb54cda56u; x = splitmix32(x); r5 = x ^ 0x5d7a8a2fu; } // SEEDW[5], 0x9e3779b9u * 6u, SEEDW[6]
|
||||
{ uint x = nonce ^ 0x5d7a8a2fu; x += 0x5384540fu; x = splitmix32(x); r6 = x ^ 0xfafccd93u; } // SEEDW[6], 0x9e3779b9u * 7u, SEEDW[7]
|
||||
{ uint x = nonce ^ 0xfafccd93u; x += 0xf1bbcdc8u; x = splitmix32(x); r7 = x ^ 0xa7198abfu; } // SEEDW[7], 0x9e3779b9u * 8u, SEEDW[0]
|
||||
|
||||
for (uint it = 0u; it < 8u; ++it) {
|
||||
uint sel = r0;
|
||||
r4 = r4 + r3 + ((((sel >> 8u) & 1u) != 0u) ? 0x5b2d5fe3u : 0x4a4c6caau); // 0 add
|
||||
r7 = r7 | r6; // 1 or
|
||||
r2 = r2 * r7; // 2 mul
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r1, 2u); r5 = r5 ^ t_; } // 3 shfl
|
||||
r4 = r4 ^ r6; // 4 xor
|
||||
r0 = r0 ^ ds[r4 & mask]; // 5 load
|
||||
r3 = rotl_imm(r3, 17u); // 6 rotl
|
||||
r1 = r1 + r4 + ((((sel >> 27u) & 1u) != 0u) ? 0x83aa2c52u : 0xaeb38cc5u); // 7 add
|
||||
r1 = rotl_imm(r1, 31u); // 8 rotl
|
||||
r4 = r4 ^ r7; // 9 xor
|
||||
{ uint b_ = (r0 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r6 = x_; } // 10 load
|
||||
{ uint b_ = (r6 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r0 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r0 = x_; } // 11 load
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r2, 1u); r5 = r5 ^ t_; } // 12 shfl
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r4, 2u); r1 = r1 ^ t_; } // 13 shfl
|
||||
r5 = r5 * r7; // 14 mul
|
||||
r3 = r3 ^ r0; // 15 xor
|
||||
r5 = r5 * r4; // 16 mul
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r0, 4u); r2 = r2 ^ t_; } // 17 shfl
|
||||
r4 = r4 + r1 + ((((sel >> 31u) & 1u) != 0u) ? 0xfb36bddau : 0x87d3a998u); // 18 add
|
||||
r0 = r0 + r1 + ((((sel >> 22u) & 1u) != 0u) ? 0xf2ef7076u : 0x88921092u); // 19 add
|
||||
r6 = r6 + r1 + ((((sel >> 3u) & 1u) != 0u) ? 0xe42e69c6u : 0x35e06b74u); // 20 add
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r5, 8u); r2 = r2 ^ t_; } // 21 shfl
|
||||
r3 = r3 + r6 + ((((sel >> 3u) & 1u) != 0u) ? 0xb45d9671u : 0x74df5734u); // 22 add
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r4, 8u); r5 = r5 ^ t_; } // 23 shfl
|
||||
r4 = r4 ^ ds[r2 & mask]; // 24 load
|
||||
r2 = r2 ^ r1; // 25 xor
|
||||
r7 = r7 * r6; // 26 mul
|
||||
{ uint b_ = (r3 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r2 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r2 = x_; } // 27 load
|
||||
r3 = rotl_imm(r3, 29u); // 28 rotl
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r0, 8u); r3 = r3 ^ t_; } // 29 shfl
|
||||
r1 = r1 ^ ds[r4 & mask]; // 30 load
|
||||
r4 = r4 - r6; // 31 sub
|
||||
r2 = r2 * r4; // 32 mul
|
||||
r4 = r3 * r3 + r4; // 33 mad
|
||||
r0 = r0 + r6 + ((((sel >> 15u) & 1u) != 0u) ? 0x97d2762du : 0x19318d72u); // 34 add
|
||||
r7 = r7 + r1 + ((((sel >> 19u) & 1u) != 0u) ? 0x79830eadu : 0x26b63296u); // 35 add
|
||||
r7 = r7 ^ ds[r2 & mask]; // 36 load
|
||||
r0 = rotr_var(r0, r7); // 37 rotr
|
||||
r2 = r2 + r7 + ((((sel >> 28u) & 1u) != 0u) ? 0x23c8dec4u : 0xb228dc81u); // 38 add
|
||||
r0 = r0 ^ ds[r5 & mask]; // 39 load
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r5, 2u); r7 = r7 ^ t_; } // 40 shfl
|
||||
r5 = r0 * r1 + r5; // 41 mad
|
||||
r2 = r2 ^ r3; // 42 xor
|
||||
r7 = r7 ^ ds[r0 & mask]; // 43 load
|
||||
{ uint b_ = (r5 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r0 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r0 = x_; } // 44 load
|
||||
r2 = r2 + r7 + ((((sel >> 22u) & 1u) != 0u) ? 0x5a3a7fe1u : 0xcc64df8eu); // 45 add
|
||||
r0 = rotr_var(r0, r5); // 46 rotr
|
||||
r3 = rotr_var(r3, r7); // 47 rotr
|
||||
r2 = r7 * r6 + r2; // 48 mad
|
||||
r6 = r3 * r5 + r6; // 49 mad
|
||||
r1 = r1 ^ ds[r6 & mask]; // 50 load
|
||||
r7 = r7 ^ ds[r1 & mask]; // 51 load
|
||||
r3 = r3 + r4 + ((((sel >> 6u) & 1u) != 0u) ? 0xcba22643u : 0x7a646d78u); // 52 add
|
||||
r4 = r4 ^ r0; // 53 xor
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r7, 4u); r3 = r3 ^ t_; } // 54 shfl
|
||||
r0 = rotr_var(r0, r1); // 55 rotr
|
||||
r5 = r5 ^ r3; // 56 xor
|
||||
r1 = r1 + r0 + ((((sel >> 8u) & 1u) != 0u) ? 0x1834af00u : 0x6f26b909u); // 57 add
|
||||
r6 = r6 ^ ds[r4 & mask]; // 58 load
|
||||
{ uint b_ = (r7 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r1 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r1 = x_; } // 59 load
|
||||
r1 = r1 ^ ds[r0 & mask]; // 60 load
|
||||
r4 = r4 ^ r7; // 61 xor
|
||||
r6 = r2 * r1 + r6; // 62 mad
|
||||
{ uint b_ = (r2 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r3 = x_; } // 63 load
|
||||
}
|
||||
uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u);
|
||||
uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u);
|
||||
out[gid] = ((ulong)hi << 32) | (ulong)lo;
|
||||
}
|
||||
|
||||
#if IGNEUM_EXCHANGE != 0
|
||||
// Reports the sub-group size this device uses for a work-group of IGNEUM_GROUP items. host.c runs it only when the
|
||||
// per-kernel query (clGetKernelSubGroupInfoKHR on igneum_hash) is unavailable; that query is preferred because a
|
||||
// compiler may pick a different wave width per kernel (RDNA: wave32 or wave64). See WAVEFRONT.md.
|
||||
IGNEUM_KERNEL_HASH void igneum_probe_subgroup(__global uint* out) {
|
||||
if (get_local_id(0) == 0u) { out[0] = get_sub_group_size(); out[1] = get_num_sub_groups(); }
|
||||
}
|
||||
#endif
|
||||
|
||||
// Header-bound variant (bind.rs): the init words come from initw, not SEEDW. Same body as igneum_hash.
|
||||
IGNEUM_KERNEL_HASH void igneum_hash_bound(__global const uint* ds, __global ulong* out, uint baseNonce, uint mask, __global const uint* initw) {
|
||||
uint gid = (uint)get_global_id(0);
|
||||
uint lid = (uint)get_local_id(0);
|
||||
uint nonce = baseNonce + gid;
|
||||
uint r0, r1, r2, r3, r4, r5, r6, r7;
|
||||
uint iw0 = initw[0], iw1 = initw[1], iw2 = initw[2], iw3 = initw[3], iw4 = initw[4], iw5 = initw[5], iw6 = initw[6], iw7 = initw[7];
|
||||
#if IGNEUM_EXCHANGE == 0
|
||||
IGNEUM_LOCAL_WORDS(xch, 2 * IGNEUM_GROUP);
|
||||
uint xk = 0u;
|
||||
#else
|
||||
(void)lid;
|
||||
#endif
|
||||
{ uint x = nonce ^ iw0; x += 0x9e3779b9u * 1u; x = splitmix32(x); r0 = x ^ iw1; }
|
||||
{ uint x = nonce ^ iw1; x += 0x9e3779b9u * 2u; x = splitmix32(x); r1 = x ^ iw2; }
|
||||
{ uint x = nonce ^ iw2; x += 0x9e3779b9u * 3u; x = splitmix32(x); r2 = x ^ iw3; }
|
||||
{ uint x = nonce ^ iw3; x += 0x9e3779b9u * 4u; x = splitmix32(x); r3 = x ^ iw4; }
|
||||
{ uint x = nonce ^ iw4; x += 0x9e3779b9u * 5u; x = splitmix32(x); r4 = x ^ iw5; }
|
||||
{ uint x = nonce ^ iw5; x += 0x9e3779b9u * 6u; x = splitmix32(x); r5 = x ^ iw6; }
|
||||
{ uint x = nonce ^ iw6; x += 0x9e3779b9u * 7u; x = splitmix32(x); r6 = x ^ iw7; }
|
||||
{ uint x = nonce ^ iw7; x += 0x9e3779b9u * 8u; x = splitmix32(x); r7 = x ^ iw0; }
|
||||
|
||||
for (uint it = 0u; it < 8u; ++it) {
|
||||
uint sel = r0;
|
||||
r4 = r4 + r3 + ((((sel >> 8u) & 1u) != 0u) ? 0x5b2d5fe3u : 0x4a4c6caau); // 0 add
|
||||
r7 = r7 | r6; // 1 or
|
||||
r2 = r2 * r7; // 2 mul
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r1, 2u); r5 = r5 ^ t_; } // 3 shfl
|
||||
r4 = r4 ^ r6; // 4 xor
|
||||
r0 = r0 ^ ds[r4 & mask]; // 5 load
|
||||
r3 = rotl_imm(r3, 17u); // 6 rotl
|
||||
r1 = r1 + r4 + ((((sel >> 27u) & 1u) != 0u) ? 0x83aa2c52u : 0xaeb38cc5u); // 7 add
|
||||
r1 = rotl_imm(r1, 31u); // 8 rotl
|
||||
r4 = r4 ^ r7; // 9 xor
|
||||
{ uint b_ = (r0 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r6 = x_; } // 10 load
|
||||
{ uint b_ = (r6 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r0 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r0 = x_; } // 11 load
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r2, 1u); r5 = r5 ^ t_; } // 12 shfl
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r4, 2u); r1 = r1 ^ t_; } // 13 shfl
|
||||
r5 = r5 * r7; // 14 mul
|
||||
r3 = r3 ^ r0; // 15 xor
|
||||
r5 = r5 * r4; // 16 mul
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r0, 4u); r2 = r2 ^ t_; } // 17 shfl
|
||||
r4 = r4 + r1 + ((((sel >> 31u) & 1u) != 0u) ? 0xfb36bddau : 0x87d3a998u); // 18 add
|
||||
r0 = r0 + r1 + ((((sel >> 22u) & 1u) != 0u) ? 0xf2ef7076u : 0x88921092u); // 19 add
|
||||
r6 = r6 + r1 + ((((sel >> 3u) & 1u) != 0u) ? 0xe42e69c6u : 0x35e06b74u); // 20 add
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r5, 8u); r2 = r2 ^ t_; } // 21 shfl
|
||||
r3 = r3 + r6 + ((((sel >> 3u) & 1u) != 0u) ? 0xb45d9671u : 0x74df5734u); // 22 add
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r4, 8u); r5 = r5 ^ t_; } // 23 shfl
|
||||
r4 = r4 ^ ds[r2 & mask]; // 24 load
|
||||
r2 = r2 ^ r1; // 25 xor
|
||||
r7 = r7 * r6; // 26 mul
|
||||
{ uint b_ = (r3 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r2 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r2 = x_; } // 27 load
|
||||
r3 = rotl_imm(r3, 29u); // 28 rotl
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r0, 8u); r3 = r3 ^ t_; } // 29 shfl
|
||||
r1 = r1 ^ ds[r4 & mask]; // 30 load
|
||||
r4 = r4 - r6; // 31 sub
|
||||
r2 = r2 * r4; // 32 mul
|
||||
r4 = r3 * r3 + r4; // 33 mad
|
||||
r0 = r0 + r6 + ((((sel >> 15u) & 1u) != 0u) ? 0x97d2762du : 0x19318d72u); // 34 add
|
||||
r7 = r7 + r1 + ((((sel >> 19u) & 1u) != 0u) ? 0x79830eadu : 0x26b63296u); // 35 add
|
||||
r7 = r7 ^ ds[r2 & mask]; // 36 load
|
||||
r0 = rotr_var(r0, r7); // 37 rotr
|
||||
r2 = r2 + r7 + ((((sel >> 28u) & 1u) != 0u) ? 0x23c8dec4u : 0xb228dc81u); // 38 add
|
||||
r0 = r0 ^ ds[r5 & mask]; // 39 load
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r5, 2u); r7 = r7 ^ t_; } // 40 shfl
|
||||
r5 = r0 * r1 + r5; // 41 mad
|
||||
r2 = r2 ^ r3; // 42 xor
|
||||
r7 = r7 ^ ds[r0 & mask]; // 43 load
|
||||
{ uint b_ = (r5 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r0 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r0 = x_; } // 44 load
|
||||
r2 = r2 + r7 + ((((sel >> 22u) & 1u) != 0u) ? 0x5a3a7fe1u : 0xcc64df8eu); // 45 add
|
||||
r0 = rotr_var(r0, r5); // 46 rotr
|
||||
r3 = rotr_var(r3, r7); // 47 rotr
|
||||
r2 = r7 * r6 + r2; // 48 mad
|
||||
r6 = r3 * r5 + r6; // 49 mad
|
||||
r1 = r1 ^ ds[r6 & mask]; // 50 load
|
||||
r7 = r7 ^ ds[r1 & mask]; // 51 load
|
||||
r3 = r3 + r4 + ((((sel >> 6u) & 1u) != 0u) ? 0xcba22643u : 0x7a646d78u); // 52 add
|
||||
r4 = r4 ^ r0; // 53 xor
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r7, 4u); r3 = r3 ^ t_; } // 54 shfl
|
||||
r0 = rotr_var(r0, r1); // 55 rotr
|
||||
r5 = r5 ^ r3; // 56 xor
|
||||
r1 = r1 + r0 + ((((sel >> 8u) & 1u) != 0u) ? 0x1834af00u : 0x6f26b909u); // 57 add
|
||||
r6 = r6 ^ ds[r4 & mask]; // 58 load
|
||||
{ uint b_ = (r7 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r1 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r1 = x_; } // 59 load
|
||||
r1 = r1 ^ ds[r0 & mask]; // 60 load
|
||||
r4 = r4 ^ r7; // 61 xor
|
||||
r6 = r2 * r1 + r6; // 62 mad
|
||||
{ uint b_ = (r2 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r3 = x_; } // 63 load
|
||||
}
|
||||
uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u);
|
||||
uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u);
|
||||
out[gid] = ((ulong)hi << 32) | (ulong)lo;
|
||||
}
|
||||
123
proto-cuda/packs-readwidth/mixA-1/kernel_bound.cu
Normal file
123
proto-cuda/packs-readwidth/mixA-1/kernel_bound.cu
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
// Generated by igneum-pow export (generator v2) for seed "igneum-readwidth/A/1". Do not edit by hand.
|
||||
// Header-bound twin of igneum_hash in kernel.cu: the init words come from a kernel argument, not SEEDW.
|
||||
// Host declarations (also in program_bound.h if present):
|
||||
// struct IgneumInitWords { uint32_t w[8]; };
|
||||
// cudaError_t igneum_launch_hash_bound(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask,
|
||||
// IgneumInitWords iw, uint32_t nonces, uint32_t blockWarps);
|
||||
// cudaError_t igneum_hash_bound_info(int* numRegs, int* blocksPerSM, uint32_t blockWarps);
|
||||
#include <cuda_runtime.h>
|
||||
#include <cstdint>
|
||||
#include "program.h"
|
||||
|
||||
struct IgneumInitWords { uint32_t w[8]; };
|
||||
|
||||
__device__ __forceinline__ uint32_t splitmix32(uint32_t x) {
|
||||
x ^= x >> 16; x *= 0x7feb352du;
|
||||
x ^= x >> 15; x *= 0x846ca68bu;
|
||||
x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
__device__ __forceinline__ uint32_t rotl_imm(uint32_t x, uint32_t n) { return (x << n) | (x >> (32u - n)); }
|
||||
__device__ __forceinline__ uint32_t rotr_var(uint32_t x, uint32_t n) { n &= 31u; return (x >> n) | (x << ((32u - n) & 31u)); }
|
||||
|
||||
__global__ void igneum_hash_bound(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask, IgneumInitWords iw) {
|
||||
uint32_t gid = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
uint32_t nonce = baseNonce + gid;
|
||||
uint32_t r0, r1, r2, r3, r4, r5, r6, r7;
|
||||
{ uint32_t x = nonce ^ iw.w[0]; x += 0x9e3779b9u * 1u; x = splitmix32(x); r0 = x ^ iw.w[1]; }
|
||||
{ uint32_t x = nonce ^ iw.w[1]; x += 0x9e3779b9u * 2u; x = splitmix32(x); r1 = x ^ iw.w[2]; }
|
||||
{ uint32_t x = nonce ^ iw.w[2]; x += 0x9e3779b9u * 3u; x = splitmix32(x); r2 = x ^ iw.w[3]; }
|
||||
{ uint32_t x = nonce ^ iw.w[3]; x += 0x9e3779b9u * 4u; x = splitmix32(x); r3 = x ^ iw.w[4]; }
|
||||
{ uint32_t x = nonce ^ iw.w[4]; x += 0x9e3779b9u * 5u; x = splitmix32(x); r4 = x ^ iw.w[5]; }
|
||||
{ uint32_t x = nonce ^ iw.w[5]; x += 0x9e3779b9u * 6u; x = splitmix32(x); r5 = x ^ iw.w[6]; }
|
||||
{ uint32_t x = nonce ^ iw.w[6]; x += 0x9e3779b9u * 7u; x = splitmix32(x); r6 = x ^ iw.w[7]; }
|
||||
{ uint32_t x = nonce ^ iw.w[7]; x += 0x9e3779b9u * 8u; x = splitmix32(x); r7 = x ^ iw.w[0]; }
|
||||
|
||||
for (uint32_t it = 0u; it < 8u; ++it) {
|
||||
uint32_t sel = r0;
|
||||
r4 = r4 + r3 + ((((sel >> 8u) & 1u) != 0u) ? 0x5b2d5fe3u : 0x4a4c6caau); // 0 add
|
||||
r7 = r7 | r6; // 1 or
|
||||
r2 = r2 * r7; // 2 mul
|
||||
r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r1, 2); // 3 shfl
|
||||
r4 = r4 ^ r6; // 4 xor
|
||||
r0 = r0 ^ ds[r4 & mask]; // 5 load
|
||||
r3 = rotl_imm(r3, 17u); // 6 rotl
|
||||
r1 = r1 + r4 + ((((sel >> 27u) & 1u) != 0u) ? 0x83aa2c52u : 0xaeb38cc5u); // 7 add
|
||||
r1 = rotl_imm(r1, 31u); // 8 rotl
|
||||
r4 = r4 ^ r7; // 9 xor
|
||||
{ uint32_t b_ = (r0 & mask) & ~3u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint32_t x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r6 = x_; } // 10 load
|
||||
{ uint32_t b_ = (r6 & mask) & ~3u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint32_t x_ = r0 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r0 = x_; } // 11 load
|
||||
r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r2, 1); // 12 shfl
|
||||
r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r4, 2); // 13 shfl
|
||||
r5 = r5 * r7; // 14 mul
|
||||
r3 = r3 ^ r0; // 15 xor
|
||||
r5 = r5 * r4; // 16 mul
|
||||
r2 = r2 ^ __shfl_xor_sync(0xffffffffu, r0, 4); // 17 shfl
|
||||
r4 = r4 + r1 + ((((sel >> 31u) & 1u) != 0u) ? 0xfb36bddau : 0x87d3a998u); // 18 add
|
||||
r0 = r0 + r1 + ((((sel >> 22u) & 1u) != 0u) ? 0xf2ef7076u : 0x88921092u); // 19 add
|
||||
r6 = r6 + r1 + ((((sel >> 3u) & 1u) != 0u) ? 0xe42e69c6u : 0x35e06b74u); // 20 add
|
||||
r2 = r2 ^ __shfl_xor_sync(0xffffffffu, r5, 8); // 21 shfl
|
||||
r3 = r3 + r6 + ((((sel >> 3u) & 1u) != 0u) ? 0xb45d9671u : 0x74df5734u); // 22 add
|
||||
r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r4, 8); // 23 shfl
|
||||
r4 = r4 ^ ds[r2 & mask]; // 24 load
|
||||
r2 = r2 ^ r1; // 25 xor
|
||||
r7 = r7 * r6; // 26 mul
|
||||
{ uint32_t b_ = (r3 & mask) & ~15u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint32_t x_ = r2 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r2 = x_; } // 27 load
|
||||
r3 = rotl_imm(r3, 29u); // 28 rotl
|
||||
r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r0, 8); // 29 shfl
|
||||
r1 = r1 ^ ds[r4 & mask]; // 30 load
|
||||
r4 = r4 - r6; // 31 sub
|
||||
r2 = r2 * r4; // 32 mul
|
||||
r4 = r3 * r3 + r4; // 33 mad
|
||||
r0 = r0 + r6 + ((((sel >> 15u) & 1u) != 0u) ? 0x97d2762du : 0x19318d72u); // 34 add
|
||||
r7 = r7 + r1 + ((((sel >> 19u) & 1u) != 0u) ? 0x79830eadu : 0x26b63296u); // 35 add
|
||||
r7 = r7 ^ ds[r2 & mask]; // 36 load
|
||||
r0 = rotr_var(r0, r7); // 37 rotr
|
||||
r2 = r2 + r7 + ((((sel >> 28u) & 1u) != 0u) ? 0x23c8dec4u : 0xb228dc81u); // 38 add
|
||||
r0 = r0 ^ ds[r5 & mask]; // 39 load
|
||||
r7 = r7 ^ __shfl_xor_sync(0xffffffffu, r5, 2); // 40 shfl
|
||||
r5 = r0 * r1 + r5; // 41 mad
|
||||
r2 = r2 ^ r3; // 42 xor
|
||||
r7 = r7 ^ ds[r0 & mask]; // 43 load
|
||||
{ uint32_t b_ = (r5 & mask) & ~3u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint32_t x_ = r0 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r0 = x_; } // 44 load
|
||||
r2 = r2 + r7 + ((((sel >> 22u) & 1u) != 0u) ? 0x5a3a7fe1u : 0xcc64df8eu); // 45 add
|
||||
r0 = rotr_var(r0, r5); // 46 rotr
|
||||
r3 = rotr_var(r3, r7); // 47 rotr
|
||||
r2 = r7 * r6 + r2; // 48 mad
|
||||
r6 = r3 * r5 + r6; // 49 mad
|
||||
r1 = r1 ^ ds[r6 & mask]; // 50 load
|
||||
r7 = r7 ^ ds[r1 & mask]; // 51 load
|
||||
r3 = r3 + r4 + ((((sel >> 6u) & 1u) != 0u) ? 0xcba22643u : 0x7a646d78u); // 52 add
|
||||
r4 = r4 ^ r0; // 53 xor
|
||||
r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r7, 4); // 54 shfl
|
||||
r0 = rotr_var(r0, r1); // 55 rotr
|
||||
r5 = r5 ^ r3; // 56 xor
|
||||
r1 = r1 + r0 + ((((sel >> 8u) & 1u) != 0u) ? 0x1834af00u : 0x6f26b909u); // 57 add
|
||||
r6 = r6 ^ ds[r4 & mask]; // 58 load
|
||||
{ uint32_t b_ = (r7 & mask) & ~15u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint32_t x_ = r1 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r1 = x_; } // 59 load
|
||||
r1 = r1 ^ ds[r0 & mask]; // 60 load
|
||||
r4 = r4 ^ r7; // 61 xor
|
||||
r6 = r2 * r1 + r6; // 62 mad
|
||||
{ uint32_t b_ = (r2 & mask) & ~3u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint32_t x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r3 = x_; } // 63 load
|
||||
}
|
||||
uint32_t lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u);
|
||||
uint32_t hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u);
|
||||
out[gid] = ((uint64_t)hi << 32) | (uint64_t)lo;
|
||||
}
|
||||
|
||||
cudaError_t igneum_launch_hash_bound(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask,
|
||||
IgneumInitWords iw, uint32_t nonces, uint32_t blockWarps) {
|
||||
if (blockWarps == 0u || blockWarps > 32u) return cudaErrorInvalidValue;
|
||||
uint32_t block = 32u * blockWarps;
|
||||
if (nonces == 0u || (nonces % block) != 0u) return cudaErrorInvalidValue;
|
||||
igneum_hash_bound<<<nonces / block, block>>>(ds, out, baseNonce, mask, iw);
|
||||
return cudaGetLastError();
|
||||
}
|
||||
|
||||
cudaError_t igneum_hash_bound_info(int* numRegs, int* blocksPerSM, uint32_t blockWarps) {
|
||||
cudaFuncAttributes attr;
|
||||
cudaError_t e = cudaFuncGetAttributes(&attr, igneum_hash_bound);
|
||||
if (e != cudaSuccess) return e;
|
||||
*numRegs = attr.numRegs;
|
||||
return cudaOccupancyMaxActiveBlocksPerMultiprocessor(blocksPerSM, igneum_hash_bound, (int)(32u * blockWarps), 0);
|
||||
}
|
||||
108
proto-cuda/packs-readwidth/mixA-1/memhard.h
Normal file
108
proto-cuda/packs-readwidth/mixA-1/memhard.h
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
// Generated by igneum-pow export (generator v2) for seed "igneum-readwidth/A/1". Do not edit by hand.
|
||||
// Memory-hard dataset core, the same text that the Mac's Metal kernels and CPU verifier were checked against.
|
||||
// Included by kernel.cu (device), host.cu (host reference) and proto-opencl/host.c (C99 host reference).
|
||||
// See proto-metal/MEMHARD.md for the construction. kernel.cl carries the same text in OpenCL C.
|
||||
#pragma once
|
||||
#ifdef __cplusplus
|
||||
#include <cstdint>
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
#if defined(__CUDACC__)
|
||||
#define IGNEUM_HD __host__ __device__ __forceinline__
|
||||
#elif defined(_MSC_VER) && !defined(__cplusplus)
|
||||
#define IGNEUM_HD static __inline
|
||||
#else
|
||||
#define IGNEUM_HD static inline
|
||||
#endif
|
||||
// Memory-hard dataset core (MEMHARD.md). Cache: 2^26 words in 2^16 segments of 64 chained ChaCha12 lines.
|
||||
// Item: 8 rounds of seed-parameterised mixer + one 64-byte cache read, then a final mixer. All parameters are literals.
|
||||
#define MH_CACHE_LINE_MASK 0x003fffffu
|
||||
#define MH_SEGMENT_LINES 64u
|
||||
#define MH_QR(a, b, c, d, r1, r2, r3, r4) { a += b; d ^= a; d = mh_rotl(d, r1); c += d; b ^= c; b = mh_rotl(b, r2); a += b; d ^= a; d = mh_rotl(d, r3); c += d; b ^= c; b = mh_rotl(b, r4); }
|
||||
IGNEUM_HD uint32_t mh_rotl(uint32_t x, uint32_t n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 at every call site
|
||||
|
||||
// y = ChaCha12 core(x) + x
|
||||
IGNEUM_HD void mh_chacha_block(const uint32_t* x, uint32_t* y) {
|
||||
for (uint32_t i = 0u; i < 16u; ++i) y[i] = x[i];
|
||||
for (uint32_t r = 0u; r < 6u; ++r) {
|
||||
MH_QR(y[0], y[4], y[8], y[12], 16u, 12u, 8u, 7u) MH_QR(y[1], y[5], y[9], y[13], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[2], y[6], y[10], y[14], 16u, 12u, 8u, 7u) MH_QR(y[3], y[7], y[11], y[15], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[0], y[5], y[10], y[15], 16u, 12u, 8u, 7u) MH_QR(y[1], y[6], y[11], y[12], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[2], y[7], y[8], y[13], 16u, 12u, 8u, 7u) MH_QR(y[3], y[4], y[9], y[14], 16u, 12u, 8u, 7u)
|
||||
}
|
||||
for (uint32_t i = 0u; i < 16u; ++i) y[i] += x[i];
|
||||
}
|
||||
|
||||
// One cache segment: 64 chained lines written at cache[seg * 1024]. in_j = prev ^ (sigma || K || seg || j || tag), prev_0 = 0.
|
||||
IGNEUM_HD void mh_cache_segment(uint32_t* cache, uint32_t seg) {
|
||||
uint32_t prev[16]; uint32_t x[16]; uint32_t y[16];
|
||||
for (uint32_t i = 0u; i < 16u; ++i) prev[i] = 0u;
|
||||
for (uint32_t j = 0u; j < MH_SEGMENT_LINES; ++j) {
|
||||
x[0] = 0x61707865u ^ prev[0]; x[1] = 0x3320646eu ^ prev[1]; x[2] = 0x79622d32u ^ prev[2]; x[3] = 0x6b206574u ^ prev[3];
|
||||
x[4] = 0x3067619fu ^ prev[4];
|
||||
x[5] = 0x3c269176u ^ prev[5];
|
||||
x[6] = 0x84a03b03u ^ prev[6];
|
||||
x[7] = 0xf8c63294u ^ prev[7];
|
||||
x[8] = 0xff977c5bu ^ prev[8];
|
||||
x[9] = 0xe60def3eu ^ prev[9];
|
||||
x[10] = 0x63630141u ^ prev[10];
|
||||
x[11] = 0xb8fbcb58u ^ prev[11];
|
||||
x[12] = seg ^ prev[12]; x[13] = j ^ prev[13]; x[14] = 0x49676e65u ^ prev[14]; x[15] = 0x756d4d48u ^ prev[15];
|
||||
mh_chacha_block(x, y);
|
||||
uint32_t* line = cache + ((seg * MH_SEGMENT_LINES + j) * 16u);
|
||||
for (uint32_t i = 0u; i < 16u; ++i) { line[i] = y[i]; prev[i] = y[i]; }
|
||||
}
|
||||
}
|
||||
|
||||
// M_r: per word (s ^ (RC + rk)) * MUL, then a column round and a diagonal round with the seed-drawn rotations.
|
||||
IGNEUM_HD void mh_mixer(uint32_t* s, uint32_t rk) {
|
||||
s[0] = (s[0] ^ (0xbab68293u + rk)) * 0x42146205u;
|
||||
s[1] = (s[1] ^ (0xcc162340u + rk)) * 0x52cbe0fbu;
|
||||
s[2] = (s[2] ^ (0x6ce151ccu + rk)) * 0x7ecf4a03u;
|
||||
s[3] = (s[3] ^ (0xe62b8997u + rk)) * 0x6728907fu;
|
||||
s[4] = (s[4] ^ (0xc9c80297u + rk)) * 0xd81d9751u;
|
||||
s[5] = (s[5] ^ (0xf74a1654u + rk)) * 0x132952c3u;
|
||||
s[6] = (s[6] ^ (0x3d704af5u + rk)) * 0xf60de277u;
|
||||
s[7] = (s[7] ^ (0x3cf522b7u + rk)) * 0x05358035u;
|
||||
s[8] = (s[8] ^ (0x2b9cac04u + rk)) * 0xbaf6499du;
|
||||
s[9] = (s[9] ^ (0xa880ac10u + rk)) * 0xe4db9667u;
|
||||
s[10] = (s[10] ^ (0x13e5dd1du + rk)) * 0x3e98f45du;
|
||||
s[11] = (s[11] ^ (0x6fc3e233u + rk)) * 0xd0004eddu;
|
||||
s[12] = (s[12] ^ (0x2d83eeacu + rk)) * 0x2691630du;
|
||||
s[13] = (s[13] ^ (0x9006e8bfu + rk)) * 0x9beb3bcfu;
|
||||
s[14] = (s[14] ^ (0x2c4b5362u + rk)) * 0xab310379u;
|
||||
s[15] = (s[15] ^ (0x31b49ee2u + rk)) * 0x99cfb423u;
|
||||
MH_QR(s[0], s[4], s[8], s[12], 20u, 20u, 19u, 4u) MH_QR(s[1], s[5], s[9], s[13], 20u, 20u, 19u, 4u)
|
||||
MH_QR(s[2], s[6], s[10], s[14], 20u, 20u, 19u, 4u) MH_QR(s[3], s[7], s[11], s[15], 20u, 20u, 19u, 4u)
|
||||
MH_QR(s[0], s[5], s[10], s[15], 26u, 3u, 3u, 27u) MH_QR(s[1], s[6], s[11], s[12], 26u, 3u, 3u, 27u)
|
||||
MH_QR(s[2], s[7], s[8], s[13], 26u, 3u, 3u, 27u) MH_QR(s[3], s[4], s[9], s[14], 26u, 3u, 3u, 27u)
|
||||
}
|
||||
|
||||
// Item t: 16 words. s = (K, t * MUL[i] + RC[i]); 8 rounds of mixer + cache line s[0] & mask; final mixer.
|
||||
IGNEUM_HD void mh_item(const uint32_t* cache, uint32_t t, uint32_t* s) {
|
||||
s[0] = 0x3067619fu;
|
||||
s[1] = 0x3c269176u;
|
||||
s[2] = 0x84a03b03u;
|
||||
s[3] = 0xf8c63294u;
|
||||
s[4] = 0xff977c5bu;
|
||||
s[5] = 0xe60def3eu;
|
||||
s[6] = 0x63630141u;
|
||||
s[7] = 0xb8fbcb58u;
|
||||
s[8] = t * 0x42146205u + 0xbab68293u;
|
||||
s[9] = t * 0x52cbe0fbu + 0xcc162340u;
|
||||
s[10] = t * 0x7ecf4a03u + 0x6ce151ccu;
|
||||
s[11] = t * 0x6728907fu + 0xe62b8997u;
|
||||
s[12] = t * 0xd81d9751u + 0xc9c80297u;
|
||||
s[13] = t * 0x132952c3u + 0xf74a1654u;
|
||||
s[14] = t * 0xf60de277u + 0x3d704af5u;
|
||||
s[15] = t * 0x05358035u + 0x3cf522b7u;
|
||||
for (uint32_t r = 0u; r < 8u; ++r) {
|
||||
mh_mixer(s, 0x9E3779B9u * (r + 1u));
|
||||
const uint32_t* line = cache + ((s[0] & MH_CACHE_LINE_MASK) * 16u);
|
||||
for (uint32_t i = 0u; i < 16u; ++i) s[i] ^= line[i];
|
||||
}
|
||||
mh_mixer(s, 0x9E3779B9u * 9u);
|
||||
}
|
||||
// dataset[w] without the dataset: derive item w >> 4 and take word w & 15.
|
||||
IGNEUM_HD uint32_t mh_word(const uint32_t* cache, uint32_t w) { uint32_t s[16]; mh_item(cache, w >> 4u, s); return s[w & 15u]; }
|
||||
106
proto-cuda/packs-readwidth/mixA-1/memhard.metal
Normal file
106
proto-cuda/packs-readwidth/mixA-1/memhard.metal
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
#include <metal_stdlib>
|
||||
using namespace metal;
|
||||
// Memory-hard dataset core (MEMHARD.md). Cache: 2^26 words in 2^16 segments of 64 chained ChaCha12 lines.
|
||||
// Item: 8 rounds of seed-parameterised mixer + one 64-byte cache read, then a final mixer. All parameters are literals.
|
||||
#define MH_CACHE_LINE_MASK 0x003fffffu
|
||||
#define MH_SEGMENT_LINES 64u
|
||||
#define MH_QR(a, b, c, d, r1, r2, r3, r4) { a += b; d ^= a; d = mh_rotl(d, r1); c += d; b ^= c; b = mh_rotl(b, r2); a += b; d ^= a; d = mh_rotl(d, r3); c += d; b ^= c; b = mh_rotl(b, r4); }
|
||||
inline uint mh_rotl(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 at every call site
|
||||
|
||||
// y = ChaCha12 core(x) + x
|
||||
inline void mh_chacha_block(const thread uint* x, thread uint* y) {
|
||||
for (uint i = 0u; i < 16u; ++i) y[i] = x[i];
|
||||
for (uint r = 0u; r < 6u; ++r) {
|
||||
MH_QR(y[0], y[4], y[8], y[12], 16u, 12u, 8u, 7u) MH_QR(y[1], y[5], y[9], y[13], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[2], y[6], y[10], y[14], 16u, 12u, 8u, 7u) MH_QR(y[3], y[7], y[11], y[15], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[0], y[5], y[10], y[15], 16u, 12u, 8u, 7u) MH_QR(y[1], y[6], y[11], y[12], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[2], y[7], y[8], y[13], 16u, 12u, 8u, 7u) MH_QR(y[3], y[4], y[9], y[14], 16u, 12u, 8u, 7u)
|
||||
}
|
||||
for (uint i = 0u; i < 16u; ++i) y[i] += x[i];
|
||||
}
|
||||
|
||||
// One cache segment: 64 chained lines written at cache[seg * 1024]. in_j = prev ^ (sigma || K || seg || j || tag), prev_0 = 0.
|
||||
inline void mh_cache_segment(device uint* cache, uint seg) {
|
||||
uint prev[16]; uint x[16]; uint y[16];
|
||||
for (uint i = 0u; i < 16u; ++i) prev[i] = 0u;
|
||||
for (uint j = 0u; j < MH_SEGMENT_LINES; ++j) {
|
||||
x[0] = 0x61707865u ^ prev[0]; x[1] = 0x3320646eu ^ prev[1]; x[2] = 0x79622d32u ^ prev[2]; x[3] = 0x6b206574u ^ prev[3];
|
||||
x[4] = 0x3067619fu ^ prev[4];
|
||||
x[5] = 0x3c269176u ^ prev[5];
|
||||
x[6] = 0x84a03b03u ^ prev[6];
|
||||
x[7] = 0xf8c63294u ^ prev[7];
|
||||
x[8] = 0xff977c5bu ^ prev[8];
|
||||
x[9] = 0xe60def3eu ^ prev[9];
|
||||
x[10] = 0x63630141u ^ prev[10];
|
||||
x[11] = 0xb8fbcb58u ^ prev[11];
|
||||
x[12] = seg ^ prev[12]; x[13] = j ^ prev[13]; x[14] = 0x49676e65u ^ prev[14]; x[15] = 0x756d4d48u ^ prev[15];
|
||||
mh_chacha_block(x, y);
|
||||
device uint* line = cache + ((seg * MH_SEGMENT_LINES + j) * 16u);
|
||||
for (uint i = 0u; i < 16u; ++i) { line[i] = y[i]; prev[i] = y[i]; }
|
||||
}
|
||||
}
|
||||
|
||||
// M_r: per word (s ^ (RC + rk)) * MUL, then a column round and a diagonal round with the seed-drawn rotations.
|
||||
inline void mh_mixer(thread uint* s, uint rk) {
|
||||
s[0] = (s[0] ^ (0xbab68293u + rk)) * 0x42146205u;
|
||||
s[1] = (s[1] ^ (0xcc162340u + rk)) * 0x52cbe0fbu;
|
||||
s[2] = (s[2] ^ (0x6ce151ccu + rk)) * 0x7ecf4a03u;
|
||||
s[3] = (s[3] ^ (0xe62b8997u + rk)) * 0x6728907fu;
|
||||
s[4] = (s[4] ^ (0xc9c80297u + rk)) * 0xd81d9751u;
|
||||
s[5] = (s[5] ^ (0xf74a1654u + rk)) * 0x132952c3u;
|
||||
s[6] = (s[6] ^ (0x3d704af5u + rk)) * 0xf60de277u;
|
||||
s[7] = (s[7] ^ (0x3cf522b7u + rk)) * 0x05358035u;
|
||||
s[8] = (s[8] ^ (0x2b9cac04u + rk)) * 0xbaf6499du;
|
||||
s[9] = (s[9] ^ (0xa880ac10u + rk)) * 0xe4db9667u;
|
||||
s[10] = (s[10] ^ (0x13e5dd1du + rk)) * 0x3e98f45du;
|
||||
s[11] = (s[11] ^ (0x6fc3e233u + rk)) * 0xd0004eddu;
|
||||
s[12] = (s[12] ^ (0x2d83eeacu + rk)) * 0x2691630du;
|
||||
s[13] = (s[13] ^ (0x9006e8bfu + rk)) * 0x9beb3bcfu;
|
||||
s[14] = (s[14] ^ (0x2c4b5362u + rk)) * 0xab310379u;
|
||||
s[15] = (s[15] ^ (0x31b49ee2u + rk)) * 0x99cfb423u;
|
||||
MH_QR(s[0], s[4], s[8], s[12], 20u, 20u, 19u, 4u) MH_QR(s[1], s[5], s[9], s[13], 20u, 20u, 19u, 4u)
|
||||
MH_QR(s[2], s[6], s[10], s[14], 20u, 20u, 19u, 4u) MH_QR(s[3], s[7], s[11], s[15], 20u, 20u, 19u, 4u)
|
||||
MH_QR(s[0], s[5], s[10], s[15], 26u, 3u, 3u, 27u) MH_QR(s[1], s[6], s[11], s[12], 26u, 3u, 3u, 27u)
|
||||
MH_QR(s[2], s[7], s[8], s[13], 26u, 3u, 3u, 27u) MH_QR(s[3], s[4], s[9], s[14], 26u, 3u, 3u, 27u)
|
||||
}
|
||||
|
||||
// Item t: 16 words. s = (K, t * MUL[i] + RC[i]); 8 rounds of mixer + cache line s[0] & mask; final mixer.
|
||||
inline void mh_item(device const uint* cache, uint t, thread uint* s) {
|
||||
s[0] = 0x3067619fu;
|
||||
s[1] = 0x3c269176u;
|
||||
s[2] = 0x84a03b03u;
|
||||
s[3] = 0xf8c63294u;
|
||||
s[4] = 0xff977c5bu;
|
||||
s[5] = 0xe60def3eu;
|
||||
s[6] = 0x63630141u;
|
||||
s[7] = 0xb8fbcb58u;
|
||||
s[8] = t * 0x42146205u + 0xbab68293u;
|
||||
s[9] = t * 0x52cbe0fbu + 0xcc162340u;
|
||||
s[10] = t * 0x7ecf4a03u + 0x6ce151ccu;
|
||||
s[11] = t * 0x6728907fu + 0xe62b8997u;
|
||||
s[12] = t * 0xd81d9751u + 0xc9c80297u;
|
||||
s[13] = t * 0x132952c3u + 0xf74a1654u;
|
||||
s[14] = t * 0xf60de277u + 0x3d704af5u;
|
||||
s[15] = t * 0x05358035u + 0x3cf522b7u;
|
||||
for (uint r = 0u; r < 8u; ++r) {
|
||||
mh_mixer(s, 0x9E3779B9u * (r + 1u));
|
||||
device const uint* line = cache + ((s[0] & MH_CACHE_LINE_MASK) * 16u);
|
||||
for (uint i = 0u; i < 16u; ++i) s[i] ^= line[i];
|
||||
}
|
||||
mh_mixer(s, 0x9E3779B9u * 9u);
|
||||
}
|
||||
// dataset[w] without the dataset: derive item w >> 4 and take word w & 15.
|
||||
inline uint mh_word(device const uint* cache, uint w) { uint s[16]; mh_item(cache, w >> 4u, s); return s[w & 15u]; }
|
||||
|
||||
// One thread per segment (2^16 threads).
|
||||
kernel void igneum_cache_fill(device uint* cache [[buffer(0)]], uint gid [[thread_position_in_grid]]) {
|
||||
mh_cache_segment(cache, gid);
|
||||
}
|
||||
// One thread per 64-byte item (dataset words / 16 threads).
|
||||
kernel void igneum_build(device const uint* cache [[buffer(0)]], device uint* dataset [[buffer(1)]],
|
||||
uint gid [[thread_position_in_grid]]) {
|
||||
uint s[16];
|
||||
mh_item(cache, gid, s);
|
||||
device uint* d = dataset + gid * 16u;
|
||||
for (uint i = 0u; i < 16u; ++i) d[i] = s[i];
|
||||
}
|
||||
60
proto-cuda/packs-readwidth/mixA-1/program.h
Normal file
60
proto-cuda/packs-readwidth/mixA-1/program.h
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
// Generated by igneum-pow export (generator v2) for seed "igneum-readwidth/A/1". Do not edit by hand.
|
||||
// Program metadata for host.cu plus the launch wrappers defined in kernel.cu.
|
||||
// Also included by proto-opencl/host.c (C99), which defines IGNEUM_NO_CUDA first and reads only the macros.
|
||||
#pragma once
|
||||
#ifdef __cplusplus
|
||||
#include <cstdint>
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
#ifndef IGNEUM_NO_CUDA
|
||||
#include <cuda_runtime.h>
|
||||
#endif
|
||||
|
||||
#define IGNEUM_SEED_STRING "igneum-readwidth/A/1"
|
||||
#define IGNEUM_SEED_BYTES_HEX "69676e65756d2d7265616477696474682f412f31"
|
||||
#define IGNEUM_GENERATOR 2
|
||||
#define IGNEUM_PROGRAM_ATTEMPT 0
|
||||
#define IGNEUM_PROGRAM_ID 0x6408f2e28fdd344cull
|
||||
#define IGNEUM_DAY_STRING "2026-10-03"
|
||||
#define IGNEUM_DAY_BYTES_HEX "6461792f323032362d31302d3033"
|
||||
#define IGNEUM_DAY0 0x3067619fu
|
||||
#define IGNEUM_DAY1 0x3c269176u
|
||||
#define IGNEUM_DATASET_LOG2 28
|
||||
#define IGNEUM_MASK 0x0fffffffu
|
||||
#define IGNEUM_LANES 32
|
||||
#define IGNEUM_ITERATIONS 8
|
||||
#define IGNEUM_INSTR_COUNT 64
|
||||
#define IGNEUM_LOADS_PER_HASH 128
|
||||
#define IGNEUM_WIDE_LOADS_PER_HASH 0
|
||||
#define IGNEUM_OP_MIX "load=16 add=12 shfl=9 xor=8 mad=5 mul=5 rotr=4 rotl=3 or=1 sub=1"
|
||||
// Read-width experiment (5 October 2026, docs/plans/read-width.md): NOT the lottery hash. A load of W words reads
|
||||
// the W-word-aligned address and folds every word into dst: x = dst ^ w[0]; x = (rotl(x, 11) * 0x9e3779b1) ^ w[j]; dst = x.
|
||||
#define IGNEUM_LOAD_CLASS "mix50-35-15"
|
||||
#define IGNEUM_LOAD_SLOTS 16
|
||||
#define IGNEUM_LOAD_MIX { 50, 35, 15 }
|
||||
#define IGNEUM_LOAD_WIDTH_COUNTS { 10, 4, 2 } // loads of 4, 16, 64 bytes per program
|
||||
#define IGNEUM_BYTES_PER_HASH 1856
|
||||
#define IGNEUM_FOLD_ROT 11
|
||||
#define IGNEUM_FOLD_MUL 0x9e3779b1u
|
||||
// 0 = closed-form dataset (ds_elem), 1 = memory-hard cache construction (MEMHARD.md, memhard.h)
|
||||
#define IGNEUM_DATASET_MODE 1
|
||||
|
||||
#define IGNEUM_SEEDW_INIT { 0xa7198abfu, 0x6cd0f8cfu, 0xe4ef8ebfu, 0x03ee1e65u, 0xcfcfc5c0u, 0x82e9e19bu, 0x5d7a8a2fu, 0xfafccd93u }
|
||||
#define IGNEUM_KEY_INIT { 0x3067619fu, 0x3c269176u, 0x84a03b03u, 0xf8c63294u, 0xff977c5bu, 0xe60def3eu, 0x63630141u, 0xb8fbcb58u }
|
||||
#define IGNEUM_CACHE_LOG2_WORDS 26
|
||||
#define IGNEUM_CACHE_SEGMENT_LOG2_LINES 6
|
||||
#define IGNEUM_CACHE_SEGMENTS 65536u
|
||||
#define IGNEUM_ITEM_ROUNDS 8
|
||||
#define IGNEUM_MIX_ROT_INIT { 20u, 20u, 19u, 4u, 26u, 3u, 3u, 27u }
|
||||
#define IGNEUM_MIX_MUL_INIT { 0x42146205u, 0x52cbe0fbu, 0x7ecf4a03u, 0x6728907fu, 0xd81d9751u, 0x132952c3u, 0xf60de277u, 0x05358035u, 0xbaf6499du, 0xe4db9667u, 0x3e98f45du, 0xd0004eddu, 0x2691630du, 0x9beb3bcfu, 0xab310379u, 0x99cfb423u }
|
||||
#define IGNEUM_MIX_RC_INIT { 0xbab68293u, 0xcc162340u, 0x6ce151ccu, 0xe62b8997u, 0xc9c80297u, 0xf74a1654u, 0x3d704af5u, 0x3cf522b7u, 0x2b9cac04u, 0xa880ac10u, 0x13e5dd1du, 0x6fc3e233u, 0x2d83eeacu, 0x9006e8bfu, 0x2c4b5362u, 0x31b49ee2u }
|
||||
|
||||
#ifndef IGNEUM_NO_CUDA
|
||||
// Defined in kernel.cu. All launch on the default stream and return cudaGetLastError().
|
||||
cudaError_t igneum_launch_cache_fill(uint32_t* cache, uint32_t nSegments);
|
||||
cudaError_t igneum_launch_build(uint32_t* ds, const uint32_t* cache, uint32_t nItems);
|
||||
cudaError_t igneum_launch_hash(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask,
|
||||
uint32_t nonces, uint32_t blockWarps);
|
||||
cudaError_t igneum_hash_info(int* numRegs, int* blocksPerSM, uint32_t blockWarps);
|
||||
#endif
|
||||
127
proto-cuda/packs-readwidth/mixA-1/program.json
Normal file
127
proto-cuda/packs-readwidth/mixA-1/program.json
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
{
|
||||
"format": "igneum-program-pack-3",
|
||||
"generator": 2,
|
||||
"attempt": 0,
|
||||
"program_id": "0x6408f2e28fdd344c",
|
||||
"program_id_derivation": "FNV-1a 64 over 'igneum-program/' || generator_le32 || seed_words as little-endian bytes || attempt_le32",
|
||||
"dataset_mode": "memory-hard",
|
||||
"seed": "igneum-readwidth/A/1",
|
||||
"seed_bytes": "69676e65756d2d7265616477696474682f412f31",
|
||||
"seed_words": ["0xa7198abf", "0x6cd0f8cf", "0xe4ef8ebf", "0x03ee1e65", "0xcfcfc5c0", "0x82e9e19b", "0x5d7a8a2f", "0xfafccd93"],
|
||||
"seed_derivation": "seed_words = FNV-1a 64 over seed_bytes (attempt 0) or seed_bytes || attempt_le32 (attempt k >= 1), basis ^ (salt * 0x9E3779B97F4A7C15) for salt 0..3, then h ^= h>>33; h *= 0xff51afd7ed558ccd; h ^= h>>33; words[2*salt] = low 32, words[2*salt+1] = high 32",
|
||||
"generator_rule": "version 2: exactly 16 load slots drawn first from instructions 1..63 (partial Fisher-Yates), the other 48 ops from the ten non-load weights (sum 75); a load's source is drawn from the registers other than dst written by an earlier instruction and not read by a load since; the candidate must pass the acceptance rule of spec 01 section 1.4.6 (static: no cyclically stale load source, every register has an injecting write; dynamic: 64 units on the seed-keyed closed-form dataset with no constant register bit, no lane-constant load site, under 164 saturated final values, every output bit within 136 of 1024, distinct addresses above 245760), else the next attempt of the seed is tried",
|
||||
"lanes": 32,
|
||||
"registers": 8,
|
||||
"iterations": 8,
|
||||
"instruction_count": 64,
|
||||
"loads_per_hash": 128,
|
||||
"load_class": "mix50-35-15",
|
||||
"load_slots": 16,
|
||||
"load_mix_percent_4_16_64": [50, 35, 15],
|
||||
"load_width_counts_4_16_64": [10, 4, 2],
|
||||
"bytes_per_hash": 1856,
|
||||
"wide_load": "read-width experiment (5 October 2026, docs/plans/read-width.md), NOT the lottery hash: a load of W words (width field, 4 or 16) reads dataset[b .. b + W) with b = (src & mask) & ~(W - 1) and folds every word into dst: x = dst ^ w[0]; for j in 1..W: x = (rotl(x, 11) * 0x9e3779b1) ^ w[j]; dst = x; width 1 is the plain load; the width is drawn per instruction from the class mix with one extra below(100) draw after the nine of version 2, and the program id is FNV-1a 64 over 'igneum-program-rw/' || generator_le32 || seed words || attempt_le32 || mix[3] || load_slots",
|
||||
"op_mix": {"load": 16, "add": 12, "shfl": 9, "xor": 8, "mad": 5, "mul": 5, "rotr": 4, "rotl": 3, "or": 1, "sub": 1},
|
||||
"register_init": "for i in 0..7: x = nonce ^ seed_words[i]; x += 0x9e3779b9 * (i+1) (mod 2^32); x = splitmix32(x); r[i] = x ^ seed_words[(i+1) & 7]",
|
||||
"splitmix32": "x ^= x>>16; x *= 0x7feb352d; x ^= x>>15; x *= 0x846ca68b; x ^= x>>16",
|
||||
"iteration": "sel = r0 sampled once at the top of each iteration, then all instructions in order",
|
||||
"output": "lo = r0 ^ rotl(r1,7) ^ rotl(r2,14) ^ rotl(r3,21); hi = r4 ^ rotl(r5,9) ^ rotl(r6,18) ^ rotl(r7,27); out = (hi << 32) | lo",
|
||||
"op_semantics": {
|
||||
"add": "dst = dst + src + (bit `bit` of sel ? imm2 : imm)",
|
||||
"sub": "dst = dst - src",
|
||||
"mul": "dst = dst * src (low 32)",
|
||||
"mulhi": "dst = high 32 bits of dst * src",
|
||||
"xor": "dst = dst ^ src",
|
||||
"or": "dst = dst | src",
|
||||
"rotl": "dst = rotl(dst, rot), rot in 1..31",
|
||||
"rotr": "dst = rotr(dst, src & 31)",
|
||||
"mad": "dst = src * src2 + dst",
|
||||
"shfl": "dst = dst ^ (src of lane (lane ^ mask)), mask in {1,2,4,8,16}, within the 32-lane warp",
|
||||
"load": "dst = dst ^ dataset[src & dataset.mask]",
|
||||
"wload": "base = (src of lane 0 & dataset.mask) & ~31; dst = dst ^ dataset[base + lane] (warp-coalesced 128-byte load, lever b, only when --wide-frac > 0)"
|
||||
},
|
||||
"dataset": {
|
||||
"log2_words": 28,
|
||||
"bytes": 1073741824,
|
||||
"mask": "0x0fffffff",
|
||||
"day": "2026-10-03",
|
||||
"day_bytes": "6461792f323032362d31302d3033",
|
||||
"day_words_from": "seed_words_from_bytes(day_bytes)",
|
||||
"d0": "0x3067619f",
|
||||
"d1": "0x3c269176",
|
||||
"mode": "memory-hard",
|
||||
"spec": "proto-metal/MEMHARD.md",
|
||||
"key": ["0x3067619f", "0x3c269176", "0x84a03b03", "0xf8c63294", "0xff977c5b", "0xe60def3e", "0x63630141", "0xb8fbcb58"],
|
||||
"key_derivation": "the 8 words of seed_words_from_bytes(day_bytes); d0, d1 are key[0], key[1]",
|
||||
"cache": {"log2_words": 26, "bytes": 268435456, "line_words": 16, "segment_lines": 64, "segments": 65536, "block": "ChaCha12 core + feed-forward, rotations 16 12 8 7", "sigma": ["0x61707865", "0x3320646e", "0x79622d32", "0x6b206574"], "tag": ["0x49676e65", "0x756d4d48"], "chain": "in_j = prev_line ^ (sigma[0..3] || key[0..7] || seg || j || tag[0..1]); line_j = block(in_j); prev_0 = 0"},
|
||||
"mixer": {"draw": "SplitMix64 seeded with key[0] | key[1] << 32: rot[0..7] = 1 + next() % 31, mul[0..15] = low32(next()) | 1, rc[0..15] = low32(next())", "rot": [20, 20, 19, 4, 26, 3, 3, 27], "mul": ["0x42146205", "0x52cbe0fb", "0x7ecf4a03", "0x6728907f", "0xd81d9751", "0x132952c3", "0xf60de277", "0x05358035", "0xbaf6499d", "0xe4db9667", "0x3e98f45d", "0xd0004edd", "0x2691630d", "0x9beb3bcf", "0xab310379", "0x99cfb423"], "rc": ["0xbab68293", "0xcc162340", "0x6ce151cc", "0xe62b8997", "0xc9c80297", "0xf74a1654", "0x3d704af5", "0x3cf522b7", "0x2b9cac04", "0xa880ac10", "0x13e5dd1d", "0x6fc3e233", "0x2d83eeac", "0x9006e8bf", "0x2c4b5362", "0x31b49ee2"], "round": "for i in 0..15: s[i] = (s[i] ^ (rc[i] + (r+1) * 0x9E3779B9)) * mul[i]; then quarter rounds on columns (0,4,8,12) (1,5,9,13) (2,6,10,14) (3,7,11,15) with rot[0..3] and diagonals (0,5,10,15) (1,6,11,12) (2,7,8,13) (3,4,9,14) with rot[4..7]", "quarter_round": "a += b; d ^= a; d = rotl(d, r1); c += d; b ^= c; b = rotl(b, r2); a += b; d ^= a; d = rotl(d, r3); c += d; b ^= c; b = rotl(b, r4)"},
|
||||
"item": "s[0..7] = key; s[8+i] = t * mul[i] + rc[i] for i in 0..7; for r in 0..7: s = M_r(s); line = s[0] & 0x003fffff; s[i] ^= cache[line * 16 + i]; then s = M_8(s); item(t) = s",
|
||||
"word": "dataset[w] = item(w >> 4)[w & 15]"
|
||||
},
|
||||
"instructions": [
|
||||
{"i": 0, "op": "add", "dst": 4, "src": 3, "src2": 4, "imm": "0x4a4c6caa", "imm2": "0x5b2d5fe3", "rot": 28, "bit": 8, "mask": 1, "width": 1},
|
||||
{"i": 1, "op": "or", "dst": 7, "src": 6, "src2": 0, "imm": "0x8c4c9f7c", "imm2": "0x3b47c42a", "rot": 3, "bit": 13, "mask": 8, "width": 1},
|
||||
{"i": 2, "op": "mul", "dst": 2, "src": 7, "src2": 1, "imm": "0xe7cf827b", "imm2": "0x786c6890", "rot": 24, "bit": 25, "mask": 8, "width": 1},
|
||||
{"i": 3, "op": "shfl", "dst": 5, "src": 1, "src2": 6, "imm": "0xa686f6b7", "imm2": "0x48920bc0", "rot": 1, "bit": 5, "mask": 2, "width": 1},
|
||||
{"i": 4, "op": "xor", "dst": 4, "src": 6, "src2": 1, "imm": "0x58489525", "imm2": "0x1c56b23f", "rot": 25, "bit": 21, "mask": 1, "width": 1},
|
||||
{"i": 5, "op": "load", "dst": 0, "src": 4, "src2": 6, "imm": "0xacf5203a", "imm2": "0x76e3d8a1", "rot": 22, "bit": 20, "mask": 1, "width": 1},
|
||||
{"i": 6, "op": "rotl", "dst": 3, "src": 1, "src2": 6, "imm": "0x2507e906", "imm2": "0xf9c5c1f1", "rot": 17, "bit": 11, "mask": 4, "width": 1},
|
||||
{"i": 7, "op": "add", "dst": 1, "src": 4, "src2": 3, "imm": "0xaeb38cc5", "imm2": "0x83aa2c52", "rot": 10, "bit": 27, "mask": 4, "width": 1},
|
||||
{"i": 8, "op": "rotl", "dst": 1, "src": 2, "src2": 4, "imm": "0x261b9557", "imm2": "0xe0df5769", "rot": 31, "bit": 30, "mask": 8, "width": 1},
|
||||
{"i": 9, "op": "xor", "dst": 4, "src": 7, "src2": 1, "imm": "0x8f733ec9", "imm2": "0x468afd76", "rot": 3, "bit": 1, "mask": 2, "width": 1},
|
||||
{"i": 10, "op": "load", "dst": 6, "src": 0, "src2": 1, "imm": "0x53eef18d", "imm2": "0x763b1f0a", "rot": 20, "bit": 20, "mask": 4, "width": 4},
|
||||
{"i": 11, "op": "load", "dst": 0, "src": 6, "src2": 4, "imm": "0xa2f22f71", "imm2": "0xe0a8243e", "rot": 20, "bit": 30, "mask": 1, "width": 4},
|
||||
{"i": 12, "op": "shfl", "dst": 5, "src": 2, "src2": 6, "imm": "0x88827407", "imm2": "0xe9f1befa", "rot": 10, "bit": 11, "mask": 1, "width": 1},
|
||||
{"i": 13, "op": "shfl", "dst": 1, "src": 4, "src2": 7, "imm": "0x88867e60", "imm2": "0x2726b465", "rot": 9, "bit": 6, "mask": 2, "width": 1},
|
||||
{"i": 14, "op": "mul", "dst": 5, "src": 7, "src2": 2, "imm": "0x41530f45", "imm2": "0xf0badd76", "rot": 1, "bit": 13, "mask": 1, "width": 1},
|
||||
{"i": 15, "op": "xor", "dst": 3, "src": 0, "src2": 6, "imm": "0x29e41472", "imm2": "0xd2c1de0c", "rot": 22, "bit": 5, "mask": 16, "width": 1},
|
||||
{"i": 16, "op": "mul", "dst": 5, "src": 4, "src2": 4, "imm": "0xafa3d0bd", "imm2": "0x1568e384", "rot": 19, "bit": 20, "mask": 2, "width": 1},
|
||||
{"i": 17, "op": "shfl", "dst": 2, "src": 0, "src2": 6, "imm": "0xffccd357", "imm2": "0x4b21f8cf", "rot": 3, "bit": 6, "mask": 4, "width": 1},
|
||||
{"i": 18, "op": "add", "dst": 4, "src": 1, "src2": 3, "imm": "0x87d3a998", "imm2": "0xfb36bdda", "rot": 29, "bit": 31, "mask": 4, "width": 1},
|
||||
{"i": 19, "op": "add", "dst": 0, "src": 1, "src2": 0, "imm": "0x88921092", "imm2": "0xf2ef7076", "rot": 20, "bit": 22, "mask": 2, "width": 1},
|
||||
{"i": 20, "op": "add", "dst": 6, "src": 1, "src2": 4, "imm": "0x35e06b74", "imm2": "0xe42e69c6", "rot": 3, "bit": 3, "mask": 2, "width": 1},
|
||||
{"i": 21, "op": "shfl", "dst": 2, "src": 5, "src2": 0, "imm": "0xa7323c7a", "imm2": "0x81d43278", "rot": 16, "bit": 10, "mask": 8, "width": 1},
|
||||
{"i": 22, "op": "add", "dst": 3, "src": 6, "src2": 2, "imm": "0x74df5734", "imm2": "0xb45d9671", "rot": 26, "bit": 3, "mask": 2, "width": 1},
|
||||
{"i": 23, "op": "shfl", "dst": 5, "src": 4, "src2": 2, "imm": "0x1e0660fe", "imm2": "0x13c7e83f", "rot": 13, "bit": 15, "mask": 8, "width": 1},
|
||||
{"i": 24, "op": "load", "dst": 4, "src": 2, "src2": 2, "imm": "0x68bfe9f0", "imm2": "0x2067c339", "rot": 5, "bit": 11, "mask": 1, "width": 1},
|
||||
{"i": 25, "op": "xor", "dst": 2, "src": 1, "src2": 3, "imm": "0x383e819c", "imm2": "0xef4f43f5", "rot": 2, "bit": 25, "mask": 2, "width": 1},
|
||||
{"i": 26, "op": "mul", "dst": 7, "src": 6, "src2": 4, "imm": "0x45892e5e", "imm2": "0x5c358e4b", "rot": 13, "bit": 9, "mask": 1, "width": 1},
|
||||
{"i": 27, "op": "load", "dst": 2, "src": 3, "src2": 2, "imm": "0x8fe1d831", "imm2": "0xe2f0a7df", "rot": 18, "bit": 5, "mask": 16, "width": 16},
|
||||
{"i": 28, "op": "rotl", "dst": 3, "src": 4, "src2": 4, "imm": "0x78e2bf43", "imm2": "0x723070c4", "rot": 29, "bit": 6, "mask": 2, "width": 1},
|
||||
{"i": 29, "op": "shfl", "dst": 3, "src": 0, "src2": 3, "imm": "0x6a40f0ce", "imm2": "0x8f751dd0", "rot": 26, "bit": 12, "mask": 8, "width": 1},
|
||||
{"i": 30, "op": "load", "dst": 1, "src": 4, "src2": 6, "imm": "0x3bcdf182", "imm2": "0x5ec397eb", "rot": 5, "bit": 24, "mask": 16, "width": 1},
|
||||
{"i": 31, "op": "sub", "dst": 4, "src": 6, "src2": 5, "imm": "0x28631d4e", "imm2": "0x1c8b6e91", "rot": 2, "bit": 13, "mask": 4, "width": 1},
|
||||
{"i": 32, "op": "mul", "dst": 2, "src": 4, "src2": 4, "imm": "0xf8b83d3f", "imm2": "0x6bbab3d3", "rot": 3, "bit": 19, "mask": 1, "width": 1},
|
||||
{"i": 33, "op": "mad", "dst": 4, "src": 3, "src2": 3, "imm": "0xdf39e98a", "imm2": "0x1c4dbde8", "rot": 8, "bit": 17, "mask": 2, "width": 1},
|
||||
{"i": 34, "op": "add", "dst": 0, "src": 6, "src2": 4, "imm": "0x19318d72", "imm2": "0x97d2762d", "rot": 14, "bit": 15, "mask": 16, "width": 1},
|
||||
{"i": 35, "op": "add", "dst": 7, "src": 1, "src2": 1, "imm": "0x26b63296", "imm2": "0x79830ead", "rot": 26, "bit": 19, "mask": 16, "width": 1},
|
||||
{"i": 36, "op": "load", "dst": 7, "src": 2, "src2": 2, "imm": "0xf2fe58f7", "imm2": "0x3813073a", "rot": 19, "bit": 7, "mask": 2, "width": 1},
|
||||
{"i": 37, "op": "rotr", "dst": 0, "src": 7, "src2": 7, "imm": "0x268c32f9", "imm2": "0x1f02f30a", "rot": 20, "bit": 10, "mask": 1, "width": 1},
|
||||
{"i": 38, "op": "add", "dst": 2, "src": 7, "src2": 1, "imm": "0xb228dc81", "imm2": "0x23c8dec4", "rot": 14, "bit": 28, "mask": 4, "width": 1},
|
||||
{"i": 39, "op": "load", "dst": 0, "src": 5, "src2": 6, "imm": "0x08c2fe36", "imm2": "0xa232fa5b", "rot": 22, "bit": 13, "mask": 16, "width": 1},
|
||||
{"i": 40, "op": "shfl", "dst": 7, "src": 5, "src2": 4, "imm": "0x8601d298", "imm2": "0x04a37e40", "rot": 27, "bit": 21, "mask": 2, "width": 1},
|
||||
{"i": 41, "op": "mad", "dst": 5, "src": 0, "src2": 1, "imm": "0xc0112c85", "imm2": "0xcae01ef3", "rot": 16, "bit": 5, "mask": 4, "width": 1},
|
||||
{"i": 42, "op": "xor", "dst": 2, "src": 3, "src2": 1, "imm": "0x19f77b37", "imm2": "0x0952e878", "rot": 28, "bit": 23, "mask": 4, "width": 1},
|
||||
{"i": 43, "op": "load", "dst": 7, "src": 0, "src2": 6, "imm": "0x020804cf", "imm2": "0x9eb73dda", "rot": 30, "bit": 2, "mask": 1, "width": 1},
|
||||
{"i": 44, "op": "load", "dst": 0, "src": 5, "src2": 6, "imm": "0x485a8a15", "imm2": "0xdeac555a", "rot": 13, "bit": 21, "mask": 8, "width": 4},
|
||||
{"i": 45, "op": "add", "dst": 2, "src": 7, "src2": 0, "imm": "0xcc64df8e", "imm2": "0x5a3a7fe1", "rot": 18, "bit": 22, "mask": 8, "width": 1},
|
||||
{"i": 46, "op": "rotr", "dst": 0, "src": 5, "src2": 5, "imm": "0xe6e78bd9", "imm2": "0x5c932006", "rot": 31, "bit": 20, "mask": 2, "width": 1},
|
||||
{"i": 47, "op": "rotr", "dst": 3, "src": 7, "src2": 4, "imm": "0xa77d4cb5", "imm2": "0x32f2b544", "rot": 15, "bit": 16, "mask": 8, "width": 1},
|
||||
{"i": 48, "op": "mad", "dst": 2, "src": 7, "src2": 6, "imm": "0x197fc3bf", "imm2": "0x02536a02", "rot": 3, "bit": 5, "mask": 16, "width": 1},
|
||||
{"i": 49, "op": "mad", "dst": 6, "src": 3, "src2": 5, "imm": "0x6aa6ad47", "imm2": "0x0f1c2695", "rot": 6, "bit": 31, "mask": 8, "width": 1},
|
||||
{"i": 50, "op": "load", "dst": 1, "src": 6, "src2": 1, "imm": "0x106ee155", "imm2": "0x6e409245", "rot": 29, "bit": 22, "mask": 2, "width": 1},
|
||||
{"i": 51, "op": "load", "dst": 7, "src": 1, "src2": 0, "imm": "0xc604b17f", "imm2": "0x7ba442ad", "rot": 8, "bit": 27, "mask": 1, "width": 1},
|
||||
{"i": 52, "op": "add", "dst": 3, "src": 4, "src2": 3, "imm": "0x7a646d78", "imm2": "0xcba22643", "rot": 1, "bit": 6, "mask": 2, "width": 1},
|
||||
{"i": 53, "op": "xor", "dst": 4, "src": 0, "src2": 1, "imm": "0x0c951e55", "imm2": "0xe4242078", "rot": 10, "bit": 14, "mask": 4, "width": 1},
|
||||
{"i": 54, "op": "shfl", "dst": 3, "src": 7, "src2": 5, "imm": "0x1e8e8986", "imm2": "0xcc7c23e9", "rot": 26, "bit": 11, "mask": 4, "width": 1},
|
||||
{"i": 55, "op": "rotr", "dst": 0, "src": 1, "src2": 1, "imm": "0x384aa1de", "imm2": "0x03bd71f3", "rot": 7, "bit": 27, "mask": 16, "width": 1},
|
||||
{"i": 56, "op": "xor", "dst": 5, "src": 3, "src2": 6, "imm": "0x0f3bbfb3", "imm2": "0x829b8b8d", "rot": 15, "bit": 3, "mask": 4, "width": 1},
|
||||
{"i": 57, "op": "add", "dst": 1, "src": 0, "src2": 0, "imm": "0x6f26b909", "imm2": "0x1834af00", "rot": 28, "bit": 8, "mask": 2, "width": 1},
|
||||
{"i": 58, "op": "load", "dst": 6, "src": 4, "src2": 2, "imm": "0x6bcbd615", "imm2": "0xadbaf0ef", "rot": 3, "bit": 4, "mask": 8, "width": 1},
|
||||
{"i": 59, "op": "load", "dst": 1, "src": 7, "src2": 1, "imm": "0x79dc0a3f", "imm2": "0x436e360d", "rot": 30, "bit": 13, "mask": 8, "width": 16},
|
||||
{"i": 60, "op": "load", "dst": 1, "src": 0, "src2": 2, "imm": "0x30cd5237", "imm2": "0x8bd46148", "rot": 22, "bit": 29, "mask": 1, "width": 1},
|
||||
{"i": 61, "op": "xor", "dst": 4, "src": 7, "src2": 4, "imm": "0x74419ddb", "imm2": "0x70d9f3d5", "rot": 3, "bit": 26, "mask": 16, "width": 1},
|
||||
{"i": 62, "op": "mad", "dst": 6, "src": 2, "src2": 1, "imm": "0x938645fc", "imm2": "0xa9e49728", "rot": 20, "bit": 27, "mask": 8, "width": 1},
|
||||
{"i": 63, "op": "load", "dst": 3, "src": 2, "src2": 2, "imm": "0x2089409e", "imm2": "0x0437ba4e", "rot": 3, "bit": 31, "mask": 16, "width": 4}
|
||||
]
|
||||
}
|
||||
109
proto-cuda/packs-readwidth/mixA-1/program.metal
Normal file
109
proto-cuda/packs-readwidth/mixA-1/program.metal
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
#include <metal_stdlib>
|
||||
using namespace metal;
|
||||
|
||||
#define MASK 0x0fffffffu
|
||||
constant uint SEEDW[8] = { 0xa7198abfu, 0x6cd0f8cfu, 0xe4ef8ebfu, 0x03ee1e65u, 0xcfcfc5c0u, 0x82e9e19bu, 0x5d7a8a2fu, 0xfafccd93u };
|
||||
|
||||
inline uint splitmix32(uint x) {
|
||||
x ^= x >> 16; x *= 0x7feb352du;
|
||||
x ^= x >> 15; x *= 0x846ca68bu;
|
||||
x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
inline uint rotl_imm(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31
|
||||
inline uint rotr_var(uint x, uint n) { n &= 31u; return (x >> n) | (x << ((32u - n) & 31u)); }
|
||||
inline uint ds_elem(uint i, uint d0, uint d1) {
|
||||
uint x = i ^ d0;
|
||||
x *= 0x9E3779B1u; x ^= x >> 15;
|
||||
x += d1;
|
||||
x *= 0x85EBCA77u; x ^= x >> 13;
|
||||
x *= 0xC2B2AE3Du; x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
|
||||
kernel void igneum_hash(device const uint* dataset [[buffer(0)]],
|
||||
device ulong* out [[buffer(1)]],
|
||||
constant uint& baseNonce [[buffer(2)]],
|
||||
uint gid [[thread_position_in_grid]]) {
|
||||
uint nonce = baseNonce + gid;
|
||||
uint r0, r1, r2, r3, r4, r5, r6, r7;
|
||||
{ uint x = nonce ^ SEEDW[0]; x += 0x9e3779b9u * 1u; x = splitmix32(x); r0 = x ^ SEEDW[1]; }
|
||||
{ uint x = nonce ^ SEEDW[1]; x += 0x9e3779b9u * 2u; x = splitmix32(x); r1 = x ^ SEEDW[2]; }
|
||||
{ uint x = nonce ^ SEEDW[2]; x += 0x9e3779b9u * 3u; x = splitmix32(x); r2 = x ^ SEEDW[3]; }
|
||||
{ uint x = nonce ^ SEEDW[3]; x += 0x9e3779b9u * 4u; x = splitmix32(x); r3 = x ^ SEEDW[4]; }
|
||||
{ uint x = nonce ^ SEEDW[4]; x += 0x9e3779b9u * 5u; x = splitmix32(x); r4 = x ^ SEEDW[5]; }
|
||||
{ uint x = nonce ^ SEEDW[5]; x += 0x9e3779b9u * 6u; x = splitmix32(x); r5 = x ^ SEEDW[6]; }
|
||||
{ uint x = nonce ^ SEEDW[6]; x += 0x9e3779b9u * 7u; x = splitmix32(x); r6 = x ^ SEEDW[7]; }
|
||||
{ uint x = nonce ^ SEEDW[7]; x += 0x9e3779b9u * 8u; x = splitmix32(x); r7 = x ^ SEEDW[0]; }
|
||||
|
||||
for (uint it = 0u; it < 8u; ++it) {
|
||||
uint sel = r0;
|
||||
r4 = r4 + r3 + select(0x4a4c6caau, 0x5b2d5fe3u, ((sel >> 8u) & 1u) != 0u); // 0
|
||||
r7 = r7 | r6; // 1
|
||||
r2 = r2 * r7; // 2
|
||||
r5 = r5 ^ simd_shuffle_xor(r1, (ushort)2); // 3
|
||||
r4 = r4 ^ r6; // 4
|
||||
r0 = r0 ^ dataset[r4 & MASK]; // 5
|
||||
r3 = rotl_imm(r3, 17u); // 6
|
||||
r1 = r1 + r4 + select(0xaeb38cc5u, 0x83aa2c52u, ((sel >> 27u) & 1u) != 0u); // 7
|
||||
r1 = rotl_imm(r1, 31u); // 8
|
||||
r4 = r4 ^ r7; // 9
|
||||
{ uint b_ = (r0 & MASK) & ~3u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r6 = x_; } // 10
|
||||
{ uint b_ = (r6 & MASK) & ~3u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint x_ = r0 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r0 = x_; } // 11
|
||||
r5 = r5 ^ simd_shuffle_xor(r2, (ushort)1); // 12
|
||||
r1 = r1 ^ simd_shuffle_xor(r4, (ushort)2); // 13
|
||||
r5 = r5 * r7; // 14
|
||||
r3 = r3 ^ r0; // 15
|
||||
r5 = r5 * r4; // 16
|
||||
r2 = r2 ^ simd_shuffle_xor(r0, (ushort)4); // 17
|
||||
r4 = r4 + r1 + select(0x87d3a998u, 0xfb36bddau, ((sel >> 31u) & 1u) != 0u); // 18
|
||||
r0 = r0 + r1 + select(0x88921092u, 0xf2ef7076u, ((sel >> 22u) & 1u) != 0u); // 19
|
||||
r6 = r6 + r1 + select(0x35e06b74u, 0xe42e69c6u, ((sel >> 3u) & 1u) != 0u); // 20
|
||||
r2 = r2 ^ simd_shuffle_xor(r5, (ushort)8); // 21
|
||||
r3 = r3 + r6 + select(0x74df5734u, 0xb45d9671u, ((sel >> 3u) & 1u) != 0u); // 22
|
||||
r5 = r5 ^ simd_shuffle_xor(r4, (ushort)8); // 23
|
||||
r4 = r4 ^ dataset[r2 & MASK]; // 24
|
||||
r2 = r2 ^ r1; // 25
|
||||
r7 = r7 * r6; // 26
|
||||
{ uint b_ = (r3 & MASK) & ~15u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint x_ = r2 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r2 = x_; } // 27
|
||||
r3 = rotl_imm(r3, 29u); // 28
|
||||
r3 = r3 ^ simd_shuffle_xor(r0, (ushort)8); // 29
|
||||
r1 = r1 ^ dataset[r4 & MASK]; // 30
|
||||
r4 = r4 - r6; // 31
|
||||
r2 = r2 * r4; // 32
|
||||
r4 = r3 * r3 + r4; // 33
|
||||
r0 = r0 + r6 + select(0x19318d72u, 0x97d2762du, ((sel >> 15u) & 1u) != 0u); // 34
|
||||
r7 = r7 + r1 + select(0x26b63296u, 0x79830eadu, ((sel >> 19u) & 1u) != 0u); // 35
|
||||
r7 = r7 ^ dataset[r2 & MASK]; // 36
|
||||
r0 = rotr_var(r0, r7); // 37
|
||||
r2 = r2 + r7 + select(0xb228dc81u, 0x23c8dec4u, ((sel >> 28u) & 1u) != 0u); // 38
|
||||
r0 = r0 ^ dataset[r5 & MASK]; // 39
|
||||
r7 = r7 ^ simd_shuffle_xor(r5, (ushort)2); // 40
|
||||
r5 = r0 * r1 + r5; // 41
|
||||
r2 = r2 ^ r3; // 42
|
||||
r7 = r7 ^ dataset[r0 & MASK]; // 43
|
||||
{ uint b_ = (r5 & MASK) & ~3u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint x_ = r0 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r0 = x_; } // 44
|
||||
r2 = r2 + r7 + select(0xcc64df8eu, 0x5a3a7fe1u, ((sel >> 22u) & 1u) != 0u); // 45
|
||||
r0 = rotr_var(r0, r5); // 46
|
||||
r3 = rotr_var(r3, r7); // 47
|
||||
r2 = r7 * r6 + r2; // 48
|
||||
r6 = r3 * r5 + r6; // 49
|
||||
r1 = r1 ^ dataset[r6 & MASK]; // 50
|
||||
r7 = r7 ^ dataset[r1 & MASK]; // 51
|
||||
r3 = r3 + r4 + select(0x7a646d78u, 0xcba22643u, ((sel >> 6u) & 1u) != 0u); // 52
|
||||
r4 = r4 ^ r0; // 53
|
||||
r3 = r3 ^ simd_shuffle_xor(r7, (ushort)4); // 54
|
||||
r0 = rotr_var(r0, r1); // 55
|
||||
r5 = r5 ^ r3; // 56
|
||||
r1 = r1 + r0 + select(0x6f26b909u, 0x1834af00u, ((sel >> 8u) & 1u) != 0u); // 57
|
||||
r6 = r6 ^ dataset[r4 & MASK]; // 58
|
||||
{ uint b_ = (r7 & MASK) & ~15u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint x_ = r1 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r1 = x_; } // 59
|
||||
r1 = r1 ^ dataset[r0 & MASK]; // 60
|
||||
r4 = r4 ^ r7; // 61
|
||||
r6 = r2 * r1 + r6; // 62
|
||||
{ uint b_ = (r2 & MASK) & ~3u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r3 = x_; } // 63
|
||||
}
|
||||
uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u);
|
||||
uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u);
|
||||
out[gid] = ((ulong)hi << 32) | (ulong)lo;
|
||||
}
|
||||
111
proto-cuda/packs-readwidth/mixA-1/program_bound.metal
Normal file
111
proto-cuda/packs-readwidth/mixA-1/program_bound.metal
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
#include <metal_stdlib>
|
||||
using namespace metal;
|
||||
|
||||
#define MASK 0x0fffffffu
|
||||
constant uint SEEDW[8] = { 0xa7198abfu, 0x6cd0f8cfu, 0xe4ef8ebfu, 0x03ee1e65u, 0xcfcfc5c0u, 0x82e9e19bu, 0x5d7a8a2fu, 0xfafccd93u };
|
||||
|
||||
inline uint splitmix32(uint x) {
|
||||
x ^= x >> 16; x *= 0x7feb352du;
|
||||
x ^= x >> 15; x *= 0x846ca68bu;
|
||||
x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
inline uint rotl_imm(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31
|
||||
inline uint rotr_var(uint x, uint n) { n &= 31u; return (x >> n) | (x << ((32u - n) & 31u)); }
|
||||
inline uint ds_elem(uint i, uint d0, uint d1) {
|
||||
uint x = i ^ d0;
|
||||
x *= 0x9E3779B1u; x ^= x >> 15;
|
||||
x += d1;
|
||||
x *= 0x85EBCA77u; x ^= x >> 13;
|
||||
x *= 0xC2B2AE3Du; x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
|
||||
// Header-bound variant: the init words come from buffer 3 (bind.rs), not from SEEDW.
|
||||
kernel void igneum_hash_bound(device const uint* dataset [[buffer(0)]],
|
||||
device ulong* out [[buffer(1)]],
|
||||
constant uint& baseNonce [[buffer(2)]],
|
||||
constant uint* initw [[buffer(3)]],
|
||||
uint gid [[thread_position_in_grid]]) {
|
||||
uint nonce = baseNonce + gid;
|
||||
uint r0, r1, r2, r3, r4, r5, r6, r7;
|
||||
{ uint x = nonce ^ initw[0]; x += 0x9e3779b9u * 1u; x = splitmix32(x); r0 = x ^ initw[1]; }
|
||||
{ uint x = nonce ^ initw[1]; x += 0x9e3779b9u * 2u; x = splitmix32(x); r1 = x ^ initw[2]; }
|
||||
{ uint x = nonce ^ initw[2]; x += 0x9e3779b9u * 3u; x = splitmix32(x); r2 = x ^ initw[3]; }
|
||||
{ uint x = nonce ^ initw[3]; x += 0x9e3779b9u * 4u; x = splitmix32(x); r3 = x ^ initw[4]; }
|
||||
{ uint x = nonce ^ initw[4]; x += 0x9e3779b9u * 5u; x = splitmix32(x); r4 = x ^ initw[5]; }
|
||||
{ uint x = nonce ^ initw[5]; x += 0x9e3779b9u * 6u; x = splitmix32(x); r5 = x ^ initw[6]; }
|
||||
{ uint x = nonce ^ initw[6]; x += 0x9e3779b9u * 7u; x = splitmix32(x); r6 = x ^ initw[7]; }
|
||||
{ uint x = nonce ^ initw[7]; x += 0x9e3779b9u * 8u; x = splitmix32(x); r7 = x ^ initw[0]; }
|
||||
|
||||
for (uint it = 0u; it < 8u; ++it) {
|
||||
uint sel = r0;
|
||||
r4 = r4 + r3 + select(0x4a4c6caau, 0x5b2d5fe3u, ((sel >> 8u) & 1u) != 0u); // 0
|
||||
r7 = r7 | r6; // 1
|
||||
r2 = r2 * r7; // 2
|
||||
r5 = r5 ^ simd_shuffle_xor(r1, (ushort)2); // 3
|
||||
r4 = r4 ^ r6; // 4
|
||||
r0 = r0 ^ dataset[r4 & MASK]; // 5
|
||||
r3 = rotl_imm(r3, 17u); // 6
|
||||
r1 = r1 + r4 + select(0xaeb38cc5u, 0x83aa2c52u, ((sel >> 27u) & 1u) != 0u); // 7
|
||||
r1 = rotl_imm(r1, 31u); // 8
|
||||
r4 = r4 ^ r7; // 9
|
||||
{ uint b_ = (r0 & MASK) & ~3u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r6 = x_; } // 10
|
||||
{ uint b_ = (r6 & MASK) & ~3u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint x_ = r0 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r0 = x_; } // 11
|
||||
r5 = r5 ^ simd_shuffle_xor(r2, (ushort)1); // 12
|
||||
r1 = r1 ^ simd_shuffle_xor(r4, (ushort)2); // 13
|
||||
r5 = r5 * r7; // 14
|
||||
r3 = r3 ^ r0; // 15
|
||||
r5 = r5 * r4; // 16
|
||||
r2 = r2 ^ simd_shuffle_xor(r0, (ushort)4); // 17
|
||||
r4 = r4 + r1 + select(0x87d3a998u, 0xfb36bddau, ((sel >> 31u) & 1u) != 0u); // 18
|
||||
r0 = r0 + r1 + select(0x88921092u, 0xf2ef7076u, ((sel >> 22u) & 1u) != 0u); // 19
|
||||
r6 = r6 + r1 + select(0x35e06b74u, 0xe42e69c6u, ((sel >> 3u) & 1u) != 0u); // 20
|
||||
r2 = r2 ^ simd_shuffle_xor(r5, (ushort)8); // 21
|
||||
r3 = r3 + r6 + select(0x74df5734u, 0xb45d9671u, ((sel >> 3u) & 1u) != 0u); // 22
|
||||
r5 = r5 ^ simd_shuffle_xor(r4, (ushort)8); // 23
|
||||
r4 = r4 ^ dataset[r2 & MASK]; // 24
|
||||
r2 = r2 ^ r1; // 25
|
||||
r7 = r7 * r6; // 26
|
||||
{ uint b_ = (r3 & MASK) & ~15u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint x_ = r2 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r2 = x_; } // 27
|
||||
r3 = rotl_imm(r3, 29u); // 28
|
||||
r3 = r3 ^ simd_shuffle_xor(r0, (ushort)8); // 29
|
||||
r1 = r1 ^ dataset[r4 & MASK]; // 30
|
||||
r4 = r4 - r6; // 31
|
||||
r2 = r2 * r4; // 32
|
||||
r4 = r3 * r3 + r4; // 33
|
||||
r0 = r0 + r6 + select(0x19318d72u, 0x97d2762du, ((sel >> 15u) & 1u) != 0u); // 34
|
||||
r7 = r7 + r1 + select(0x26b63296u, 0x79830eadu, ((sel >> 19u) & 1u) != 0u); // 35
|
||||
r7 = r7 ^ dataset[r2 & MASK]; // 36
|
||||
r0 = rotr_var(r0, r7); // 37
|
||||
r2 = r2 + r7 + select(0xb228dc81u, 0x23c8dec4u, ((sel >> 28u) & 1u) != 0u); // 38
|
||||
r0 = r0 ^ dataset[r5 & MASK]; // 39
|
||||
r7 = r7 ^ simd_shuffle_xor(r5, (ushort)2); // 40
|
||||
r5 = r0 * r1 + r5; // 41
|
||||
r2 = r2 ^ r3; // 42
|
||||
r7 = r7 ^ dataset[r0 & MASK]; // 43
|
||||
{ uint b_ = (r5 & MASK) & ~3u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint x_ = r0 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r0 = x_; } // 44
|
||||
r2 = r2 + r7 + select(0xcc64df8eu, 0x5a3a7fe1u, ((sel >> 22u) & 1u) != 0u); // 45
|
||||
r0 = rotr_var(r0, r5); // 46
|
||||
r3 = rotr_var(r3, r7); // 47
|
||||
r2 = r7 * r6 + r2; // 48
|
||||
r6 = r3 * r5 + r6; // 49
|
||||
r1 = r1 ^ dataset[r6 & MASK]; // 50
|
||||
r7 = r7 ^ dataset[r1 & MASK]; // 51
|
||||
r3 = r3 + r4 + select(0x7a646d78u, 0xcba22643u, ((sel >> 6u) & 1u) != 0u); // 52
|
||||
r4 = r4 ^ r0; // 53
|
||||
r3 = r3 ^ simd_shuffle_xor(r7, (ushort)4); // 54
|
||||
r0 = rotr_var(r0, r1); // 55
|
||||
r5 = r5 ^ r3; // 56
|
||||
r1 = r1 + r0 + select(0x6f26b909u, 0x1834af00u, ((sel >> 8u) & 1u) != 0u); // 57
|
||||
r6 = r6 ^ dataset[r4 & MASK]; // 58
|
||||
{ uint b_ = (r7 & MASK) & ~15u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint x_ = r1 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r1 = x_; } // 59
|
||||
r1 = r1 ^ dataset[r0 & MASK]; // 60
|
||||
r4 = r4 ^ r7; // 61
|
||||
r6 = r2 * r1 + r6; // 62
|
||||
{ uint b_ = (r2 & MASK) & ~3u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r3 = x_; } // 63
|
||||
}
|
||||
uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u);
|
||||
uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u);
|
||||
out[gid] = ((ulong)hi << 32) | (ulong)lo;
|
||||
}
|
||||
57
proto-cuda/packs-readwidth/mixA-1/vectors.h
Normal file
57
proto-cuda/packs-readwidth/mixA-1/vectors.h
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
// Generated by igneum-pow export (generator v2) for seed "igneum-readwidth/A/1". Do not edit by hand.
|
||||
// Expected outputs: igneum-pow (Rust) CPU interpreter, generator v2, memory-hard dataset
|
||||
#pragma once
|
||||
#ifdef __cplusplus
|
||||
#include <cstdint>
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
#define IGNEUM_VEC_WARPS 3
|
||||
static const uint32_t IGNEUM_VEC_BASE[IGNEUM_VEC_WARPS] = { 0u, 4096u, 1000000u };
|
||||
static const uint64_t IGNEUM_VEC_OUT[IGNEUM_VEC_WARPS][32] = {
|
||||
{ // base nonce 0
|
||||
0x9a39e4c3b724e139ull, 0x0b2f9aefe9b5a7d9ull, 0x489f25154d36b837ull, 0x2bacca9851bedf63ull, 0x23b9e9d6f6f024a2ull, 0xa297adc388367ac7ull, 0x5f77305cf55428e2ull, 0x13f19dd950363e8cull,
|
||||
0xd3cc9c7923f85ae7ull, 0x5fdfc76e2559aaebull, 0x24bbc07c2b73b227ull, 0x5c128b8728383521ull, 0x95536c4dd0071840ull, 0xc2337e88f9eba324ull, 0x8a0d0d5db0b8c0c0ull, 0x4aa918c941e517f8ull,
|
||||
0x00b15821dc1a563dull, 0xa13888b391d5c4ffull, 0x2545a17fbecd2233ull, 0xf340d8b211921866ull, 0x827e215990856eccull, 0xa524b3dff5acb2f2ull, 0x495b540800df7c9eull, 0x9e274c9e9ed7edc5ull,
|
||||
0x5b8c358f08d10146ull, 0x7745916245fd6bd6ull, 0x20ab3090ecbf86e7ull, 0x3c2429a761881d58ull, 0xb14ad7a2b75a3e5bull, 0xd040113da7d8929aull, 0x0aac7bad8ef1785full, 0x69ef296bba30963dull
|
||||
},
|
||||
{ // base nonce 4096
|
||||
0x380980b425973372ull, 0xb039f8c8f2085f2eull, 0xdb9093fb95d8bffbull, 0x87fb86cda3374fcfull, 0x4138cea25d6a4d5full, 0xbe0a9b404a88c69full, 0xc696db4aa95e6473ull, 0x6d7fd33fb2be2a34ull,
|
||||
0x46acefa0c5e54e1full, 0xe898e7d08e946d6cull, 0xea998c0f7965842aull, 0xf6b60065df70f28dull, 0x24622e14557fd974ull, 0x5730af77da1186ffull, 0xf776630a6ff0a022ull, 0xa69c82d11c376933ull,
|
||||
0x93fb4e2c9c12456full, 0xa7a30a3c776b32cfull, 0x1669db65ca0f2724ull, 0x491df6828bfc7ad0ull, 0xeb5bf506947713c2ull, 0xe83fd62f415cfe9eull, 0xbc4415e97b359dd0ull, 0x2ab09721b97d003full,
|
||||
0xaf04c23a63a7bb7full, 0x6c4986d838379e4aull, 0x0dcecd1729525d44ull, 0x92ba240b16950bbaull, 0xed6df8cc108a7e50ull, 0x60252d3be009c7eaull, 0x300d103ffc4e8d35ull, 0x73522acf3d2f56d4ull
|
||||
},
|
||||
{ // base nonce 1000000
|
||||
0x254a52e3824ffcb7ull, 0x35f6dfb86ffa9f8eull, 0x27838da0f63ce460ull, 0xd25ec8a499e26256ull, 0xfe3b4f012071b8b2ull, 0xde760f5a3e5378cdull, 0x0810bd3a5f232ac3ull, 0x7ee980b9098f2df2ull,
|
||||
0xbae54f58f6daab8eull, 0x6f89d253a6b184f1ull, 0xb9c87bb5f8914f6full, 0xd264d719aa5d7bd5ull, 0x23e89f82b32a5a44ull, 0x080a72f8a360f627ull, 0xe28b507b1cba42beull, 0x25b77fdc149f8eb7ull,
|
||||
0x1a34f036f09596f5ull, 0x3e67e706d4719f7eull, 0x33764e53c58097a6ull, 0xbcf62943f155349aull, 0x8eb89841fbcb8ee5ull, 0x386b0433a1567ee7ull, 0x0c5775cb8fce2a91ull, 0x64518cc52f393a59ull,
|
||||
0x8f3cdb40e81a1cddull, 0x6af5a66a0a2436c1ull, 0xb76a5386454bef44ull, 0xfdd12f4ff2f53256ull, 0xf9ff7b79b577274full, 0xe7ed16e8ad89f703ull, 0x5a64c33fdfec335eull, 0xda50f54c2c547ac1ull
|
||||
}
|
||||
};
|
||||
|
||||
// Dataset self-test: dataset[0..15] and dataset[IGNEUM_MASK] (268435455).
|
||||
static const uint32_t IGNEUM_DS_HEAD[16] = {
|
||||
0xffc3cd94u, 0x5920ccd8u, 0x392f44bbu, 0x5e57f67au, 0x2f2bc2a9u, 0x620b0e36u, 0xbdc09014u, 0x436654bfu,
|
||||
0x311e0b48u, 0x1abd93adu, 0x59cc7ce8u, 0xee5247b2u, 0x86171fe8u, 0x6d874751u, 0xc9f7728fu, 0x7c2a435du
|
||||
};
|
||||
static const uint32_t IGNEUM_DS_LAST_INDEX = 268435455u;
|
||||
static const uint32_t IGNEUM_DS_LAST = 0xa33ada72u;
|
||||
// 64 sampled dataset words (index, value) computed on the Mac.
|
||||
#define IGNEUM_DS_SAMPLES 64
|
||||
static const uint32_t IGNEUM_DS_SAMPLE_INDEX[IGNEUM_DS_SAMPLES] = {
|
||||
59471966u, 217795994u, 208353206u, 42483309u, 172547758u, 148076330u, 183853158u, 214389424u, 267488061u, 169781097u, 184093494u, 153880993u, 84977930u, 46426879u, 3093825u, 225364072u, 44593546u, 260713159u, 168250303u, 52384140u, 223401610u, 45554030u, 95410555u, 175039924u, 79171087u, 267580473u, 24168642u, 37981670u, 171551130u, 195559979u, 204611762u, 140997658u, 138925853u, 86637313u, 20736778u, 219665210u, 160430336u, 264654675u, 8013395u, 228945585u, 213884386u, 104419827u, 44185464u, 142737231u, 99284897u, 132475900u, 61861762u, 132056166u, 262388043u, 91878046u, 117353561u, 124768597u, 71352993u, 190698941u, 46055428u, 55281366u, 165145231u, 106810753u, 171985651u, 232085256u, 159510492u, 40072060u, 209107596u, 39023794u
|
||||
};
|
||||
static const uint32_t IGNEUM_DS_SAMPLE_VALUE[IGNEUM_DS_SAMPLES] = {
|
||||
0xe8b73d94u, 0x337028b5u, 0xafe148c9u, 0xab99f7aeu, 0x434ea619u, 0xd85cb880u, 0x54764c7fu, 0x82c7e420u, 0xedf4cb9eu, 0x9884c959u, 0x223ee793u, 0x3a9ccf69u, 0x81da4fd2u, 0xd6ce8cb9u, 0xe3922dcau, 0x3e7e6bdeu, 0x382a3acau, 0x567e7f7fu, 0x25a0f084u, 0xbfeef128u, 0xe338abfbu, 0x7c3b5280u, 0x909bc5f1u, 0xd8b74b9cu, 0x8e31a22eu, 0x26b5f1d8u, 0x79122c00u, 0xcafc3340u, 0xd5e02ea3u, 0x1aee1afdu, 0xdb090d9au, 0xb049f435u, 0x4954d8bau, 0x03797ba0u, 0x196eefbdu, 0xd153412au, 0xbe5d2c4bu, 0xdaa14f0eu, 0x8e61ed07u, 0x9e9a64c6u, 0x2e29ff36u, 0x392a8589u, 0xb56a5912u, 0xfa6e8b57u, 0xd1a737cbu, 0xb0fa841au, 0xbe1c341fu, 0xe25be0f1u, 0xe937f543u, 0xebab2248u, 0x8e1b607au, 0x202a2fedu, 0x95e2819cu, 0x9c9652d4u, 0x32fedef0u, 0xdecfff82u, 0xcb5d43e5u, 0xb735806au, 0x8905939cu, 0xfbf8472du, 0xada74e5du, 0x7ebdeeeau, 0x0119f2b3u, 0xa9a376b8u
|
||||
};
|
||||
// Cache self-test (memory-hard mode): cache[0..15], the last 16 words, and FNV-1a 64 over all 2^26 words.
|
||||
static const uint32_t IGNEUM_CACHE_HEAD[16] = {
|
||||
0x355a86d2u, 0x7957db1cu, 0xd21772afu, 0x6fc1e09bu, 0xd55ce61du, 0x6e6a278bu, 0xd3f543ceu, 0x223d8e82u,
|
||||
0x143ab337u, 0x2e9f05bdu, 0x2eb389bfu, 0x0c6e449eu, 0x5cfa4222u, 0xba6560feu, 0x8e3e1aa4u, 0xdbcc1d53u
|
||||
};
|
||||
static const uint32_t IGNEUM_CACHE_LAST[16] = {
|
||||
0x41190d91u, 0xbd277957u, 0x22ddbb49u, 0x6986f207u, 0xdf69a4d6u, 0x26401a3au, 0x818230fbu, 0xc417122du,
|
||||
0x3597b211u, 0xb553ce55u, 0xcf39cc0du, 0x3b7fc43au, 0x3fd43b00u, 0x67e1c80eu, 0xffa7ea7du, 0xca2960abu
|
||||
};
|
||||
static const uint64_t IGNEUM_CACHE_FNV64 = 0x48c4f5bf24166b2eull;
|
||||
36
proto-cuda/packs-readwidth/mixA-1/vectors.json
Normal file
36
proto-cuda/packs-readwidth/mixA-1/vectors.json
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
{
|
||||
"seed": "igneum-readwidth/A/1",
|
||||
"day": "2026-10-03",
|
||||
"dataset_mode": "memory-hard",
|
||||
"dataset_log2_words": 28,
|
||||
"mask": "0x0fffffff",
|
||||
"lanes": 32,
|
||||
"source": "igneum-pow (Rust) CPU interpreter, generator v2, memory-hard dataset",
|
||||
"warps": [
|
||||
{"base_nonce": 0, "expected": [
|
||||
"0x9a39e4c3b724e139", "0x0b2f9aefe9b5a7d9", "0x489f25154d36b837", "0x2bacca9851bedf63", "0x23b9e9d6f6f024a2", "0xa297adc388367ac7", "0x5f77305cf55428e2", "0x13f19dd950363e8c",
|
||||
"0xd3cc9c7923f85ae7", "0x5fdfc76e2559aaeb", "0x24bbc07c2b73b227", "0x5c128b8728383521", "0x95536c4dd0071840", "0xc2337e88f9eba324", "0x8a0d0d5db0b8c0c0", "0x4aa918c941e517f8",
|
||||
"0x00b15821dc1a563d", "0xa13888b391d5c4ff", "0x2545a17fbecd2233", "0xf340d8b211921866", "0x827e215990856ecc", "0xa524b3dff5acb2f2", "0x495b540800df7c9e", "0x9e274c9e9ed7edc5",
|
||||
"0x5b8c358f08d10146", "0x7745916245fd6bd6", "0x20ab3090ecbf86e7", "0x3c2429a761881d58", "0xb14ad7a2b75a3e5b", "0xd040113da7d8929a", "0x0aac7bad8ef1785f", "0x69ef296bba30963d"
|
||||
]},
|
||||
{"base_nonce": 4096, "expected": [
|
||||
"0x380980b425973372", "0xb039f8c8f2085f2e", "0xdb9093fb95d8bffb", "0x87fb86cda3374fcf", "0x4138cea25d6a4d5f", "0xbe0a9b404a88c69f", "0xc696db4aa95e6473", "0x6d7fd33fb2be2a34",
|
||||
"0x46acefa0c5e54e1f", "0xe898e7d08e946d6c", "0xea998c0f7965842a", "0xf6b60065df70f28d", "0x24622e14557fd974", "0x5730af77da1186ff", "0xf776630a6ff0a022", "0xa69c82d11c376933",
|
||||
"0x93fb4e2c9c12456f", "0xa7a30a3c776b32cf", "0x1669db65ca0f2724", "0x491df6828bfc7ad0", "0xeb5bf506947713c2", "0xe83fd62f415cfe9e", "0xbc4415e97b359dd0", "0x2ab09721b97d003f",
|
||||
"0xaf04c23a63a7bb7f", "0x6c4986d838379e4a", "0x0dcecd1729525d44", "0x92ba240b16950bba", "0xed6df8cc108a7e50", "0x60252d3be009c7ea", "0x300d103ffc4e8d35", "0x73522acf3d2f56d4"
|
||||
]},
|
||||
{"base_nonce": 1000000, "expected": [
|
||||
"0x254a52e3824ffcb7", "0x35f6dfb86ffa9f8e", "0x27838da0f63ce460", "0xd25ec8a499e26256", "0xfe3b4f012071b8b2", "0xde760f5a3e5378cd", "0x0810bd3a5f232ac3", "0x7ee980b9098f2df2",
|
||||
"0xbae54f58f6daab8e", "0x6f89d253a6b184f1", "0xb9c87bb5f8914f6f", "0xd264d719aa5d7bd5", "0x23e89f82b32a5a44", "0x080a72f8a360f627", "0xe28b507b1cba42be", "0x25b77fdc149f8eb7",
|
||||
"0x1a34f036f09596f5", "0x3e67e706d4719f7e", "0x33764e53c58097a6", "0xbcf62943f155349a", "0x8eb89841fbcb8ee5", "0x386b0433a1567ee7", "0x0c5775cb8fce2a91", "0x64518cc52f393a59",
|
||||
"0x8f3cdb40e81a1cdd", "0x6af5a66a0a2436c1", "0xb76a5386454bef44", "0xfdd12f4ff2f53256", "0xf9ff7b79b577274f", "0xe7ed16e8ad89f703", "0x5a64c33fdfec335e", "0xda50f54c2c547ac1"
|
||||
]}
|
||||
],
|
||||
"dataset_head": ["0xffc3cd94", "0x5920ccd8", "0x392f44bb", "0x5e57f67a", "0x2f2bc2a9", "0x620b0e36", "0xbdc09014", "0x436654bf", "0x311e0b48", "0x1abd93ad", "0x59cc7ce8", "0xee5247b2", "0x86171fe8", "0x6d874751", "0xc9f7728f", "0x7c2a435d"],
|
||||
"dataset_last_index": 268435455,
|
||||
"dataset_last": "0xa33ada72",
|
||||
"dataset_samples": [{"index": 59471966, "value": "0xe8b73d94"}, {"index": 217795994, "value": "0x337028b5"}, {"index": 208353206, "value": "0xafe148c9"}, {"index": 42483309, "value": "0xab99f7ae"}, {"index": 172547758, "value": "0x434ea619"}, {"index": 148076330, "value": "0xd85cb880"}, {"index": 183853158, "value": "0x54764c7f"}, {"index": 214389424, "value": "0x82c7e420"}, {"index": 267488061, "value": "0xedf4cb9e"}, {"index": 169781097, "value": "0x9884c959"}, {"index": 184093494, "value": "0x223ee793"}, {"index": 153880993, "value": "0x3a9ccf69"}, {"index": 84977930, "value": "0x81da4fd2"}, {"index": 46426879, "value": "0xd6ce8cb9"}, {"index": 3093825, "value": "0xe3922dca"}, {"index": 225364072, "value": "0x3e7e6bde"}, {"index": 44593546, "value": "0x382a3aca"}, {"index": 260713159, "value": "0x567e7f7f"}, {"index": 168250303, "value": "0x25a0f084"}, {"index": 52384140, "value": "0xbfeef128"}, {"index": 223401610, "value": "0xe338abfb"}, {"index": 45554030, "value": "0x7c3b5280"}, {"index": 95410555, "value": "0x909bc5f1"}, {"index": 175039924, "value": "0xd8b74b9c"}, {"index": 79171087, "value": "0x8e31a22e"}, {"index": 267580473, "value": "0x26b5f1d8"}, {"index": 24168642, "value": "0x79122c00"}, {"index": 37981670, "value": "0xcafc3340"}, {"index": 171551130, "value": "0xd5e02ea3"}, {"index": 195559979, "value": "0x1aee1afd"}, {"index": 204611762, "value": "0xdb090d9a"}, {"index": 140997658, "value": "0xb049f435"}, {"index": 138925853, "value": "0x4954d8ba"}, {"index": 86637313, "value": "0x03797ba0"}, {"index": 20736778, "value": "0x196eefbd"}, {"index": 219665210, "value": "0xd153412a"}, {"index": 160430336, "value": "0xbe5d2c4b"}, {"index": 264654675, "value": "0xdaa14f0e"}, {"index": 8013395, "value": "0x8e61ed07"}, {"index": 228945585, "value": "0x9e9a64c6"}, {"index": 213884386, "value": "0x2e29ff36"}, {"index": 104419827, "value": "0x392a8589"}, {"index": 44185464, "value": "0xb56a5912"}, {"index": 142737231, "value": "0xfa6e8b57"}, {"index": 99284897, "value": "0xd1a737cb"}, {"index": 132475900, "value": "0xb0fa841a"}, {"index": 61861762, "value": "0xbe1c341f"}, {"index": 132056166, "value": "0xe25be0f1"}, {"index": 262388043, "value": "0xe937f543"}, {"index": 91878046, "value": "0xebab2248"}, {"index": 117353561, "value": "0x8e1b607a"}, {"index": 124768597, "value": "0x202a2fed"}, {"index": 71352993, "value": "0x95e2819c"}, {"index": 190698941, "value": "0x9c9652d4"}, {"index": 46055428, "value": "0x32fedef0"}, {"index": 55281366, "value": "0xdecfff82"}, {"index": 165145231, "value": "0xcb5d43e5"}, {"index": 106810753, "value": "0xb735806a"}, {"index": 171985651, "value": "0x8905939c"}, {"index": 232085256, "value": "0xfbf8472d"}, {"index": 159510492, "value": "0xada74e5d"}, {"index": 40072060, "value": "0x7ebdeeea"}, {"index": 209107596, "value": "0x0119f2b3"}, {"index": 39023794, "value": "0xa9a376b8"}],
|
||||
"cache_head": ["0x355a86d2", "0x7957db1c", "0xd21772af", "0x6fc1e09b", "0xd55ce61d", "0x6e6a278b", "0xd3f543ce", "0x223d8e82", "0x143ab337", "0x2e9f05bd", "0x2eb389bf", "0x0c6e449e", "0x5cfa4222", "0xba6560fe", "0x8e3e1aa4", "0xdbcc1d53"],
|
||||
"cache_last_line": ["0x41190d91", "0xbd277957", "0x22ddbb49", "0x6986f207", "0xdf69a4d6", "0x26401a3a", "0x818230fb", "0xc417122d", "0x3597b211", "0xb553ce55", "0xcf39cc0d", "0x3b7fc43a", "0x3fd43b00", "0x67e1c80e", "0xffa7ea7d", "0xca2960ab"],
|
||||
"cache_fnv1a64": "0x48c4f5bf24166b2e"
|
||||
}
|
||||
278
proto-cuda/packs-readwidth/mixA-2/kernel.cl
Normal file
278
proto-cuda/packs-readwidth/mixA-2/kernel.cl
Normal file
|
|
@ -0,0 +1,278 @@
|
|||
// Generated by igneum-pow export (generator v2) for seed "igneum-readwidth/A/2". Do not edit by hand.
|
||||
// OpenCL C twin of the Metal kernel for the same seed (see proto-opencl/README.md, WAVEFRONT.md and program.metal).
|
||||
// Built from source at runtime by proto-opencl/host.c, which passes these defines:
|
||||
// IGNEUM_GROUP work-group size of igneum_hash, a multiple of 32 (default 32: one work-group = one 32-lane unit)
|
||||
// IGNEUM_EXCHANGE 0 = local-memory exchange with a barrier (any device, any wave width; the default)
|
||||
// 1 = sub_group_shuffle_xor (cl_khr_subgroup_shuffle), only with IGNEUM_GROUP 32 and a sub-group size of exactly 32
|
||||
// 2 = intel_sub_group_shuffle_xor (cl_intel_subgroups), same condition
|
||||
// The verification unit is always 32 lanes. A 64-wide hardware wave (AMD GCN/CDNA, RDNA in wave64) runs two units;
|
||||
// the exchange masks are 1, 2, 4, 8, 16, so every partner lane lies inside the lane's own aligned run of 32.
|
||||
#ifndef IGNEUM_GROUP
|
||||
#define IGNEUM_GROUP 32
|
||||
#endif
|
||||
#ifndef IGNEUM_EXCHANGE
|
||||
#define IGNEUM_EXCHANGE 0
|
||||
#endif
|
||||
#ifdef __OPENCL_VERSION__
|
||||
#define IGNEUM_KERNEL_HASH __kernel __attribute__((reqd_work_group_size(IGNEUM_GROUP, 1, 1)))
|
||||
#define IGNEUM_LOCAL_WORDS(name, n) __local uint name[n]
|
||||
#if IGNEUM_EXCHANGE == 1
|
||||
#ifdef cl_khr_subgroups
|
||||
#pragma OPENCL EXTENSION cl_khr_subgroups : enable
|
||||
#endif
|
||||
#ifdef cl_khr_subgroup_shuffle
|
||||
#pragma OPENCL EXTENSION cl_khr_subgroup_shuffle : enable
|
||||
#endif
|
||||
#elif IGNEUM_EXCHANGE == 2
|
||||
#pragma OPENCL EXTENSION cl_intel_subgroups : enable
|
||||
#endif
|
||||
#else
|
||||
// Not an OpenCL compiler: proto-opencl/emu compiles this file as C++ and supplies the built-ins and these two macros.
|
||||
#include "emu_opencl.h"
|
||||
#endif
|
||||
|
||||
#if IGNEUM_EXCHANGE == 1
|
||||
#define IGNEUM_SHFL_XOR(dst, a, m) dst = sub_group_shuffle_xor((a), (uint)(m))
|
||||
#define IGNEUM_BCAST0(dst, a) dst = sub_group_broadcast((a), 0u)
|
||||
#elif IGNEUM_EXCHANGE == 2
|
||||
#define IGNEUM_SHFL_XOR(dst, a, m) dst = intel_sub_group_shuffle_xor((a), (uint)(m))
|
||||
#define IGNEUM_BCAST0(dst, a) dst = sub_group_broadcast((a), 0u)
|
||||
#else
|
||||
// Local-memory exchange. Two buffers of IGNEUM_GROUP words alternate (xk counts exchanges), so one barrier per
|
||||
// exchange is enough: a lane can only overwrite buffer b at exchange k+2 after passing barrier k+1, and every lane
|
||||
// reaches barrier k+1 only after its read of buffer b at exchange k. The partner lid ^ m stays inside the lane's
|
||||
// aligned run of 32 because m < 32. Control flow is uniform, so every work-item reaches every barrier.
|
||||
#define IGNEUM_SHFL_XOR(dst, a, m) { xch[(xk & 1u) * IGNEUM_GROUP + lid] = (a); barrier(CLK_LOCAL_MEM_FENCE); dst = xch[(xk & 1u) * IGNEUM_GROUP + (lid ^ (uint)(m))]; xk += 1u; }
|
||||
#define IGNEUM_BCAST0(dst, a) { xch[(xk & 1u) * IGNEUM_GROUP + lid] = (a); barrier(CLK_LOCAL_MEM_FENCE); dst = xch[(xk & 1u) * IGNEUM_GROUP + (lid & ~31u)]; xk += 1u; }
|
||||
#endif
|
||||
|
||||
static inline uint splitmix32(uint x) {
|
||||
x ^= x >> 16; x *= 0x7feb352du;
|
||||
x ^= x >> 15; x *= 0x846ca68bu;
|
||||
x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
// n is a literal in 1..31 at every call site. OpenCL rotate() rotates left by n modulo 32.
|
||||
static inline uint rotl_imm(uint x, uint n) { return rotate(x, n); }
|
||||
// Right rotation by n modulo 32 as a left rotation by (32 - n) modulo 32; n == 0 gives x.
|
||||
static inline uint rotr_var(uint x, uint n) { return rotate(x, (0u - n) & 31u); }
|
||||
static inline uint ds_elem(uint i, uint d0, uint d1) {
|
||||
uint x = i ^ d0;
|
||||
x *= 0x9E3779B1u; x ^= x >> 15;
|
||||
x += d1;
|
||||
x *= 0x85EBCA77u; x ^= x >> 13;
|
||||
x *= 0xC2B2AE3Du; x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
|
||||
// Memory-hard dataset core (MEMHARD.md). Cache: 2^26 words in 2^16 segments of 64 chained ChaCha12 lines.
|
||||
// Item: 8 rounds of seed-parameterised mixer + one 64-byte cache read, then a final mixer. All parameters are literals.
|
||||
#define MH_CACHE_LINE_MASK 0x003fffffu
|
||||
#define MH_SEGMENT_LINES 64u
|
||||
#define MH_QR(a, b, c, d, r1, r2, r3, r4) { a += b; d ^= a; d = mh_rotl(d, r1); c += d; b ^= c; b = mh_rotl(b, r2); a += b; d ^= a; d = mh_rotl(d, r3); c += d; b ^= c; b = mh_rotl(b, r4); }
|
||||
static inline uint mh_rotl(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 at every call site
|
||||
|
||||
// y = ChaCha12 core(x) + x
|
||||
static inline void mh_chacha_block(const uint* x, uint* y) {
|
||||
for (uint i = 0u; i < 16u; ++i) y[i] = x[i];
|
||||
for (uint r = 0u; r < 6u; ++r) {
|
||||
MH_QR(y[0], y[4], y[8], y[12], 16u, 12u, 8u, 7u) MH_QR(y[1], y[5], y[9], y[13], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[2], y[6], y[10], y[14], 16u, 12u, 8u, 7u) MH_QR(y[3], y[7], y[11], y[15], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[0], y[5], y[10], y[15], 16u, 12u, 8u, 7u) MH_QR(y[1], y[6], y[11], y[12], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[2], y[7], y[8], y[13], 16u, 12u, 8u, 7u) MH_QR(y[3], y[4], y[9], y[14], 16u, 12u, 8u, 7u)
|
||||
}
|
||||
for (uint i = 0u; i < 16u; ++i) y[i] += x[i];
|
||||
}
|
||||
|
||||
// One cache segment: 64 chained lines written at cache[seg * 1024]. in_j = prev ^ (sigma || K || seg || j || tag), prev_0 = 0.
|
||||
static inline void mh_cache_segment(__global uint* cache, uint seg) {
|
||||
uint prev[16]; uint x[16]; uint y[16];
|
||||
for (uint i = 0u; i < 16u; ++i) prev[i] = 0u;
|
||||
for (uint j = 0u; j < MH_SEGMENT_LINES; ++j) {
|
||||
x[0] = 0x61707865u ^ prev[0]; x[1] = 0x3320646eu ^ prev[1]; x[2] = 0x79622d32u ^ prev[2]; x[3] = 0x6b206574u ^ prev[3];
|
||||
x[4] = 0x3067619fu ^ prev[4];
|
||||
x[5] = 0x3c269176u ^ prev[5];
|
||||
x[6] = 0x84a03b03u ^ prev[6];
|
||||
x[7] = 0xf8c63294u ^ prev[7];
|
||||
x[8] = 0xff977c5bu ^ prev[8];
|
||||
x[9] = 0xe60def3eu ^ prev[9];
|
||||
x[10] = 0x63630141u ^ prev[10];
|
||||
x[11] = 0xb8fbcb58u ^ prev[11];
|
||||
x[12] = seg ^ prev[12]; x[13] = j ^ prev[13]; x[14] = 0x49676e65u ^ prev[14]; x[15] = 0x756d4d48u ^ prev[15];
|
||||
mh_chacha_block(x, y);
|
||||
__global uint* line = cache + ((seg * MH_SEGMENT_LINES + j) * 16u);
|
||||
for (uint i = 0u; i < 16u; ++i) { line[i] = y[i]; prev[i] = y[i]; }
|
||||
}
|
||||
}
|
||||
|
||||
// M_r: per word (s ^ (RC + rk)) * MUL, then a column round and a diagonal round with the seed-drawn rotations.
|
||||
static inline void mh_mixer(uint* s, uint rk) {
|
||||
s[0] = (s[0] ^ (0xbab68293u + rk)) * 0x42146205u;
|
||||
s[1] = (s[1] ^ (0xcc162340u + rk)) * 0x52cbe0fbu;
|
||||
s[2] = (s[2] ^ (0x6ce151ccu + rk)) * 0x7ecf4a03u;
|
||||
s[3] = (s[3] ^ (0xe62b8997u + rk)) * 0x6728907fu;
|
||||
s[4] = (s[4] ^ (0xc9c80297u + rk)) * 0xd81d9751u;
|
||||
s[5] = (s[5] ^ (0xf74a1654u + rk)) * 0x132952c3u;
|
||||
s[6] = (s[6] ^ (0x3d704af5u + rk)) * 0xf60de277u;
|
||||
s[7] = (s[7] ^ (0x3cf522b7u + rk)) * 0x05358035u;
|
||||
s[8] = (s[8] ^ (0x2b9cac04u + rk)) * 0xbaf6499du;
|
||||
s[9] = (s[9] ^ (0xa880ac10u + rk)) * 0xe4db9667u;
|
||||
s[10] = (s[10] ^ (0x13e5dd1du + rk)) * 0x3e98f45du;
|
||||
s[11] = (s[11] ^ (0x6fc3e233u + rk)) * 0xd0004eddu;
|
||||
s[12] = (s[12] ^ (0x2d83eeacu + rk)) * 0x2691630du;
|
||||
s[13] = (s[13] ^ (0x9006e8bfu + rk)) * 0x9beb3bcfu;
|
||||
s[14] = (s[14] ^ (0x2c4b5362u + rk)) * 0xab310379u;
|
||||
s[15] = (s[15] ^ (0x31b49ee2u + rk)) * 0x99cfb423u;
|
||||
MH_QR(s[0], s[4], s[8], s[12], 20u, 20u, 19u, 4u) MH_QR(s[1], s[5], s[9], s[13], 20u, 20u, 19u, 4u)
|
||||
MH_QR(s[2], s[6], s[10], s[14], 20u, 20u, 19u, 4u) MH_QR(s[3], s[7], s[11], s[15], 20u, 20u, 19u, 4u)
|
||||
MH_QR(s[0], s[5], s[10], s[15], 26u, 3u, 3u, 27u) MH_QR(s[1], s[6], s[11], s[12], 26u, 3u, 3u, 27u)
|
||||
MH_QR(s[2], s[7], s[8], s[13], 26u, 3u, 3u, 27u) MH_QR(s[3], s[4], s[9], s[14], 26u, 3u, 3u, 27u)
|
||||
}
|
||||
|
||||
// Item t: 16 words. s = (K, t * MUL[i] + RC[i]); 8 rounds of mixer + cache line s[0] & mask; final mixer.
|
||||
static inline void mh_item(__global const uint* cache, uint t, uint* s) {
|
||||
s[0] = 0x3067619fu;
|
||||
s[1] = 0x3c269176u;
|
||||
s[2] = 0x84a03b03u;
|
||||
s[3] = 0xf8c63294u;
|
||||
s[4] = 0xff977c5bu;
|
||||
s[5] = 0xe60def3eu;
|
||||
s[6] = 0x63630141u;
|
||||
s[7] = 0xb8fbcb58u;
|
||||
s[8] = t * 0x42146205u + 0xbab68293u;
|
||||
s[9] = t * 0x52cbe0fbu + 0xcc162340u;
|
||||
s[10] = t * 0x7ecf4a03u + 0x6ce151ccu;
|
||||
s[11] = t * 0x6728907fu + 0xe62b8997u;
|
||||
s[12] = t * 0xd81d9751u + 0xc9c80297u;
|
||||
s[13] = t * 0x132952c3u + 0xf74a1654u;
|
||||
s[14] = t * 0xf60de277u + 0x3d704af5u;
|
||||
s[15] = t * 0x05358035u + 0x3cf522b7u;
|
||||
for (uint r = 0u; r < 8u; ++r) {
|
||||
mh_mixer(s, 0x9E3779B9u * (r + 1u));
|
||||
__global const uint* line = cache + ((s[0] & MH_CACHE_LINE_MASK) * 16u);
|
||||
for (uint i = 0u; i < 16u; ++i) s[i] ^= line[i];
|
||||
}
|
||||
mh_mixer(s, 0x9E3779B9u * 9u);
|
||||
}
|
||||
// dataset[w] without the dataset: derive item w >> 4 and take word w & 15.
|
||||
static inline uint mh_word(__global const uint* cache, uint w) { uint s[16]; mh_item(cache, w >> 4u, s); return s[w & 15u]; }
|
||||
|
||||
// Memory-hard dataset (MEMHARD.md). One work-item per cache segment; one work-item per 64-byte dataset item.
|
||||
// The same constants as memhard.h in this pack (one emitter, three dialects).
|
||||
__kernel void igneum_cache_fill(__global uint* cache, uint nSegments) {
|
||||
uint seg = (uint)get_global_id(0);
|
||||
if (seg < nSegments) mh_cache_segment(cache, seg);
|
||||
}
|
||||
__kernel void igneum_build(__global uint* ds, __global const uint* cache, uint nItems) {
|
||||
uint t = (uint)get_global_id(0);
|
||||
if (t < nItems) {
|
||||
uint s[16];
|
||||
mh_item(cache, t, s);
|
||||
__global uint* d = ds + ((ulong)t * 16u);
|
||||
for (uint i = 0u; i < 16u; ++i) d[i] = s[i];
|
||||
}
|
||||
}
|
||||
|
||||
// One hash per work-item. IGNEUM_GROUP is a multiple of 32; lane = lid & 31 and every exchange stays inside the
|
||||
// lane's own aligned run of 32 work-items, exactly like simd_shuffle_xor inside a 32-wide Metal SIMD group and
|
||||
// __shfl_xor_sync inside a CUDA warp. Control flow is uniform (no branches at all).
|
||||
IGNEUM_KERNEL_HASH void igneum_hash(__global const uint* ds, __global ulong* out, uint baseNonce, uint mask) {
|
||||
uint gid = (uint)get_global_id(0);
|
||||
uint lid = (uint)get_local_id(0);
|
||||
uint nonce = baseNonce + gid;
|
||||
uint r0, r1, r2, r3, r4, r5, r6, r7;
|
||||
#if IGNEUM_EXCHANGE == 0
|
||||
IGNEUM_LOCAL_WORDS(xch, 2 * IGNEUM_GROUP);
|
||||
uint xk = 0u;
|
||||
#else
|
||||
(void)lid;
|
||||
#endif
|
||||
{ uint x = nonce ^ 0x774fd410u; x += 0x9e3779b9u; x = splitmix32(x); r0 = x ^ 0x520f91b2u; } // SEEDW[0], 0x9e3779b9u * 1u, SEEDW[1]
|
||||
{ uint x = nonce ^ 0x520f91b2u; x += 0x3c6ef372u; x = splitmix32(x); r1 = x ^ 0x9357786fu; } // SEEDW[1], 0x9e3779b9u * 2u, SEEDW[2]
|
||||
{ uint x = nonce ^ 0x9357786fu; x += 0xdaa66d2bu; x = splitmix32(x); r2 = x ^ 0x8bbe44d7u; } // SEEDW[2], 0x9e3779b9u * 3u, SEEDW[3]
|
||||
{ uint x = nonce ^ 0x8bbe44d7u; x += 0x78dde6e4u; x = splitmix32(x); r3 = x ^ 0x23db18feu; } // SEEDW[3], 0x9e3779b9u * 4u, SEEDW[4]
|
||||
{ uint x = nonce ^ 0x23db18feu; x += 0x1715609du; x = splitmix32(x); r4 = x ^ 0x52022aecu; } // SEEDW[4], 0x9e3779b9u * 5u, SEEDW[5]
|
||||
{ uint x = nonce ^ 0x52022aecu; x += 0xb54cda56u; x = splitmix32(x); r5 = x ^ 0x653ea608u; } // SEEDW[5], 0x9e3779b9u * 6u, SEEDW[6]
|
||||
{ uint x = nonce ^ 0x653ea608u; x += 0x5384540fu; x = splitmix32(x); r6 = x ^ 0x57788e47u; } // SEEDW[6], 0x9e3779b9u * 7u, SEEDW[7]
|
||||
{ uint x = nonce ^ 0x57788e47u; x += 0xf1bbcdc8u; x = splitmix32(x); r7 = x ^ 0x774fd410u; } // SEEDW[7], 0x9e3779b9u * 8u, SEEDW[0]
|
||||
|
||||
for (uint it = 0u; it < 8u; ++it) {
|
||||
uint sel = r0;
|
||||
r2 = r2 + r7 + ((((sel >> 7u) & 1u) != 0u) ? 0xd8952471u : 0x17c8e8eeu); // 0 add
|
||||
r0 = rotr_var(r0, r5); // 1 rotr
|
||||
r5 = r5 + r0 + ((((sel >> 21u) & 1u) != 0u) ? 0x4325cc6au : 0x37d9560au); // 2 add
|
||||
r7 = r7 ^ r5; // 3 xor
|
||||
{ uint b_ = (r0 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r3 = x_; } // 4 load
|
||||
{ uint b_ = (r7 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r5 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r5 = x_; } // 5 load
|
||||
r0 = mul_hi(r0, r5); // 6 mulhi
|
||||
r4 = r4 * r7; // 7 mul
|
||||
r0 = r5 * r6 + r0; // 8 mad
|
||||
{ uint b_ = (r2 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r6 = x_; } // 9 load
|
||||
r0 = r0 ^ r6; // 10 xor
|
||||
r5 = r5 + r3 + ((((sel >> 22u) & 1u) != 0u) ? 0x81619a4cu : 0xbc4eca12u); // 11 add
|
||||
r4 = mul_hi(r4, r2); // 12 mulhi
|
||||
r2 = r2 ^ ds[r0 & mask]; // 13 load
|
||||
r0 = r0 + r2 + ((((sel >> 3u) & 1u) != 0u) ? 0xa557fd2bu : 0xcf9919eeu); // 14 add
|
||||
r4 = r4 + r5 + ((((sel >> 7u) & 1u) != 0u) ? 0x33857f70u : 0x36ec1d20u); // 15 add
|
||||
r7 = r7 + r5 + ((((sel >> 6u) & 1u) != 0u) ? 0x40495714u : 0x42f5db15u); // 16 add
|
||||
r7 = r7 ^ ds[r5 & mask]; // 17 load
|
||||
r3 = r3 ^ r6; // 18 xor
|
||||
{ uint b_ = (r2 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r7 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r7 = x_; } // 19 load
|
||||
{ uint b_ = (r3 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r5 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r5 = x_; } // 20 load
|
||||
r1 = r1 ^ ds[r0 & mask]; // 21 load
|
||||
r1 = mul_hi(r1, r3); // 22 mulhi
|
||||
r1 = rotr_var(r1, r5); // 23 rotr
|
||||
r2 = mul_hi(r2, r0); // 24 mulhi
|
||||
{ uint b_ = (r4 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r0 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r0 = x_; } // 25 load
|
||||
{ uint b_ = (r1 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r0 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r0 = x_; } // 26 load
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r2, 2u); r5 = r5 ^ t_; } // 27 shfl
|
||||
r5 = r5 + r4 + ((((sel >> 12u) & 1u) != 0u) ? 0x58a2eb85u : 0x22029cb9u); // 28 add
|
||||
{ uint b_ = (r5 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r2 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r2 = x_; } // 29 load
|
||||
r6 = r6 * r5; // 30 mul
|
||||
r6 = r6 ^ ds[r2 & mask]; // 31 load
|
||||
r7 = mul_hi(r7, r5); // 32 mulhi
|
||||
r0 = r0 ^ ds[r7 & mask]; // 33 load
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r2, 1u); r7 = r7 ^ t_; } // 34 shfl
|
||||
r7 = r7 * r0; // 35 mul
|
||||
r5 = r5 ^ ds[r7 & mask]; // 36 load
|
||||
r3 = rotr_var(r3, r2); // 37 rotr
|
||||
r6 = rotl_imm(r6, 1u); // 38 rotl
|
||||
r3 = r3 * r0; // 39 mul
|
||||
r3 = mul_hi(r3, r7); // 40 mulhi
|
||||
r5 = r5 ^ r2; // 41 xor
|
||||
r4 = r4 * r0; // 42 mul
|
||||
r3 = r3 + r0 + ((((sel >> 4u) & 1u) != 0u) ? 0xfaaf2d1eu : 0x831bfab3u); // 43 add
|
||||
r0 = r1 * r6 + r0; // 44 mad
|
||||
r6 = rotl_imm(r6, 26u); // 45 rotl
|
||||
r2 = r2 ^ r1; // 46 xor
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r0 = r0 ^ t_; } // 47 shfl
|
||||
r1 = r1 ^ r2; // 48 xor
|
||||
r3 = r3 + r5 + ((((sel >> 7u) & 1u) != 0u) ? 0xc5759120u : 0x31df1a86u); // 49 add
|
||||
r1 = r4 * r1 + r1; // 50 mad
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r4, 2u); r1 = r1 ^ t_; } // 51 shfl
|
||||
r5 = r5 + r4 + ((((sel >> 16u) & 1u) != 0u) ? 0x4e4a2759u : 0x553b85d1u); // 52 add
|
||||
r1 = r1 ^ ds[r3 & mask]; // 53 load
|
||||
r6 = rotl_imm(r6, 21u); // 54 rotl
|
||||
r1 = mul_hi(r1, r4); // 55 mulhi
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r3, 1u); r0 = r0 ^ t_; } // 56 shfl
|
||||
r1 = r1 ^ r2; // 57 xor
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r6, 16u); r3 = r3 ^ t_; } // 58 shfl
|
||||
r5 = r5 * r0; // 59 mul
|
||||
r4 = r4 ^ ds[r2 & mask]; // 60 load
|
||||
r0 = rotr_var(r0, r4); // 61 rotr
|
||||
r6 = r6 * r7; // 62 mul
|
||||
r6 = rotl_imm(r6, 2u); // 63 rotl
|
||||
}
|
||||
uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u);
|
||||
uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u);
|
||||
out[gid] = ((ulong)hi << 32) | (ulong)lo;
|
||||
}
|
||||
|
||||
#if IGNEUM_EXCHANGE != 0
|
||||
// Reports the sub-group size this device uses for a work-group of IGNEUM_GROUP items. host.c runs it only when the
|
||||
// per-kernel query (clGetKernelSubGroupInfoKHR on igneum_hash) is unavailable; that query is preferred because a
|
||||
// compiler may pick a different wave width per kernel (RDNA: wave32 or wave64). See WAVEFRONT.md.
|
||||
IGNEUM_KERNEL_HASH void igneum_probe_subgroup(__global uint* out) {
|
||||
if (get_local_id(0) == 0u) { out[0] = get_sub_group_size(); out[1] = get_num_sub_groups(); }
|
||||
}
|
||||
#endif
|
||||
164
proto-cuda/packs-readwidth/mixA-2/kernel.cu
Normal file
164
proto-cuda/packs-readwidth/mixA-2/kernel.cu
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
// Generated by igneum-pow export (generator v2) for seed "igneum-readwidth/A/2". Do not edit by hand.
|
||||
// Bit-exact twin of the Metal kernel for the same seed (see proto-cuda/CHECKLIST.md and program.metal).
|
||||
// Compiled ahead of time by nvcc together with proto-cuda/host.cu. No NVRTC.
|
||||
#include <cuda_runtime.h>
|
||||
#include <cstdint>
|
||||
#include "program.h"
|
||||
#include "memhard.h"
|
||||
|
||||
__device__ __forceinline__ uint32_t splitmix32(uint32_t x) {
|
||||
x ^= x >> 16; x *= 0x7feb352du;
|
||||
x ^= x >> 15; x *= 0x846ca68bu;
|
||||
x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
// n is a literal in 1..31 at every call site, so both shift amounts are in 1..31.
|
||||
__device__ __forceinline__ uint32_t rotl_imm(uint32_t x, uint32_t n) { return (x << n) | (x >> (32u - n)); }
|
||||
// n is masked to 0..31; the second shift amount is masked too, so n == 0 gives x.
|
||||
__device__ __forceinline__ uint32_t rotr_var(uint32_t x, uint32_t n) { n &= 31u; return (x >> n) | (x << ((32u - n) & 31u)); }
|
||||
__device__ __forceinline__ uint32_t ds_elem(uint32_t i, uint32_t d0, uint32_t d1) {
|
||||
uint32_t x = i ^ d0;
|
||||
x *= 0x9E3779B1u; x ^= x >> 15;
|
||||
x += d1;
|
||||
x *= 0x85EBCA77u; x ^= x >> 13;
|
||||
x *= 0xC2B2AE3Du; x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
|
||||
// Memory-hard dataset (MEMHARD.md). One thread per cache segment; one thread per 64-byte dataset item.
|
||||
// The core functions (mh_cache_segment, mh_item) are in memhard.h and are also compiled for the host.
|
||||
__global__ void igneum_cache_fill(uint32_t* cache, uint32_t nSegments) {
|
||||
uint32_t seg = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
if (seg < nSegments) mh_cache_segment(cache, seg);
|
||||
}
|
||||
__global__ void igneum_build(uint32_t* ds, const uint32_t* cache, uint32_t nItems) {
|
||||
uint32_t t = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
if (t < nItems) {
|
||||
uint32_t s[16];
|
||||
mh_item(cache, t, s);
|
||||
uint32_t* d = ds + (size_t)t * 16u;
|
||||
for (uint32_t i = 0u; i < 16u; ++i) d[i] = s[i];
|
||||
}
|
||||
}
|
||||
|
||||
// One hash per thread. blockDim.x is a multiple of 32; lane = threadIdx.x & 31 and every
|
||||
// __shfl_xor_sync stays inside the lane's own warp, exactly like simd_shuffle_xor inside a
|
||||
// 32-wide Metal SIMD group. Control flow is uniform, so the full 0xffffffff member mask is valid.
|
||||
__global__ void igneum_hash(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask) {
|
||||
uint32_t gid = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
uint32_t nonce = baseNonce + gid;
|
||||
uint32_t r0, r1, r2, r3, r4, r5, r6, r7;
|
||||
{ uint32_t x = nonce ^ 0x774fd410u; x += 0x9e3779b9u; x = splitmix32(x); r0 = x ^ 0x520f91b2u; } // SEEDW[0], 0x9e3779b9u * 1u, SEEDW[1]
|
||||
{ uint32_t x = nonce ^ 0x520f91b2u; x += 0x3c6ef372u; x = splitmix32(x); r1 = x ^ 0x9357786fu; } // SEEDW[1], 0x9e3779b9u * 2u, SEEDW[2]
|
||||
{ uint32_t x = nonce ^ 0x9357786fu; x += 0xdaa66d2bu; x = splitmix32(x); r2 = x ^ 0x8bbe44d7u; } // SEEDW[2], 0x9e3779b9u * 3u, SEEDW[3]
|
||||
{ uint32_t x = nonce ^ 0x8bbe44d7u; x += 0x78dde6e4u; x = splitmix32(x); r3 = x ^ 0x23db18feu; } // SEEDW[3], 0x9e3779b9u * 4u, SEEDW[4]
|
||||
{ uint32_t x = nonce ^ 0x23db18feu; x += 0x1715609du; x = splitmix32(x); r4 = x ^ 0x52022aecu; } // SEEDW[4], 0x9e3779b9u * 5u, SEEDW[5]
|
||||
{ uint32_t x = nonce ^ 0x52022aecu; x += 0xb54cda56u; x = splitmix32(x); r5 = x ^ 0x653ea608u; } // SEEDW[5], 0x9e3779b9u * 6u, SEEDW[6]
|
||||
{ uint32_t x = nonce ^ 0x653ea608u; x += 0x5384540fu; x = splitmix32(x); r6 = x ^ 0x57788e47u; } // SEEDW[6], 0x9e3779b9u * 7u, SEEDW[7]
|
||||
{ uint32_t x = nonce ^ 0x57788e47u; x += 0xf1bbcdc8u; x = splitmix32(x); r7 = x ^ 0x774fd410u; } // SEEDW[7], 0x9e3779b9u * 8u, SEEDW[0]
|
||||
|
||||
for (uint32_t it = 0u; it < 8u; ++it) {
|
||||
uint32_t sel = r0;
|
||||
r2 = r2 + r7 + ((((sel >> 7u) & 1u) != 0u) ? 0xd8952471u : 0x17c8e8eeu); // 0 add
|
||||
r0 = rotr_var(r0, r5); // 1 rotr
|
||||
r5 = r5 + r0 + ((((sel >> 21u) & 1u) != 0u) ? 0x4325cc6au : 0x37d9560au); // 2 add
|
||||
r7 = r7 ^ r5; // 3 xor
|
||||
{ uint32_t b_ = (r0 & mask) & ~15u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint32_t x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r3 = x_; } // 4 load
|
||||
{ uint32_t b_ = (r7 & mask) & ~3u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint32_t x_ = r5 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r5 = x_; } // 5 load
|
||||
r0 = __umulhi(r0, r5); // 6 mulhi
|
||||
r4 = r4 * r7; // 7 mul
|
||||
r0 = r5 * r6 + r0; // 8 mad
|
||||
{ uint32_t b_ = (r2 & mask) & ~3u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint32_t x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r6 = x_; } // 9 load
|
||||
r0 = r0 ^ r6; // 10 xor
|
||||
r5 = r5 + r3 + ((((sel >> 22u) & 1u) != 0u) ? 0x81619a4cu : 0xbc4eca12u); // 11 add
|
||||
r4 = __umulhi(r4, r2); // 12 mulhi
|
||||
r2 = r2 ^ ds[r0 & mask]; // 13 load
|
||||
r0 = r0 + r2 + ((((sel >> 3u) & 1u) != 0u) ? 0xa557fd2bu : 0xcf9919eeu); // 14 add
|
||||
r4 = r4 + r5 + ((((sel >> 7u) & 1u) != 0u) ? 0x33857f70u : 0x36ec1d20u); // 15 add
|
||||
r7 = r7 + r5 + ((((sel >> 6u) & 1u) != 0u) ? 0x40495714u : 0x42f5db15u); // 16 add
|
||||
r7 = r7 ^ ds[r5 & mask]; // 17 load
|
||||
r3 = r3 ^ r6; // 18 xor
|
||||
{ uint32_t b_ = (r2 & mask) & ~15u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint32_t x_ = r7 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r7 = x_; } // 19 load
|
||||
{ uint32_t b_ = (r3 & mask) & ~3u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint32_t x_ = r5 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r5 = x_; } // 20 load
|
||||
r1 = r1 ^ ds[r0 & mask]; // 21 load
|
||||
r1 = __umulhi(r1, r3); // 22 mulhi
|
||||
r1 = rotr_var(r1, r5); // 23 rotr
|
||||
r2 = __umulhi(r2, r0); // 24 mulhi
|
||||
{ uint32_t b_ = (r4 & mask) & ~15u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint32_t x_ = r0 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r0 = x_; } // 25 load
|
||||
{ uint32_t b_ = (r1 & mask) & ~3u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint32_t x_ = r0 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r0 = x_; } // 26 load
|
||||
r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r2, 2); // 27 shfl
|
||||
r5 = r5 + r4 + ((((sel >> 12u) & 1u) != 0u) ? 0x58a2eb85u : 0x22029cb9u); // 28 add
|
||||
{ uint32_t b_ = (r5 & mask) & ~3u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint32_t x_ = r2 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r2 = x_; } // 29 load
|
||||
r6 = r6 * r5; // 30 mul
|
||||
r6 = r6 ^ ds[r2 & mask]; // 31 load
|
||||
r7 = __umulhi(r7, r5); // 32 mulhi
|
||||
r0 = r0 ^ ds[r7 & mask]; // 33 load
|
||||
r7 = r7 ^ __shfl_xor_sync(0xffffffffu, r2, 1); // 34 shfl
|
||||
r7 = r7 * r0; // 35 mul
|
||||
r5 = r5 ^ ds[r7 & mask]; // 36 load
|
||||
r3 = rotr_var(r3, r2); // 37 rotr
|
||||
r6 = rotl_imm(r6, 1u); // 38 rotl
|
||||
r3 = r3 * r0; // 39 mul
|
||||
r3 = __umulhi(r3, r7); // 40 mulhi
|
||||
r5 = r5 ^ r2; // 41 xor
|
||||
r4 = r4 * r0; // 42 mul
|
||||
r3 = r3 + r0 + ((((sel >> 4u) & 1u) != 0u) ? 0xfaaf2d1eu : 0x831bfab3u); // 43 add
|
||||
r0 = r1 * r6 + r0; // 44 mad
|
||||
r6 = rotl_imm(r6, 26u); // 45 rotl
|
||||
r2 = r2 ^ r1; // 46 xor
|
||||
r0 = r0 ^ __shfl_xor_sync(0xffffffffu, r7, 2); // 47 shfl
|
||||
r1 = r1 ^ r2; // 48 xor
|
||||
r3 = r3 + r5 + ((((sel >> 7u) & 1u) != 0u) ? 0xc5759120u : 0x31df1a86u); // 49 add
|
||||
r1 = r4 * r1 + r1; // 50 mad
|
||||
r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r4, 2); // 51 shfl
|
||||
r5 = r5 + r4 + ((((sel >> 16u) & 1u) != 0u) ? 0x4e4a2759u : 0x553b85d1u); // 52 add
|
||||
r1 = r1 ^ ds[r3 & mask]; // 53 load
|
||||
r6 = rotl_imm(r6, 21u); // 54 rotl
|
||||
r1 = __umulhi(r1, r4); // 55 mulhi
|
||||
r0 = r0 ^ __shfl_xor_sync(0xffffffffu, r3, 1); // 56 shfl
|
||||
r1 = r1 ^ r2; // 57 xor
|
||||
r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r6, 16); // 58 shfl
|
||||
r5 = r5 * r0; // 59 mul
|
||||
r4 = r4 ^ ds[r2 & mask]; // 60 load
|
||||
r0 = rotr_var(r0, r4); // 61 rotr
|
||||
r6 = r6 * r7; // 62 mul
|
||||
r6 = rotl_imm(r6, 2u); // 63 rotl
|
||||
}
|
||||
uint32_t lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u);
|
||||
uint32_t hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u);
|
||||
out[gid] = ((uint64_t)hi << 32) | (uint64_t)lo;
|
||||
}
|
||||
|
||||
// Host-side launch wrappers. Declared in program.h, called from host.cu.
|
||||
cudaError_t igneum_launch_cache_fill(uint32_t* cache, uint32_t nSegments) {
|
||||
if (nSegments == 0u) return cudaErrorInvalidValue;
|
||||
uint32_t block = 256u;
|
||||
uint32_t grid = (nSegments + block - 1u) / block;
|
||||
igneum_cache_fill<<<grid, block>>>(cache, nSegments);
|
||||
return cudaGetLastError();
|
||||
}
|
||||
|
||||
cudaError_t igneum_launch_build(uint32_t* ds, const uint32_t* cache, uint32_t nItems) {
|
||||
if (nItems == 0u) return cudaErrorInvalidValue;
|
||||
uint32_t block = 256u;
|
||||
uint32_t grid = (nItems + block - 1u) / block;
|
||||
igneum_build<<<grid, block>>>(ds, cache, nItems);
|
||||
return cudaGetLastError();
|
||||
}
|
||||
|
||||
cudaError_t igneum_launch_hash(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask,
|
||||
uint32_t nonces, uint32_t blockWarps) {
|
||||
if (blockWarps == 0u || blockWarps > 32u) return cudaErrorInvalidValue;
|
||||
uint32_t block = 32u * blockWarps;
|
||||
if (nonces == 0u || (nonces % block) != 0u) return cudaErrorInvalidValue;
|
||||
igneum_hash<<<nonces / block, block>>>(ds, out, baseNonce, mask);
|
||||
return cudaGetLastError();
|
||||
}
|
||||
|
||||
cudaError_t igneum_hash_info(int* numRegs, int* blocksPerSM, uint32_t blockWarps) {
|
||||
cudaFuncAttributes attr;
|
||||
cudaError_t e = cudaFuncGetAttributes(&attr, igneum_hash);
|
||||
if (e != cudaSuccess) return e;
|
||||
*numRegs = attr.numRegs;
|
||||
return cudaOccupancyMaxActiveBlocksPerMultiprocessor(blocksPerSM, igneum_hash, (int)(32u * blockWarps), 0);
|
||||
}
|
||||
372
proto-cuda/packs-readwidth/mixA-2/kernel_bound.cl
Normal file
372
proto-cuda/packs-readwidth/mixA-2/kernel_bound.cl
Normal file
|
|
@ -0,0 +1,372 @@
|
|||
// Generated by igneum-pow export (generator v2) for seed "igneum-readwidth/A/2". Do not edit by hand.
|
||||
// OpenCL C twin of the Metal kernel for the same seed (see proto-opencl/README.md, WAVEFRONT.md and program.metal).
|
||||
// Built from source at runtime by proto-opencl/host.c, which passes these defines:
|
||||
// IGNEUM_GROUP work-group size of igneum_hash, a multiple of 32 (default 32: one work-group = one 32-lane unit)
|
||||
// IGNEUM_EXCHANGE 0 = local-memory exchange with a barrier (any device, any wave width; the default)
|
||||
// 1 = sub_group_shuffle_xor (cl_khr_subgroup_shuffle), only with IGNEUM_GROUP 32 and a sub-group size of exactly 32
|
||||
// 2 = intel_sub_group_shuffle_xor (cl_intel_subgroups), same condition
|
||||
// The verification unit is always 32 lanes. A 64-wide hardware wave (AMD GCN/CDNA, RDNA in wave64) runs two units;
|
||||
// the exchange masks are 1, 2, 4, 8, 16, so every partner lane lies inside the lane's own aligned run of 32.
|
||||
#ifndef IGNEUM_GROUP
|
||||
#define IGNEUM_GROUP 32
|
||||
#endif
|
||||
#ifndef IGNEUM_EXCHANGE
|
||||
#define IGNEUM_EXCHANGE 0
|
||||
#endif
|
||||
#ifdef __OPENCL_VERSION__
|
||||
#define IGNEUM_KERNEL_HASH __kernel __attribute__((reqd_work_group_size(IGNEUM_GROUP, 1, 1)))
|
||||
#define IGNEUM_LOCAL_WORDS(name, n) __local uint name[n]
|
||||
#if IGNEUM_EXCHANGE == 1
|
||||
#ifdef cl_khr_subgroups
|
||||
#pragma OPENCL EXTENSION cl_khr_subgroups : enable
|
||||
#endif
|
||||
#ifdef cl_khr_subgroup_shuffle
|
||||
#pragma OPENCL EXTENSION cl_khr_subgroup_shuffle : enable
|
||||
#endif
|
||||
#elif IGNEUM_EXCHANGE == 2
|
||||
#pragma OPENCL EXTENSION cl_intel_subgroups : enable
|
||||
#endif
|
||||
#else
|
||||
// Not an OpenCL compiler: proto-opencl/emu compiles this file as C++ and supplies the built-ins and these two macros.
|
||||
#include "emu_opencl.h"
|
||||
#endif
|
||||
|
||||
#if IGNEUM_EXCHANGE == 1
|
||||
#define IGNEUM_SHFL_XOR(dst, a, m) dst = sub_group_shuffle_xor((a), (uint)(m))
|
||||
#define IGNEUM_BCAST0(dst, a) dst = sub_group_broadcast((a), 0u)
|
||||
#elif IGNEUM_EXCHANGE == 2
|
||||
#define IGNEUM_SHFL_XOR(dst, a, m) dst = intel_sub_group_shuffle_xor((a), (uint)(m))
|
||||
#define IGNEUM_BCAST0(dst, a) dst = sub_group_broadcast((a), 0u)
|
||||
#else
|
||||
// Local-memory exchange. Two buffers of IGNEUM_GROUP words alternate (xk counts exchanges), so one barrier per
|
||||
// exchange is enough: a lane can only overwrite buffer b at exchange k+2 after passing barrier k+1, and every lane
|
||||
// reaches barrier k+1 only after its read of buffer b at exchange k. The partner lid ^ m stays inside the lane's
|
||||
// aligned run of 32 because m < 32. Control flow is uniform, so every work-item reaches every barrier.
|
||||
#define IGNEUM_SHFL_XOR(dst, a, m) { xch[(xk & 1u) * IGNEUM_GROUP + lid] = (a); barrier(CLK_LOCAL_MEM_FENCE); dst = xch[(xk & 1u) * IGNEUM_GROUP + (lid ^ (uint)(m))]; xk += 1u; }
|
||||
#define IGNEUM_BCAST0(dst, a) { xch[(xk & 1u) * IGNEUM_GROUP + lid] = (a); barrier(CLK_LOCAL_MEM_FENCE); dst = xch[(xk & 1u) * IGNEUM_GROUP + (lid & ~31u)]; xk += 1u; }
|
||||
#endif
|
||||
|
||||
static inline uint splitmix32(uint x) {
|
||||
x ^= x >> 16; x *= 0x7feb352du;
|
||||
x ^= x >> 15; x *= 0x846ca68bu;
|
||||
x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
// n is a literal in 1..31 at every call site. OpenCL rotate() rotates left by n modulo 32.
|
||||
static inline uint rotl_imm(uint x, uint n) { return rotate(x, n); }
|
||||
// Right rotation by n modulo 32 as a left rotation by (32 - n) modulo 32; n == 0 gives x.
|
||||
static inline uint rotr_var(uint x, uint n) { return rotate(x, (0u - n) & 31u); }
|
||||
static inline uint ds_elem(uint i, uint d0, uint d1) {
|
||||
uint x = i ^ d0;
|
||||
x *= 0x9E3779B1u; x ^= x >> 15;
|
||||
x += d1;
|
||||
x *= 0x85EBCA77u; x ^= x >> 13;
|
||||
x *= 0xC2B2AE3Du; x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
|
||||
// Memory-hard dataset core (MEMHARD.md). Cache: 2^26 words in 2^16 segments of 64 chained ChaCha12 lines.
|
||||
// Item: 8 rounds of seed-parameterised mixer + one 64-byte cache read, then a final mixer. All parameters are literals.
|
||||
#define MH_CACHE_LINE_MASK 0x003fffffu
|
||||
#define MH_SEGMENT_LINES 64u
|
||||
#define MH_QR(a, b, c, d, r1, r2, r3, r4) { a += b; d ^= a; d = mh_rotl(d, r1); c += d; b ^= c; b = mh_rotl(b, r2); a += b; d ^= a; d = mh_rotl(d, r3); c += d; b ^= c; b = mh_rotl(b, r4); }
|
||||
static inline uint mh_rotl(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 at every call site
|
||||
|
||||
// y = ChaCha12 core(x) + x
|
||||
static inline void mh_chacha_block(const uint* x, uint* y) {
|
||||
for (uint i = 0u; i < 16u; ++i) y[i] = x[i];
|
||||
for (uint r = 0u; r < 6u; ++r) {
|
||||
MH_QR(y[0], y[4], y[8], y[12], 16u, 12u, 8u, 7u) MH_QR(y[1], y[5], y[9], y[13], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[2], y[6], y[10], y[14], 16u, 12u, 8u, 7u) MH_QR(y[3], y[7], y[11], y[15], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[0], y[5], y[10], y[15], 16u, 12u, 8u, 7u) MH_QR(y[1], y[6], y[11], y[12], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[2], y[7], y[8], y[13], 16u, 12u, 8u, 7u) MH_QR(y[3], y[4], y[9], y[14], 16u, 12u, 8u, 7u)
|
||||
}
|
||||
for (uint i = 0u; i < 16u; ++i) y[i] += x[i];
|
||||
}
|
||||
|
||||
// One cache segment: 64 chained lines written at cache[seg * 1024]. in_j = prev ^ (sigma || K || seg || j || tag), prev_0 = 0.
|
||||
static inline void mh_cache_segment(__global uint* cache, uint seg) {
|
||||
uint prev[16]; uint x[16]; uint y[16];
|
||||
for (uint i = 0u; i < 16u; ++i) prev[i] = 0u;
|
||||
for (uint j = 0u; j < MH_SEGMENT_LINES; ++j) {
|
||||
x[0] = 0x61707865u ^ prev[0]; x[1] = 0x3320646eu ^ prev[1]; x[2] = 0x79622d32u ^ prev[2]; x[3] = 0x6b206574u ^ prev[3];
|
||||
x[4] = 0x3067619fu ^ prev[4];
|
||||
x[5] = 0x3c269176u ^ prev[5];
|
||||
x[6] = 0x84a03b03u ^ prev[6];
|
||||
x[7] = 0xf8c63294u ^ prev[7];
|
||||
x[8] = 0xff977c5bu ^ prev[8];
|
||||
x[9] = 0xe60def3eu ^ prev[9];
|
||||
x[10] = 0x63630141u ^ prev[10];
|
||||
x[11] = 0xb8fbcb58u ^ prev[11];
|
||||
x[12] = seg ^ prev[12]; x[13] = j ^ prev[13]; x[14] = 0x49676e65u ^ prev[14]; x[15] = 0x756d4d48u ^ prev[15];
|
||||
mh_chacha_block(x, y);
|
||||
__global uint* line = cache + ((seg * MH_SEGMENT_LINES + j) * 16u);
|
||||
for (uint i = 0u; i < 16u; ++i) { line[i] = y[i]; prev[i] = y[i]; }
|
||||
}
|
||||
}
|
||||
|
||||
// M_r: per word (s ^ (RC + rk)) * MUL, then a column round and a diagonal round with the seed-drawn rotations.
|
||||
static inline void mh_mixer(uint* s, uint rk) {
|
||||
s[0] = (s[0] ^ (0xbab68293u + rk)) * 0x42146205u;
|
||||
s[1] = (s[1] ^ (0xcc162340u + rk)) * 0x52cbe0fbu;
|
||||
s[2] = (s[2] ^ (0x6ce151ccu + rk)) * 0x7ecf4a03u;
|
||||
s[3] = (s[3] ^ (0xe62b8997u + rk)) * 0x6728907fu;
|
||||
s[4] = (s[4] ^ (0xc9c80297u + rk)) * 0xd81d9751u;
|
||||
s[5] = (s[5] ^ (0xf74a1654u + rk)) * 0x132952c3u;
|
||||
s[6] = (s[6] ^ (0x3d704af5u + rk)) * 0xf60de277u;
|
||||
s[7] = (s[7] ^ (0x3cf522b7u + rk)) * 0x05358035u;
|
||||
s[8] = (s[8] ^ (0x2b9cac04u + rk)) * 0xbaf6499du;
|
||||
s[9] = (s[9] ^ (0xa880ac10u + rk)) * 0xe4db9667u;
|
||||
s[10] = (s[10] ^ (0x13e5dd1du + rk)) * 0x3e98f45du;
|
||||
s[11] = (s[11] ^ (0x6fc3e233u + rk)) * 0xd0004eddu;
|
||||
s[12] = (s[12] ^ (0x2d83eeacu + rk)) * 0x2691630du;
|
||||
s[13] = (s[13] ^ (0x9006e8bfu + rk)) * 0x9beb3bcfu;
|
||||
s[14] = (s[14] ^ (0x2c4b5362u + rk)) * 0xab310379u;
|
||||
s[15] = (s[15] ^ (0x31b49ee2u + rk)) * 0x99cfb423u;
|
||||
MH_QR(s[0], s[4], s[8], s[12], 20u, 20u, 19u, 4u) MH_QR(s[1], s[5], s[9], s[13], 20u, 20u, 19u, 4u)
|
||||
MH_QR(s[2], s[6], s[10], s[14], 20u, 20u, 19u, 4u) MH_QR(s[3], s[7], s[11], s[15], 20u, 20u, 19u, 4u)
|
||||
MH_QR(s[0], s[5], s[10], s[15], 26u, 3u, 3u, 27u) MH_QR(s[1], s[6], s[11], s[12], 26u, 3u, 3u, 27u)
|
||||
MH_QR(s[2], s[7], s[8], s[13], 26u, 3u, 3u, 27u) MH_QR(s[3], s[4], s[9], s[14], 26u, 3u, 3u, 27u)
|
||||
}
|
||||
|
||||
// Item t: 16 words. s = (K, t * MUL[i] + RC[i]); 8 rounds of mixer + cache line s[0] & mask; final mixer.
|
||||
static inline void mh_item(__global const uint* cache, uint t, uint* s) {
|
||||
s[0] = 0x3067619fu;
|
||||
s[1] = 0x3c269176u;
|
||||
s[2] = 0x84a03b03u;
|
||||
s[3] = 0xf8c63294u;
|
||||
s[4] = 0xff977c5bu;
|
||||
s[5] = 0xe60def3eu;
|
||||
s[6] = 0x63630141u;
|
||||
s[7] = 0xb8fbcb58u;
|
||||
s[8] = t * 0x42146205u + 0xbab68293u;
|
||||
s[9] = t * 0x52cbe0fbu + 0xcc162340u;
|
||||
s[10] = t * 0x7ecf4a03u + 0x6ce151ccu;
|
||||
s[11] = t * 0x6728907fu + 0xe62b8997u;
|
||||
s[12] = t * 0xd81d9751u + 0xc9c80297u;
|
||||
s[13] = t * 0x132952c3u + 0xf74a1654u;
|
||||
s[14] = t * 0xf60de277u + 0x3d704af5u;
|
||||
s[15] = t * 0x05358035u + 0x3cf522b7u;
|
||||
for (uint r = 0u; r < 8u; ++r) {
|
||||
mh_mixer(s, 0x9E3779B9u * (r + 1u));
|
||||
__global const uint* line = cache + ((s[0] & MH_CACHE_LINE_MASK) * 16u);
|
||||
for (uint i = 0u; i < 16u; ++i) s[i] ^= line[i];
|
||||
}
|
||||
mh_mixer(s, 0x9E3779B9u * 9u);
|
||||
}
|
||||
// dataset[w] without the dataset: derive item w >> 4 and take word w & 15.
|
||||
static inline uint mh_word(__global const uint* cache, uint w) { uint s[16]; mh_item(cache, w >> 4u, s); return s[w & 15u]; }
|
||||
|
||||
// Memory-hard dataset (MEMHARD.md). One work-item per cache segment; one work-item per 64-byte dataset item.
|
||||
// The same constants as memhard.h in this pack (one emitter, three dialects).
|
||||
__kernel void igneum_cache_fill(__global uint* cache, uint nSegments) {
|
||||
uint seg = (uint)get_global_id(0);
|
||||
if (seg < nSegments) mh_cache_segment(cache, seg);
|
||||
}
|
||||
__kernel void igneum_build(__global uint* ds, __global const uint* cache, uint nItems) {
|
||||
uint t = (uint)get_global_id(0);
|
||||
if (t < nItems) {
|
||||
uint s[16];
|
||||
mh_item(cache, t, s);
|
||||
__global uint* d = ds + ((ulong)t * 16u);
|
||||
for (uint i = 0u; i < 16u; ++i) d[i] = s[i];
|
||||
}
|
||||
}
|
||||
|
||||
// One hash per work-item. IGNEUM_GROUP is a multiple of 32; lane = lid & 31 and every exchange stays inside the
|
||||
// lane's own aligned run of 32 work-items, exactly like simd_shuffle_xor inside a 32-wide Metal SIMD group and
|
||||
// __shfl_xor_sync inside a CUDA warp. Control flow is uniform (no branches at all).
|
||||
IGNEUM_KERNEL_HASH void igneum_hash(__global const uint* ds, __global ulong* out, uint baseNonce, uint mask) {
|
||||
uint gid = (uint)get_global_id(0);
|
||||
uint lid = (uint)get_local_id(0);
|
||||
uint nonce = baseNonce + gid;
|
||||
uint r0, r1, r2, r3, r4, r5, r6, r7;
|
||||
#if IGNEUM_EXCHANGE == 0
|
||||
IGNEUM_LOCAL_WORDS(xch, 2 * IGNEUM_GROUP);
|
||||
uint xk = 0u;
|
||||
#else
|
||||
(void)lid;
|
||||
#endif
|
||||
{ uint x = nonce ^ 0x774fd410u; x += 0x9e3779b9u; x = splitmix32(x); r0 = x ^ 0x520f91b2u; } // SEEDW[0], 0x9e3779b9u * 1u, SEEDW[1]
|
||||
{ uint x = nonce ^ 0x520f91b2u; x += 0x3c6ef372u; x = splitmix32(x); r1 = x ^ 0x9357786fu; } // SEEDW[1], 0x9e3779b9u * 2u, SEEDW[2]
|
||||
{ uint x = nonce ^ 0x9357786fu; x += 0xdaa66d2bu; x = splitmix32(x); r2 = x ^ 0x8bbe44d7u; } // SEEDW[2], 0x9e3779b9u * 3u, SEEDW[3]
|
||||
{ uint x = nonce ^ 0x8bbe44d7u; x += 0x78dde6e4u; x = splitmix32(x); r3 = x ^ 0x23db18feu; } // SEEDW[3], 0x9e3779b9u * 4u, SEEDW[4]
|
||||
{ uint x = nonce ^ 0x23db18feu; x += 0x1715609du; x = splitmix32(x); r4 = x ^ 0x52022aecu; } // SEEDW[4], 0x9e3779b9u * 5u, SEEDW[5]
|
||||
{ uint x = nonce ^ 0x52022aecu; x += 0xb54cda56u; x = splitmix32(x); r5 = x ^ 0x653ea608u; } // SEEDW[5], 0x9e3779b9u * 6u, SEEDW[6]
|
||||
{ uint x = nonce ^ 0x653ea608u; x += 0x5384540fu; x = splitmix32(x); r6 = x ^ 0x57788e47u; } // SEEDW[6], 0x9e3779b9u * 7u, SEEDW[7]
|
||||
{ uint x = nonce ^ 0x57788e47u; x += 0xf1bbcdc8u; x = splitmix32(x); r7 = x ^ 0x774fd410u; } // SEEDW[7], 0x9e3779b9u * 8u, SEEDW[0]
|
||||
|
||||
for (uint it = 0u; it < 8u; ++it) {
|
||||
uint sel = r0;
|
||||
r2 = r2 + r7 + ((((sel >> 7u) & 1u) != 0u) ? 0xd8952471u : 0x17c8e8eeu); // 0 add
|
||||
r0 = rotr_var(r0, r5); // 1 rotr
|
||||
r5 = r5 + r0 + ((((sel >> 21u) & 1u) != 0u) ? 0x4325cc6au : 0x37d9560au); // 2 add
|
||||
r7 = r7 ^ r5; // 3 xor
|
||||
{ uint b_ = (r0 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r3 = x_; } // 4 load
|
||||
{ uint b_ = (r7 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r5 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r5 = x_; } // 5 load
|
||||
r0 = mul_hi(r0, r5); // 6 mulhi
|
||||
r4 = r4 * r7; // 7 mul
|
||||
r0 = r5 * r6 + r0; // 8 mad
|
||||
{ uint b_ = (r2 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r6 = x_; } // 9 load
|
||||
r0 = r0 ^ r6; // 10 xor
|
||||
r5 = r5 + r3 + ((((sel >> 22u) & 1u) != 0u) ? 0x81619a4cu : 0xbc4eca12u); // 11 add
|
||||
r4 = mul_hi(r4, r2); // 12 mulhi
|
||||
r2 = r2 ^ ds[r0 & mask]; // 13 load
|
||||
r0 = r0 + r2 + ((((sel >> 3u) & 1u) != 0u) ? 0xa557fd2bu : 0xcf9919eeu); // 14 add
|
||||
r4 = r4 + r5 + ((((sel >> 7u) & 1u) != 0u) ? 0x33857f70u : 0x36ec1d20u); // 15 add
|
||||
r7 = r7 + r5 + ((((sel >> 6u) & 1u) != 0u) ? 0x40495714u : 0x42f5db15u); // 16 add
|
||||
r7 = r7 ^ ds[r5 & mask]; // 17 load
|
||||
r3 = r3 ^ r6; // 18 xor
|
||||
{ uint b_ = (r2 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r7 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r7 = x_; } // 19 load
|
||||
{ uint b_ = (r3 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r5 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r5 = x_; } // 20 load
|
||||
r1 = r1 ^ ds[r0 & mask]; // 21 load
|
||||
r1 = mul_hi(r1, r3); // 22 mulhi
|
||||
r1 = rotr_var(r1, r5); // 23 rotr
|
||||
r2 = mul_hi(r2, r0); // 24 mulhi
|
||||
{ uint b_ = (r4 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r0 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r0 = x_; } // 25 load
|
||||
{ uint b_ = (r1 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r0 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r0 = x_; } // 26 load
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r2, 2u); r5 = r5 ^ t_; } // 27 shfl
|
||||
r5 = r5 + r4 + ((((sel >> 12u) & 1u) != 0u) ? 0x58a2eb85u : 0x22029cb9u); // 28 add
|
||||
{ uint b_ = (r5 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r2 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r2 = x_; } // 29 load
|
||||
r6 = r6 * r5; // 30 mul
|
||||
r6 = r6 ^ ds[r2 & mask]; // 31 load
|
||||
r7 = mul_hi(r7, r5); // 32 mulhi
|
||||
r0 = r0 ^ ds[r7 & mask]; // 33 load
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r2, 1u); r7 = r7 ^ t_; } // 34 shfl
|
||||
r7 = r7 * r0; // 35 mul
|
||||
r5 = r5 ^ ds[r7 & mask]; // 36 load
|
||||
r3 = rotr_var(r3, r2); // 37 rotr
|
||||
r6 = rotl_imm(r6, 1u); // 38 rotl
|
||||
r3 = r3 * r0; // 39 mul
|
||||
r3 = mul_hi(r3, r7); // 40 mulhi
|
||||
r5 = r5 ^ r2; // 41 xor
|
||||
r4 = r4 * r0; // 42 mul
|
||||
r3 = r3 + r0 + ((((sel >> 4u) & 1u) != 0u) ? 0xfaaf2d1eu : 0x831bfab3u); // 43 add
|
||||
r0 = r1 * r6 + r0; // 44 mad
|
||||
r6 = rotl_imm(r6, 26u); // 45 rotl
|
||||
r2 = r2 ^ r1; // 46 xor
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r0 = r0 ^ t_; } // 47 shfl
|
||||
r1 = r1 ^ r2; // 48 xor
|
||||
r3 = r3 + r5 + ((((sel >> 7u) & 1u) != 0u) ? 0xc5759120u : 0x31df1a86u); // 49 add
|
||||
r1 = r4 * r1 + r1; // 50 mad
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r4, 2u); r1 = r1 ^ t_; } // 51 shfl
|
||||
r5 = r5 + r4 + ((((sel >> 16u) & 1u) != 0u) ? 0x4e4a2759u : 0x553b85d1u); // 52 add
|
||||
r1 = r1 ^ ds[r3 & mask]; // 53 load
|
||||
r6 = rotl_imm(r6, 21u); // 54 rotl
|
||||
r1 = mul_hi(r1, r4); // 55 mulhi
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r3, 1u); r0 = r0 ^ t_; } // 56 shfl
|
||||
r1 = r1 ^ r2; // 57 xor
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r6, 16u); r3 = r3 ^ t_; } // 58 shfl
|
||||
r5 = r5 * r0; // 59 mul
|
||||
r4 = r4 ^ ds[r2 & mask]; // 60 load
|
||||
r0 = rotr_var(r0, r4); // 61 rotr
|
||||
r6 = r6 * r7; // 62 mul
|
||||
r6 = rotl_imm(r6, 2u); // 63 rotl
|
||||
}
|
||||
uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u);
|
||||
uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u);
|
||||
out[gid] = ((ulong)hi << 32) | (ulong)lo;
|
||||
}
|
||||
|
||||
#if IGNEUM_EXCHANGE != 0
|
||||
// Reports the sub-group size this device uses for a work-group of IGNEUM_GROUP items. host.c runs it only when the
|
||||
// per-kernel query (clGetKernelSubGroupInfoKHR on igneum_hash) is unavailable; that query is preferred because a
|
||||
// compiler may pick a different wave width per kernel (RDNA: wave32 or wave64). See WAVEFRONT.md.
|
||||
IGNEUM_KERNEL_HASH void igneum_probe_subgroup(__global uint* out) {
|
||||
if (get_local_id(0) == 0u) { out[0] = get_sub_group_size(); out[1] = get_num_sub_groups(); }
|
||||
}
|
||||
#endif
|
||||
|
||||
// Header-bound variant (bind.rs): the init words come from initw, not SEEDW. Same body as igneum_hash.
|
||||
IGNEUM_KERNEL_HASH void igneum_hash_bound(__global const uint* ds, __global ulong* out, uint baseNonce, uint mask, __global const uint* initw) {
|
||||
uint gid = (uint)get_global_id(0);
|
||||
uint lid = (uint)get_local_id(0);
|
||||
uint nonce = baseNonce + gid;
|
||||
uint r0, r1, r2, r3, r4, r5, r6, r7;
|
||||
uint iw0 = initw[0], iw1 = initw[1], iw2 = initw[2], iw3 = initw[3], iw4 = initw[4], iw5 = initw[5], iw6 = initw[6], iw7 = initw[7];
|
||||
#if IGNEUM_EXCHANGE == 0
|
||||
IGNEUM_LOCAL_WORDS(xch, 2 * IGNEUM_GROUP);
|
||||
uint xk = 0u;
|
||||
#else
|
||||
(void)lid;
|
||||
#endif
|
||||
{ uint x = nonce ^ iw0; x += 0x9e3779b9u * 1u; x = splitmix32(x); r0 = x ^ iw1; }
|
||||
{ uint x = nonce ^ iw1; x += 0x9e3779b9u * 2u; x = splitmix32(x); r1 = x ^ iw2; }
|
||||
{ uint x = nonce ^ iw2; x += 0x9e3779b9u * 3u; x = splitmix32(x); r2 = x ^ iw3; }
|
||||
{ uint x = nonce ^ iw3; x += 0x9e3779b9u * 4u; x = splitmix32(x); r3 = x ^ iw4; }
|
||||
{ uint x = nonce ^ iw4; x += 0x9e3779b9u * 5u; x = splitmix32(x); r4 = x ^ iw5; }
|
||||
{ uint x = nonce ^ iw5; x += 0x9e3779b9u * 6u; x = splitmix32(x); r5 = x ^ iw6; }
|
||||
{ uint x = nonce ^ iw6; x += 0x9e3779b9u * 7u; x = splitmix32(x); r6 = x ^ iw7; }
|
||||
{ uint x = nonce ^ iw7; x += 0x9e3779b9u * 8u; x = splitmix32(x); r7 = x ^ iw0; }
|
||||
|
||||
for (uint it = 0u; it < 8u; ++it) {
|
||||
uint sel = r0;
|
||||
r2 = r2 + r7 + ((((sel >> 7u) & 1u) != 0u) ? 0xd8952471u : 0x17c8e8eeu); // 0 add
|
||||
r0 = rotr_var(r0, r5); // 1 rotr
|
||||
r5 = r5 + r0 + ((((sel >> 21u) & 1u) != 0u) ? 0x4325cc6au : 0x37d9560au); // 2 add
|
||||
r7 = r7 ^ r5; // 3 xor
|
||||
{ uint b_ = (r0 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r3 = x_; } // 4 load
|
||||
{ uint b_ = (r7 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r5 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r5 = x_; } // 5 load
|
||||
r0 = mul_hi(r0, r5); // 6 mulhi
|
||||
r4 = r4 * r7; // 7 mul
|
||||
r0 = r5 * r6 + r0; // 8 mad
|
||||
{ uint b_ = (r2 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r6 = x_; } // 9 load
|
||||
r0 = r0 ^ r6; // 10 xor
|
||||
r5 = r5 + r3 + ((((sel >> 22u) & 1u) != 0u) ? 0x81619a4cu : 0xbc4eca12u); // 11 add
|
||||
r4 = mul_hi(r4, r2); // 12 mulhi
|
||||
r2 = r2 ^ ds[r0 & mask]; // 13 load
|
||||
r0 = r0 + r2 + ((((sel >> 3u) & 1u) != 0u) ? 0xa557fd2bu : 0xcf9919eeu); // 14 add
|
||||
r4 = r4 + r5 + ((((sel >> 7u) & 1u) != 0u) ? 0x33857f70u : 0x36ec1d20u); // 15 add
|
||||
r7 = r7 + r5 + ((((sel >> 6u) & 1u) != 0u) ? 0x40495714u : 0x42f5db15u); // 16 add
|
||||
r7 = r7 ^ ds[r5 & mask]; // 17 load
|
||||
r3 = r3 ^ r6; // 18 xor
|
||||
{ uint b_ = (r2 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r7 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r7 = x_; } // 19 load
|
||||
{ uint b_ = (r3 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r5 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r5 = x_; } // 20 load
|
||||
r1 = r1 ^ ds[r0 & mask]; // 21 load
|
||||
r1 = mul_hi(r1, r3); // 22 mulhi
|
||||
r1 = rotr_var(r1, r5); // 23 rotr
|
||||
r2 = mul_hi(r2, r0); // 24 mulhi
|
||||
{ uint b_ = (r4 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r0 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r0 = x_; } // 25 load
|
||||
{ uint b_ = (r1 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r0 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r0 = x_; } // 26 load
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r2, 2u); r5 = r5 ^ t_; } // 27 shfl
|
||||
r5 = r5 + r4 + ((((sel >> 12u) & 1u) != 0u) ? 0x58a2eb85u : 0x22029cb9u); // 28 add
|
||||
{ uint b_ = (r5 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r2 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r2 = x_; } // 29 load
|
||||
r6 = r6 * r5; // 30 mul
|
||||
r6 = r6 ^ ds[r2 & mask]; // 31 load
|
||||
r7 = mul_hi(r7, r5); // 32 mulhi
|
||||
r0 = r0 ^ ds[r7 & mask]; // 33 load
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r2, 1u); r7 = r7 ^ t_; } // 34 shfl
|
||||
r7 = r7 * r0; // 35 mul
|
||||
r5 = r5 ^ ds[r7 & mask]; // 36 load
|
||||
r3 = rotr_var(r3, r2); // 37 rotr
|
||||
r6 = rotl_imm(r6, 1u); // 38 rotl
|
||||
r3 = r3 * r0; // 39 mul
|
||||
r3 = mul_hi(r3, r7); // 40 mulhi
|
||||
r5 = r5 ^ r2; // 41 xor
|
||||
r4 = r4 * r0; // 42 mul
|
||||
r3 = r3 + r0 + ((((sel >> 4u) & 1u) != 0u) ? 0xfaaf2d1eu : 0x831bfab3u); // 43 add
|
||||
r0 = r1 * r6 + r0; // 44 mad
|
||||
r6 = rotl_imm(r6, 26u); // 45 rotl
|
||||
r2 = r2 ^ r1; // 46 xor
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r0 = r0 ^ t_; } // 47 shfl
|
||||
r1 = r1 ^ r2; // 48 xor
|
||||
r3 = r3 + r5 + ((((sel >> 7u) & 1u) != 0u) ? 0xc5759120u : 0x31df1a86u); // 49 add
|
||||
r1 = r4 * r1 + r1; // 50 mad
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r4, 2u); r1 = r1 ^ t_; } // 51 shfl
|
||||
r5 = r5 + r4 + ((((sel >> 16u) & 1u) != 0u) ? 0x4e4a2759u : 0x553b85d1u); // 52 add
|
||||
r1 = r1 ^ ds[r3 & mask]; // 53 load
|
||||
r6 = rotl_imm(r6, 21u); // 54 rotl
|
||||
r1 = mul_hi(r1, r4); // 55 mulhi
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r3, 1u); r0 = r0 ^ t_; } // 56 shfl
|
||||
r1 = r1 ^ r2; // 57 xor
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r6, 16u); r3 = r3 ^ t_; } // 58 shfl
|
||||
r5 = r5 * r0; // 59 mul
|
||||
r4 = r4 ^ ds[r2 & mask]; // 60 load
|
||||
r0 = rotr_var(r0, r4); // 61 rotr
|
||||
r6 = r6 * r7; // 62 mul
|
||||
r6 = rotl_imm(r6, 2u); // 63 rotl
|
||||
}
|
||||
uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u);
|
||||
uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u);
|
||||
out[gid] = ((ulong)hi << 32) | (ulong)lo;
|
||||
}
|
||||
123
proto-cuda/packs-readwidth/mixA-2/kernel_bound.cu
Normal file
123
proto-cuda/packs-readwidth/mixA-2/kernel_bound.cu
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
// Generated by igneum-pow export (generator v2) for seed "igneum-readwidth/A/2". Do not edit by hand.
|
||||
// Header-bound twin of igneum_hash in kernel.cu: the init words come from a kernel argument, not SEEDW.
|
||||
// Host declarations (also in program_bound.h if present):
|
||||
// struct IgneumInitWords { uint32_t w[8]; };
|
||||
// cudaError_t igneum_launch_hash_bound(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask,
|
||||
// IgneumInitWords iw, uint32_t nonces, uint32_t blockWarps);
|
||||
// cudaError_t igneum_hash_bound_info(int* numRegs, int* blocksPerSM, uint32_t blockWarps);
|
||||
#include <cuda_runtime.h>
|
||||
#include <cstdint>
|
||||
#include "program.h"
|
||||
|
||||
struct IgneumInitWords { uint32_t w[8]; };
|
||||
|
||||
__device__ __forceinline__ uint32_t splitmix32(uint32_t x) {
|
||||
x ^= x >> 16; x *= 0x7feb352du;
|
||||
x ^= x >> 15; x *= 0x846ca68bu;
|
||||
x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
__device__ __forceinline__ uint32_t rotl_imm(uint32_t x, uint32_t n) { return (x << n) | (x >> (32u - n)); }
|
||||
__device__ __forceinline__ uint32_t rotr_var(uint32_t x, uint32_t n) { n &= 31u; return (x >> n) | (x << ((32u - n) & 31u)); }
|
||||
|
||||
__global__ void igneum_hash_bound(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask, IgneumInitWords iw) {
|
||||
uint32_t gid = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
uint32_t nonce = baseNonce + gid;
|
||||
uint32_t r0, r1, r2, r3, r4, r5, r6, r7;
|
||||
{ uint32_t x = nonce ^ iw.w[0]; x += 0x9e3779b9u * 1u; x = splitmix32(x); r0 = x ^ iw.w[1]; }
|
||||
{ uint32_t x = nonce ^ iw.w[1]; x += 0x9e3779b9u * 2u; x = splitmix32(x); r1 = x ^ iw.w[2]; }
|
||||
{ uint32_t x = nonce ^ iw.w[2]; x += 0x9e3779b9u * 3u; x = splitmix32(x); r2 = x ^ iw.w[3]; }
|
||||
{ uint32_t x = nonce ^ iw.w[3]; x += 0x9e3779b9u * 4u; x = splitmix32(x); r3 = x ^ iw.w[4]; }
|
||||
{ uint32_t x = nonce ^ iw.w[4]; x += 0x9e3779b9u * 5u; x = splitmix32(x); r4 = x ^ iw.w[5]; }
|
||||
{ uint32_t x = nonce ^ iw.w[5]; x += 0x9e3779b9u * 6u; x = splitmix32(x); r5 = x ^ iw.w[6]; }
|
||||
{ uint32_t x = nonce ^ iw.w[6]; x += 0x9e3779b9u * 7u; x = splitmix32(x); r6 = x ^ iw.w[7]; }
|
||||
{ uint32_t x = nonce ^ iw.w[7]; x += 0x9e3779b9u * 8u; x = splitmix32(x); r7 = x ^ iw.w[0]; }
|
||||
|
||||
for (uint32_t it = 0u; it < 8u; ++it) {
|
||||
uint32_t sel = r0;
|
||||
r2 = r2 + r7 + ((((sel >> 7u) & 1u) != 0u) ? 0xd8952471u : 0x17c8e8eeu); // 0 add
|
||||
r0 = rotr_var(r0, r5); // 1 rotr
|
||||
r5 = r5 + r0 + ((((sel >> 21u) & 1u) != 0u) ? 0x4325cc6au : 0x37d9560au); // 2 add
|
||||
r7 = r7 ^ r5; // 3 xor
|
||||
{ uint32_t b_ = (r0 & mask) & ~15u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint32_t x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r3 = x_; } // 4 load
|
||||
{ uint32_t b_ = (r7 & mask) & ~3u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint32_t x_ = r5 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r5 = x_; } // 5 load
|
||||
r0 = __umulhi(r0, r5); // 6 mulhi
|
||||
r4 = r4 * r7; // 7 mul
|
||||
r0 = r5 * r6 + r0; // 8 mad
|
||||
{ uint32_t b_ = (r2 & mask) & ~3u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint32_t x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r6 = x_; } // 9 load
|
||||
r0 = r0 ^ r6; // 10 xor
|
||||
r5 = r5 + r3 + ((((sel >> 22u) & 1u) != 0u) ? 0x81619a4cu : 0xbc4eca12u); // 11 add
|
||||
r4 = __umulhi(r4, r2); // 12 mulhi
|
||||
r2 = r2 ^ ds[r0 & mask]; // 13 load
|
||||
r0 = r0 + r2 + ((((sel >> 3u) & 1u) != 0u) ? 0xa557fd2bu : 0xcf9919eeu); // 14 add
|
||||
r4 = r4 + r5 + ((((sel >> 7u) & 1u) != 0u) ? 0x33857f70u : 0x36ec1d20u); // 15 add
|
||||
r7 = r7 + r5 + ((((sel >> 6u) & 1u) != 0u) ? 0x40495714u : 0x42f5db15u); // 16 add
|
||||
r7 = r7 ^ ds[r5 & mask]; // 17 load
|
||||
r3 = r3 ^ r6; // 18 xor
|
||||
{ uint32_t b_ = (r2 & mask) & ~15u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint32_t x_ = r7 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r7 = x_; } // 19 load
|
||||
{ uint32_t b_ = (r3 & mask) & ~3u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint32_t x_ = r5 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r5 = x_; } // 20 load
|
||||
r1 = r1 ^ ds[r0 & mask]; // 21 load
|
||||
r1 = __umulhi(r1, r3); // 22 mulhi
|
||||
r1 = rotr_var(r1, r5); // 23 rotr
|
||||
r2 = __umulhi(r2, r0); // 24 mulhi
|
||||
{ uint32_t b_ = (r4 & mask) & ~15u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint32_t x_ = r0 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r0 = x_; } // 25 load
|
||||
{ uint32_t b_ = (r1 & mask) & ~3u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint32_t x_ = r0 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r0 = x_; } // 26 load
|
||||
r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r2, 2); // 27 shfl
|
||||
r5 = r5 + r4 + ((((sel >> 12u) & 1u) != 0u) ? 0x58a2eb85u : 0x22029cb9u); // 28 add
|
||||
{ uint32_t b_ = (r5 & mask) & ~3u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint32_t x_ = r2 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r2 = x_; } // 29 load
|
||||
r6 = r6 * r5; // 30 mul
|
||||
r6 = r6 ^ ds[r2 & mask]; // 31 load
|
||||
r7 = __umulhi(r7, r5); // 32 mulhi
|
||||
r0 = r0 ^ ds[r7 & mask]; // 33 load
|
||||
r7 = r7 ^ __shfl_xor_sync(0xffffffffu, r2, 1); // 34 shfl
|
||||
r7 = r7 * r0; // 35 mul
|
||||
r5 = r5 ^ ds[r7 & mask]; // 36 load
|
||||
r3 = rotr_var(r3, r2); // 37 rotr
|
||||
r6 = rotl_imm(r6, 1u); // 38 rotl
|
||||
r3 = r3 * r0; // 39 mul
|
||||
r3 = __umulhi(r3, r7); // 40 mulhi
|
||||
r5 = r5 ^ r2; // 41 xor
|
||||
r4 = r4 * r0; // 42 mul
|
||||
r3 = r3 + r0 + ((((sel >> 4u) & 1u) != 0u) ? 0xfaaf2d1eu : 0x831bfab3u); // 43 add
|
||||
r0 = r1 * r6 + r0; // 44 mad
|
||||
r6 = rotl_imm(r6, 26u); // 45 rotl
|
||||
r2 = r2 ^ r1; // 46 xor
|
||||
r0 = r0 ^ __shfl_xor_sync(0xffffffffu, r7, 2); // 47 shfl
|
||||
r1 = r1 ^ r2; // 48 xor
|
||||
r3 = r3 + r5 + ((((sel >> 7u) & 1u) != 0u) ? 0xc5759120u : 0x31df1a86u); // 49 add
|
||||
r1 = r4 * r1 + r1; // 50 mad
|
||||
r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r4, 2); // 51 shfl
|
||||
r5 = r5 + r4 + ((((sel >> 16u) & 1u) != 0u) ? 0x4e4a2759u : 0x553b85d1u); // 52 add
|
||||
r1 = r1 ^ ds[r3 & mask]; // 53 load
|
||||
r6 = rotl_imm(r6, 21u); // 54 rotl
|
||||
r1 = __umulhi(r1, r4); // 55 mulhi
|
||||
r0 = r0 ^ __shfl_xor_sync(0xffffffffu, r3, 1); // 56 shfl
|
||||
r1 = r1 ^ r2; // 57 xor
|
||||
r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r6, 16); // 58 shfl
|
||||
r5 = r5 * r0; // 59 mul
|
||||
r4 = r4 ^ ds[r2 & mask]; // 60 load
|
||||
r0 = rotr_var(r0, r4); // 61 rotr
|
||||
r6 = r6 * r7; // 62 mul
|
||||
r6 = rotl_imm(r6, 2u); // 63 rotl
|
||||
}
|
||||
uint32_t lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u);
|
||||
uint32_t hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u);
|
||||
out[gid] = ((uint64_t)hi << 32) | (uint64_t)lo;
|
||||
}
|
||||
|
||||
cudaError_t igneum_launch_hash_bound(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask,
|
||||
IgneumInitWords iw, uint32_t nonces, uint32_t blockWarps) {
|
||||
if (blockWarps == 0u || blockWarps > 32u) return cudaErrorInvalidValue;
|
||||
uint32_t block = 32u * blockWarps;
|
||||
if (nonces == 0u || (nonces % block) != 0u) return cudaErrorInvalidValue;
|
||||
igneum_hash_bound<<<nonces / block, block>>>(ds, out, baseNonce, mask, iw);
|
||||
return cudaGetLastError();
|
||||
}
|
||||
|
||||
cudaError_t igneum_hash_bound_info(int* numRegs, int* blocksPerSM, uint32_t blockWarps) {
|
||||
cudaFuncAttributes attr;
|
||||
cudaError_t e = cudaFuncGetAttributes(&attr, igneum_hash_bound);
|
||||
if (e != cudaSuccess) return e;
|
||||
*numRegs = attr.numRegs;
|
||||
return cudaOccupancyMaxActiveBlocksPerMultiprocessor(blocksPerSM, igneum_hash_bound, (int)(32u * blockWarps), 0);
|
||||
}
|
||||
108
proto-cuda/packs-readwidth/mixA-2/memhard.h
Normal file
108
proto-cuda/packs-readwidth/mixA-2/memhard.h
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
// Generated by igneum-pow export (generator v2) for seed "igneum-readwidth/A/2". Do not edit by hand.
|
||||
// Memory-hard dataset core, the same text that the Mac's Metal kernels and CPU verifier were checked against.
|
||||
// Included by kernel.cu (device), host.cu (host reference) and proto-opencl/host.c (C99 host reference).
|
||||
// See proto-metal/MEMHARD.md for the construction. kernel.cl carries the same text in OpenCL C.
|
||||
#pragma once
|
||||
#ifdef __cplusplus
|
||||
#include <cstdint>
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
#if defined(__CUDACC__)
|
||||
#define IGNEUM_HD __host__ __device__ __forceinline__
|
||||
#elif defined(_MSC_VER) && !defined(__cplusplus)
|
||||
#define IGNEUM_HD static __inline
|
||||
#else
|
||||
#define IGNEUM_HD static inline
|
||||
#endif
|
||||
// Memory-hard dataset core (MEMHARD.md). Cache: 2^26 words in 2^16 segments of 64 chained ChaCha12 lines.
|
||||
// Item: 8 rounds of seed-parameterised mixer + one 64-byte cache read, then a final mixer. All parameters are literals.
|
||||
#define MH_CACHE_LINE_MASK 0x003fffffu
|
||||
#define MH_SEGMENT_LINES 64u
|
||||
#define MH_QR(a, b, c, d, r1, r2, r3, r4) { a += b; d ^= a; d = mh_rotl(d, r1); c += d; b ^= c; b = mh_rotl(b, r2); a += b; d ^= a; d = mh_rotl(d, r3); c += d; b ^= c; b = mh_rotl(b, r4); }
|
||||
IGNEUM_HD uint32_t mh_rotl(uint32_t x, uint32_t n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 at every call site
|
||||
|
||||
// y = ChaCha12 core(x) + x
|
||||
IGNEUM_HD void mh_chacha_block(const uint32_t* x, uint32_t* y) {
|
||||
for (uint32_t i = 0u; i < 16u; ++i) y[i] = x[i];
|
||||
for (uint32_t r = 0u; r < 6u; ++r) {
|
||||
MH_QR(y[0], y[4], y[8], y[12], 16u, 12u, 8u, 7u) MH_QR(y[1], y[5], y[9], y[13], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[2], y[6], y[10], y[14], 16u, 12u, 8u, 7u) MH_QR(y[3], y[7], y[11], y[15], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[0], y[5], y[10], y[15], 16u, 12u, 8u, 7u) MH_QR(y[1], y[6], y[11], y[12], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[2], y[7], y[8], y[13], 16u, 12u, 8u, 7u) MH_QR(y[3], y[4], y[9], y[14], 16u, 12u, 8u, 7u)
|
||||
}
|
||||
for (uint32_t i = 0u; i < 16u; ++i) y[i] += x[i];
|
||||
}
|
||||
|
||||
// One cache segment: 64 chained lines written at cache[seg * 1024]. in_j = prev ^ (sigma || K || seg || j || tag), prev_0 = 0.
|
||||
IGNEUM_HD void mh_cache_segment(uint32_t* cache, uint32_t seg) {
|
||||
uint32_t prev[16]; uint32_t x[16]; uint32_t y[16];
|
||||
for (uint32_t i = 0u; i < 16u; ++i) prev[i] = 0u;
|
||||
for (uint32_t j = 0u; j < MH_SEGMENT_LINES; ++j) {
|
||||
x[0] = 0x61707865u ^ prev[0]; x[1] = 0x3320646eu ^ prev[1]; x[2] = 0x79622d32u ^ prev[2]; x[3] = 0x6b206574u ^ prev[3];
|
||||
x[4] = 0x3067619fu ^ prev[4];
|
||||
x[5] = 0x3c269176u ^ prev[5];
|
||||
x[6] = 0x84a03b03u ^ prev[6];
|
||||
x[7] = 0xf8c63294u ^ prev[7];
|
||||
x[8] = 0xff977c5bu ^ prev[8];
|
||||
x[9] = 0xe60def3eu ^ prev[9];
|
||||
x[10] = 0x63630141u ^ prev[10];
|
||||
x[11] = 0xb8fbcb58u ^ prev[11];
|
||||
x[12] = seg ^ prev[12]; x[13] = j ^ prev[13]; x[14] = 0x49676e65u ^ prev[14]; x[15] = 0x756d4d48u ^ prev[15];
|
||||
mh_chacha_block(x, y);
|
||||
uint32_t* line = cache + ((seg * MH_SEGMENT_LINES + j) * 16u);
|
||||
for (uint32_t i = 0u; i < 16u; ++i) { line[i] = y[i]; prev[i] = y[i]; }
|
||||
}
|
||||
}
|
||||
|
||||
// M_r: per word (s ^ (RC + rk)) * MUL, then a column round and a diagonal round with the seed-drawn rotations.
|
||||
IGNEUM_HD void mh_mixer(uint32_t* s, uint32_t rk) {
|
||||
s[0] = (s[0] ^ (0xbab68293u + rk)) * 0x42146205u;
|
||||
s[1] = (s[1] ^ (0xcc162340u + rk)) * 0x52cbe0fbu;
|
||||
s[2] = (s[2] ^ (0x6ce151ccu + rk)) * 0x7ecf4a03u;
|
||||
s[3] = (s[3] ^ (0xe62b8997u + rk)) * 0x6728907fu;
|
||||
s[4] = (s[4] ^ (0xc9c80297u + rk)) * 0xd81d9751u;
|
||||
s[5] = (s[5] ^ (0xf74a1654u + rk)) * 0x132952c3u;
|
||||
s[6] = (s[6] ^ (0x3d704af5u + rk)) * 0xf60de277u;
|
||||
s[7] = (s[7] ^ (0x3cf522b7u + rk)) * 0x05358035u;
|
||||
s[8] = (s[8] ^ (0x2b9cac04u + rk)) * 0xbaf6499du;
|
||||
s[9] = (s[9] ^ (0xa880ac10u + rk)) * 0xe4db9667u;
|
||||
s[10] = (s[10] ^ (0x13e5dd1du + rk)) * 0x3e98f45du;
|
||||
s[11] = (s[11] ^ (0x6fc3e233u + rk)) * 0xd0004eddu;
|
||||
s[12] = (s[12] ^ (0x2d83eeacu + rk)) * 0x2691630du;
|
||||
s[13] = (s[13] ^ (0x9006e8bfu + rk)) * 0x9beb3bcfu;
|
||||
s[14] = (s[14] ^ (0x2c4b5362u + rk)) * 0xab310379u;
|
||||
s[15] = (s[15] ^ (0x31b49ee2u + rk)) * 0x99cfb423u;
|
||||
MH_QR(s[0], s[4], s[8], s[12], 20u, 20u, 19u, 4u) MH_QR(s[1], s[5], s[9], s[13], 20u, 20u, 19u, 4u)
|
||||
MH_QR(s[2], s[6], s[10], s[14], 20u, 20u, 19u, 4u) MH_QR(s[3], s[7], s[11], s[15], 20u, 20u, 19u, 4u)
|
||||
MH_QR(s[0], s[5], s[10], s[15], 26u, 3u, 3u, 27u) MH_QR(s[1], s[6], s[11], s[12], 26u, 3u, 3u, 27u)
|
||||
MH_QR(s[2], s[7], s[8], s[13], 26u, 3u, 3u, 27u) MH_QR(s[3], s[4], s[9], s[14], 26u, 3u, 3u, 27u)
|
||||
}
|
||||
|
||||
// Item t: 16 words. s = (K, t * MUL[i] + RC[i]); 8 rounds of mixer + cache line s[0] & mask; final mixer.
|
||||
IGNEUM_HD void mh_item(const uint32_t* cache, uint32_t t, uint32_t* s) {
|
||||
s[0] = 0x3067619fu;
|
||||
s[1] = 0x3c269176u;
|
||||
s[2] = 0x84a03b03u;
|
||||
s[3] = 0xf8c63294u;
|
||||
s[4] = 0xff977c5bu;
|
||||
s[5] = 0xe60def3eu;
|
||||
s[6] = 0x63630141u;
|
||||
s[7] = 0xb8fbcb58u;
|
||||
s[8] = t * 0x42146205u + 0xbab68293u;
|
||||
s[9] = t * 0x52cbe0fbu + 0xcc162340u;
|
||||
s[10] = t * 0x7ecf4a03u + 0x6ce151ccu;
|
||||
s[11] = t * 0x6728907fu + 0xe62b8997u;
|
||||
s[12] = t * 0xd81d9751u + 0xc9c80297u;
|
||||
s[13] = t * 0x132952c3u + 0xf74a1654u;
|
||||
s[14] = t * 0xf60de277u + 0x3d704af5u;
|
||||
s[15] = t * 0x05358035u + 0x3cf522b7u;
|
||||
for (uint32_t r = 0u; r < 8u; ++r) {
|
||||
mh_mixer(s, 0x9E3779B9u * (r + 1u));
|
||||
const uint32_t* line = cache + ((s[0] & MH_CACHE_LINE_MASK) * 16u);
|
||||
for (uint32_t i = 0u; i < 16u; ++i) s[i] ^= line[i];
|
||||
}
|
||||
mh_mixer(s, 0x9E3779B9u * 9u);
|
||||
}
|
||||
// dataset[w] without the dataset: derive item w >> 4 and take word w & 15.
|
||||
IGNEUM_HD uint32_t mh_word(const uint32_t* cache, uint32_t w) { uint32_t s[16]; mh_item(cache, w >> 4u, s); return s[w & 15u]; }
|
||||
106
proto-cuda/packs-readwidth/mixA-2/memhard.metal
Normal file
106
proto-cuda/packs-readwidth/mixA-2/memhard.metal
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
#include <metal_stdlib>
|
||||
using namespace metal;
|
||||
// Memory-hard dataset core (MEMHARD.md). Cache: 2^26 words in 2^16 segments of 64 chained ChaCha12 lines.
|
||||
// Item: 8 rounds of seed-parameterised mixer + one 64-byte cache read, then a final mixer. All parameters are literals.
|
||||
#define MH_CACHE_LINE_MASK 0x003fffffu
|
||||
#define MH_SEGMENT_LINES 64u
|
||||
#define MH_QR(a, b, c, d, r1, r2, r3, r4) { a += b; d ^= a; d = mh_rotl(d, r1); c += d; b ^= c; b = mh_rotl(b, r2); a += b; d ^= a; d = mh_rotl(d, r3); c += d; b ^= c; b = mh_rotl(b, r4); }
|
||||
inline uint mh_rotl(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 at every call site
|
||||
|
||||
// y = ChaCha12 core(x) + x
|
||||
inline void mh_chacha_block(const thread uint* x, thread uint* y) {
|
||||
for (uint i = 0u; i < 16u; ++i) y[i] = x[i];
|
||||
for (uint r = 0u; r < 6u; ++r) {
|
||||
MH_QR(y[0], y[4], y[8], y[12], 16u, 12u, 8u, 7u) MH_QR(y[1], y[5], y[9], y[13], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[2], y[6], y[10], y[14], 16u, 12u, 8u, 7u) MH_QR(y[3], y[7], y[11], y[15], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[0], y[5], y[10], y[15], 16u, 12u, 8u, 7u) MH_QR(y[1], y[6], y[11], y[12], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[2], y[7], y[8], y[13], 16u, 12u, 8u, 7u) MH_QR(y[3], y[4], y[9], y[14], 16u, 12u, 8u, 7u)
|
||||
}
|
||||
for (uint i = 0u; i < 16u; ++i) y[i] += x[i];
|
||||
}
|
||||
|
||||
// One cache segment: 64 chained lines written at cache[seg * 1024]. in_j = prev ^ (sigma || K || seg || j || tag), prev_0 = 0.
|
||||
inline void mh_cache_segment(device uint* cache, uint seg) {
|
||||
uint prev[16]; uint x[16]; uint y[16];
|
||||
for (uint i = 0u; i < 16u; ++i) prev[i] = 0u;
|
||||
for (uint j = 0u; j < MH_SEGMENT_LINES; ++j) {
|
||||
x[0] = 0x61707865u ^ prev[0]; x[1] = 0x3320646eu ^ prev[1]; x[2] = 0x79622d32u ^ prev[2]; x[3] = 0x6b206574u ^ prev[3];
|
||||
x[4] = 0x3067619fu ^ prev[4];
|
||||
x[5] = 0x3c269176u ^ prev[5];
|
||||
x[6] = 0x84a03b03u ^ prev[6];
|
||||
x[7] = 0xf8c63294u ^ prev[7];
|
||||
x[8] = 0xff977c5bu ^ prev[8];
|
||||
x[9] = 0xe60def3eu ^ prev[9];
|
||||
x[10] = 0x63630141u ^ prev[10];
|
||||
x[11] = 0xb8fbcb58u ^ prev[11];
|
||||
x[12] = seg ^ prev[12]; x[13] = j ^ prev[13]; x[14] = 0x49676e65u ^ prev[14]; x[15] = 0x756d4d48u ^ prev[15];
|
||||
mh_chacha_block(x, y);
|
||||
device uint* line = cache + ((seg * MH_SEGMENT_LINES + j) * 16u);
|
||||
for (uint i = 0u; i < 16u; ++i) { line[i] = y[i]; prev[i] = y[i]; }
|
||||
}
|
||||
}
|
||||
|
||||
// M_r: per word (s ^ (RC + rk)) * MUL, then a column round and a diagonal round with the seed-drawn rotations.
|
||||
inline void mh_mixer(thread uint* s, uint rk) {
|
||||
s[0] = (s[0] ^ (0xbab68293u + rk)) * 0x42146205u;
|
||||
s[1] = (s[1] ^ (0xcc162340u + rk)) * 0x52cbe0fbu;
|
||||
s[2] = (s[2] ^ (0x6ce151ccu + rk)) * 0x7ecf4a03u;
|
||||
s[3] = (s[3] ^ (0xe62b8997u + rk)) * 0x6728907fu;
|
||||
s[4] = (s[4] ^ (0xc9c80297u + rk)) * 0xd81d9751u;
|
||||
s[5] = (s[5] ^ (0xf74a1654u + rk)) * 0x132952c3u;
|
||||
s[6] = (s[6] ^ (0x3d704af5u + rk)) * 0xf60de277u;
|
||||
s[7] = (s[7] ^ (0x3cf522b7u + rk)) * 0x05358035u;
|
||||
s[8] = (s[8] ^ (0x2b9cac04u + rk)) * 0xbaf6499du;
|
||||
s[9] = (s[9] ^ (0xa880ac10u + rk)) * 0xe4db9667u;
|
||||
s[10] = (s[10] ^ (0x13e5dd1du + rk)) * 0x3e98f45du;
|
||||
s[11] = (s[11] ^ (0x6fc3e233u + rk)) * 0xd0004eddu;
|
||||
s[12] = (s[12] ^ (0x2d83eeacu + rk)) * 0x2691630du;
|
||||
s[13] = (s[13] ^ (0x9006e8bfu + rk)) * 0x9beb3bcfu;
|
||||
s[14] = (s[14] ^ (0x2c4b5362u + rk)) * 0xab310379u;
|
||||
s[15] = (s[15] ^ (0x31b49ee2u + rk)) * 0x99cfb423u;
|
||||
MH_QR(s[0], s[4], s[8], s[12], 20u, 20u, 19u, 4u) MH_QR(s[1], s[5], s[9], s[13], 20u, 20u, 19u, 4u)
|
||||
MH_QR(s[2], s[6], s[10], s[14], 20u, 20u, 19u, 4u) MH_QR(s[3], s[7], s[11], s[15], 20u, 20u, 19u, 4u)
|
||||
MH_QR(s[0], s[5], s[10], s[15], 26u, 3u, 3u, 27u) MH_QR(s[1], s[6], s[11], s[12], 26u, 3u, 3u, 27u)
|
||||
MH_QR(s[2], s[7], s[8], s[13], 26u, 3u, 3u, 27u) MH_QR(s[3], s[4], s[9], s[14], 26u, 3u, 3u, 27u)
|
||||
}
|
||||
|
||||
// Item t: 16 words. s = (K, t * MUL[i] + RC[i]); 8 rounds of mixer + cache line s[0] & mask; final mixer.
|
||||
inline void mh_item(device const uint* cache, uint t, thread uint* s) {
|
||||
s[0] = 0x3067619fu;
|
||||
s[1] = 0x3c269176u;
|
||||
s[2] = 0x84a03b03u;
|
||||
s[3] = 0xf8c63294u;
|
||||
s[4] = 0xff977c5bu;
|
||||
s[5] = 0xe60def3eu;
|
||||
s[6] = 0x63630141u;
|
||||
s[7] = 0xb8fbcb58u;
|
||||
s[8] = t * 0x42146205u + 0xbab68293u;
|
||||
s[9] = t * 0x52cbe0fbu + 0xcc162340u;
|
||||
s[10] = t * 0x7ecf4a03u + 0x6ce151ccu;
|
||||
s[11] = t * 0x6728907fu + 0xe62b8997u;
|
||||
s[12] = t * 0xd81d9751u + 0xc9c80297u;
|
||||
s[13] = t * 0x132952c3u + 0xf74a1654u;
|
||||
s[14] = t * 0xf60de277u + 0x3d704af5u;
|
||||
s[15] = t * 0x05358035u + 0x3cf522b7u;
|
||||
for (uint r = 0u; r < 8u; ++r) {
|
||||
mh_mixer(s, 0x9E3779B9u * (r + 1u));
|
||||
device const uint* line = cache + ((s[0] & MH_CACHE_LINE_MASK) * 16u);
|
||||
for (uint i = 0u; i < 16u; ++i) s[i] ^= line[i];
|
||||
}
|
||||
mh_mixer(s, 0x9E3779B9u * 9u);
|
||||
}
|
||||
// dataset[w] without the dataset: derive item w >> 4 and take word w & 15.
|
||||
inline uint mh_word(device const uint* cache, uint w) { uint s[16]; mh_item(cache, w >> 4u, s); return s[w & 15u]; }
|
||||
|
||||
// One thread per segment (2^16 threads).
|
||||
kernel void igneum_cache_fill(device uint* cache [[buffer(0)]], uint gid [[thread_position_in_grid]]) {
|
||||
mh_cache_segment(cache, gid);
|
||||
}
|
||||
// One thread per 64-byte item (dataset words / 16 threads).
|
||||
kernel void igneum_build(device const uint* cache [[buffer(0)]], device uint* dataset [[buffer(1)]],
|
||||
uint gid [[thread_position_in_grid]]) {
|
||||
uint s[16];
|
||||
mh_item(cache, gid, s);
|
||||
device uint* d = dataset + gid * 16u;
|
||||
for (uint i = 0u; i < 16u; ++i) d[i] = s[i];
|
||||
}
|
||||
60
proto-cuda/packs-readwidth/mixA-2/program.h
Normal file
60
proto-cuda/packs-readwidth/mixA-2/program.h
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
// Generated by igneum-pow export (generator v2) for seed "igneum-readwidth/A/2". Do not edit by hand.
|
||||
// Program metadata for host.cu plus the launch wrappers defined in kernel.cu.
|
||||
// Also included by proto-opencl/host.c (C99), which defines IGNEUM_NO_CUDA first and reads only the macros.
|
||||
#pragma once
|
||||
#ifdef __cplusplus
|
||||
#include <cstdint>
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
#ifndef IGNEUM_NO_CUDA
|
||||
#include <cuda_runtime.h>
|
||||
#endif
|
||||
|
||||
#define IGNEUM_SEED_STRING "igneum-readwidth/A/2"
|
||||
#define IGNEUM_SEED_BYTES_HEX "69676e65756d2d7265616477696474682f412f32"
|
||||
#define IGNEUM_GENERATOR 2
|
||||
#define IGNEUM_PROGRAM_ATTEMPT 0
|
||||
#define IGNEUM_PROGRAM_ID 0x11d47bbfc868120eull
|
||||
#define IGNEUM_DAY_STRING "2026-10-03"
|
||||
#define IGNEUM_DAY_BYTES_HEX "6461792f323032362d31302d3033"
|
||||
#define IGNEUM_DAY0 0x3067619fu
|
||||
#define IGNEUM_DAY1 0x3c269176u
|
||||
#define IGNEUM_DATASET_LOG2 28
|
||||
#define IGNEUM_MASK 0x0fffffffu
|
||||
#define IGNEUM_LANES 32
|
||||
#define IGNEUM_ITERATIONS 8
|
||||
#define IGNEUM_INSTR_COUNT 64
|
||||
#define IGNEUM_LOADS_PER_HASH 128
|
||||
#define IGNEUM_WIDE_LOADS_PER_HASH 0
|
||||
#define IGNEUM_OP_MIX "load=16 add=10 mul=7 mulhi=7 xor=7 shfl=6 rotl=4 rotr=4 mad=3"
|
||||
// Read-width experiment (5 October 2026, docs/plans/read-width.md): NOT the lottery hash. A load of W words reads
|
||||
// the W-word-aligned address and folds every word into dst: x = dst ^ w[0]; x = (rotl(x, 11) * 0x9e3779b1) ^ w[j]; dst = x.
|
||||
#define IGNEUM_LOAD_CLASS "mix50-35-15"
|
||||
#define IGNEUM_LOAD_SLOTS 16
|
||||
#define IGNEUM_LOAD_MIX { 50, 35, 15 }
|
||||
#define IGNEUM_LOAD_WIDTH_COUNTS { 8, 5, 3 } // loads of 4, 16, 64 bytes per program
|
||||
#define IGNEUM_BYTES_PER_HASH 2432
|
||||
#define IGNEUM_FOLD_ROT 11
|
||||
#define IGNEUM_FOLD_MUL 0x9e3779b1u
|
||||
// 0 = closed-form dataset (ds_elem), 1 = memory-hard cache construction (MEMHARD.md, memhard.h)
|
||||
#define IGNEUM_DATASET_MODE 1
|
||||
|
||||
#define IGNEUM_SEEDW_INIT { 0x774fd410u, 0x520f91b2u, 0x9357786fu, 0x8bbe44d7u, 0x23db18feu, 0x52022aecu, 0x653ea608u, 0x57788e47u }
|
||||
#define IGNEUM_KEY_INIT { 0x3067619fu, 0x3c269176u, 0x84a03b03u, 0xf8c63294u, 0xff977c5bu, 0xe60def3eu, 0x63630141u, 0xb8fbcb58u }
|
||||
#define IGNEUM_CACHE_LOG2_WORDS 26
|
||||
#define IGNEUM_CACHE_SEGMENT_LOG2_LINES 6
|
||||
#define IGNEUM_CACHE_SEGMENTS 65536u
|
||||
#define IGNEUM_ITEM_ROUNDS 8
|
||||
#define IGNEUM_MIX_ROT_INIT { 20u, 20u, 19u, 4u, 26u, 3u, 3u, 27u }
|
||||
#define IGNEUM_MIX_MUL_INIT { 0x42146205u, 0x52cbe0fbu, 0x7ecf4a03u, 0x6728907fu, 0xd81d9751u, 0x132952c3u, 0xf60de277u, 0x05358035u, 0xbaf6499du, 0xe4db9667u, 0x3e98f45du, 0xd0004eddu, 0x2691630du, 0x9beb3bcfu, 0xab310379u, 0x99cfb423u }
|
||||
#define IGNEUM_MIX_RC_INIT { 0xbab68293u, 0xcc162340u, 0x6ce151ccu, 0xe62b8997u, 0xc9c80297u, 0xf74a1654u, 0x3d704af5u, 0x3cf522b7u, 0x2b9cac04u, 0xa880ac10u, 0x13e5dd1du, 0x6fc3e233u, 0x2d83eeacu, 0x9006e8bfu, 0x2c4b5362u, 0x31b49ee2u }
|
||||
|
||||
#ifndef IGNEUM_NO_CUDA
|
||||
// Defined in kernel.cu. All launch on the default stream and return cudaGetLastError().
|
||||
cudaError_t igneum_launch_cache_fill(uint32_t* cache, uint32_t nSegments);
|
||||
cudaError_t igneum_launch_build(uint32_t* ds, const uint32_t* cache, uint32_t nItems);
|
||||
cudaError_t igneum_launch_hash(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask,
|
||||
uint32_t nonces, uint32_t blockWarps);
|
||||
cudaError_t igneum_hash_info(int* numRegs, int* blocksPerSM, uint32_t blockWarps);
|
||||
#endif
|
||||
127
proto-cuda/packs-readwidth/mixA-2/program.json
Normal file
127
proto-cuda/packs-readwidth/mixA-2/program.json
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
{
|
||||
"format": "igneum-program-pack-3",
|
||||
"generator": 2,
|
||||
"attempt": 0,
|
||||
"program_id": "0x11d47bbfc868120e",
|
||||
"program_id_derivation": "FNV-1a 64 over 'igneum-program/' || generator_le32 || seed_words as little-endian bytes || attempt_le32",
|
||||
"dataset_mode": "memory-hard",
|
||||
"seed": "igneum-readwidth/A/2",
|
||||
"seed_bytes": "69676e65756d2d7265616477696474682f412f32",
|
||||
"seed_words": ["0x774fd410", "0x520f91b2", "0x9357786f", "0x8bbe44d7", "0x23db18fe", "0x52022aec", "0x653ea608", "0x57788e47"],
|
||||
"seed_derivation": "seed_words = FNV-1a 64 over seed_bytes (attempt 0) or seed_bytes || attempt_le32 (attempt k >= 1), basis ^ (salt * 0x9E3779B97F4A7C15) for salt 0..3, then h ^= h>>33; h *= 0xff51afd7ed558ccd; h ^= h>>33; words[2*salt] = low 32, words[2*salt+1] = high 32",
|
||||
"generator_rule": "version 2: exactly 16 load slots drawn first from instructions 1..63 (partial Fisher-Yates), the other 48 ops from the ten non-load weights (sum 75); a load's source is drawn from the registers other than dst written by an earlier instruction and not read by a load since; the candidate must pass the acceptance rule of spec 01 section 1.4.6 (static: no cyclically stale load source, every register has an injecting write; dynamic: 64 units on the seed-keyed closed-form dataset with no constant register bit, no lane-constant load site, under 164 saturated final values, every output bit within 136 of 1024, distinct addresses above 245760), else the next attempt of the seed is tried",
|
||||
"lanes": 32,
|
||||
"registers": 8,
|
||||
"iterations": 8,
|
||||
"instruction_count": 64,
|
||||
"loads_per_hash": 128,
|
||||
"load_class": "mix50-35-15",
|
||||
"load_slots": 16,
|
||||
"load_mix_percent_4_16_64": [50, 35, 15],
|
||||
"load_width_counts_4_16_64": [8, 5, 3],
|
||||
"bytes_per_hash": 2432,
|
||||
"wide_load": "read-width experiment (5 October 2026, docs/plans/read-width.md), NOT the lottery hash: a load of W words (width field, 4 or 16) reads dataset[b .. b + W) with b = (src & mask) & ~(W - 1) and folds every word into dst: x = dst ^ w[0]; for j in 1..W: x = (rotl(x, 11) * 0x9e3779b1) ^ w[j]; dst = x; width 1 is the plain load; the width is drawn per instruction from the class mix with one extra below(100) draw after the nine of version 2, and the program id is FNV-1a 64 over 'igneum-program-rw/' || generator_le32 || seed words || attempt_le32 || mix[3] || load_slots",
|
||||
"op_mix": {"load": 16, "add": 10, "mul": 7, "mulhi": 7, "xor": 7, "shfl": 6, "rotl": 4, "rotr": 4, "mad": 3},
|
||||
"register_init": "for i in 0..7: x = nonce ^ seed_words[i]; x += 0x9e3779b9 * (i+1) (mod 2^32); x = splitmix32(x); r[i] = x ^ seed_words[(i+1) & 7]",
|
||||
"splitmix32": "x ^= x>>16; x *= 0x7feb352d; x ^= x>>15; x *= 0x846ca68b; x ^= x>>16",
|
||||
"iteration": "sel = r0 sampled once at the top of each iteration, then all instructions in order",
|
||||
"output": "lo = r0 ^ rotl(r1,7) ^ rotl(r2,14) ^ rotl(r3,21); hi = r4 ^ rotl(r5,9) ^ rotl(r6,18) ^ rotl(r7,27); out = (hi << 32) | lo",
|
||||
"op_semantics": {
|
||||
"add": "dst = dst + src + (bit `bit` of sel ? imm2 : imm)",
|
||||
"sub": "dst = dst - src",
|
||||
"mul": "dst = dst * src (low 32)",
|
||||
"mulhi": "dst = high 32 bits of dst * src",
|
||||
"xor": "dst = dst ^ src",
|
||||
"or": "dst = dst | src",
|
||||
"rotl": "dst = rotl(dst, rot), rot in 1..31",
|
||||
"rotr": "dst = rotr(dst, src & 31)",
|
||||
"mad": "dst = src * src2 + dst",
|
||||
"shfl": "dst = dst ^ (src of lane (lane ^ mask)), mask in {1,2,4,8,16}, within the 32-lane warp",
|
||||
"load": "dst = dst ^ dataset[src & dataset.mask]",
|
||||
"wload": "base = (src of lane 0 & dataset.mask) & ~31; dst = dst ^ dataset[base + lane] (warp-coalesced 128-byte load, lever b, only when --wide-frac > 0)"
|
||||
},
|
||||
"dataset": {
|
||||
"log2_words": 28,
|
||||
"bytes": 1073741824,
|
||||
"mask": "0x0fffffff",
|
||||
"day": "2026-10-03",
|
||||
"day_bytes": "6461792f323032362d31302d3033",
|
||||
"day_words_from": "seed_words_from_bytes(day_bytes)",
|
||||
"d0": "0x3067619f",
|
||||
"d1": "0x3c269176",
|
||||
"mode": "memory-hard",
|
||||
"spec": "proto-metal/MEMHARD.md",
|
||||
"key": ["0x3067619f", "0x3c269176", "0x84a03b03", "0xf8c63294", "0xff977c5b", "0xe60def3e", "0x63630141", "0xb8fbcb58"],
|
||||
"key_derivation": "the 8 words of seed_words_from_bytes(day_bytes); d0, d1 are key[0], key[1]",
|
||||
"cache": {"log2_words": 26, "bytes": 268435456, "line_words": 16, "segment_lines": 64, "segments": 65536, "block": "ChaCha12 core + feed-forward, rotations 16 12 8 7", "sigma": ["0x61707865", "0x3320646e", "0x79622d32", "0x6b206574"], "tag": ["0x49676e65", "0x756d4d48"], "chain": "in_j = prev_line ^ (sigma[0..3] || key[0..7] || seg || j || tag[0..1]); line_j = block(in_j); prev_0 = 0"},
|
||||
"mixer": {"draw": "SplitMix64 seeded with key[0] | key[1] << 32: rot[0..7] = 1 + next() % 31, mul[0..15] = low32(next()) | 1, rc[0..15] = low32(next())", "rot": [20, 20, 19, 4, 26, 3, 3, 27], "mul": ["0x42146205", "0x52cbe0fb", "0x7ecf4a03", "0x6728907f", "0xd81d9751", "0x132952c3", "0xf60de277", "0x05358035", "0xbaf6499d", "0xe4db9667", "0x3e98f45d", "0xd0004edd", "0x2691630d", "0x9beb3bcf", "0xab310379", "0x99cfb423"], "rc": ["0xbab68293", "0xcc162340", "0x6ce151cc", "0xe62b8997", "0xc9c80297", "0xf74a1654", "0x3d704af5", "0x3cf522b7", "0x2b9cac04", "0xa880ac10", "0x13e5dd1d", "0x6fc3e233", "0x2d83eeac", "0x9006e8bf", "0x2c4b5362", "0x31b49ee2"], "round": "for i in 0..15: s[i] = (s[i] ^ (rc[i] + (r+1) * 0x9E3779B9)) * mul[i]; then quarter rounds on columns (0,4,8,12) (1,5,9,13) (2,6,10,14) (3,7,11,15) with rot[0..3] and diagonals (0,5,10,15) (1,6,11,12) (2,7,8,13) (3,4,9,14) with rot[4..7]", "quarter_round": "a += b; d ^= a; d = rotl(d, r1); c += d; b ^= c; b = rotl(b, r2); a += b; d ^= a; d = rotl(d, r3); c += d; b ^= c; b = rotl(b, r4)"},
|
||||
"item": "s[0..7] = key; s[8+i] = t * mul[i] + rc[i] for i in 0..7; for r in 0..7: s = M_r(s); line = s[0] & 0x003fffff; s[i] ^= cache[line * 16 + i]; then s = M_8(s); item(t) = s",
|
||||
"word": "dataset[w] = item(w >> 4)[w & 15]"
|
||||
},
|
||||
"instructions": [
|
||||
{"i": 0, "op": "add", "dst": 2, "src": 7, "src2": 4, "imm": "0x17c8e8ee", "imm2": "0xd8952471", "rot": 31, "bit": 7, "mask": 4, "width": 1},
|
||||
{"i": 1, "op": "rotr", "dst": 0, "src": 5, "src2": 2, "imm": "0xcd7dcc5c", "imm2": "0xa1188ae7", "rot": 15, "bit": 23, "mask": 16, "width": 1},
|
||||
{"i": 2, "op": "add", "dst": 5, "src": 0, "src2": 1, "imm": "0x37d9560a", "imm2": "0x4325cc6a", "rot": 4, "bit": 21, "mask": 2, "width": 1},
|
||||
{"i": 3, "op": "xor", "dst": 7, "src": 5, "src2": 3, "imm": "0x6e598036", "imm2": "0x3370fa87", "rot": 22, "bit": 10, "mask": 4, "width": 1},
|
||||
{"i": 4, "op": "load", "dst": 3, "src": 0, "src2": 4, "imm": "0x072213d2", "imm2": "0xa024aa08", "rot": 9, "bit": 1, "mask": 16, "width": 16},
|
||||
{"i": 5, "op": "load", "dst": 5, "src": 7, "src2": 4, "imm": "0x3f74f8d4", "imm2": "0x29345708", "rot": 6, "bit": 9, "mask": 8, "width": 4},
|
||||
{"i": 6, "op": "mulhi", "dst": 0, "src": 5, "src2": 2, "imm": "0x0b8090fa", "imm2": "0x6677fdf7", "rot": 15, "bit": 24, "mask": 8, "width": 1},
|
||||
{"i": 7, "op": "mul", "dst": 4, "src": 7, "src2": 4, "imm": "0xf40f7deb", "imm2": "0x93c66180", "rot": 23, "bit": 1, "mask": 1, "width": 1},
|
||||
{"i": 8, "op": "mad", "dst": 0, "src": 5, "src2": 6, "imm": "0xfdce2834", "imm2": "0x61107ebf", "rot": 1, "bit": 10, "mask": 8, "width": 1},
|
||||
{"i": 9, "op": "load", "dst": 6, "src": 2, "src2": 6, "imm": "0x99c257d5", "imm2": "0x7b8a8224", "rot": 10, "bit": 29, "mask": 2, "width": 4},
|
||||
{"i": 10, "op": "xor", "dst": 0, "src": 6, "src2": 6, "imm": "0x1d598c2f", "imm2": "0x989541c3", "rot": 5, "bit": 7, "mask": 4, "width": 1},
|
||||
{"i": 11, "op": "add", "dst": 5, "src": 3, "src2": 3, "imm": "0xbc4eca12", "imm2": "0x81619a4c", "rot": 9, "bit": 22, "mask": 16, "width": 1},
|
||||
{"i": 12, "op": "mulhi", "dst": 4, "src": 2, "src2": 0, "imm": "0xdd65e362", "imm2": "0x3928839a", "rot": 14, "bit": 28, "mask": 4, "width": 1},
|
||||
{"i": 13, "op": "load", "dst": 2, "src": 0, "src2": 6, "imm": "0x059fcec1", "imm2": "0x1e541b07", "rot": 4, "bit": 21, "mask": 1, "width": 1},
|
||||
{"i": 14, "op": "add", "dst": 0, "src": 2, "src2": 6, "imm": "0xcf9919ee", "imm2": "0xa557fd2b", "rot": 6, "bit": 3, "mask": 1, "width": 1},
|
||||
{"i": 15, "op": "add", "dst": 4, "src": 5, "src2": 0, "imm": "0x36ec1d20", "imm2": "0x33857f70", "rot": 21, "bit": 7, "mask": 8, "width": 1},
|
||||
{"i": 16, "op": "add", "dst": 7, "src": 5, "src2": 1, "imm": "0x42f5db15", "imm2": "0x40495714", "rot": 18, "bit": 6, "mask": 8, "width": 1},
|
||||
{"i": 17, "op": "load", "dst": 7, "src": 5, "src2": 1, "imm": "0xf649fe2d", "imm2": "0x4477242b", "rot": 27, "bit": 3, "mask": 8, "width": 1},
|
||||
{"i": 18, "op": "xor", "dst": 3, "src": 6, "src2": 7, "imm": "0xae781ff8", "imm2": "0xbe6ecc6d", "rot": 30, "bit": 18, "mask": 1, "width": 1},
|
||||
{"i": 19, "op": "load", "dst": 7, "src": 2, "src2": 4, "imm": "0x68e68ea0", "imm2": "0x4dc840da", "rot": 19, "bit": 5, "mask": 1, "width": 16},
|
||||
{"i": 20, "op": "load", "dst": 5, "src": 3, "src2": 3, "imm": "0x59d3176d", "imm2": "0xdb77debd", "rot": 28, "bit": 5, "mask": 16, "width": 4},
|
||||
{"i": 21, "op": "load", "dst": 1, "src": 0, "src2": 5, "imm": "0xbdc0a385", "imm2": "0x464f9bc3", "rot": 17, "bit": 12, "mask": 8, "width": 1},
|
||||
{"i": 22, "op": "mulhi", "dst": 1, "src": 3, "src2": 2, "imm": "0xa654255b", "imm2": "0xea4103de", "rot": 27, "bit": 31, "mask": 2, "width": 1},
|
||||
{"i": 23, "op": "rotr", "dst": 1, "src": 5, "src2": 7, "imm": "0xa3991a21", "imm2": "0x4a407fc9", "rot": 22, "bit": 9, "mask": 16, "width": 1},
|
||||
{"i": 24, "op": "mulhi", "dst": 2, "src": 0, "src2": 7, "imm": "0x06fa7a88", "imm2": "0x06f12fe9", "rot": 3, "bit": 30, "mask": 16, "width": 1},
|
||||
{"i": 25, "op": "load", "dst": 0, "src": 4, "src2": 5, "imm": "0xf9075dec", "imm2": "0xe902c837", "rot": 16, "bit": 22, "mask": 2, "width": 16},
|
||||
{"i": 26, "op": "load", "dst": 0, "src": 1, "src2": 2, "imm": "0xd363edf4", "imm2": "0x8445583d", "rot": 10, "bit": 21, "mask": 1, "width": 4},
|
||||
{"i": 27, "op": "shfl", "dst": 5, "src": 2, "src2": 7, "imm": "0x8327fa2f", "imm2": "0x3a6092b0", "rot": 1, "bit": 23, "mask": 2, "width": 1},
|
||||
{"i": 28, "op": "add", "dst": 5, "src": 4, "src2": 3, "imm": "0x22029cb9", "imm2": "0x58a2eb85", "rot": 20, "bit": 12, "mask": 8, "width": 1},
|
||||
{"i": 29, "op": "load", "dst": 2, "src": 5, "src2": 0, "imm": "0x508d6c6e", "imm2": "0x51e70669", "rot": 23, "bit": 5, "mask": 4, "width": 4},
|
||||
{"i": 30, "op": "mul", "dst": 6, "src": 5, "src2": 0, "imm": "0xbbd10d76", "imm2": "0xcc8e1885", "rot": 29, "bit": 31, "mask": 1, "width": 1},
|
||||
{"i": 31, "op": "load", "dst": 6, "src": 2, "src2": 7, "imm": "0x032a9acc", "imm2": "0x0e202d4e", "rot": 9, "bit": 31, "mask": 16, "width": 1},
|
||||
{"i": 32, "op": "mulhi", "dst": 7, "src": 5, "src2": 7, "imm": "0x050c9aca", "imm2": "0x68f23dcc", "rot": 8, "bit": 8, "mask": 8, "width": 1},
|
||||
{"i": 33, "op": "load", "dst": 0, "src": 7, "src2": 6, "imm": "0x170bc6d7", "imm2": "0x8a08c2e4", "rot": 2, "bit": 15, "mask": 1, "width": 1},
|
||||
{"i": 34, "op": "shfl", "dst": 7, "src": 2, "src2": 6, "imm": "0x691b40d0", "imm2": "0x44b77bc4", "rot": 11, "bit": 16, "mask": 1, "width": 1},
|
||||
{"i": 35, "op": "mul", "dst": 7, "src": 0, "src2": 0, "imm": "0x708adb53", "imm2": "0x8101af24", "rot": 12, "bit": 19, "mask": 1, "width": 1},
|
||||
{"i": 36, "op": "load", "dst": 5, "src": 7, "src2": 3, "imm": "0x0c731099", "imm2": "0x8f29d683", "rot": 3, "bit": 9, "mask": 4, "width": 1},
|
||||
{"i": 37, "op": "rotr", "dst": 3, "src": 2, "src2": 0, "imm": "0x08ea65a2", "imm2": "0xc22ef0f2", "rot": 26, "bit": 7, "mask": 8, "width": 1},
|
||||
{"i": 38, "op": "rotl", "dst": 6, "src": 7, "src2": 6, "imm": "0xa5e2e082", "imm2": "0x3e9f9d96", "rot": 1, "bit": 22, "mask": 16, "width": 1},
|
||||
{"i": 39, "op": "mul", "dst": 3, "src": 0, "src2": 0, "imm": "0xb08ca537", "imm2": "0x98bd2f28", "rot": 15, "bit": 8, "mask": 2, "width": 1},
|
||||
{"i": 40, "op": "mulhi", "dst": 3, "src": 7, "src2": 0, "imm": "0x6b4f575a", "imm2": "0x0de8bd13", "rot": 14, "bit": 27, "mask": 2, "width": 1},
|
||||
{"i": 41, "op": "xor", "dst": 5, "src": 2, "src2": 1, "imm": "0xb651de8e", "imm2": "0x74c00b0c", "rot": 24, "bit": 21, "mask": 16, "width": 1},
|
||||
{"i": 42, "op": "mul", "dst": 4, "src": 0, "src2": 6, "imm": "0xd604a95a", "imm2": "0x93ad566c", "rot": 20, "bit": 16, "mask": 8, "width": 1},
|
||||
{"i": 43, "op": "add", "dst": 3, "src": 0, "src2": 1, "imm": "0x831bfab3", "imm2": "0xfaaf2d1e", "rot": 2, "bit": 4, "mask": 16, "width": 1},
|
||||
{"i": 44, "op": "mad", "dst": 0, "src": 1, "src2": 6, "imm": "0x40201b32", "imm2": "0xde9bd02f", "rot": 8, "bit": 6, "mask": 4, "width": 1},
|
||||
{"i": 45, "op": "rotl", "dst": 6, "src": 1, "src2": 5, "imm": "0x4bfbff1c", "imm2": "0x02d87bfc", "rot": 26, "bit": 8, "mask": 4, "width": 1},
|
||||
{"i": 46, "op": "xor", "dst": 2, "src": 1, "src2": 2, "imm": "0xc069583c", "imm2": "0x88265351", "rot": 26, "bit": 15, "mask": 2, "width": 1},
|
||||
{"i": 47, "op": "shfl", "dst": 0, "src": 7, "src2": 7, "imm": "0xffe42b00", "imm2": "0x8c0acfed", "rot": 21, "bit": 7, "mask": 2, "width": 1},
|
||||
{"i": 48, "op": "xor", "dst": 1, "src": 2, "src2": 1, "imm": "0x2f594ed1", "imm2": "0x7d51b0fb", "rot": 12, "bit": 19, "mask": 4, "width": 1},
|
||||
{"i": 49, "op": "add", "dst": 3, "src": 5, "src2": 4, "imm": "0x31df1a86", "imm2": "0xc5759120", "rot": 23, "bit": 7, "mask": 1, "width": 1},
|
||||
{"i": 50, "op": "mad", "dst": 1, "src": 4, "src2": 1, "imm": "0x1a81eb4c", "imm2": "0xb0108e0b", "rot": 27, "bit": 7, "mask": 1, "width": 1},
|
||||
{"i": 51, "op": "shfl", "dst": 1, "src": 4, "src2": 7, "imm": "0x1a207d4c", "imm2": "0x44993b80", "rot": 27, "bit": 27, "mask": 2, "width": 1},
|
||||
{"i": 52, "op": "add", "dst": 5, "src": 4, "src2": 4, "imm": "0x553b85d1", "imm2": "0x4e4a2759", "rot": 8, "bit": 16, "mask": 16, "width": 1},
|
||||
{"i": 53, "op": "load", "dst": 1, "src": 3, "src2": 4, "imm": "0x0c0b1b74", "imm2": "0x39083c8c", "rot": 4, "bit": 11, "mask": 1, "width": 1},
|
||||
{"i": 54, "op": "rotl", "dst": 6, "src": 4, "src2": 0, "imm": "0x1da26beb", "imm2": "0x0ddad11c", "rot": 21, "bit": 27, "mask": 2, "width": 1},
|
||||
{"i": 55, "op": "mulhi", "dst": 1, "src": 4, "src2": 7, "imm": "0x1fe9ea90", "imm2": "0x9457576e", "rot": 2, "bit": 2, "mask": 1, "width": 1},
|
||||
{"i": 56, "op": "shfl", "dst": 0, "src": 3, "src2": 4, "imm": "0x15776f9f", "imm2": "0xe087579f", "rot": 14, "bit": 11, "mask": 1, "width": 1},
|
||||
{"i": 57, "op": "xor", "dst": 1, "src": 2, "src2": 5, "imm": "0x1c5bb8e2", "imm2": "0x977e10b3", "rot": 18, "bit": 27, "mask": 16, "width": 1},
|
||||
{"i": 58, "op": "shfl", "dst": 3, "src": 6, "src2": 3, "imm": "0x37ecda35", "imm2": "0x21944e21", "rot": 3, "bit": 12, "mask": 16, "width": 1},
|
||||
{"i": 59, "op": "mul", "dst": 5, "src": 0, "src2": 6, "imm": "0xf3685385", "imm2": "0x86144005", "rot": 21, "bit": 30, "mask": 4, "width": 1},
|
||||
{"i": 60, "op": "load", "dst": 4, "src": 2, "src2": 0, "imm": "0xfdcc24f2", "imm2": "0x9bc020dc", "rot": 7, "bit": 18, "mask": 2, "width": 1},
|
||||
{"i": 61, "op": "rotr", "dst": 0, "src": 4, "src2": 2, "imm": "0x9a85b0f3", "imm2": "0xc04760bd", "rot": 26, "bit": 4, "mask": 16, "width": 1},
|
||||
{"i": 62, "op": "mul", "dst": 6, "src": 7, "src2": 7, "imm": "0x261783fc", "imm2": "0x7e75e2f9", "rot": 9, "bit": 0, "mask": 16, "width": 1},
|
||||
{"i": 63, "op": "rotl", "dst": 6, "src": 0, "src2": 4, "imm": "0x3569c3f0", "imm2": "0xbe2e19c5", "rot": 2, "bit": 18, "mask": 8, "width": 1}
|
||||
]
|
||||
}
|
||||
109
proto-cuda/packs-readwidth/mixA-2/program.metal
Normal file
109
proto-cuda/packs-readwidth/mixA-2/program.metal
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
#include <metal_stdlib>
|
||||
using namespace metal;
|
||||
|
||||
#define MASK 0x0fffffffu
|
||||
constant uint SEEDW[8] = { 0x774fd410u, 0x520f91b2u, 0x9357786fu, 0x8bbe44d7u, 0x23db18feu, 0x52022aecu, 0x653ea608u, 0x57788e47u };
|
||||
|
||||
inline uint splitmix32(uint x) {
|
||||
x ^= x >> 16; x *= 0x7feb352du;
|
||||
x ^= x >> 15; x *= 0x846ca68bu;
|
||||
x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
inline uint rotl_imm(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31
|
||||
inline uint rotr_var(uint x, uint n) { n &= 31u; return (x >> n) | (x << ((32u - n) & 31u)); }
|
||||
inline uint ds_elem(uint i, uint d0, uint d1) {
|
||||
uint x = i ^ d0;
|
||||
x *= 0x9E3779B1u; x ^= x >> 15;
|
||||
x += d1;
|
||||
x *= 0x85EBCA77u; x ^= x >> 13;
|
||||
x *= 0xC2B2AE3Du; x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
|
||||
kernel void igneum_hash(device const uint* dataset [[buffer(0)]],
|
||||
device ulong* out [[buffer(1)]],
|
||||
constant uint& baseNonce [[buffer(2)]],
|
||||
uint gid [[thread_position_in_grid]]) {
|
||||
uint nonce = baseNonce + gid;
|
||||
uint r0, r1, r2, r3, r4, r5, r6, r7;
|
||||
{ uint x = nonce ^ SEEDW[0]; x += 0x9e3779b9u * 1u; x = splitmix32(x); r0 = x ^ SEEDW[1]; }
|
||||
{ uint x = nonce ^ SEEDW[1]; x += 0x9e3779b9u * 2u; x = splitmix32(x); r1 = x ^ SEEDW[2]; }
|
||||
{ uint x = nonce ^ SEEDW[2]; x += 0x9e3779b9u * 3u; x = splitmix32(x); r2 = x ^ SEEDW[3]; }
|
||||
{ uint x = nonce ^ SEEDW[3]; x += 0x9e3779b9u * 4u; x = splitmix32(x); r3 = x ^ SEEDW[4]; }
|
||||
{ uint x = nonce ^ SEEDW[4]; x += 0x9e3779b9u * 5u; x = splitmix32(x); r4 = x ^ SEEDW[5]; }
|
||||
{ uint x = nonce ^ SEEDW[5]; x += 0x9e3779b9u * 6u; x = splitmix32(x); r5 = x ^ SEEDW[6]; }
|
||||
{ uint x = nonce ^ SEEDW[6]; x += 0x9e3779b9u * 7u; x = splitmix32(x); r6 = x ^ SEEDW[7]; }
|
||||
{ uint x = nonce ^ SEEDW[7]; x += 0x9e3779b9u * 8u; x = splitmix32(x); r7 = x ^ SEEDW[0]; }
|
||||
|
||||
for (uint it = 0u; it < 8u; ++it) {
|
||||
uint sel = r0;
|
||||
r2 = r2 + r7 + select(0x17c8e8eeu, 0xd8952471u, ((sel >> 7u) & 1u) != 0u); // 0
|
||||
r0 = rotr_var(r0, r5); // 1
|
||||
r5 = r5 + r0 + select(0x37d9560au, 0x4325cc6au, ((sel >> 21u) & 1u) != 0u); // 2
|
||||
r7 = r7 ^ r5; // 3
|
||||
{ uint b_ = (r0 & MASK) & ~15u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r3 = x_; } // 4
|
||||
{ uint b_ = (r7 & MASK) & ~3u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint x_ = r5 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r5 = x_; } // 5
|
||||
r0 = mulhi(r0, r5); // 6
|
||||
r4 = r4 * r7; // 7
|
||||
r0 = r5 * r6 + r0; // 8
|
||||
{ uint b_ = (r2 & MASK) & ~3u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r6 = x_; } // 9
|
||||
r0 = r0 ^ r6; // 10
|
||||
r5 = r5 + r3 + select(0xbc4eca12u, 0x81619a4cu, ((sel >> 22u) & 1u) != 0u); // 11
|
||||
r4 = mulhi(r4, r2); // 12
|
||||
r2 = r2 ^ dataset[r0 & MASK]; // 13
|
||||
r0 = r0 + r2 + select(0xcf9919eeu, 0xa557fd2bu, ((sel >> 3u) & 1u) != 0u); // 14
|
||||
r4 = r4 + r5 + select(0x36ec1d20u, 0x33857f70u, ((sel >> 7u) & 1u) != 0u); // 15
|
||||
r7 = r7 + r5 + select(0x42f5db15u, 0x40495714u, ((sel >> 6u) & 1u) != 0u); // 16
|
||||
r7 = r7 ^ dataset[r5 & MASK]; // 17
|
||||
r3 = r3 ^ r6; // 18
|
||||
{ uint b_ = (r2 & MASK) & ~15u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint x_ = r7 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r7 = x_; } // 19
|
||||
{ uint b_ = (r3 & MASK) & ~3u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint x_ = r5 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r5 = x_; } // 20
|
||||
r1 = r1 ^ dataset[r0 & MASK]; // 21
|
||||
r1 = mulhi(r1, r3); // 22
|
||||
r1 = rotr_var(r1, r5); // 23
|
||||
r2 = mulhi(r2, r0); // 24
|
||||
{ uint b_ = (r4 & MASK) & ~15u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint x_ = r0 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r0 = x_; } // 25
|
||||
{ uint b_ = (r1 & MASK) & ~3u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint x_ = r0 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r0 = x_; } // 26
|
||||
r5 = r5 ^ simd_shuffle_xor(r2, (ushort)2); // 27
|
||||
r5 = r5 + r4 + select(0x22029cb9u, 0x58a2eb85u, ((sel >> 12u) & 1u) != 0u); // 28
|
||||
{ uint b_ = (r5 & MASK) & ~3u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint x_ = r2 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r2 = x_; } // 29
|
||||
r6 = r6 * r5; // 30
|
||||
r6 = r6 ^ dataset[r2 & MASK]; // 31
|
||||
r7 = mulhi(r7, r5); // 32
|
||||
r0 = r0 ^ dataset[r7 & MASK]; // 33
|
||||
r7 = r7 ^ simd_shuffle_xor(r2, (ushort)1); // 34
|
||||
r7 = r7 * r0; // 35
|
||||
r5 = r5 ^ dataset[r7 & MASK]; // 36
|
||||
r3 = rotr_var(r3, r2); // 37
|
||||
r6 = rotl_imm(r6, 1u); // 38
|
||||
r3 = r3 * r0; // 39
|
||||
r3 = mulhi(r3, r7); // 40
|
||||
r5 = r5 ^ r2; // 41
|
||||
r4 = r4 * r0; // 42
|
||||
r3 = r3 + r0 + select(0x831bfab3u, 0xfaaf2d1eu, ((sel >> 4u) & 1u) != 0u); // 43
|
||||
r0 = r1 * r6 + r0; // 44
|
||||
r6 = rotl_imm(r6, 26u); // 45
|
||||
r2 = r2 ^ r1; // 46
|
||||
r0 = r0 ^ simd_shuffle_xor(r7, (ushort)2); // 47
|
||||
r1 = r1 ^ r2; // 48
|
||||
r3 = r3 + r5 + select(0x31df1a86u, 0xc5759120u, ((sel >> 7u) & 1u) != 0u); // 49
|
||||
r1 = r4 * r1 + r1; // 50
|
||||
r1 = r1 ^ simd_shuffle_xor(r4, (ushort)2); // 51
|
||||
r5 = r5 + r4 + select(0x553b85d1u, 0x4e4a2759u, ((sel >> 16u) & 1u) != 0u); // 52
|
||||
r1 = r1 ^ dataset[r3 & MASK]; // 53
|
||||
r6 = rotl_imm(r6, 21u); // 54
|
||||
r1 = mulhi(r1, r4); // 55
|
||||
r0 = r0 ^ simd_shuffle_xor(r3, (ushort)1); // 56
|
||||
r1 = r1 ^ r2; // 57
|
||||
r3 = r3 ^ simd_shuffle_xor(r6, (ushort)16); // 58
|
||||
r5 = r5 * r0; // 59
|
||||
r4 = r4 ^ dataset[r2 & MASK]; // 60
|
||||
r0 = rotr_var(r0, r4); // 61
|
||||
r6 = r6 * r7; // 62
|
||||
r6 = rotl_imm(r6, 2u); // 63
|
||||
}
|
||||
uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u);
|
||||
uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u);
|
||||
out[gid] = ((ulong)hi << 32) | (ulong)lo;
|
||||
}
|
||||
111
proto-cuda/packs-readwidth/mixA-2/program_bound.metal
Normal file
111
proto-cuda/packs-readwidth/mixA-2/program_bound.metal
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
#include <metal_stdlib>
|
||||
using namespace metal;
|
||||
|
||||
#define MASK 0x0fffffffu
|
||||
constant uint SEEDW[8] = { 0x774fd410u, 0x520f91b2u, 0x9357786fu, 0x8bbe44d7u, 0x23db18feu, 0x52022aecu, 0x653ea608u, 0x57788e47u };
|
||||
|
||||
inline uint splitmix32(uint x) {
|
||||
x ^= x >> 16; x *= 0x7feb352du;
|
||||
x ^= x >> 15; x *= 0x846ca68bu;
|
||||
x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
inline uint rotl_imm(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31
|
||||
inline uint rotr_var(uint x, uint n) { n &= 31u; return (x >> n) | (x << ((32u - n) & 31u)); }
|
||||
inline uint ds_elem(uint i, uint d0, uint d1) {
|
||||
uint x = i ^ d0;
|
||||
x *= 0x9E3779B1u; x ^= x >> 15;
|
||||
x += d1;
|
||||
x *= 0x85EBCA77u; x ^= x >> 13;
|
||||
x *= 0xC2B2AE3Du; x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
|
||||
// Header-bound variant: the init words come from buffer 3 (bind.rs), not from SEEDW.
|
||||
kernel void igneum_hash_bound(device const uint* dataset [[buffer(0)]],
|
||||
device ulong* out [[buffer(1)]],
|
||||
constant uint& baseNonce [[buffer(2)]],
|
||||
constant uint* initw [[buffer(3)]],
|
||||
uint gid [[thread_position_in_grid]]) {
|
||||
uint nonce = baseNonce + gid;
|
||||
uint r0, r1, r2, r3, r4, r5, r6, r7;
|
||||
{ uint x = nonce ^ initw[0]; x += 0x9e3779b9u * 1u; x = splitmix32(x); r0 = x ^ initw[1]; }
|
||||
{ uint x = nonce ^ initw[1]; x += 0x9e3779b9u * 2u; x = splitmix32(x); r1 = x ^ initw[2]; }
|
||||
{ uint x = nonce ^ initw[2]; x += 0x9e3779b9u * 3u; x = splitmix32(x); r2 = x ^ initw[3]; }
|
||||
{ uint x = nonce ^ initw[3]; x += 0x9e3779b9u * 4u; x = splitmix32(x); r3 = x ^ initw[4]; }
|
||||
{ uint x = nonce ^ initw[4]; x += 0x9e3779b9u * 5u; x = splitmix32(x); r4 = x ^ initw[5]; }
|
||||
{ uint x = nonce ^ initw[5]; x += 0x9e3779b9u * 6u; x = splitmix32(x); r5 = x ^ initw[6]; }
|
||||
{ uint x = nonce ^ initw[6]; x += 0x9e3779b9u * 7u; x = splitmix32(x); r6 = x ^ initw[7]; }
|
||||
{ uint x = nonce ^ initw[7]; x += 0x9e3779b9u * 8u; x = splitmix32(x); r7 = x ^ initw[0]; }
|
||||
|
||||
for (uint it = 0u; it < 8u; ++it) {
|
||||
uint sel = r0;
|
||||
r2 = r2 + r7 + select(0x17c8e8eeu, 0xd8952471u, ((sel >> 7u) & 1u) != 0u); // 0
|
||||
r0 = rotr_var(r0, r5); // 1
|
||||
r5 = r5 + r0 + select(0x37d9560au, 0x4325cc6au, ((sel >> 21u) & 1u) != 0u); // 2
|
||||
r7 = r7 ^ r5; // 3
|
||||
{ uint b_ = (r0 & MASK) & ~15u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r3 = x_; } // 4
|
||||
{ uint b_ = (r7 & MASK) & ~3u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint x_ = r5 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r5 = x_; } // 5
|
||||
r0 = mulhi(r0, r5); // 6
|
||||
r4 = r4 * r7; // 7
|
||||
r0 = r5 * r6 + r0; // 8
|
||||
{ uint b_ = (r2 & MASK) & ~3u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r6 = x_; } // 9
|
||||
r0 = r0 ^ r6; // 10
|
||||
r5 = r5 + r3 + select(0xbc4eca12u, 0x81619a4cu, ((sel >> 22u) & 1u) != 0u); // 11
|
||||
r4 = mulhi(r4, r2); // 12
|
||||
r2 = r2 ^ dataset[r0 & MASK]; // 13
|
||||
r0 = r0 + r2 + select(0xcf9919eeu, 0xa557fd2bu, ((sel >> 3u) & 1u) != 0u); // 14
|
||||
r4 = r4 + r5 + select(0x36ec1d20u, 0x33857f70u, ((sel >> 7u) & 1u) != 0u); // 15
|
||||
r7 = r7 + r5 + select(0x42f5db15u, 0x40495714u, ((sel >> 6u) & 1u) != 0u); // 16
|
||||
r7 = r7 ^ dataset[r5 & MASK]; // 17
|
||||
r3 = r3 ^ r6; // 18
|
||||
{ uint b_ = (r2 & MASK) & ~15u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint x_ = r7 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r7 = x_; } // 19
|
||||
{ uint b_ = (r3 & MASK) & ~3u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint x_ = r5 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r5 = x_; } // 20
|
||||
r1 = r1 ^ dataset[r0 & MASK]; // 21
|
||||
r1 = mulhi(r1, r3); // 22
|
||||
r1 = rotr_var(r1, r5); // 23
|
||||
r2 = mulhi(r2, r0); // 24
|
||||
{ uint b_ = (r4 & MASK) & ~15u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint x_ = r0 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r0 = x_; } // 25
|
||||
{ uint b_ = (r1 & MASK) & ~3u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint x_ = r0 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r0 = x_; } // 26
|
||||
r5 = r5 ^ simd_shuffle_xor(r2, (ushort)2); // 27
|
||||
r5 = r5 + r4 + select(0x22029cb9u, 0x58a2eb85u, ((sel >> 12u) & 1u) != 0u); // 28
|
||||
{ uint b_ = (r5 & MASK) & ~3u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint x_ = r2 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r2 = x_; } // 29
|
||||
r6 = r6 * r5; // 30
|
||||
r6 = r6 ^ dataset[r2 & MASK]; // 31
|
||||
r7 = mulhi(r7, r5); // 32
|
||||
r0 = r0 ^ dataset[r7 & MASK]; // 33
|
||||
r7 = r7 ^ simd_shuffle_xor(r2, (ushort)1); // 34
|
||||
r7 = r7 * r0; // 35
|
||||
r5 = r5 ^ dataset[r7 & MASK]; // 36
|
||||
r3 = rotr_var(r3, r2); // 37
|
||||
r6 = rotl_imm(r6, 1u); // 38
|
||||
r3 = r3 * r0; // 39
|
||||
r3 = mulhi(r3, r7); // 40
|
||||
r5 = r5 ^ r2; // 41
|
||||
r4 = r4 * r0; // 42
|
||||
r3 = r3 + r0 + select(0x831bfab3u, 0xfaaf2d1eu, ((sel >> 4u) & 1u) != 0u); // 43
|
||||
r0 = r1 * r6 + r0; // 44
|
||||
r6 = rotl_imm(r6, 26u); // 45
|
||||
r2 = r2 ^ r1; // 46
|
||||
r0 = r0 ^ simd_shuffle_xor(r7, (ushort)2); // 47
|
||||
r1 = r1 ^ r2; // 48
|
||||
r3 = r3 + r5 + select(0x31df1a86u, 0xc5759120u, ((sel >> 7u) & 1u) != 0u); // 49
|
||||
r1 = r4 * r1 + r1; // 50
|
||||
r1 = r1 ^ simd_shuffle_xor(r4, (ushort)2); // 51
|
||||
r5 = r5 + r4 + select(0x553b85d1u, 0x4e4a2759u, ((sel >> 16u) & 1u) != 0u); // 52
|
||||
r1 = r1 ^ dataset[r3 & MASK]; // 53
|
||||
r6 = rotl_imm(r6, 21u); // 54
|
||||
r1 = mulhi(r1, r4); // 55
|
||||
r0 = r0 ^ simd_shuffle_xor(r3, (ushort)1); // 56
|
||||
r1 = r1 ^ r2; // 57
|
||||
r3 = r3 ^ simd_shuffle_xor(r6, (ushort)16); // 58
|
||||
r5 = r5 * r0; // 59
|
||||
r4 = r4 ^ dataset[r2 & MASK]; // 60
|
||||
r0 = rotr_var(r0, r4); // 61
|
||||
r6 = r6 * r7; // 62
|
||||
r6 = rotl_imm(r6, 2u); // 63
|
||||
}
|
||||
uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u);
|
||||
uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u);
|
||||
out[gid] = ((ulong)hi << 32) | (ulong)lo;
|
||||
}
|
||||
57
proto-cuda/packs-readwidth/mixA-2/vectors.h
Normal file
57
proto-cuda/packs-readwidth/mixA-2/vectors.h
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
// Generated by igneum-pow export (generator v2) for seed "igneum-readwidth/A/2". Do not edit by hand.
|
||||
// Expected outputs: igneum-pow (Rust) CPU interpreter, generator v2, memory-hard dataset
|
||||
#pragma once
|
||||
#ifdef __cplusplus
|
||||
#include <cstdint>
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
#define IGNEUM_VEC_WARPS 3
|
||||
static const uint32_t IGNEUM_VEC_BASE[IGNEUM_VEC_WARPS] = { 0u, 4096u, 1000000u };
|
||||
static const uint64_t IGNEUM_VEC_OUT[IGNEUM_VEC_WARPS][32] = {
|
||||
{ // base nonce 0
|
||||
0x1e5a818edb31f50eull, 0x39ab5ff405f05a3aull, 0x8ba99b65319aea26ull, 0x00e66c9a5d9edc85ull, 0x673a7e5b68954010ull, 0x7182b60aa5acefacull, 0x14242454aa3bdad1ull, 0x68c88b2b4ee2d9a4ull,
|
||||
0xd5a63f69306d1985ull, 0x7f1ed7474726b715ull, 0x10b2f2b157e45181ull, 0x267f18d74afdb191ull, 0xe6d713eba1ee4ec4ull, 0xd1112f5d2ca5a7e6ull, 0xd4407d80e22e732dull, 0xf0ddeb92365545aeull,
|
||||
0xc877c1ad94896995ull, 0x9ecf17f1b4b9be25ull, 0x1f529607bcdc4065ull, 0xe7cc5c40d4e4d57bull, 0xb29bf3beadf6f5d7ull, 0xbc674c35c773fcacull, 0x35ffa42b4c965803ull, 0xaf0c5c09e68ba314ull,
|
||||
0x6a313419bd31d9a6ull, 0xae5dd12365e96057ull, 0xd36b68108f13bf22ull, 0xb24bce1326403870ull, 0x4e79d454a075b862ull, 0x6301a9ec32ab72a7ull, 0x2be3716f8db33d01ull, 0x0259670d3010002eull
|
||||
},
|
||||
{ // base nonce 4096
|
||||
0x8caaf6166eb165bbull, 0xa589ad41c360235full, 0x221d65887c34c329ull, 0xb167f8e67bddb1c8ull, 0x3368dcad623b40adull, 0x0143881c07493949ull, 0x0c0d44b06195e623ull, 0xa23ac0e6640ff95full,
|
||||
0x60e159dc557915a2ull, 0xea2b4ca8b06d5887ull, 0x5ff87ec91d1267e9ull, 0x49999f98b08dc991ull, 0x4a27b1ae7e9d2044ull, 0xad16f2167074cbceull, 0x2fe4de42eac4c102ull, 0x02b2e4945eb0f25full,
|
||||
0x00ec90afcc4c7be1ull, 0xedd7998f09f6202bull, 0xe871ff53c81ba442ull, 0xea2cbe8c86632596ull, 0x8c4ef1bbc35954f2ull, 0x2fe50dcc0129f200ull, 0x45089308785c4e5aull, 0xecdb829e3482a126ull,
|
||||
0x6092081b5ac666a3ull, 0xf20050f6cf7c36d0ull, 0x577b199c944cff9aull, 0xe567ab065574693cull, 0xd38fa9a00813f5bbull, 0x3f3b602229a4e685ull, 0x4bc63c32b3eee422ull, 0x0267ae18d258e96bull
|
||||
},
|
||||
{ // base nonce 1000000
|
||||
0xbc346fa7af395ccaull, 0xf6ab289812882ea5ull, 0x1af5ae5da7af7f73ull, 0x3f1c7f8f7c1a0dd2ull, 0x01f938d5c871fedcull, 0x375a820f2322f11aull, 0x33be6d6c9d5e59e1ull, 0xc401cdcff783f93bull,
|
||||
0x5e41cc8a873b6cdeull, 0x17b7410058197847ull, 0x9ea7c3ca06afb2d1ull, 0x601ddfbee56db4c5ull, 0x69e68ca477d75cb8ull, 0x7c226802f7f403a9ull, 0xcdb9bceade734442ull, 0x0a0a9e8e2524ceebull,
|
||||
0x52a88bf50c886dbfull, 0x7a395acb2fc42cdfull, 0x060fe78ab0c1382bull, 0xeb448b87bdfd6af3ull, 0x8f9832144201dba5ull, 0x65a8bd919a4a5230ull, 0xea3ec06d53c77fa3ull, 0xab2ea3b4dcb53ae0ull,
|
||||
0xbacf785210da5784ull, 0x01ccffb87836c39bull, 0x95eff222af8774d5ull, 0xeb12cd87ca802c98ull, 0x500473c6eb87f917ull, 0xf63aebcada9c2a14ull, 0xc3416375ce92b971ull, 0xe23abae6636093f9ull
|
||||
}
|
||||
};
|
||||
|
||||
// Dataset self-test: dataset[0..15] and dataset[IGNEUM_MASK] (268435455).
|
||||
static const uint32_t IGNEUM_DS_HEAD[16] = {
|
||||
0xffc3cd94u, 0x5920ccd8u, 0x392f44bbu, 0x5e57f67au, 0x2f2bc2a9u, 0x620b0e36u, 0xbdc09014u, 0x436654bfu,
|
||||
0x311e0b48u, 0x1abd93adu, 0x59cc7ce8u, 0xee5247b2u, 0x86171fe8u, 0x6d874751u, 0xc9f7728fu, 0x7c2a435du
|
||||
};
|
||||
static const uint32_t IGNEUM_DS_LAST_INDEX = 268435455u;
|
||||
static const uint32_t IGNEUM_DS_LAST = 0xa33ada72u;
|
||||
// 64 sampled dataset words (index, value) computed on the Mac.
|
||||
#define IGNEUM_DS_SAMPLES 64
|
||||
static const uint32_t IGNEUM_DS_SAMPLE_INDEX[IGNEUM_DS_SAMPLES] = {
|
||||
59471966u, 217795994u, 208353206u, 42483309u, 172547758u, 148076330u, 183853158u, 214389424u, 267488061u, 169781097u, 184093494u, 153880993u, 84977930u, 46426879u, 3093825u, 225364072u, 44593546u, 260713159u, 168250303u, 52384140u, 223401610u, 45554030u, 95410555u, 175039924u, 79171087u, 267580473u, 24168642u, 37981670u, 171551130u, 195559979u, 204611762u, 140997658u, 138925853u, 86637313u, 20736778u, 219665210u, 160430336u, 264654675u, 8013395u, 228945585u, 213884386u, 104419827u, 44185464u, 142737231u, 99284897u, 132475900u, 61861762u, 132056166u, 262388043u, 91878046u, 117353561u, 124768597u, 71352993u, 190698941u, 46055428u, 55281366u, 165145231u, 106810753u, 171985651u, 232085256u, 159510492u, 40072060u, 209107596u, 39023794u
|
||||
};
|
||||
static const uint32_t IGNEUM_DS_SAMPLE_VALUE[IGNEUM_DS_SAMPLES] = {
|
||||
0xe8b73d94u, 0x337028b5u, 0xafe148c9u, 0xab99f7aeu, 0x434ea619u, 0xd85cb880u, 0x54764c7fu, 0x82c7e420u, 0xedf4cb9eu, 0x9884c959u, 0x223ee793u, 0x3a9ccf69u, 0x81da4fd2u, 0xd6ce8cb9u, 0xe3922dcau, 0x3e7e6bdeu, 0x382a3acau, 0x567e7f7fu, 0x25a0f084u, 0xbfeef128u, 0xe338abfbu, 0x7c3b5280u, 0x909bc5f1u, 0xd8b74b9cu, 0x8e31a22eu, 0x26b5f1d8u, 0x79122c00u, 0xcafc3340u, 0xd5e02ea3u, 0x1aee1afdu, 0xdb090d9au, 0xb049f435u, 0x4954d8bau, 0x03797ba0u, 0x196eefbdu, 0xd153412au, 0xbe5d2c4bu, 0xdaa14f0eu, 0x8e61ed07u, 0x9e9a64c6u, 0x2e29ff36u, 0x392a8589u, 0xb56a5912u, 0xfa6e8b57u, 0xd1a737cbu, 0xb0fa841au, 0xbe1c341fu, 0xe25be0f1u, 0xe937f543u, 0xebab2248u, 0x8e1b607au, 0x202a2fedu, 0x95e2819cu, 0x9c9652d4u, 0x32fedef0u, 0xdecfff82u, 0xcb5d43e5u, 0xb735806au, 0x8905939cu, 0xfbf8472du, 0xada74e5du, 0x7ebdeeeau, 0x0119f2b3u, 0xa9a376b8u
|
||||
};
|
||||
// Cache self-test (memory-hard mode): cache[0..15], the last 16 words, and FNV-1a 64 over all 2^26 words.
|
||||
static const uint32_t IGNEUM_CACHE_HEAD[16] = {
|
||||
0x355a86d2u, 0x7957db1cu, 0xd21772afu, 0x6fc1e09bu, 0xd55ce61du, 0x6e6a278bu, 0xd3f543ceu, 0x223d8e82u,
|
||||
0x143ab337u, 0x2e9f05bdu, 0x2eb389bfu, 0x0c6e449eu, 0x5cfa4222u, 0xba6560feu, 0x8e3e1aa4u, 0xdbcc1d53u
|
||||
};
|
||||
static const uint32_t IGNEUM_CACHE_LAST[16] = {
|
||||
0x41190d91u, 0xbd277957u, 0x22ddbb49u, 0x6986f207u, 0xdf69a4d6u, 0x26401a3au, 0x818230fbu, 0xc417122du,
|
||||
0x3597b211u, 0xb553ce55u, 0xcf39cc0du, 0x3b7fc43au, 0x3fd43b00u, 0x67e1c80eu, 0xffa7ea7du, 0xca2960abu
|
||||
};
|
||||
static const uint64_t IGNEUM_CACHE_FNV64 = 0x48c4f5bf24166b2eull;
|
||||
36
proto-cuda/packs-readwidth/mixA-2/vectors.json
Normal file
36
proto-cuda/packs-readwidth/mixA-2/vectors.json
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
{
|
||||
"seed": "igneum-readwidth/A/2",
|
||||
"day": "2026-10-03",
|
||||
"dataset_mode": "memory-hard",
|
||||
"dataset_log2_words": 28,
|
||||
"mask": "0x0fffffff",
|
||||
"lanes": 32,
|
||||
"source": "igneum-pow (Rust) CPU interpreter, generator v2, memory-hard dataset",
|
||||
"warps": [
|
||||
{"base_nonce": 0, "expected": [
|
||||
"0x1e5a818edb31f50e", "0x39ab5ff405f05a3a", "0x8ba99b65319aea26", "0x00e66c9a5d9edc85", "0x673a7e5b68954010", "0x7182b60aa5acefac", "0x14242454aa3bdad1", "0x68c88b2b4ee2d9a4",
|
||||
"0xd5a63f69306d1985", "0x7f1ed7474726b715", "0x10b2f2b157e45181", "0x267f18d74afdb191", "0xe6d713eba1ee4ec4", "0xd1112f5d2ca5a7e6", "0xd4407d80e22e732d", "0xf0ddeb92365545ae",
|
||||
"0xc877c1ad94896995", "0x9ecf17f1b4b9be25", "0x1f529607bcdc4065", "0xe7cc5c40d4e4d57b", "0xb29bf3beadf6f5d7", "0xbc674c35c773fcac", "0x35ffa42b4c965803", "0xaf0c5c09e68ba314",
|
||||
"0x6a313419bd31d9a6", "0xae5dd12365e96057", "0xd36b68108f13bf22", "0xb24bce1326403870", "0x4e79d454a075b862", "0x6301a9ec32ab72a7", "0x2be3716f8db33d01", "0x0259670d3010002e"
|
||||
]},
|
||||
{"base_nonce": 4096, "expected": [
|
||||
"0x8caaf6166eb165bb", "0xa589ad41c360235f", "0x221d65887c34c329", "0xb167f8e67bddb1c8", "0x3368dcad623b40ad", "0x0143881c07493949", "0x0c0d44b06195e623", "0xa23ac0e6640ff95f",
|
||||
"0x60e159dc557915a2", "0xea2b4ca8b06d5887", "0x5ff87ec91d1267e9", "0x49999f98b08dc991", "0x4a27b1ae7e9d2044", "0xad16f2167074cbce", "0x2fe4de42eac4c102", "0x02b2e4945eb0f25f",
|
||||
"0x00ec90afcc4c7be1", "0xedd7998f09f6202b", "0xe871ff53c81ba442", "0xea2cbe8c86632596", "0x8c4ef1bbc35954f2", "0x2fe50dcc0129f200", "0x45089308785c4e5a", "0xecdb829e3482a126",
|
||||
"0x6092081b5ac666a3", "0xf20050f6cf7c36d0", "0x577b199c944cff9a", "0xe567ab065574693c", "0xd38fa9a00813f5bb", "0x3f3b602229a4e685", "0x4bc63c32b3eee422", "0x0267ae18d258e96b"
|
||||
]},
|
||||
{"base_nonce": 1000000, "expected": [
|
||||
"0xbc346fa7af395cca", "0xf6ab289812882ea5", "0x1af5ae5da7af7f73", "0x3f1c7f8f7c1a0dd2", "0x01f938d5c871fedc", "0x375a820f2322f11a", "0x33be6d6c9d5e59e1", "0xc401cdcff783f93b",
|
||||
"0x5e41cc8a873b6cde", "0x17b7410058197847", "0x9ea7c3ca06afb2d1", "0x601ddfbee56db4c5", "0x69e68ca477d75cb8", "0x7c226802f7f403a9", "0xcdb9bceade734442", "0x0a0a9e8e2524ceeb",
|
||||
"0x52a88bf50c886dbf", "0x7a395acb2fc42cdf", "0x060fe78ab0c1382b", "0xeb448b87bdfd6af3", "0x8f9832144201dba5", "0x65a8bd919a4a5230", "0xea3ec06d53c77fa3", "0xab2ea3b4dcb53ae0",
|
||||
"0xbacf785210da5784", "0x01ccffb87836c39b", "0x95eff222af8774d5", "0xeb12cd87ca802c98", "0x500473c6eb87f917", "0xf63aebcada9c2a14", "0xc3416375ce92b971", "0xe23abae6636093f9"
|
||||
]}
|
||||
],
|
||||
"dataset_head": ["0xffc3cd94", "0x5920ccd8", "0x392f44bb", "0x5e57f67a", "0x2f2bc2a9", "0x620b0e36", "0xbdc09014", "0x436654bf", "0x311e0b48", "0x1abd93ad", "0x59cc7ce8", "0xee5247b2", "0x86171fe8", "0x6d874751", "0xc9f7728f", "0x7c2a435d"],
|
||||
"dataset_last_index": 268435455,
|
||||
"dataset_last": "0xa33ada72",
|
||||
"dataset_samples": [{"index": 59471966, "value": "0xe8b73d94"}, {"index": 217795994, "value": "0x337028b5"}, {"index": 208353206, "value": "0xafe148c9"}, {"index": 42483309, "value": "0xab99f7ae"}, {"index": 172547758, "value": "0x434ea619"}, {"index": 148076330, "value": "0xd85cb880"}, {"index": 183853158, "value": "0x54764c7f"}, {"index": 214389424, "value": "0x82c7e420"}, {"index": 267488061, "value": "0xedf4cb9e"}, {"index": 169781097, "value": "0x9884c959"}, {"index": 184093494, "value": "0x223ee793"}, {"index": 153880993, "value": "0x3a9ccf69"}, {"index": 84977930, "value": "0x81da4fd2"}, {"index": 46426879, "value": "0xd6ce8cb9"}, {"index": 3093825, "value": "0xe3922dca"}, {"index": 225364072, "value": "0x3e7e6bde"}, {"index": 44593546, "value": "0x382a3aca"}, {"index": 260713159, "value": "0x567e7f7f"}, {"index": 168250303, "value": "0x25a0f084"}, {"index": 52384140, "value": "0xbfeef128"}, {"index": 223401610, "value": "0xe338abfb"}, {"index": 45554030, "value": "0x7c3b5280"}, {"index": 95410555, "value": "0x909bc5f1"}, {"index": 175039924, "value": "0xd8b74b9c"}, {"index": 79171087, "value": "0x8e31a22e"}, {"index": 267580473, "value": "0x26b5f1d8"}, {"index": 24168642, "value": "0x79122c00"}, {"index": 37981670, "value": "0xcafc3340"}, {"index": 171551130, "value": "0xd5e02ea3"}, {"index": 195559979, "value": "0x1aee1afd"}, {"index": 204611762, "value": "0xdb090d9a"}, {"index": 140997658, "value": "0xb049f435"}, {"index": 138925853, "value": "0x4954d8ba"}, {"index": 86637313, "value": "0x03797ba0"}, {"index": 20736778, "value": "0x196eefbd"}, {"index": 219665210, "value": "0xd153412a"}, {"index": 160430336, "value": "0xbe5d2c4b"}, {"index": 264654675, "value": "0xdaa14f0e"}, {"index": 8013395, "value": "0x8e61ed07"}, {"index": 228945585, "value": "0x9e9a64c6"}, {"index": 213884386, "value": "0x2e29ff36"}, {"index": 104419827, "value": "0x392a8589"}, {"index": 44185464, "value": "0xb56a5912"}, {"index": 142737231, "value": "0xfa6e8b57"}, {"index": 99284897, "value": "0xd1a737cb"}, {"index": 132475900, "value": "0xb0fa841a"}, {"index": 61861762, "value": "0xbe1c341f"}, {"index": 132056166, "value": "0xe25be0f1"}, {"index": 262388043, "value": "0xe937f543"}, {"index": 91878046, "value": "0xebab2248"}, {"index": 117353561, "value": "0x8e1b607a"}, {"index": 124768597, "value": "0x202a2fed"}, {"index": 71352993, "value": "0x95e2819c"}, {"index": 190698941, "value": "0x9c9652d4"}, {"index": 46055428, "value": "0x32fedef0"}, {"index": 55281366, "value": "0xdecfff82"}, {"index": 165145231, "value": "0xcb5d43e5"}, {"index": 106810753, "value": "0xb735806a"}, {"index": 171985651, "value": "0x8905939c"}, {"index": 232085256, "value": "0xfbf8472d"}, {"index": 159510492, "value": "0xada74e5d"}, {"index": 40072060, "value": "0x7ebdeeea"}, {"index": 209107596, "value": "0x0119f2b3"}, {"index": 39023794, "value": "0xa9a376b8"}],
|
||||
"cache_head": ["0x355a86d2", "0x7957db1c", "0xd21772af", "0x6fc1e09b", "0xd55ce61d", "0x6e6a278b", "0xd3f543ce", "0x223d8e82", "0x143ab337", "0x2e9f05bd", "0x2eb389bf", "0x0c6e449e", "0x5cfa4222", "0xba6560fe", "0x8e3e1aa4", "0xdbcc1d53"],
|
||||
"cache_last_line": ["0x41190d91", "0xbd277957", "0x22ddbb49", "0x6986f207", "0xdf69a4d6", "0x26401a3a", "0x818230fb", "0xc417122d", "0x3597b211", "0xb553ce55", "0xcf39cc0d", "0x3b7fc43a", "0x3fd43b00", "0x67e1c80e", "0xffa7ea7d", "0xca2960ab"],
|
||||
"cache_fnv1a64": "0x48c4f5bf24166b2e"
|
||||
}
|
||||
278
proto-cuda/packs-readwidth/mixA-3/kernel.cl
Normal file
278
proto-cuda/packs-readwidth/mixA-3/kernel.cl
Normal file
|
|
@ -0,0 +1,278 @@
|
|||
// Generated by igneum-pow export (generator v2) for seed "igneum-readwidth/A/3". Do not edit by hand.
|
||||
// OpenCL C twin of the Metal kernel for the same seed (see proto-opencl/README.md, WAVEFRONT.md and program.metal).
|
||||
// Built from source at runtime by proto-opencl/host.c, which passes these defines:
|
||||
// IGNEUM_GROUP work-group size of igneum_hash, a multiple of 32 (default 32: one work-group = one 32-lane unit)
|
||||
// IGNEUM_EXCHANGE 0 = local-memory exchange with a barrier (any device, any wave width; the default)
|
||||
// 1 = sub_group_shuffle_xor (cl_khr_subgroup_shuffle), only with IGNEUM_GROUP 32 and a sub-group size of exactly 32
|
||||
// 2 = intel_sub_group_shuffle_xor (cl_intel_subgroups), same condition
|
||||
// The verification unit is always 32 lanes. A 64-wide hardware wave (AMD GCN/CDNA, RDNA in wave64) runs two units;
|
||||
// the exchange masks are 1, 2, 4, 8, 16, so every partner lane lies inside the lane's own aligned run of 32.
|
||||
#ifndef IGNEUM_GROUP
|
||||
#define IGNEUM_GROUP 32
|
||||
#endif
|
||||
#ifndef IGNEUM_EXCHANGE
|
||||
#define IGNEUM_EXCHANGE 0
|
||||
#endif
|
||||
#ifdef __OPENCL_VERSION__
|
||||
#define IGNEUM_KERNEL_HASH __kernel __attribute__((reqd_work_group_size(IGNEUM_GROUP, 1, 1)))
|
||||
#define IGNEUM_LOCAL_WORDS(name, n) __local uint name[n]
|
||||
#if IGNEUM_EXCHANGE == 1
|
||||
#ifdef cl_khr_subgroups
|
||||
#pragma OPENCL EXTENSION cl_khr_subgroups : enable
|
||||
#endif
|
||||
#ifdef cl_khr_subgroup_shuffle
|
||||
#pragma OPENCL EXTENSION cl_khr_subgroup_shuffle : enable
|
||||
#endif
|
||||
#elif IGNEUM_EXCHANGE == 2
|
||||
#pragma OPENCL EXTENSION cl_intel_subgroups : enable
|
||||
#endif
|
||||
#else
|
||||
// Not an OpenCL compiler: proto-opencl/emu compiles this file as C++ and supplies the built-ins and these two macros.
|
||||
#include "emu_opencl.h"
|
||||
#endif
|
||||
|
||||
#if IGNEUM_EXCHANGE == 1
|
||||
#define IGNEUM_SHFL_XOR(dst, a, m) dst = sub_group_shuffle_xor((a), (uint)(m))
|
||||
#define IGNEUM_BCAST0(dst, a) dst = sub_group_broadcast((a), 0u)
|
||||
#elif IGNEUM_EXCHANGE == 2
|
||||
#define IGNEUM_SHFL_XOR(dst, a, m) dst = intel_sub_group_shuffle_xor((a), (uint)(m))
|
||||
#define IGNEUM_BCAST0(dst, a) dst = sub_group_broadcast((a), 0u)
|
||||
#else
|
||||
// Local-memory exchange. Two buffers of IGNEUM_GROUP words alternate (xk counts exchanges), so one barrier per
|
||||
// exchange is enough: a lane can only overwrite buffer b at exchange k+2 after passing barrier k+1, and every lane
|
||||
// reaches barrier k+1 only after its read of buffer b at exchange k. The partner lid ^ m stays inside the lane's
|
||||
// aligned run of 32 because m < 32. Control flow is uniform, so every work-item reaches every barrier.
|
||||
#define IGNEUM_SHFL_XOR(dst, a, m) { xch[(xk & 1u) * IGNEUM_GROUP + lid] = (a); barrier(CLK_LOCAL_MEM_FENCE); dst = xch[(xk & 1u) * IGNEUM_GROUP + (lid ^ (uint)(m))]; xk += 1u; }
|
||||
#define IGNEUM_BCAST0(dst, a) { xch[(xk & 1u) * IGNEUM_GROUP + lid] = (a); barrier(CLK_LOCAL_MEM_FENCE); dst = xch[(xk & 1u) * IGNEUM_GROUP + (lid & ~31u)]; xk += 1u; }
|
||||
#endif
|
||||
|
||||
static inline uint splitmix32(uint x) {
|
||||
x ^= x >> 16; x *= 0x7feb352du;
|
||||
x ^= x >> 15; x *= 0x846ca68bu;
|
||||
x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
// n is a literal in 1..31 at every call site. OpenCL rotate() rotates left by n modulo 32.
|
||||
static inline uint rotl_imm(uint x, uint n) { return rotate(x, n); }
|
||||
// Right rotation by n modulo 32 as a left rotation by (32 - n) modulo 32; n == 0 gives x.
|
||||
static inline uint rotr_var(uint x, uint n) { return rotate(x, (0u - n) & 31u); }
|
||||
static inline uint ds_elem(uint i, uint d0, uint d1) {
|
||||
uint x = i ^ d0;
|
||||
x *= 0x9E3779B1u; x ^= x >> 15;
|
||||
x += d1;
|
||||
x *= 0x85EBCA77u; x ^= x >> 13;
|
||||
x *= 0xC2B2AE3Du; x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
|
||||
// Memory-hard dataset core (MEMHARD.md). Cache: 2^26 words in 2^16 segments of 64 chained ChaCha12 lines.
|
||||
// Item: 8 rounds of seed-parameterised mixer + one 64-byte cache read, then a final mixer. All parameters are literals.
|
||||
#define MH_CACHE_LINE_MASK 0x003fffffu
|
||||
#define MH_SEGMENT_LINES 64u
|
||||
#define MH_QR(a, b, c, d, r1, r2, r3, r4) { a += b; d ^= a; d = mh_rotl(d, r1); c += d; b ^= c; b = mh_rotl(b, r2); a += b; d ^= a; d = mh_rotl(d, r3); c += d; b ^= c; b = mh_rotl(b, r4); }
|
||||
static inline uint mh_rotl(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 at every call site
|
||||
|
||||
// y = ChaCha12 core(x) + x
|
||||
static inline void mh_chacha_block(const uint* x, uint* y) {
|
||||
for (uint i = 0u; i < 16u; ++i) y[i] = x[i];
|
||||
for (uint r = 0u; r < 6u; ++r) {
|
||||
MH_QR(y[0], y[4], y[8], y[12], 16u, 12u, 8u, 7u) MH_QR(y[1], y[5], y[9], y[13], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[2], y[6], y[10], y[14], 16u, 12u, 8u, 7u) MH_QR(y[3], y[7], y[11], y[15], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[0], y[5], y[10], y[15], 16u, 12u, 8u, 7u) MH_QR(y[1], y[6], y[11], y[12], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[2], y[7], y[8], y[13], 16u, 12u, 8u, 7u) MH_QR(y[3], y[4], y[9], y[14], 16u, 12u, 8u, 7u)
|
||||
}
|
||||
for (uint i = 0u; i < 16u; ++i) y[i] += x[i];
|
||||
}
|
||||
|
||||
// One cache segment: 64 chained lines written at cache[seg * 1024]. in_j = prev ^ (sigma || K || seg || j || tag), prev_0 = 0.
|
||||
static inline void mh_cache_segment(__global uint* cache, uint seg) {
|
||||
uint prev[16]; uint x[16]; uint y[16];
|
||||
for (uint i = 0u; i < 16u; ++i) prev[i] = 0u;
|
||||
for (uint j = 0u; j < MH_SEGMENT_LINES; ++j) {
|
||||
x[0] = 0x61707865u ^ prev[0]; x[1] = 0x3320646eu ^ prev[1]; x[2] = 0x79622d32u ^ prev[2]; x[3] = 0x6b206574u ^ prev[3];
|
||||
x[4] = 0x3067619fu ^ prev[4];
|
||||
x[5] = 0x3c269176u ^ prev[5];
|
||||
x[6] = 0x84a03b03u ^ prev[6];
|
||||
x[7] = 0xf8c63294u ^ prev[7];
|
||||
x[8] = 0xff977c5bu ^ prev[8];
|
||||
x[9] = 0xe60def3eu ^ prev[9];
|
||||
x[10] = 0x63630141u ^ prev[10];
|
||||
x[11] = 0xb8fbcb58u ^ prev[11];
|
||||
x[12] = seg ^ prev[12]; x[13] = j ^ prev[13]; x[14] = 0x49676e65u ^ prev[14]; x[15] = 0x756d4d48u ^ prev[15];
|
||||
mh_chacha_block(x, y);
|
||||
__global uint* line = cache + ((seg * MH_SEGMENT_LINES + j) * 16u);
|
||||
for (uint i = 0u; i < 16u; ++i) { line[i] = y[i]; prev[i] = y[i]; }
|
||||
}
|
||||
}
|
||||
|
||||
// M_r: per word (s ^ (RC + rk)) * MUL, then a column round and a diagonal round with the seed-drawn rotations.
|
||||
static inline void mh_mixer(uint* s, uint rk) {
|
||||
s[0] = (s[0] ^ (0xbab68293u + rk)) * 0x42146205u;
|
||||
s[1] = (s[1] ^ (0xcc162340u + rk)) * 0x52cbe0fbu;
|
||||
s[2] = (s[2] ^ (0x6ce151ccu + rk)) * 0x7ecf4a03u;
|
||||
s[3] = (s[3] ^ (0xe62b8997u + rk)) * 0x6728907fu;
|
||||
s[4] = (s[4] ^ (0xc9c80297u + rk)) * 0xd81d9751u;
|
||||
s[5] = (s[5] ^ (0xf74a1654u + rk)) * 0x132952c3u;
|
||||
s[6] = (s[6] ^ (0x3d704af5u + rk)) * 0xf60de277u;
|
||||
s[7] = (s[7] ^ (0x3cf522b7u + rk)) * 0x05358035u;
|
||||
s[8] = (s[8] ^ (0x2b9cac04u + rk)) * 0xbaf6499du;
|
||||
s[9] = (s[9] ^ (0xa880ac10u + rk)) * 0xe4db9667u;
|
||||
s[10] = (s[10] ^ (0x13e5dd1du + rk)) * 0x3e98f45du;
|
||||
s[11] = (s[11] ^ (0x6fc3e233u + rk)) * 0xd0004eddu;
|
||||
s[12] = (s[12] ^ (0x2d83eeacu + rk)) * 0x2691630du;
|
||||
s[13] = (s[13] ^ (0x9006e8bfu + rk)) * 0x9beb3bcfu;
|
||||
s[14] = (s[14] ^ (0x2c4b5362u + rk)) * 0xab310379u;
|
||||
s[15] = (s[15] ^ (0x31b49ee2u + rk)) * 0x99cfb423u;
|
||||
MH_QR(s[0], s[4], s[8], s[12], 20u, 20u, 19u, 4u) MH_QR(s[1], s[5], s[9], s[13], 20u, 20u, 19u, 4u)
|
||||
MH_QR(s[2], s[6], s[10], s[14], 20u, 20u, 19u, 4u) MH_QR(s[3], s[7], s[11], s[15], 20u, 20u, 19u, 4u)
|
||||
MH_QR(s[0], s[5], s[10], s[15], 26u, 3u, 3u, 27u) MH_QR(s[1], s[6], s[11], s[12], 26u, 3u, 3u, 27u)
|
||||
MH_QR(s[2], s[7], s[8], s[13], 26u, 3u, 3u, 27u) MH_QR(s[3], s[4], s[9], s[14], 26u, 3u, 3u, 27u)
|
||||
}
|
||||
|
||||
// Item t: 16 words. s = (K, t * MUL[i] + RC[i]); 8 rounds of mixer + cache line s[0] & mask; final mixer.
|
||||
static inline void mh_item(__global const uint* cache, uint t, uint* s) {
|
||||
s[0] = 0x3067619fu;
|
||||
s[1] = 0x3c269176u;
|
||||
s[2] = 0x84a03b03u;
|
||||
s[3] = 0xf8c63294u;
|
||||
s[4] = 0xff977c5bu;
|
||||
s[5] = 0xe60def3eu;
|
||||
s[6] = 0x63630141u;
|
||||
s[7] = 0xb8fbcb58u;
|
||||
s[8] = t * 0x42146205u + 0xbab68293u;
|
||||
s[9] = t * 0x52cbe0fbu + 0xcc162340u;
|
||||
s[10] = t * 0x7ecf4a03u + 0x6ce151ccu;
|
||||
s[11] = t * 0x6728907fu + 0xe62b8997u;
|
||||
s[12] = t * 0xd81d9751u + 0xc9c80297u;
|
||||
s[13] = t * 0x132952c3u + 0xf74a1654u;
|
||||
s[14] = t * 0xf60de277u + 0x3d704af5u;
|
||||
s[15] = t * 0x05358035u + 0x3cf522b7u;
|
||||
for (uint r = 0u; r < 8u; ++r) {
|
||||
mh_mixer(s, 0x9E3779B9u * (r + 1u));
|
||||
__global const uint* line = cache + ((s[0] & MH_CACHE_LINE_MASK) * 16u);
|
||||
for (uint i = 0u; i < 16u; ++i) s[i] ^= line[i];
|
||||
}
|
||||
mh_mixer(s, 0x9E3779B9u * 9u);
|
||||
}
|
||||
// dataset[w] without the dataset: derive item w >> 4 and take word w & 15.
|
||||
static inline uint mh_word(__global const uint* cache, uint w) { uint s[16]; mh_item(cache, w >> 4u, s); return s[w & 15u]; }
|
||||
|
||||
// Memory-hard dataset (MEMHARD.md). One work-item per cache segment; one work-item per 64-byte dataset item.
|
||||
// The same constants as memhard.h in this pack (one emitter, three dialects).
|
||||
__kernel void igneum_cache_fill(__global uint* cache, uint nSegments) {
|
||||
uint seg = (uint)get_global_id(0);
|
||||
if (seg < nSegments) mh_cache_segment(cache, seg);
|
||||
}
|
||||
__kernel void igneum_build(__global uint* ds, __global const uint* cache, uint nItems) {
|
||||
uint t = (uint)get_global_id(0);
|
||||
if (t < nItems) {
|
||||
uint s[16];
|
||||
mh_item(cache, t, s);
|
||||
__global uint* d = ds + ((ulong)t * 16u);
|
||||
for (uint i = 0u; i < 16u; ++i) d[i] = s[i];
|
||||
}
|
||||
}
|
||||
|
||||
// One hash per work-item. IGNEUM_GROUP is a multiple of 32; lane = lid & 31 and every exchange stays inside the
|
||||
// lane's own aligned run of 32 work-items, exactly like simd_shuffle_xor inside a 32-wide Metal SIMD group and
|
||||
// __shfl_xor_sync inside a CUDA warp. Control flow is uniform (no branches at all).
|
||||
IGNEUM_KERNEL_HASH void igneum_hash(__global const uint* ds, __global ulong* out, uint baseNonce, uint mask) {
|
||||
uint gid = (uint)get_global_id(0);
|
||||
uint lid = (uint)get_local_id(0);
|
||||
uint nonce = baseNonce + gid;
|
||||
uint r0, r1, r2, r3, r4, r5, r6, r7;
|
||||
#if IGNEUM_EXCHANGE == 0
|
||||
IGNEUM_LOCAL_WORDS(xch, 2 * IGNEUM_GROUP);
|
||||
uint xk = 0u;
|
||||
#else
|
||||
(void)lid;
|
||||
#endif
|
||||
{ uint x = nonce ^ 0x30b957f0u; x += 0x9e3779b9u; x = splitmix32(x); r0 = x ^ 0x374e2a95u; } // SEEDW[0], 0x9e3779b9u * 1u, SEEDW[1]
|
||||
{ uint x = nonce ^ 0x374e2a95u; x += 0x3c6ef372u; x = splitmix32(x); r1 = x ^ 0xf416345eu; } // SEEDW[1], 0x9e3779b9u * 2u, SEEDW[2]
|
||||
{ uint x = nonce ^ 0xf416345eu; x += 0xdaa66d2bu; x = splitmix32(x); r2 = x ^ 0x7af15ccbu; } // SEEDW[2], 0x9e3779b9u * 3u, SEEDW[3]
|
||||
{ uint x = nonce ^ 0x7af15ccbu; x += 0x78dde6e4u; x = splitmix32(x); r3 = x ^ 0xf0bcabc5u; } // SEEDW[3], 0x9e3779b9u * 4u, SEEDW[4]
|
||||
{ uint x = nonce ^ 0xf0bcabc5u; x += 0x1715609du; x = splitmix32(x); r4 = x ^ 0xb5b36f35u; } // SEEDW[4], 0x9e3779b9u * 5u, SEEDW[5]
|
||||
{ uint x = nonce ^ 0xb5b36f35u; x += 0xb54cda56u; x = splitmix32(x); r5 = x ^ 0xf99641c7u; } // SEEDW[5], 0x9e3779b9u * 6u, SEEDW[6]
|
||||
{ uint x = nonce ^ 0xf99641c7u; x += 0x5384540fu; x = splitmix32(x); r6 = x ^ 0xd0312afeu; } // SEEDW[6], 0x9e3779b9u * 7u, SEEDW[7]
|
||||
{ uint x = nonce ^ 0xd0312afeu; x += 0xf1bbcdc8u; x = splitmix32(x); r7 = x ^ 0x30b957f0u; } // SEEDW[7], 0x9e3779b9u * 8u, SEEDW[0]
|
||||
|
||||
for (uint it = 0u; it < 8u; ++it) {
|
||||
uint sel = r0;
|
||||
r3 = rotr_var(r3, r4); // 0 rotr
|
||||
r0 = r0 ^ r7; // 1 xor
|
||||
{ uint b_ = (r0 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r1 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r1 = x_; } // 2 load
|
||||
r5 = rotl_imm(r5, 15u); // 3 rotl
|
||||
r2 = r2 + r3 + ((((sel >> 6u) & 1u) != 0u) ? 0xd35e575cu : 0xd7a264d9u); // 4 add
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r2, 1u); r5 = r5 ^ t_; } // 5 shfl
|
||||
r1 = r2 * r5 + r1; // 6 mad
|
||||
r2 = r2 | r3; // 7 or
|
||||
r3 = r3 ^ r5; // 8 xor
|
||||
r0 = r0 + r3 + ((((sel >> 29u) & 1u) != 0u) ? 0xd98be6edu : 0x4e543e70u); // 9 add
|
||||
r5 = rotr_var(r5, r1); // 10 rotr
|
||||
r3 = r3 * r5; // 11 mul
|
||||
r2 = r2 ^ r7; // 12 xor
|
||||
r1 = r1 + r6 + ((((sel >> 30u) & 1u) != 0u) ? 0x97a9219cu : 0xe36f3c9fu); // 13 add
|
||||
r2 = r2 | r1; // 14 or
|
||||
r1 = r1 | r3; // 15 or
|
||||
r7 = r3 * r7 + r7; // 16 mad
|
||||
r3 = r3 + r2 + ((((sel >> 13u) & 1u) != 0u) ? 0xf799b153u : 0x0c0a7b49u); // 17 add
|
||||
r7 = r7 ^ ds[r5 & mask]; // 18 load
|
||||
r7 = r7 ^ ds[r2 & mask]; // 19 load
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r0, 8u); r5 = r5 ^ t_; } // 20 shfl
|
||||
r4 = r4 ^ ds[r1 & mask]; // 21 load
|
||||
r5 = r5 ^ ds[r7 & mask]; // 22 load
|
||||
r4 = r4 ^ r2; // 23 xor
|
||||
r5 = r5 + r3 + ((((sel >> 14u) & 1u) != 0u) ? 0x26eb8325u : 0x011f9670u); // 24 add
|
||||
r0 = r0 * r1; // 25 mul
|
||||
r4 = r4 ^ r7; // 26 xor
|
||||
r7 = r7 + r5 + ((((sel >> 26u) & 1u) != 0u) ? 0xf12a4057u : 0x42177757u); // 27 add
|
||||
r5 = r0 * r7 + r5; // 28 mad
|
||||
r3 = r3 * r6; // 29 mul
|
||||
r6 = rotl_imm(r6, 24u); // 30 rotl
|
||||
r4 = rotr_var(r4, r0); // 31 rotr
|
||||
r6 = r6 ^ ds[r4 & mask]; // 32 load
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r1, 1u); r0 = r0 ^ t_; } // 33 shfl
|
||||
r4 = r4 * r5; // 34 mul
|
||||
r2 = rotl_imm(r2, 15u); // 35 rotl
|
||||
r7 = r7 + r3 + ((((sel >> 5u) & 1u) != 0u) ? 0xc1b9573fu : 0xe0ebc725u); // 36 add
|
||||
{ uint b_ = (r2 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r0 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r0 = x_; } // 37 load
|
||||
r7 = r0 * r2 + r7; // 38 mad
|
||||
r0 = r0 + r7 + ((((sel >> 16u) & 1u) != 0u) ? 0xde4cd365u : 0xd0b844deu); // 39 add
|
||||
{ uint b_ = (r6 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r7 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r7 = x_; } // 40 load
|
||||
r0 = r0 ^ r1; // 41 xor
|
||||
r1 = rotl_imm(r1, 19u); // 42 rotl
|
||||
r7 = r7 ^ r1; // 43 xor
|
||||
r2 = r2 * r4; // 44 mul
|
||||
{ uint b_ = (r4 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r6 = x_; } // 45 load
|
||||
r7 = r7 + r3 + ((((sel >> 28u) & 1u) != 0u) ? 0x5d12f1a2u : 0x7633c48cu); // 46 add
|
||||
r3 = r3 ^ ds[r2 & mask]; // 47 load
|
||||
{ uint b_ = (r5 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r2 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r2 = x_; } // 48 load
|
||||
r7 = r7 * r5; // 49 mul
|
||||
r3 = r7 * r0 + r3; // 50 mad
|
||||
{ uint b_ = (r2 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r3 = x_; } // 51 load
|
||||
{ uint b_ = (r7 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r4 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r4 = x_; } // 52 load
|
||||
r4 = mul_hi(r4, r1); // 53 mulhi
|
||||
r7 = r7 + r4 + ((((sel >> 24u) & 1u) != 0u) ? 0xd8ed09bau : 0xf64a6e41u); // 54 add
|
||||
r5 = mul_hi(r5, r3); // 55 mulhi
|
||||
r5 = r5 * r7; // 56 mul
|
||||
{ uint b_ = (r0 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r3 = x_; } // 57 load
|
||||
r5 = mul_hi(r5, r2); // 58 mulhi
|
||||
r7 = r7 * r5; // 59 mul
|
||||
{ uint b_ = (r3 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r6 = x_; } // 60 load
|
||||
r7 = r1 * r1 + r7; // 61 mad
|
||||
r0 = r0 ^ ds[r7 & mask]; // 62 load
|
||||
r5 = r5 * r3; // 63 mul
|
||||
}
|
||||
uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u);
|
||||
uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u);
|
||||
out[gid] = ((ulong)hi << 32) | (ulong)lo;
|
||||
}
|
||||
|
||||
#if IGNEUM_EXCHANGE != 0
|
||||
// Reports the sub-group size this device uses for a work-group of IGNEUM_GROUP items. host.c runs it only when the
|
||||
// per-kernel query (clGetKernelSubGroupInfoKHR on igneum_hash) is unavailable; that query is preferred because a
|
||||
// compiler may pick a different wave width per kernel (RDNA: wave32 or wave64). See WAVEFRONT.md.
|
||||
IGNEUM_KERNEL_HASH void igneum_probe_subgroup(__global uint* out) {
|
||||
if (get_local_id(0) == 0u) { out[0] = get_sub_group_size(); out[1] = get_num_sub_groups(); }
|
||||
}
|
||||
#endif
|
||||
164
proto-cuda/packs-readwidth/mixA-3/kernel.cu
Normal file
164
proto-cuda/packs-readwidth/mixA-3/kernel.cu
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
// Generated by igneum-pow export (generator v2) for seed "igneum-readwidth/A/3". Do not edit by hand.
|
||||
// Bit-exact twin of the Metal kernel for the same seed (see proto-cuda/CHECKLIST.md and program.metal).
|
||||
// Compiled ahead of time by nvcc together with proto-cuda/host.cu. No NVRTC.
|
||||
#include <cuda_runtime.h>
|
||||
#include <cstdint>
|
||||
#include "program.h"
|
||||
#include "memhard.h"
|
||||
|
||||
__device__ __forceinline__ uint32_t splitmix32(uint32_t x) {
|
||||
x ^= x >> 16; x *= 0x7feb352du;
|
||||
x ^= x >> 15; x *= 0x846ca68bu;
|
||||
x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
// n is a literal in 1..31 at every call site, so both shift amounts are in 1..31.
|
||||
__device__ __forceinline__ uint32_t rotl_imm(uint32_t x, uint32_t n) { return (x << n) | (x >> (32u - n)); }
|
||||
// n is masked to 0..31; the second shift amount is masked too, so n == 0 gives x.
|
||||
__device__ __forceinline__ uint32_t rotr_var(uint32_t x, uint32_t n) { n &= 31u; return (x >> n) | (x << ((32u - n) & 31u)); }
|
||||
__device__ __forceinline__ uint32_t ds_elem(uint32_t i, uint32_t d0, uint32_t d1) {
|
||||
uint32_t x = i ^ d0;
|
||||
x *= 0x9E3779B1u; x ^= x >> 15;
|
||||
x += d1;
|
||||
x *= 0x85EBCA77u; x ^= x >> 13;
|
||||
x *= 0xC2B2AE3Du; x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
|
||||
// Memory-hard dataset (MEMHARD.md). One thread per cache segment; one thread per 64-byte dataset item.
|
||||
// The core functions (mh_cache_segment, mh_item) are in memhard.h and are also compiled for the host.
|
||||
__global__ void igneum_cache_fill(uint32_t* cache, uint32_t nSegments) {
|
||||
uint32_t seg = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
if (seg < nSegments) mh_cache_segment(cache, seg);
|
||||
}
|
||||
__global__ void igneum_build(uint32_t* ds, const uint32_t* cache, uint32_t nItems) {
|
||||
uint32_t t = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
if (t < nItems) {
|
||||
uint32_t s[16];
|
||||
mh_item(cache, t, s);
|
||||
uint32_t* d = ds + (size_t)t * 16u;
|
||||
for (uint32_t i = 0u; i < 16u; ++i) d[i] = s[i];
|
||||
}
|
||||
}
|
||||
|
||||
// One hash per thread. blockDim.x is a multiple of 32; lane = threadIdx.x & 31 and every
|
||||
// __shfl_xor_sync stays inside the lane's own warp, exactly like simd_shuffle_xor inside a
|
||||
// 32-wide Metal SIMD group. Control flow is uniform, so the full 0xffffffff member mask is valid.
|
||||
__global__ void igneum_hash(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask) {
|
||||
uint32_t gid = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
uint32_t nonce = baseNonce + gid;
|
||||
uint32_t r0, r1, r2, r3, r4, r5, r6, r7;
|
||||
{ uint32_t x = nonce ^ 0x30b957f0u; x += 0x9e3779b9u; x = splitmix32(x); r0 = x ^ 0x374e2a95u; } // SEEDW[0], 0x9e3779b9u * 1u, SEEDW[1]
|
||||
{ uint32_t x = nonce ^ 0x374e2a95u; x += 0x3c6ef372u; x = splitmix32(x); r1 = x ^ 0xf416345eu; } // SEEDW[1], 0x9e3779b9u * 2u, SEEDW[2]
|
||||
{ uint32_t x = nonce ^ 0xf416345eu; x += 0xdaa66d2bu; x = splitmix32(x); r2 = x ^ 0x7af15ccbu; } // SEEDW[2], 0x9e3779b9u * 3u, SEEDW[3]
|
||||
{ uint32_t x = nonce ^ 0x7af15ccbu; x += 0x78dde6e4u; x = splitmix32(x); r3 = x ^ 0xf0bcabc5u; } // SEEDW[3], 0x9e3779b9u * 4u, SEEDW[4]
|
||||
{ uint32_t x = nonce ^ 0xf0bcabc5u; x += 0x1715609du; x = splitmix32(x); r4 = x ^ 0xb5b36f35u; } // SEEDW[4], 0x9e3779b9u * 5u, SEEDW[5]
|
||||
{ uint32_t x = nonce ^ 0xb5b36f35u; x += 0xb54cda56u; x = splitmix32(x); r5 = x ^ 0xf99641c7u; } // SEEDW[5], 0x9e3779b9u * 6u, SEEDW[6]
|
||||
{ uint32_t x = nonce ^ 0xf99641c7u; x += 0x5384540fu; x = splitmix32(x); r6 = x ^ 0xd0312afeu; } // SEEDW[6], 0x9e3779b9u * 7u, SEEDW[7]
|
||||
{ uint32_t x = nonce ^ 0xd0312afeu; x += 0xf1bbcdc8u; x = splitmix32(x); r7 = x ^ 0x30b957f0u; } // SEEDW[7], 0x9e3779b9u * 8u, SEEDW[0]
|
||||
|
||||
for (uint32_t it = 0u; it < 8u; ++it) {
|
||||
uint32_t sel = r0;
|
||||
r3 = rotr_var(r3, r4); // 0 rotr
|
||||
r0 = r0 ^ r7; // 1 xor
|
||||
{ uint32_t b_ = (r0 & mask) & ~15u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint32_t x_ = r1 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r1 = x_; } // 2 load
|
||||
r5 = rotl_imm(r5, 15u); // 3 rotl
|
||||
r2 = r2 + r3 + ((((sel >> 6u) & 1u) != 0u) ? 0xd35e575cu : 0xd7a264d9u); // 4 add
|
||||
r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r2, 1); // 5 shfl
|
||||
r1 = r2 * r5 + r1; // 6 mad
|
||||
r2 = r2 | r3; // 7 or
|
||||
r3 = r3 ^ r5; // 8 xor
|
||||
r0 = r0 + r3 + ((((sel >> 29u) & 1u) != 0u) ? 0xd98be6edu : 0x4e543e70u); // 9 add
|
||||
r5 = rotr_var(r5, r1); // 10 rotr
|
||||
r3 = r3 * r5; // 11 mul
|
||||
r2 = r2 ^ r7; // 12 xor
|
||||
r1 = r1 + r6 + ((((sel >> 30u) & 1u) != 0u) ? 0x97a9219cu : 0xe36f3c9fu); // 13 add
|
||||
r2 = r2 | r1; // 14 or
|
||||
r1 = r1 | r3; // 15 or
|
||||
r7 = r3 * r7 + r7; // 16 mad
|
||||
r3 = r3 + r2 + ((((sel >> 13u) & 1u) != 0u) ? 0xf799b153u : 0x0c0a7b49u); // 17 add
|
||||
r7 = r7 ^ ds[r5 & mask]; // 18 load
|
||||
r7 = r7 ^ ds[r2 & mask]; // 19 load
|
||||
r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r0, 8); // 20 shfl
|
||||
r4 = r4 ^ ds[r1 & mask]; // 21 load
|
||||
r5 = r5 ^ ds[r7 & mask]; // 22 load
|
||||
r4 = r4 ^ r2; // 23 xor
|
||||
r5 = r5 + r3 + ((((sel >> 14u) & 1u) != 0u) ? 0x26eb8325u : 0x011f9670u); // 24 add
|
||||
r0 = r0 * r1; // 25 mul
|
||||
r4 = r4 ^ r7; // 26 xor
|
||||
r7 = r7 + r5 + ((((sel >> 26u) & 1u) != 0u) ? 0xf12a4057u : 0x42177757u); // 27 add
|
||||
r5 = r0 * r7 + r5; // 28 mad
|
||||
r3 = r3 * r6; // 29 mul
|
||||
r6 = rotl_imm(r6, 24u); // 30 rotl
|
||||
r4 = rotr_var(r4, r0); // 31 rotr
|
||||
r6 = r6 ^ ds[r4 & mask]; // 32 load
|
||||
r0 = r0 ^ __shfl_xor_sync(0xffffffffu, r1, 1); // 33 shfl
|
||||
r4 = r4 * r5; // 34 mul
|
||||
r2 = rotl_imm(r2, 15u); // 35 rotl
|
||||
r7 = r7 + r3 + ((((sel >> 5u) & 1u) != 0u) ? 0xc1b9573fu : 0xe0ebc725u); // 36 add
|
||||
{ uint32_t b_ = (r2 & mask) & ~3u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint32_t x_ = r0 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r0 = x_; } // 37 load
|
||||
r7 = r0 * r2 + r7; // 38 mad
|
||||
r0 = r0 + r7 + ((((sel >> 16u) & 1u) != 0u) ? 0xde4cd365u : 0xd0b844deu); // 39 add
|
||||
{ uint32_t b_ = (r6 & mask) & ~15u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint32_t x_ = r7 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r7 = x_; } // 40 load
|
||||
r0 = r0 ^ r1; // 41 xor
|
||||
r1 = rotl_imm(r1, 19u); // 42 rotl
|
||||
r7 = r7 ^ r1; // 43 xor
|
||||
r2 = r2 * r4; // 44 mul
|
||||
{ uint32_t b_ = (r4 & mask) & ~15u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint32_t x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r6 = x_; } // 45 load
|
||||
r7 = r7 + r3 + ((((sel >> 28u) & 1u) != 0u) ? 0x5d12f1a2u : 0x7633c48cu); // 46 add
|
||||
r3 = r3 ^ ds[r2 & mask]; // 47 load
|
||||
{ uint32_t b_ = (r5 & mask) & ~15u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint32_t x_ = r2 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r2 = x_; } // 48 load
|
||||
r7 = r7 * r5; // 49 mul
|
||||
r3 = r7 * r0 + r3; // 50 mad
|
||||
{ uint32_t b_ = (r2 & mask) & ~3u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint32_t x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r3 = x_; } // 51 load
|
||||
{ uint32_t b_ = (r7 & mask) & ~3u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint32_t x_ = r4 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r4 = x_; } // 52 load
|
||||
r4 = __umulhi(r4, r1); // 53 mulhi
|
||||
r7 = r7 + r4 + ((((sel >> 24u) & 1u) != 0u) ? 0xd8ed09bau : 0xf64a6e41u); // 54 add
|
||||
r5 = __umulhi(r5, r3); // 55 mulhi
|
||||
r5 = r5 * r7; // 56 mul
|
||||
{ uint32_t b_ = (r0 & mask) & ~15u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint32_t x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r3 = x_; } // 57 load
|
||||
r5 = __umulhi(r5, r2); // 58 mulhi
|
||||
r7 = r7 * r5; // 59 mul
|
||||
{ uint32_t b_ = (r3 & mask) & ~15u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint32_t x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r6 = x_; } // 60 load
|
||||
r7 = r1 * r1 + r7; // 61 mad
|
||||
r0 = r0 ^ ds[r7 & mask]; // 62 load
|
||||
r5 = r5 * r3; // 63 mul
|
||||
}
|
||||
uint32_t lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u);
|
||||
uint32_t hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u);
|
||||
out[gid] = ((uint64_t)hi << 32) | (uint64_t)lo;
|
||||
}
|
||||
|
||||
// Host-side launch wrappers. Declared in program.h, called from host.cu.
|
||||
cudaError_t igneum_launch_cache_fill(uint32_t* cache, uint32_t nSegments) {
|
||||
if (nSegments == 0u) return cudaErrorInvalidValue;
|
||||
uint32_t block = 256u;
|
||||
uint32_t grid = (nSegments + block - 1u) / block;
|
||||
igneum_cache_fill<<<grid, block>>>(cache, nSegments);
|
||||
return cudaGetLastError();
|
||||
}
|
||||
|
||||
cudaError_t igneum_launch_build(uint32_t* ds, const uint32_t* cache, uint32_t nItems) {
|
||||
if (nItems == 0u) return cudaErrorInvalidValue;
|
||||
uint32_t block = 256u;
|
||||
uint32_t grid = (nItems + block - 1u) / block;
|
||||
igneum_build<<<grid, block>>>(ds, cache, nItems);
|
||||
return cudaGetLastError();
|
||||
}
|
||||
|
||||
cudaError_t igneum_launch_hash(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask,
|
||||
uint32_t nonces, uint32_t blockWarps) {
|
||||
if (blockWarps == 0u || blockWarps > 32u) return cudaErrorInvalidValue;
|
||||
uint32_t block = 32u * blockWarps;
|
||||
if (nonces == 0u || (nonces % block) != 0u) return cudaErrorInvalidValue;
|
||||
igneum_hash<<<nonces / block, block>>>(ds, out, baseNonce, mask);
|
||||
return cudaGetLastError();
|
||||
}
|
||||
|
||||
cudaError_t igneum_hash_info(int* numRegs, int* blocksPerSM, uint32_t blockWarps) {
|
||||
cudaFuncAttributes attr;
|
||||
cudaError_t e = cudaFuncGetAttributes(&attr, igneum_hash);
|
||||
if (e != cudaSuccess) return e;
|
||||
*numRegs = attr.numRegs;
|
||||
return cudaOccupancyMaxActiveBlocksPerMultiprocessor(blocksPerSM, igneum_hash, (int)(32u * blockWarps), 0);
|
||||
}
|
||||
372
proto-cuda/packs-readwidth/mixA-3/kernel_bound.cl
Normal file
372
proto-cuda/packs-readwidth/mixA-3/kernel_bound.cl
Normal file
|
|
@ -0,0 +1,372 @@
|
|||
// Generated by igneum-pow export (generator v2) for seed "igneum-readwidth/A/3". Do not edit by hand.
|
||||
// OpenCL C twin of the Metal kernel for the same seed (see proto-opencl/README.md, WAVEFRONT.md and program.metal).
|
||||
// Built from source at runtime by proto-opencl/host.c, which passes these defines:
|
||||
// IGNEUM_GROUP work-group size of igneum_hash, a multiple of 32 (default 32: one work-group = one 32-lane unit)
|
||||
// IGNEUM_EXCHANGE 0 = local-memory exchange with a barrier (any device, any wave width; the default)
|
||||
// 1 = sub_group_shuffle_xor (cl_khr_subgroup_shuffle), only with IGNEUM_GROUP 32 and a sub-group size of exactly 32
|
||||
// 2 = intel_sub_group_shuffle_xor (cl_intel_subgroups), same condition
|
||||
// The verification unit is always 32 lanes. A 64-wide hardware wave (AMD GCN/CDNA, RDNA in wave64) runs two units;
|
||||
// the exchange masks are 1, 2, 4, 8, 16, so every partner lane lies inside the lane's own aligned run of 32.
|
||||
#ifndef IGNEUM_GROUP
|
||||
#define IGNEUM_GROUP 32
|
||||
#endif
|
||||
#ifndef IGNEUM_EXCHANGE
|
||||
#define IGNEUM_EXCHANGE 0
|
||||
#endif
|
||||
#ifdef __OPENCL_VERSION__
|
||||
#define IGNEUM_KERNEL_HASH __kernel __attribute__((reqd_work_group_size(IGNEUM_GROUP, 1, 1)))
|
||||
#define IGNEUM_LOCAL_WORDS(name, n) __local uint name[n]
|
||||
#if IGNEUM_EXCHANGE == 1
|
||||
#ifdef cl_khr_subgroups
|
||||
#pragma OPENCL EXTENSION cl_khr_subgroups : enable
|
||||
#endif
|
||||
#ifdef cl_khr_subgroup_shuffle
|
||||
#pragma OPENCL EXTENSION cl_khr_subgroup_shuffle : enable
|
||||
#endif
|
||||
#elif IGNEUM_EXCHANGE == 2
|
||||
#pragma OPENCL EXTENSION cl_intel_subgroups : enable
|
||||
#endif
|
||||
#else
|
||||
// Not an OpenCL compiler: proto-opencl/emu compiles this file as C++ and supplies the built-ins and these two macros.
|
||||
#include "emu_opencl.h"
|
||||
#endif
|
||||
|
||||
#if IGNEUM_EXCHANGE == 1
|
||||
#define IGNEUM_SHFL_XOR(dst, a, m) dst = sub_group_shuffle_xor((a), (uint)(m))
|
||||
#define IGNEUM_BCAST0(dst, a) dst = sub_group_broadcast((a), 0u)
|
||||
#elif IGNEUM_EXCHANGE == 2
|
||||
#define IGNEUM_SHFL_XOR(dst, a, m) dst = intel_sub_group_shuffle_xor((a), (uint)(m))
|
||||
#define IGNEUM_BCAST0(dst, a) dst = sub_group_broadcast((a), 0u)
|
||||
#else
|
||||
// Local-memory exchange. Two buffers of IGNEUM_GROUP words alternate (xk counts exchanges), so one barrier per
|
||||
// exchange is enough: a lane can only overwrite buffer b at exchange k+2 after passing barrier k+1, and every lane
|
||||
// reaches barrier k+1 only after its read of buffer b at exchange k. The partner lid ^ m stays inside the lane's
|
||||
// aligned run of 32 because m < 32. Control flow is uniform, so every work-item reaches every barrier.
|
||||
#define IGNEUM_SHFL_XOR(dst, a, m) { xch[(xk & 1u) * IGNEUM_GROUP + lid] = (a); barrier(CLK_LOCAL_MEM_FENCE); dst = xch[(xk & 1u) * IGNEUM_GROUP + (lid ^ (uint)(m))]; xk += 1u; }
|
||||
#define IGNEUM_BCAST0(dst, a) { xch[(xk & 1u) * IGNEUM_GROUP + lid] = (a); barrier(CLK_LOCAL_MEM_FENCE); dst = xch[(xk & 1u) * IGNEUM_GROUP + (lid & ~31u)]; xk += 1u; }
|
||||
#endif
|
||||
|
||||
static inline uint splitmix32(uint x) {
|
||||
x ^= x >> 16; x *= 0x7feb352du;
|
||||
x ^= x >> 15; x *= 0x846ca68bu;
|
||||
x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
// n is a literal in 1..31 at every call site. OpenCL rotate() rotates left by n modulo 32.
|
||||
static inline uint rotl_imm(uint x, uint n) { return rotate(x, n); }
|
||||
// Right rotation by n modulo 32 as a left rotation by (32 - n) modulo 32; n == 0 gives x.
|
||||
static inline uint rotr_var(uint x, uint n) { return rotate(x, (0u - n) & 31u); }
|
||||
static inline uint ds_elem(uint i, uint d0, uint d1) {
|
||||
uint x = i ^ d0;
|
||||
x *= 0x9E3779B1u; x ^= x >> 15;
|
||||
x += d1;
|
||||
x *= 0x85EBCA77u; x ^= x >> 13;
|
||||
x *= 0xC2B2AE3Du; x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
|
||||
// Memory-hard dataset core (MEMHARD.md). Cache: 2^26 words in 2^16 segments of 64 chained ChaCha12 lines.
|
||||
// Item: 8 rounds of seed-parameterised mixer + one 64-byte cache read, then a final mixer. All parameters are literals.
|
||||
#define MH_CACHE_LINE_MASK 0x003fffffu
|
||||
#define MH_SEGMENT_LINES 64u
|
||||
#define MH_QR(a, b, c, d, r1, r2, r3, r4) { a += b; d ^= a; d = mh_rotl(d, r1); c += d; b ^= c; b = mh_rotl(b, r2); a += b; d ^= a; d = mh_rotl(d, r3); c += d; b ^= c; b = mh_rotl(b, r4); }
|
||||
static inline uint mh_rotl(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 at every call site
|
||||
|
||||
// y = ChaCha12 core(x) + x
|
||||
static inline void mh_chacha_block(const uint* x, uint* y) {
|
||||
for (uint i = 0u; i < 16u; ++i) y[i] = x[i];
|
||||
for (uint r = 0u; r < 6u; ++r) {
|
||||
MH_QR(y[0], y[4], y[8], y[12], 16u, 12u, 8u, 7u) MH_QR(y[1], y[5], y[9], y[13], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[2], y[6], y[10], y[14], 16u, 12u, 8u, 7u) MH_QR(y[3], y[7], y[11], y[15], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[0], y[5], y[10], y[15], 16u, 12u, 8u, 7u) MH_QR(y[1], y[6], y[11], y[12], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[2], y[7], y[8], y[13], 16u, 12u, 8u, 7u) MH_QR(y[3], y[4], y[9], y[14], 16u, 12u, 8u, 7u)
|
||||
}
|
||||
for (uint i = 0u; i < 16u; ++i) y[i] += x[i];
|
||||
}
|
||||
|
||||
// One cache segment: 64 chained lines written at cache[seg * 1024]. in_j = prev ^ (sigma || K || seg || j || tag), prev_0 = 0.
|
||||
static inline void mh_cache_segment(__global uint* cache, uint seg) {
|
||||
uint prev[16]; uint x[16]; uint y[16];
|
||||
for (uint i = 0u; i < 16u; ++i) prev[i] = 0u;
|
||||
for (uint j = 0u; j < MH_SEGMENT_LINES; ++j) {
|
||||
x[0] = 0x61707865u ^ prev[0]; x[1] = 0x3320646eu ^ prev[1]; x[2] = 0x79622d32u ^ prev[2]; x[3] = 0x6b206574u ^ prev[3];
|
||||
x[4] = 0x3067619fu ^ prev[4];
|
||||
x[5] = 0x3c269176u ^ prev[5];
|
||||
x[6] = 0x84a03b03u ^ prev[6];
|
||||
x[7] = 0xf8c63294u ^ prev[7];
|
||||
x[8] = 0xff977c5bu ^ prev[8];
|
||||
x[9] = 0xe60def3eu ^ prev[9];
|
||||
x[10] = 0x63630141u ^ prev[10];
|
||||
x[11] = 0xb8fbcb58u ^ prev[11];
|
||||
x[12] = seg ^ prev[12]; x[13] = j ^ prev[13]; x[14] = 0x49676e65u ^ prev[14]; x[15] = 0x756d4d48u ^ prev[15];
|
||||
mh_chacha_block(x, y);
|
||||
__global uint* line = cache + ((seg * MH_SEGMENT_LINES + j) * 16u);
|
||||
for (uint i = 0u; i < 16u; ++i) { line[i] = y[i]; prev[i] = y[i]; }
|
||||
}
|
||||
}
|
||||
|
||||
// M_r: per word (s ^ (RC + rk)) * MUL, then a column round and a diagonal round with the seed-drawn rotations.
|
||||
static inline void mh_mixer(uint* s, uint rk) {
|
||||
s[0] = (s[0] ^ (0xbab68293u + rk)) * 0x42146205u;
|
||||
s[1] = (s[1] ^ (0xcc162340u + rk)) * 0x52cbe0fbu;
|
||||
s[2] = (s[2] ^ (0x6ce151ccu + rk)) * 0x7ecf4a03u;
|
||||
s[3] = (s[3] ^ (0xe62b8997u + rk)) * 0x6728907fu;
|
||||
s[4] = (s[4] ^ (0xc9c80297u + rk)) * 0xd81d9751u;
|
||||
s[5] = (s[5] ^ (0xf74a1654u + rk)) * 0x132952c3u;
|
||||
s[6] = (s[6] ^ (0x3d704af5u + rk)) * 0xf60de277u;
|
||||
s[7] = (s[7] ^ (0x3cf522b7u + rk)) * 0x05358035u;
|
||||
s[8] = (s[8] ^ (0x2b9cac04u + rk)) * 0xbaf6499du;
|
||||
s[9] = (s[9] ^ (0xa880ac10u + rk)) * 0xe4db9667u;
|
||||
s[10] = (s[10] ^ (0x13e5dd1du + rk)) * 0x3e98f45du;
|
||||
s[11] = (s[11] ^ (0x6fc3e233u + rk)) * 0xd0004eddu;
|
||||
s[12] = (s[12] ^ (0x2d83eeacu + rk)) * 0x2691630du;
|
||||
s[13] = (s[13] ^ (0x9006e8bfu + rk)) * 0x9beb3bcfu;
|
||||
s[14] = (s[14] ^ (0x2c4b5362u + rk)) * 0xab310379u;
|
||||
s[15] = (s[15] ^ (0x31b49ee2u + rk)) * 0x99cfb423u;
|
||||
MH_QR(s[0], s[4], s[8], s[12], 20u, 20u, 19u, 4u) MH_QR(s[1], s[5], s[9], s[13], 20u, 20u, 19u, 4u)
|
||||
MH_QR(s[2], s[6], s[10], s[14], 20u, 20u, 19u, 4u) MH_QR(s[3], s[7], s[11], s[15], 20u, 20u, 19u, 4u)
|
||||
MH_QR(s[0], s[5], s[10], s[15], 26u, 3u, 3u, 27u) MH_QR(s[1], s[6], s[11], s[12], 26u, 3u, 3u, 27u)
|
||||
MH_QR(s[2], s[7], s[8], s[13], 26u, 3u, 3u, 27u) MH_QR(s[3], s[4], s[9], s[14], 26u, 3u, 3u, 27u)
|
||||
}
|
||||
|
||||
// Item t: 16 words. s = (K, t * MUL[i] + RC[i]); 8 rounds of mixer + cache line s[0] & mask; final mixer.
|
||||
static inline void mh_item(__global const uint* cache, uint t, uint* s) {
|
||||
s[0] = 0x3067619fu;
|
||||
s[1] = 0x3c269176u;
|
||||
s[2] = 0x84a03b03u;
|
||||
s[3] = 0xf8c63294u;
|
||||
s[4] = 0xff977c5bu;
|
||||
s[5] = 0xe60def3eu;
|
||||
s[6] = 0x63630141u;
|
||||
s[7] = 0xb8fbcb58u;
|
||||
s[8] = t * 0x42146205u + 0xbab68293u;
|
||||
s[9] = t * 0x52cbe0fbu + 0xcc162340u;
|
||||
s[10] = t * 0x7ecf4a03u + 0x6ce151ccu;
|
||||
s[11] = t * 0x6728907fu + 0xe62b8997u;
|
||||
s[12] = t * 0xd81d9751u + 0xc9c80297u;
|
||||
s[13] = t * 0x132952c3u + 0xf74a1654u;
|
||||
s[14] = t * 0xf60de277u + 0x3d704af5u;
|
||||
s[15] = t * 0x05358035u + 0x3cf522b7u;
|
||||
for (uint r = 0u; r < 8u; ++r) {
|
||||
mh_mixer(s, 0x9E3779B9u * (r + 1u));
|
||||
__global const uint* line = cache + ((s[0] & MH_CACHE_LINE_MASK) * 16u);
|
||||
for (uint i = 0u; i < 16u; ++i) s[i] ^= line[i];
|
||||
}
|
||||
mh_mixer(s, 0x9E3779B9u * 9u);
|
||||
}
|
||||
// dataset[w] without the dataset: derive item w >> 4 and take word w & 15.
|
||||
static inline uint mh_word(__global const uint* cache, uint w) { uint s[16]; mh_item(cache, w >> 4u, s); return s[w & 15u]; }
|
||||
|
||||
// Memory-hard dataset (MEMHARD.md). One work-item per cache segment; one work-item per 64-byte dataset item.
|
||||
// The same constants as memhard.h in this pack (one emitter, three dialects).
|
||||
__kernel void igneum_cache_fill(__global uint* cache, uint nSegments) {
|
||||
uint seg = (uint)get_global_id(0);
|
||||
if (seg < nSegments) mh_cache_segment(cache, seg);
|
||||
}
|
||||
__kernel void igneum_build(__global uint* ds, __global const uint* cache, uint nItems) {
|
||||
uint t = (uint)get_global_id(0);
|
||||
if (t < nItems) {
|
||||
uint s[16];
|
||||
mh_item(cache, t, s);
|
||||
__global uint* d = ds + ((ulong)t * 16u);
|
||||
for (uint i = 0u; i < 16u; ++i) d[i] = s[i];
|
||||
}
|
||||
}
|
||||
|
||||
// One hash per work-item. IGNEUM_GROUP is a multiple of 32; lane = lid & 31 and every exchange stays inside the
|
||||
// lane's own aligned run of 32 work-items, exactly like simd_shuffle_xor inside a 32-wide Metal SIMD group and
|
||||
// __shfl_xor_sync inside a CUDA warp. Control flow is uniform (no branches at all).
|
||||
IGNEUM_KERNEL_HASH void igneum_hash(__global const uint* ds, __global ulong* out, uint baseNonce, uint mask) {
|
||||
uint gid = (uint)get_global_id(0);
|
||||
uint lid = (uint)get_local_id(0);
|
||||
uint nonce = baseNonce + gid;
|
||||
uint r0, r1, r2, r3, r4, r5, r6, r7;
|
||||
#if IGNEUM_EXCHANGE == 0
|
||||
IGNEUM_LOCAL_WORDS(xch, 2 * IGNEUM_GROUP);
|
||||
uint xk = 0u;
|
||||
#else
|
||||
(void)lid;
|
||||
#endif
|
||||
{ uint x = nonce ^ 0x30b957f0u; x += 0x9e3779b9u; x = splitmix32(x); r0 = x ^ 0x374e2a95u; } // SEEDW[0], 0x9e3779b9u * 1u, SEEDW[1]
|
||||
{ uint x = nonce ^ 0x374e2a95u; x += 0x3c6ef372u; x = splitmix32(x); r1 = x ^ 0xf416345eu; } // SEEDW[1], 0x9e3779b9u * 2u, SEEDW[2]
|
||||
{ uint x = nonce ^ 0xf416345eu; x += 0xdaa66d2bu; x = splitmix32(x); r2 = x ^ 0x7af15ccbu; } // SEEDW[2], 0x9e3779b9u * 3u, SEEDW[3]
|
||||
{ uint x = nonce ^ 0x7af15ccbu; x += 0x78dde6e4u; x = splitmix32(x); r3 = x ^ 0xf0bcabc5u; } // SEEDW[3], 0x9e3779b9u * 4u, SEEDW[4]
|
||||
{ uint x = nonce ^ 0xf0bcabc5u; x += 0x1715609du; x = splitmix32(x); r4 = x ^ 0xb5b36f35u; } // SEEDW[4], 0x9e3779b9u * 5u, SEEDW[5]
|
||||
{ uint x = nonce ^ 0xb5b36f35u; x += 0xb54cda56u; x = splitmix32(x); r5 = x ^ 0xf99641c7u; } // SEEDW[5], 0x9e3779b9u * 6u, SEEDW[6]
|
||||
{ uint x = nonce ^ 0xf99641c7u; x += 0x5384540fu; x = splitmix32(x); r6 = x ^ 0xd0312afeu; } // SEEDW[6], 0x9e3779b9u * 7u, SEEDW[7]
|
||||
{ uint x = nonce ^ 0xd0312afeu; x += 0xf1bbcdc8u; x = splitmix32(x); r7 = x ^ 0x30b957f0u; } // SEEDW[7], 0x9e3779b9u * 8u, SEEDW[0]
|
||||
|
||||
for (uint it = 0u; it < 8u; ++it) {
|
||||
uint sel = r0;
|
||||
r3 = rotr_var(r3, r4); // 0 rotr
|
||||
r0 = r0 ^ r7; // 1 xor
|
||||
{ uint b_ = (r0 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r1 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r1 = x_; } // 2 load
|
||||
r5 = rotl_imm(r5, 15u); // 3 rotl
|
||||
r2 = r2 + r3 + ((((sel >> 6u) & 1u) != 0u) ? 0xd35e575cu : 0xd7a264d9u); // 4 add
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r2, 1u); r5 = r5 ^ t_; } // 5 shfl
|
||||
r1 = r2 * r5 + r1; // 6 mad
|
||||
r2 = r2 | r3; // 7 or
|
||||
r3 = r3 ^ r5; // 8 xor
|
||||
r0 = r0 + r3 + ((((sel >> 29u) & 1u) != 0u) ? 0xd98be6edu : 0x4e543e70u); // 9 add
|
||||
r5 = rotr_var(r5, r1); // 10 rotr
|
||||
r3 = r3 * r5; // 11 mul
|
||||
r2 = r2 ^ r7; // 12 xor
|
||||
r1 = r1 + r6 + ((((sel >> 30u) & 1u) != 0u) ? 0x97a9219cu : 0xe36f3c9fu); // 13 add
|
||||
r2 = r2 | r1; // 14 or
|
||||
r1 = r1 | r3; // 15 or
|
||||
r7 = r3 * r7 + r7; // 16 mad
|
||||
r3 = r3 + r2 + ((((sel >> 13u) & 1u) != 0u) ? 0xf799b153u : 0x0c0a7b49u); // 17 add
|
||||
r7 = r7 ^ ds[r5 & mask]; // 18 load
|
||||
r7 = r7 ^ ds[r2 & mask]; // 19 load
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r0, 8u); r5 = r5 ^ t_; } // 20 shfl
|
||||
r4 = r4 ^ ds[r1 & mask]; // 21 load
|
||||
r5 = r5 ^ ds[r7 & mask]; // 22 load
|
||||
r4 = r4 ^ r2; // 23 xor
|
||||
r5 = r5 + r3 + ((((sel >> 14u) & 1u) != 0u) ? 0x26eb8325u : 0x011f9670u); // 24 add
|
||||
r0 = r0 * r1; // 25 mul
|
||||
r4 = r4 ^ r7; // 26 xor
|
||||
r7 = r7 + r5 + ((((sel >> 26u) & 1u) != 0u) ? 0xf12a4057u : 0x42177757u); // 27 add
|
||||
r5 = r0 * r7 + r5; // 28 mad
|
||||
r3 = r3 * r6; // 29 mul
|
||||
r6 = rotl_imm(r6, 24u); // 30 rotl
|
||||
r4 = rotr_var(r4, r0); // 31 rotr
|
||||
r6 = r6 ^ ds[r4 & mask]; // 32 load
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r1, 1u); r0 = r0 ^ t_; } // 33 shfl
|
||||
r4 = r4 * r5; // 34 mul
|
||||
r2 = rotl_imm(r2, 15u); // 35 rotl
|
||||
r7 = r7 + r3 + ((((sel >> 5u) & 1u) != 0u) ? 0xc1b9573fu : 0xe0ebc725u); // 36 add
|
||||
{ uint b_ = (r2 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r0 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r0 = x_; } // 37 load
|
||||
r7 = r0 * r2 + r7; // 38 mad
|
||||
r0 = r0 + r7 + ((((sel >> 16u) & 1u) != 0u) ? 0xde4cd365u : 0xd0b844deu); // 39 add
|
||||
{ uint b_ = (r6 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r7 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r7 = x_; } // 40 load
|
||||
r0 = r0 ^ r1; // 41 xor
|
||||
r1 = rotl_imm(r1, 19u); // 42 rotl
|
||||
r7 = r7 ^ r1; // 43 xor
|
||||
r2 = r2 * r4; // 44 mul
|
||||
{ uint b_ = (r4 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r6 = x_; } // 45 load
|
||||
r7 = r7 + r3 + ((((sel >> 28u) & 1u) != 0u) ? 0x5d12f1a2u : 0x7633c48cu); // 46 add
|
||||
r3 = r3 ^ ds[r2 & mask]; // 47 load
|
||||
{ uint b_ = (r5 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r2 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r2 = x_; } // 48 load
|
||||
r7 = r7 * r5; // 49 mul
|
||||
r3 = r7 * r0 + r3; // 50 mad
|
||||
{ uint b_ = (r2 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r3 = x_; } // 51 load
|
||||
{ uint b_ = (r7 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r4 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r4 = x_; } // 52 load
|
||||
r4 = mul_hi(r4, r1); // 53 mulhi
|
||||
r7 = r7 + r4 + ((((sel >> 24u) & 1u) != 0u) ? 0xd8ed09bau : 0xf64a6e41u); // 54 add
|
||||
r5 = mul_hi(r5, r3); // 55 mulhi
|
||||
r5 = r5 * r7; // 56 mul
|
||||
{ uint b_ = (r0 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r3 = x_; } // 57 load
|
||||
r5 = mul_hi(r5, r2); // 58 mulhi
|
||||
r7 = r7 * r5; // 59 mul
|
||||
{ uint b_ = (r3 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r6 = x_; } // 60 load
|
||||
r7 = r1 * r1 + r7; // 61 mad
|
||||
r0 = r0 ^ ds[r7 & mask]; // 62 load
|
||||
r5 = r5 * r3; // 63 mul
|
||||
}
|
||||
uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u);
|
||||
uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u);
|
||||
out[gid] = ((ulong)hi << 32) | (ulong)lo;
|
||||
}
|
||||
|
||||
#if IGNEUM_EXCHANGE != 0
|
||||
// Reports the sub-group size this device uses for a work-group of IGNEUM_GROUP items. host.c runs it only when the
|
||||
// per-kernel query (clGetKernelSubGroupInfoKHR on igneum_hash) is unavailable; that query is preferred because a
|
||||
// compiler may pick a different wave width per kernel (RDNA: wave32 or wave64). See WAVEFRONT.md.
|
||||
IGNEUM_KERNEL_HASH void igneum_probe_subgroup(__global uint* out) {
|
||||
if (get_local_id(0) == 0u) { out[0] = get_sub_group_size(); out[1] = get_num_sub_groups(); }
|
||||
}
|
||||
#endif
|
||||
|
||||
// Header-bound variant (bind.rs): the init words come from initw, not SEEDW. Same body as igneum_hash.
|
||||
IGNEUM_KERNEL_HASH void igneum_hash_bound(__global const uint* ds, __global ulong* out, uint baseNonce, uint mask, __global const uint* initw) {
|
||||
uint gid = (uint)get_global_id(0);
|
||||
uint lid = (uint)get_local_id(0);
|
||||
uint nonce = baseNonce + gid;
|
||||
uint r0, r1, r2, r3, r4, r5, r6, r7;
|
||||
uint iw0 = initw[0], iw1 = initw[1], iw2 = initw[2], iw3 = initw[3], iw4 = initw[4], iw5 = initw[5], iw6 = initw[6], iw7 = initw[7];
|
||||
#if IGNEUM_EXCHANGE == 0
|
||||
IGNEUM_LOCAL_WORDS(xch, 2 * IGNEUM_GROUP);
|
||||
uint xk = 0u;
|
||||
#else
|
||||
(void)lid;
|
||||
#endif
|
||||
{ uint x = nonce ^ iw0; x += 0x9e3779b9u * 1u; x = splitmix32(x); r0 = x ^ iw1; }
|
||||
{ uint x = nonce ^ iw1; x += 0x9e3779b9u * 2u; x = splitmix32(x); r1 = x ^ iw2; }
|
||||
{ uint x = nonce ^ iw2; x += 0x9e3779b9u * 3u; x = splitmix32(x); r2 = x ^ iw3; }
|
||||
{ uint x = nonce ^ iw3; x += 0x9e3779b9u * 4u; x = splitmix32(x); r3 = x ^ iw4; }
|
||||
{ uint x = nonce ^ iw4; x += 0x9e3779b9u * 5u; x = splitmix32(x); r4 = x ^ iw5; }
|
||||
{ uint x = nonce ^ iw5; x += 0x9e3779b9u * 6u; x = splitmix32(x); r5 = x ^ iw6; }
|
||||
{ uint x = nonce ^ iw6; x += 0x9e3779b9u * 7u; x = splitmix32(x); r6 = x ^ iw7; }
|
||||
{ uint x = nonce ^ iw7; x += 0x9e3779b9u * 8u; x = splitmix32(x); r7 = x ^ iw0; }
|
||||
|
||||
for (uint it = 0u; it < 8u; ++it) {
|
||||
uint sel = r0;
|
||||
r3 = rotr_var(r3, r4); // 0 rotr
|
||||
r0 = r0 ^ r7; // 1 xor
|
||||
{ uint b_ = (r0 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r1 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r1 = x_; } // 2 load
|
||||
r5 = rotl_imm(r5, 15u); // 3 rotl
|
||||
r2 = r2 + r3 + ((((sel >> 6u) & 1u) != 0u) ? 0xd35e575cu : 0xd7a264d9u); // 4 add
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r2, 1u); r5 = r5 ^ t_; } // 5 shfl
|
||||
r1 = r2 * r5 + r1; // 6 mad
|
||||
r2 = r2 | r3; // 7 or
|
||||
r3 = r3 ^ r5; // 8 xor
|
||||
r0 = r0 + r3 + ((((sel >> 29u) & 1u) != 0u) ? 0xd98be6edu : 0x4e543e70u); // 9 add
|
||||
r5 = rotr_var(r5, r1); // 10 rotr
|
||||
r3 = r3 * r5; // 11 mul
|
||||
r2 = r2 ^ r7; // 12 xor
|
||||
r1 = r1 + r6 + ((((sel >> 30u) & 1u) != 0u) ? 0x97a9219cu : 0xe36f3c9fu); // 13 add
|
||||
r2 = r2 | r1; // 14 or
|
||||
r1 = r1 | r3; // 15 or
|
||||
r7 = r3 * r7 + r7; // 16 mad
|
||||
r3 = r3 + r2 + ((((sel >> 13u) & 1u) != 0u) ? 0xf799b153u : 0x0c0a7b49u); // 17 add
|
||||
r7 = r7 ^ ds[r5 & mask]; // 18 load
|
||||
r7 = r7 ^ ds[r2 & mask]; // 19 load
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r0, 8u); r5 = r5 ^ t_; } // 20 shfl
|
||||
r4 = r4 ^ ds[r1 & mask]; // 21 load
|
||||
r5 = r5 ^ ds[r7 & mask]; // 22 load
|
||||
r4 = r4 ^ r2; // 23 xor
|
||||
r5 = r5 + r3 + ((((sel >> 14u) & 1u) != 0u) ? 0x26eb8325u : 0x011f9670u); // 24 add
|
||||
r0 = r0 * r1; // 25 mul
|
||||
r4 = r4 ^ r7; // 26 xor
|
||||
r7 = r7 + r5 + ((((sel >> 26u) & 1u) != 0u) ? 0xf12a4057u : 0x42177757u); // 27 add
|
||||
r5 = r0 * r7 + r5; // 28 mad
|
||||
r3 = r3 * r6; // 29 mul
|
||||
r6 = rotl_imm(r6, 24u); // 30 rotl
|
||||
r4 = rotr_var(r4, r0); // 31 rotr
|
||||
r6 = r6 ^ ds[r4 & mask]; // 32 load
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r1, 1u); r0 = r0 ^ t_; } // 33 shfl
|
||||
r4 = r4 * r5; // 34 mul
|
||||
r2 = rotl_imm(r2, 15u); // 35 rotl
|
||||
r7 = r7 + r3 + ((((sel >> 5u) & 1u) != 0u) ? 0xc1b9573fu : 0xe0ebc725u); // 36 add
|
||||
{ uint b_ = (r2 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r0 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r0 = x_; } // 37 load
|
||||
r7 = r0 * r2 + r7; // 38 mad
|
||||
r0 = r0 + r7 + ((((sel >> 16u) & 1u) != 0u) ? 0xde4cd365u : 0xd0b844deu); // 39 add
|
||||
{ uint b_ = (r6 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r7 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r7 = x_; } // 40 load
|
||||
r0 = r0 ^ r1; // 41 xor
|
||||
r1 = rotl_imm(r1, 19u); // 42 rotl
|
||||
r7 = r7 ^ r1; // 43 xor
|
||||
r2 = r2 * r4; // 44 mul
|
||||
{ uint b_ = (r4 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r6 = x_; } // 45 load
|
||||
r7 = r7 + r3 + ((((sel >> 28u) & 1u) != 0u) ? 0x5d12f1a2u : 0x7633c48cu); // 46 add
|
||||
r3 = r3 ^ ds[r2 & mask]; // 47 load
|
||||
{ uint b_ = (r5 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r2 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r2 = x_; } // 48 load
|
||||
r7 = r7 * r5; // 49 mul
|
||||
r3 = r7 * r0 + r3; // 50 mad
|
||||
{ uint b_ = (r2 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r3 = x_; } // 51 load
|
||||
{ uint b_ = (r7 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r4 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r4 = x_; } // 52 load
|
||||
r4 = mul_hi(r4, r1); // 53 mulhi
|
||||
r7 = r7 + r4 + ((((sel >> 24u) & 1u) != 0u) ? 0xd8ed09bau : 0xf64a6e41u); // 54 add
|
||||
r5 = mul_hi(r5, r3); // 55 mulhi
|
||||
r5 = r5 * r7; // 56 mul
|
||||
{ uint b_ = (r0 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r3 = x_; } // 57 load
|
||||
r5 = mul_hi(r5, r2); // 58 mulhi
|
||||
r7 = r7 * r5; // 59 mul
|
||||
{ uint b_ = (r3 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r6 = x_; } // 60 load
|
||||
r7 = r1 * r1 + r7; // 61 mad
|
||||
r0 = r0 ^ ds[r7 & mask]; // 62 load
|
||||
r5 = r5 * r3; // 63 mul
|
||||
}
|
||||
uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u);
|
||||
uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u);
|
||||
out[gid] = ((ulong)hi << 32) | (ulong)lo;
|
||||
}
|
||||
123
proto-cuda/packs-readwidth/mixA-3/kernel_bound.cu
Normal file
123
proto-cuda/packs-readwidth/mixA-3/kernel_bound.cu
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
// Generated by igneum-pow export (generator v2) for seed "igneum-readwidth/A/3". Do not edit by hand.
|
||||
// Header-bound twin of igneum_hash in kernel.cu: the init words come from a kernel argument, not SEEDW.
|
||||
// Host declarations (also in program_bound.h if present):
|
||||
// struct IgneumInitWords { uint32_t w[8]; };
|
||||
// cudaError_t igneum_launch_hash_bound(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask,
|
||||
// IgneumInitWords iw, uint32_t nonces, uint32_t blockWarps);
|
||||
// cudaError_t igneum_hash_bound_info(int* numRegs, int* blocksPerSM, uint32_t blockWarps);
|
||||
#include <cuda_runtime.h>
|
||||
#include <cstdint>
|
||||
#include "program.h"
|
||||
|
||||
struct IgneumInitWords { uint32_t w[8]; };
|
||||
|
||||
__device__ __forceinline__ uint32_t splitmix32(uint32_t x) {
|
||||
x ^= x >> 16; x *= 0x7feb352du;
|
||||
x ^= x >> 15; x *= 0x846ca68bu;
|
||||
x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
__device__ __forceinline__ uint32_t rotl_imm(uint32_t x, uint32_t n) { return (x << n) | (x >> (32u - n)); }
|
||||
__device__ __forceinline__ uint32_t rotr_var(uint32_t x, uint32_t n) { n &= 31u; return (x >> n) | (x << ((32u - n) & 31u)); }
|
||||
|
||||
__global__ void igneum_hash_bound(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask, IgneumInitWords iw) {
|
||||
uint32_t gid = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
uint32_t nonce = baseNonce + gid;
|
||||
uint32_t r0, r1, r2, r3, r4, r5, r6, r7;
|
||||
{ uint32_t x = nonce ^ iw.w[0]; x += 0x9e3779b9u * 1u; x = splitmix32(x); r0 = x ^ iw.w[1]; }
|
||||
{ uint32_t x = nonce ^ iw.w[1]; x += 0x9e3779b9u * 2u; x = splitmix32(x); r1 = x ^ iw.w[2]; }
|
||||
{ uint32_t x = nonce ^ iw.w[2]; x += 0x9e3779b9u * 3u; x = splitmix32(x); r2 = x ^ iw.w[3]; }
|
||||
{ uint32_t x = nonce ^ iw.w[3]; x += 0x9e3779b9u * 4u; x = splitmix32(x); r3 = x ^ iw.w[4]; }
|
||||
{ uint32_t x = nonce ^ iw.w[4]; x += 0x9e3779b9u * 5u; x = splitmix32(x); r4 = x ^ iw.w[5]; }
|
||||
{ uint32_t x = nonce ^ iw.w[5]; x += 0x9e3779b9u * 6u; x = splitmix32(x); r5 = x ^ iw.w[6]; }
|
||||
{ uint32_t x = nonce ^ iw.w[6]; x += 0x9e3779b9u * 7u; x = splitmix32(x); r6 = x ^ iw.w[7]; }
|
||||
{ uint32_t x = nonce ^ iw.w[7]; x += 0x9e3779b9u * 8u; x = splitmix32(x); r7 = x ^ iw.w[0]; }
|
||||
|
||||
for (uint32_t it = 0u; it < 8u; ++it) {
|
||||
uint32_t sel = r0;
|
||||
r3 = rotr_var(r3, r4); // 0 rotr
|
||||
r0 = r0 ^ r7; // 1 xor
|
||||
{ uint32_t b_ = (r0 & mask) & ~15u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint32_t x_ = r1 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r1 = x_; } // 2 load
|
||||
r5 = rotl_imm(r5, 15u); // 3 rotl
|
||||
r2 = r2 + r3 + ((((sel >> 6u) & 1u) != 0u) ? 0xd35e575cu : 0xd7a264d9u); // 4 add
|
||||
r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r2, 1); // 5 shfl
|
||||
r1 = r2 * r5 + r1; // 6 mad
|
||||
r2 = r2 | r3; // 7 or
|
||||
r3 = r3 ^ r5; // 8 xor
|
||||
r0 = r0 + r3 + ((((sel >> 29u) & 1u) != 0u) ? 0xd98be6edu : 0x4e543e70u); // 9 add
|
||||
r5 = rotr_var(r5, r1); // 10 rotr
|
||||
r3 = r3 * r5; // 11 mul
|
||||
r2 = r2 ^ r7; // 12 xor
|
||||
r1 = r1 + r6 + ((((sel >> 30u) & 1u) != 0u) ? 0x97a9219cu : 0xe36f3c9fu); // 13 add
|
||||
r2 = r2 | r1; // 14 or
|
||||
r1 = r1 | r3; // 15 or
|
||||
r7 = r3 * r7 + r7; // 16 mad
|
||||
r3 = r3 + r2 + ((((sel >> 13u) & 1u) != 0u) ? 0xf799b153u : 0x0c0a7b49u); // 17 add
|
||||
r7 = r7 ^ ds[r5 & mask]; // 18 load
|
||||
r7 = r7 ^ ds[r2 & mask]; // 19 load
|
||||
r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r0, 8); // 20 shfl
|
||||
r4 = r4 ^ ds[r1 & mask]; // 21 load
|
||||
r5 = r5 ^ ds[r7 & mask]; // 22 load
|
||||
r4 = r4 ^ r2; // 23 xor
|
||||
r5 = r5 + r3 + ((((sel >> 14u) & 1u) != 0u) ? 0x26eb8325u : 0x011f9670u); // 24 add
|
||||
r0 = r0 * r1; // 25 mul
|
||||
r4 = r4 ^ r7; // 26 xor
|
||||
r7 = r7 + r5 + ((((sel >> 26u) & 1u) != 0u) ? 0xf12a4057u : 0x42177757u); // 27 add
|
||||
r5 = r0 * r7 + r5; // 28 mad
|
||||
r3 = r3 * r6; // 29 mul
|
||||
r6 = rotl_imm(r6, 24u); // 30 rotl
|
||||
r4 = rotr_var(r4, r0); // 31 rotr
|
||||
r6 = r6 ^ ds[r4 & mask]; // 32 load
|
||||
r0 = r0 ^ __shfl_xor_sync(0xffffffffu, r1, 1); // 33 shfl
|
||||
r4 = r4 * r5; // 34 mul
|
||||
r2 = rotl_imm(r2, 15u); // 35 rotl
|
||||
r7 = r7 + r3 + ((((sel >> 5u) & 1u) != 0u) ? 0xc1b9573fu : 0xe0ebc725u); // 36 add
|
||||
{ uint32_t b_ = (r2 & mask) & ~3u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint32_t x_ = r0 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r0 = x_; } // 37 load
|
||||
r7 = r0 * r2 + r7; // 38 mad
|
||||
r0 = r0 + r7 + ((((sel >> 16u) & 1u) != 0u) ? 0xde4cd365u : 0xd0b844deu); // 39 add
|
||||
{ uint32_t b_ = (r6 & mask) & ~15u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint32_t x_ = r7 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r7 = x_; } // 40 load
|
||||
r0 = r0 ^ r1; // 41 xor
|
||||
r1 = rotl_imm(r1, 19u); // 42 rotl
|
||||
r7 = r7 ^ r1; // 43 xor
|
||||
r2 = r2 * r4; // 44 mul
|
||||
{ uint32_t b_ = (r4 & mask) & ~15u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint32_t x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r6 = x_; } // 45 load
|
||||
r7 = r7 + r3 + ((((sel >> 28u) & 1u) != 0u) ? 0x5d12f1a2u : 0x7633c48cu); // 46 add
|
||||
r3 = r3 ^ ds[r2 & mask]; // 47 load
|
||||
{ uint32_t b_ = (r5 & mask) & ~15u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint32_t x_ = r2 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r2 = x_; } // 48 load
|
||||
r7 = r7 * r5; // 49 mul
|
||||
r3 = r7 * r0 + r3; // 50 mad
|
||||
{ uint32_t b_ = (r2 & mask) & ~3u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint32_t x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r3 = x_; } // 51 load
|
||||
{ uint32_t b_ = (r7 & mask) & ~3u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint32_t x_ = r4 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r4 = x_; } // 52 load
|
||||
r4 = __umulhi(r4, r1); // 53 mulhi
|
||||
r7 = r7 + r4 + ((((sel >> 24u) & 1u) != 0u) ? 0xd8ed09bau : 0xf64a6e41u); // 54 add
|
||||
r5 = __umulhi(r5, r3); // 55 mulhi
|
||||
r5 = r5 * r7; // 56 mul
|
||||
{ uint32_t b_ = (r0 & mask) & ~15u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint32_t x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r3 = x_; } // 57 load
|
||||
r5 = __umulhi(r5, r2); // 58 mulhi
|
||||
r7 = r7 * r5; // 59 mul
|
||||
{ uint32_t b_ = (r3 & mask) & ~15u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint32_t x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r6 = x_; } // 60 load
|
||||
r7 = r1 * r1 + r7; // 61 mad
|
||||
r0 = r0 ^ ds[r7 & mask]; // 62 load
|
||||
r5 = r5 * r3; // 63 mul
|
||||
}
|
||||
uint32_t lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u);
|
||||
uint32_t hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u);
|
||||
out[gid] = ((uint64_t)hi << 32) | (uint64_t)lo;
|
||||
}
|
||||
|
||||
cudaError_t igneum_launch_hash_bound(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask,
|
||||
IgneumInitWords iw, uint32_t nonces, uint32_t blockWarps) {
|
||||
if (blockWarps == 0u || blockWarps > 32u) return cudaErrorInvalidValue;
|
||||
uint32_t block = 32u * blockWarps;
|
||||
if (nonces == 0u || (nonces % block) != 0u) return cudaErrorInvalidValue;
|
||||
igneum_hash_bound<<<nonces / block, block>>>(ds, out, baseNonce, mask, iw);
|
||||
return cudaGetLastError();
|
||||
}
|
||||
|
||||
cudaError_t igneum_hash_bound_info(int* numRegs, int* blocksPerSM, uint32_t blockWarps) {
|
||||
cudaFuncAttributes attr;
|
||||
cudaError_t e = cudaFuncGetAttributes(&attr, igneum_hash_bound);
|
||||
if (e != cudaSuccess) return e;
|
||||
*numRegs = attr.numRegs;
|
||||
return cudaOccupancyMaxActiveBlocksPerMultiprocessor(blocksPerSM, igneum_hash_bound, (int)(32u * blockWarps), 0);
|
||||
}
|
||||
108
proto-cuda/packs-readwidth/mixA-3/memhard.h
Normal file
108
proto-cuda/packs-readwidth/mixA-3/memhard.h
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
// Generated by igneum-pow export (generator v2) for seed "igneum-readwidth/A/3". Do not edit by hand.
|
||||
// Memory-hard dataset core, the same text that the Mac's Metal kernels and CPU verifier were checked against.
|
||||
// Included by kernel.cu (device), host.cu (host reference) and proto-opencl/host.c (C99 host reference).
|
||||
// See proto-metal/MEMHARD.md for the construction. kernel.cl carries the same text in OpenCL C.
|
||||
#pragma once
|
||||
#ifdef __cplusplus
|
||||
#include <cstdint>
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
#if defined(__CUDACC__)
|
||||
#define IGNEUM_HD __host__ __device__ __forceinline__
|
||||
#elif defined(_MSC_VER) && !defined(__cplusplus)
|
||||
#define IGNEUM_HD static __inline
|
||||
#else
|
||||
#define IGNEUM_HD static inline
|
||||
#endif
|
||||
// Memory-hard dataset core (MEMHARD.md). Cache: 2^26 words in 2^16 segments of 64 chained ChaCha12 lines.
|
||||
// Item: 8 rounds of seed-parameterised mixer + one 64-byte cache read, then a final mixer. All parameters are literals.
|
||||
#define MH_CACHE_LINE_MASK 0x003fffffu
|
||||
#define MH_SEGMENT_LINES 64u
|
||||
#define MH_QR(a, b, c, d, r1, r2, r3, r4) { a += b; d ^= a; d = mh_rotl(d, r1); c += d; b ^= c; b = mh_rotl(b, r2); a += b; d ^= a; d = mh_rotl(d, r3); c += d; b ^= c; b = mh_rotl(b, r4); }
|
||||
IGNEUM_HD uint32_t mh_rotl(uint32_t x, uint32_t n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 at every call site
|
||||
|
||||
// y = ChaCha12 core(x) + x
|
||||
IGNEUM_HD void mh_chacha_block(const uint32_t* x, uint32_t* y) {
|
||||
for (uint32_t i = 0u; i < 16u; ++i) y[i] = x[i];
|
||||
for (uint32_t r = 0u; r < 6u; ++r) {
|
||||
MH_QR(y[0], y[4], y[8], y[12], 16u, 12u, 8u, 7u) MH_QR(y[1], y[5], y[9], y[13], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[2], y[6], y[10], y[14], 16u, 12u, 8u, 7u) MH_QR(y[3], y[7], y[11], y[15], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[0], y[5], y[10], y[15], 16u, 12u, 8u, 7u) MH_QR(y[1], y[6], y[11], y[12], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[2], y[7], y[8], y[13], 16u, 12u, 8u, 7u) MH_QR(y[3], y[4], y[9], y[14], 16u, 12u, 8u, 7u)
|
||||
}
|
||||
for (uint32_t i = 0u; i < 16u; ++i) y[i] += x[i];
|
||||
}
|
||||
|
||||
// One cache segment: 64 chained lines written at cache[seg * 1024]. in_j = prev ^ (sigma || K || seg || j || tag), prev_0 = 0.
|
||||
IGNEUM_HD void mh_cache_segment(uint32_t* cache, uint32_t seg) {
|
||||
uint32_t prev[16]; uint32_t x[16]; uint32_t y[16];
|
||||
for (uint32_t i = 0u; i < 16u; ++i) prev[i] = 0u;
|
||||
for (uint32_t j = 0u; j < MH_SEGMENT_LINES; ++j) {
|
||||
x[0] = 0x61707865u ^ prev[0]; x[1] = 0x3320646eu ^ prev[1]; x[2] = 0x79622d32u ^ prev[2]; x[3] = 0x6b206574u ^ prev[3];
|
||||
x[4] = 0x3067619fu ^ prev[4];
|
||||
x[5] = 0x3c269176u ^ prev[5];
|
||||
x[6] = 0x84a03b03u ^ prev[6];
|
||||
x[7] = 0xf8c63294u ^ prev[7];
|
||||
x[8] = 0xff977c5bu ^ prev[8];
|
||||
x[9] = 0xe60def3eu ^ prev[9];
|
||||
x[10] = 0x63630141u ^ prev[10];
|
||||
x[11] = 0xb8fbcb58u ^ prev[11];
|
||||
x[12] = seg ^ prev[12]; x[13] = j ^ prev[13]; x[14] = 0x49676e65u ^ prev[14]; x[15] = 0x756d4d48u ^ prev[15];
|
||||
mh_chacha_block(x, y);
|
||||
uint32_t* line = cache + ((seg * MH_SEGMENT_LINES + j) * 16u);
|
||||
for (uint32_t i = 0u; i < 16u; ++i) { line[i] = y[i]; prev[i] = y[i]; }
|
||||
}
|
||||
}
|
||||
|
||||
// M_r: per word (s ^ (RC + rk)) * MUL, then a column round and a diagonal round with the seed-drawn rotations.
|
||||
IGNEUM_HD void mh_mixer(uint32_t* s, uint32_t rk) {
|
||||
s[0] = (s[0] ^ (0xbab68293u + rk)) * 0x42146205u;
|
||||
s[1] = (s[1] ^ (0xcc162340u + rk)) * 0x52cbe0fbu;
|
||||
s[2] = (s[2] ^ (0x6ce151ccu + rk)) * 0x7ecf4a03u;
|
||||
s[3] = (s[3] ^ (0xe62b8997u + rk)) * 0x6728907fu;
|
||||
s[4] = (s[4] ^ (0xc9c80297u + rk)) * 0xd81d9751u;
|
||||
s[5] = (s[5] ^ (0xf74a1654u + rk)) * 0x132952c3u;
|
||||
s[6] = (s[6] ^ (0x3d704af5u + rk)) * 0xf60de277u;
|
||||
s[7] = (s[7] ^ (0x3cf522b7u + rk)) * 0x05358035u;
|
||||
s[8] = (s[8] ^ (0x2b9cac04u + rk)) * 0xbaf6499du;
|
||||
s[9] = (s[9] ^ (0xa880ac10u + rk)) * 0xe4db9667u;
|
||||
s[10] = (s[10] ^ (0x13e5dd1du + rk)) * 0x3e98f45du;
|
||||
s[11] = (s[11] ^ (0x6fc3e233u + rk)) * 0xd0004eddu;
|
||||
s[12] = (s[12] ^ (0x2d83eeacu + rk)) * 0x2691630du;
|
||||
s[13] = (s[13] ^ (0x9006e8bfu + rk)) * 0x9beb3bcfu;
|
||||
s[14] = (s[14] ^ (0x2c4b5362u + rk)) * 0xab310379u;
|
||||
s[15] = (s[15] ^ (0x31b49ee2u + rk)) * 0x99cfb423u;
|
||||
MH_QR(s[0], s[4], s[8], s[12], 20u, 20u, 19u, 4u) MH_QR(s[1], s[5], s[9], s[13], 20u, 20u, 19u, 4u)
|
||||
MH_QR(s[2], s[6], s[10], s[14], 20u, 20u, 19u, 4u) MH_QR(s[3], s[7], s[11], s[15], 20u, 20u, 19u, 4u)
|
||||
MH_QR(s[0], s[5], s[10], s[15], 26u, 3u, 3u, 27u) MH_QR(s[1], s[6], s[11], s[12], 26u, 3u, 3u, 27u)
|
||||
MH_QR(s[2], s[7], s[8], s[13], 26u, 3u, 3u, 27u) MH_QR(s[3], s[4], s[9], s[14], 26u, 3u, 3u, 27u)
|
||||
}
|
||||
|
||||
// Item t: 16 words. s = (K, t * MUL[i] + RC[i]); 8 rounds of mixer + cache line s[0] & mask; final mixer.
|
||||
IGNEUM_HD void mh_item(const uint32_t* cache, uint32_t t, uint32_t* s) {
|
||||
s[0] = 0x3067619fu;
|
||||
s[1] = 0x3c269176u;
|
||||
s[2] = 0x84a03b03u;
|
||||
s[3] = 0xf8c63294u;
|
||||
s[4] = 0xff977c5bu;
|
||||
s[5] = 0xe60def3eu;
|
||||
s[6] = 0x63630141u;
|
||||
s[7] = 0xb8fbcb58u;
|
||||
s[8] = t * 0x42146205u + 0xbab68293u;
|
||||
s[9] = t * 0x52cbe0fbu + 0xcc162340u;
|
||||
s[10] = t * 0x7ecf4a03u + 0x6ce151ccu;
|
||||
s[11] = t * 0x6728907fu + 0xe62b8997u;
|
||||
s[12] = t * 0xd81d9751u + 0xc9c80297u;
|
||||
s[13] = t * 0x132952c3u + 0xf74a1654u;
|
||||
s[14] = t * 0xf60de277u + 0x3d704af5u;
|
||||
s[15] = t * 0x05358035u + 0x3cf522b7u;
|
||||
for (uint32_t r = 0u; r < 8u; ++r) {
|
||||
mh_mixer(s, 0x9E3779B9u * (r + 1u));
|
||||
const uint32_t* line = cache + ((s[0] & MH_CACHE_LINE_MASK) * 16u);
|
||||
for (uint32_t i = 0u; i < 16u; ++i) s[i] ^= line[i];
|
||||
}
|
||||
mh_mixer(s, 0x9E3779B9u * 9u);
|
||||
}
|
||||
// dataset[w] without the dataset: derive item w >> 4 and take word w & 15.
|
||||
IGNEUM_HD uint32_t mh_word(const uint32_t* cache, uint32_t w) { uint32_t s[16]; mh_item(cache, w >> 4u, s); return s[w & 15u]; }
|
||||
106
proto-cuda/packs-readwidth/mixA-3/memhard.metal
Normal file
106
proto-cuda/packs-readwidth/mixA-3/memhard.metal
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
#include <metal_stdlib>
|
||||
using namespace metal;
|
||||
// Memory-hard dataset core (MEMHARD.md). Cache: 2^26 words in 2^16 segments of 64 chained ChaCha12 lines.
|
||||
// Item: 8 rounds of seed-parameterised mixer + one 64-byte cache read, then a final mixer. All parameters are literals.
|
||||
#define MH_CACHE_LINE_MASK 0x003fffffu
|
||||
#define MH_SEGMENT_LINES 64u
|
||||
#define MH_QR(a, b, c, d, r1, r2, r3, r4) { a += b; d ^= a; d = mh_rotl(d, r1); c += d; b ^= c; b = mh_rotl(b, r2); a += b; d ^= a; d = mh_rotl(d, r3); c += d; b ^= c; b = mh_rotl(b, r4); }
|
||||
inline uint mh_rotl(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 at every call site
|
||||
|
||||
// y = ChaCha12 core(x) + x
|
||||
inline void mh_chacha_block(const thread uint* x, thread uint* y) {
|
||||
for (uint i = 0u; i < 16u; ++i) y[i] = x[i];
|
||||
for (uint r = 0u; r < 6u; ++r) {
|
||||
MH_QR(y[0], y[4], y[8], y[12], 16u, 12u, 8u, 7u) MH_QR(y[1], y[5], y[9], y[13], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[2], y[6], y[10], y[14], 16u, 12u, 8u, 7u) MH_QR(y[3], y[7], y[11], y[15], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[0], y[5], y[10], y[15], 16u, 12u, 8u, 7u) MH_QR(y[1], y[6], y[11], y[12], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[2], y[7], y[8], y[13], 16u, 12u, 8u, 7u) MH_QR(y[3], y[4], y[9], y[14], 16u, 12u, 8u, 7u)
|
||||
}
|
||||
for (uint i = 0u; i < 16u; ++i) y[i] += x[i];
|
||||
}
|
||||
|
||||
// One cache segment: 64 chained lines written at cache[seg * 1024]. in_j = prev ^ (sigma || K || seg || j || tag), prev_0 = 0.
|
||||
inline void mh_cache_segment(device uint* cache, uint seg) {
|
||||
uint prev[16]; uint x[16]; uint y[16];
|
||||
for (uint i = 0u; i < 16u; ++i) prev[i] = 0u;
|
||||
for (uint j = 0u; j < MH_SEGMENT_LINES; ++j) {
|
||||
x[0] = 0x61707865u ^ prev[0]; x[1] = 0x3320646eu ^ prev[1]; x[2] = 0x79622d32u ^ prev[2]; x[3] = 0x6b206574u ^ prev[3];
|
||||
x[4] = 0x3067619fu ^ prev[4];
|
||||
x[5] = 0x3c269176u ^ prev[5];
|
||||
x[6] = 0x84a03b03u ^ prev[6];
|
||||
x[7] = 0xf8c63294u ^ prev[7];
|
||||
x[8] = 0xff977c5bu ^ prev[8];
|
||||
x[9] = 0xe60def3eu ^ prev[9];
|
||||
x[10] = 0x63630141u ^ prev[10];
|
||||
x[11] = 0xb8fbcb58u ^ prev[11];
|
||||
x[12] = seg ^ prev[12]; x[13] = j ^ prev[13]; x[14] = 0x49676e65u ^ prev[14]; x[15] = 0x756d4d48u ^ prev[15];
|
||||
mh_chacha_block(x, y);
|
||||
device uint* line = cache + ((seg * MH_SEGMENT_LINES + j) * 16u);
|
||||
for (uint i = 0u; i < 16u; ++i) { line[i] = y[i]; prev[i] = y[i]; }
|
||||
}
|
||||
}
|
||||
|
||||
// M_r: per word (s ^ (RC + rk)) * MUL, then a column round and a diagonal round with the seed-drawn rotations.
|
||||
inline void mh_mixer(thread uint* s, uint rk) {
|
||||
s[0] = (s[0] ^ (0xbab68293u + rk)) * 0x42146205u;
|
||||
s[1] = (s[1] ^ (0xcc162340u + rk)) * 0x52cbe0fbu;
|
||||
s[2] = (s[2] ^ (0x6ce151ccu + rk)) * 0x7ecf4a03u;
|
||||
s[3] = (s[3] ^ (0xe62b8997u + rk)) * 0x6728907fu;
|
||||
s[4] = (s[4] ^ (0xc9c80297u + rk)) * 0xd81d9751u;
|
||||
s[5] = (s[5] ^ (0xf74a1654u + rk)) * 0x132952c3u;
|
||||
s[6] = (s[6] ^ (0x3d704af5u + rk)) * 0xf60de277u;
|
||||
s[7] = (s[7] ^ (0x3cf522b7u + rk)) * 0x05358035u;
|
||||
s[8] = (s[8] ^ (0x2b9cac04u + rk)) * 0xbaf6499du;
|
||||
s[9] = (s[9] ^ (0xa880ac10u + rk)) * 0xe4db9667u;
|
||||
s[10] = (s[10] ^ (0x13e5dd1du + rk)) * 0x3e98f45du;
|
||||
s[11] = (s[11] ^ (0x6fc3e233u + rk)) * 0xd0004eddu;
|
||||
s[12] = (s[12] ^ (0x2d83eeacu + rk)) * 0x2691630du;
|
||||
s[13] = (s[13] ^ (0x9006e8bfu + rk)) * 0x9beb3bcfu;
|
||||
s[14] = (s[14] ^ (0x2c4b5362u + rk)) * 0xab310379u;
|
||||
s[15] = (s[15] ^ (0x31b49ee2u + rk)) * 0x99cfb423u;
|
||||
MH_QR(s[0], s[4], s[8], s[12], 20u, 20u, 19u, 4u) MH_QR(s[1], s[5], s[9], s[13], 20u, 20u, 19u, 4u)
|
||||
MH_QR(s[2], s[6], s[10], s[14], 20u, 20u, 19u, 4u) MH_QR(s[3], s[7], s[11], s[15], 20u, 20u, 19u, 4u)
|
||||
MH_QR(s[0], s[5], s[10], s[15], 26u, 3u, 3u, 27u) MH_QR(s[1], s[6], s[11], s[12], 26u, 3u, 3u, 27u)
|
||||
MH_QR(s[2], s[7], s[8], s[13], 26u, 3u, 3u, 27u) MH_QR(s[3], s[4], s[9], s[14], 26u, 3u, 3u, 27u)
|
||||
}
|
||||
|
||||
// Item t: 16 words. s = (K, t * MUL[i] + RC[i]); 8 rounds of mixer + cache line s[0] & mask; final mixer.
|
||||
inline void mh_item(device const uint* cache, uint t, thread uint* s) {
|
||||
s[0] = 0x3067619fu;
|
||||
s[1] = 0x3c269176u;
|
||||
s[2] = 0x84a03b03u;
|
||||
s[3] = 0xf8c63294u;
|
||||
s[4] = 0xff977c5bu;
|
||||
s[5] = 0xe60def3eu;
|
||||
s[6] = 0x63630141u;
|
||||
s[7] = 0xb8fbcb58u;
|
||||
s[8] = t * 0x42146205u + 0xbab68293u;
|
||||
s[9] = t * 0x52cbe0fbu + 0xcc162340u;
|
||||
s[10] = t * 0x7ecf4a03u + 0x6ce151ccu;
|
||||
s[11] = t * 0x6728907fu + 0xe62b8997u;
|
||||
s[12] = t * 0xd81d9751u + 0xc9c80297u;
|
||||
s[13] = t * 0x132952c3u + 0xf74a1654u;
|
||||
s[14] = t * 0xf60de277u + 0x3d704af5u;
|
||||
s[15] = t * 0x05358035u + 0x3cf522b7u;
|
||||
for (uint r = 0u; r < 8u; ++r) {
|
||||
mh_mixer(s, 0x9E3779B9u * (r + 1u));
|
||||
device const uint* line = cache + ((s[0] & MH_CACHE_LINE_MASK) * 16u);
|
||||
for (uint i = 0u; i < 16u; ++i) s[i] ^= line[i];
|
||||
}
|
||||
mh_mixer(s, 0x9E3779B9u * 9u);
|
||||
}
|
||||
// dataset[w] without the dataset: derive item w >> 4 and take word w & 15.
|
||||
inline uint mh_word(device const uint* cache, uint w) { uint s[16]; mh_item(cache, w >> 4u, s); return s[w & 15u]; }
|
||||
|
||||
// One thread per segment (2^16 threads).
|
||||
kernel void igneum_cache_fill(device uint* cache [[buffer(0)]], uint gid [[thread_position_in_grid]]) {
|
||||
mh_cache_segment(cache, gid);
|
||||
}
|
||||
// One thread per 64-byte item (dataset words / 16 threads).
|
||||
kernel void igneum_build(device const uint* cache [[buffer(0)]], device uint* dataset [[buffer(1)]],
|
||||
uint gid [[thread_position_in_grid]]) {
|
||||
uint s[16];
|
||||
mh_item(cache, gid, s);
|
||||
device uint* d = dataset + gid * 16u;
|
||||
for (uint i = 0u; i < 16u; ++i) d[i] = s[i];
|
||||
}
|
||||
60
proto-cuda/packs-readwidth/mixA-3/program.h
Normal file
60
proto-cuda/packs-readwidth/mixA-3/program.h
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
// Generated by igneum-pow export (generator v2) for seed "igneum-readwidth/A/3". Do not edit by hand.
|
||||
// Program metadata for host.cu plus the launch wrappers defined in kernel.cu.
|
||||
// Also included by proto-opencl/host.c (C99), which defines IGNEUM_NO_CUDA first and reads only the macros.
|
||||
#pragma once
|
||||
#ifdef __cplusplus
|
||||
#include <cstdint>
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
#ifndef IGNEUM_NO_CUDA
|
||||
#include <cuda_runtime.h>
|
||||
#endif
|
||||
|
||||
#define IGNEUM_SEED_STRING "igneum-readwidth/A/3"
|
||||
#define IGNEUM_SEED_BYTES_HEX "69676e65756d2d7265616477696474682f412f33"
|
||||
#define IGNEUM_GENERATOR 2
|
||||
#define IGNEUM_PROGRAM_ATTEMPT 0
|
||||
#define IGNEUM_PROGRAM_ID 0x67648c3193a33f6cull
|
||||
#define IGNEUM_DAY_STRING "2026-10-03"
|
||||
#define IGNEUM_DAY_BYTES_HEX "6461792f323032362d31302d3033"
|
||||
#define IGNEUM_DAY0 0x3067619fu
|
||||
#define IGNEUM_DAY1 0x3c269176u
|
||||
#define IGNEUM_DATASET_LOG2 28
|
||||
#define IGNEUM_MASK 0x0fffffffu
|
||||
#define IGNEUM_LANES 32
|
||||
#define IGNEUM_ITERATIONS 8
|
||||
#define IGNEUM_INSTR_COUNT 64
|
||||
#define IGNEUM_LOADS_PER_HASH 128
|
||||
#define IGNEUM_WIDE_LOADS_PER_HASH 0
|
||||
#define IGNEUM_OP_MIX "load=16 add=10 mul=9 xor=7 mad=6 rotl=4 mulhi=3 or=3 rotr=3 shfl=3"
|
||||
// Read-width experiment (5 October 2026, docs/plans/read-width.md): NOT the lottery hash. A load of W words reads
|
||||
// the W-word-aligned address and folds every word into dst: x = dst ^ w[0]; x = (rotl(x, 11) * 0x9e3779b1) ^ w[j]; dst = x.
|
||||
#define IGNEUM_LOAD_CLASS "mix50-35-15"
|
||||
#define IGNEUM_LOAD_SLOTS 16
|
||||
#define IGNEUM_LOAD_MIX { 50, 35, 15 }
|
||||
#define IGNEUM_LOAD_WIDTH_COUNTS { 7, 3, 6 } // loads of 4, 16, 64 bytes per program
|
||||
#define IGNEUM_BYTES_PER_HASH 3680
|
||||
#define IGNEUM_FOLD_ROT 11
|
||||
#define IGNEUM_FOLD_MUL 0x9e3779b1u
|
||||
// 0 = closed-form dataset (ds_elem), 1 = memory-hard cache construction (MEMHARD.md, memhard.h)
|
||||
#define IGNEUM_DATASET_MODE 1
|
||||
|
||||
#define IGNEUM_SEEDW_INIT { 0x30b957f0u, 0x374e2a95u, 0xf416345eu, 0x7af15ccbu, 0xf0bcabc5u, 0xb5b36f35u, 0xf99641c7u, 0xd0312afeu }
|
||||
#define IGNEUM_KEY_INIT { 0x3067619fu, 0x3c269176u, 0x84a03b03u, 0xf8c63294u, 0xff977c5bu, 0xe60def3eu, 0x63630141u, 0xb8fbcb58u }
|
||||
#define IGNEUM_CACHE_LOG2_WORDS 26
|
||||
#define IGNEUM_CACHE_SEGMENT_LOG2_LINES 6
|
||||
#define IGNEUM_CACHE_SEGMENTS 65536u
|
||||
#define IGNEUM_ITEM_ROUNDS 8
|
||||
#define IGNEUM_MIX_ROT_INIT { 20u, 20u, 19u, 4u, 26u, 3u, 3u, 27u }
|
||||
#define IGNEUM_MIX_MUL_INIT { 0x42146205u, 0x52cbe0fbu, 0x7ecf4a03u, 0x6728907fu, 0xd81d9751u, 0x132952c3u, 0xf60de277u, 0x05358035u, 0xbaf6499du, 0xe4db9667u, 0x3e98f45du, 0xd0004eddu, 0x2691630du, 0x9beb3bcfu, 0xab310379u, 0x99cfb423u }
|
||||
#define IGNEUM_MIX_RC_INIT { 0xbab68293u, 0xcc162340u, 0x6ce151ccu, 0xe62b8997u, 0xc9c80297u, 0xf74a1654u, 0x3d704af5u, 0x3cf522b7u, 0x2b9cac04u, 0xa880ac10u, 0x13e5dd1du, 0x6fc3e233u, 0x2d83eeacu, 0x9006e8bfu, 0x2c4b5362u, 0x31b49ee2u }
|
||||
|
||||
#ifndef IGNEUM_NO_CUDA
|
||||
// Defined in kernel.cu. All launch on the default stream and return cudaGetLastError().
|
||||
cudaError_t igneum_launch_cache_fill(uint32_t* cache, uint32_t nSegments);
|
||||
cudaError_t igneum_launch_build(uint32_t* ds, const uint32_t* cache, uint32_t nItems);
|
||||
cudaError_t igneum_launch_hash(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask,
|
||||
uint32_t nonces, uint32_t blockWarps);
|
||||
cudaError_t igneum_hash_info(int* numRegs, int* blocksPerSM, uint32_t blockWarps);
|
||||
#endif
|
||||
127
proto-cuda/packs-readwidth/mixA-3/program.json
Normal file
127
proto-cuda/packs-readwidth/mixA-3/program.json
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
{
|
||||
"format": "igneum-program-pack-3",
|
||||
"generator": 2,
|
||||
"attempt": 0,
|
||||
"program_id": "0x67648c3193a33f6c",
|
||||
"program_id_derivation": "FNV-1a 64 over 'igneum-program/' || generator_le32 || seed_words as little-endian bytes || attempt_le32",
|
||||
"dataset_mode": "memory-hard",
|
||||
"seed": "igneum-readwidth/A/3",
|
||||
"seed_bytes": "69676e65756d2d7265616477696474682f412f33",
|
||||
"seed_words": ["0x30b957f0", "0x374e2a95", "0xf416345e", "0x7af15ccb", "0xf0bcabc5", "0xb5b36f35", "0xf99641c7", "0xd0312afe"],
|
||||
"seed_derivation": "seed_words = FNV-1a 64 over seed_bytes (attempt 0) or seed_bytes || attempt_le32 (attempt k >= 1), basis ^ (salt * 0x9E3779B97F4A7C15) for salt 0..3, then h ^= h>>33; h *= 0xff51afd7ed558ccd; h ^= h>>33; words[2*salt] = low 32, words[2*salt+1] = high 32",
|
||||
"generator_rule": "version 2: exactly 16 load slots drawn first from instructions 1..63 (partial Fisher-Yates), the other 48 ops from the ten non-load weights (sum 75); a load's source is drawn from the registers other than dst written by an earlier instruction and not read by a load since; the candidate must pass the acceptance rule of spec 01 section 1.4.6 (static: no cyclically stale load source, every register has an injecting write; dynamic: 64 units on the seed-keyed closed-form dataset with no constant register bit, no lane-constant load site, under 164 saturated final values, every output bit within 136 of 1024, distinct addresses above 245760), else the next attempt of the seed is tried",
|
||||
"lanes": 32,
|
||||
"registers": 8,
|
||||
"iterations": 8,
|
||||
"instruction_count": 64,
|
||||
"loads_per_hash": 128,
|
||||
"load_class": "mix50-35-15",
|
||||
"load_slots": 16,
|
||||
"load_mix_percent_4_16_64": [50, 35, 15],
|
||||
"load_width_counts_4_16_64": [7, 3, 6],
|
||||
"bytes_per_hash": 3680,
|
||||
"wide_load": "read-width experiment (5 October 2026, docs/plans/read-width.md), NOT the lottery hash: a load of W words (width field, 4 or 16) reads dataset[b .. b + W) with b = (src & mask) & ~(W - 1) and folds every word into dst: x = dst ^ w[0]; for j in 1..W: x = (rotl(x, 11) * 0x9e3779b1) ^ w[j]; dst = x; width 1 is the plain load; the width is drawn per instruction from the class mix with one extra below(100) draw after the nine of version 2, and the program id is FNV-1a 64 over 'igneum-program-rw/' || generator_le32 || seed words || attempt_le32 || mix[3] || load_slots",
|
||||
"op_mix": {"load": 16, "add": 10, "mul": 9, "xor": 7, "mad": 6, "rotl": 4, "mulhi": 3, "or": 3, "rotr": 3, "shfl": 3},
|
||||
"register_init": "for i in 0..7: x = nonce ^ seed_words[i]; x += 0x9e3779b9 * (i+1) (mod 2^32); x = splitmix32(x); r[i] = x ^ seed_words[(i+1) & 7]",
|
||||
"splitmix32": "x ^= x>>16; x *= 0x7feb352d; x ^= x>>15; x *= 0x846ca68b; x ^= x>>16",
|
||||
"iteration": "sel = r0 sampled once at the top of each iteration, then all instructions in order",
|
||||
"output": "lo = r0 ^ rotl(r1,7) ^ rotl(r2,14) ^ rotl(r3,21); hi = r4 ^ rotl(r5,9) ^ rotl(r6,18) ^ rotl(r7,27); out = (hi << 32) | lo",
|
||||
"op_semantics": {
|
||||
"add": "dst = dst + src + (bit `bit` of sel ? imm2 : imm)",
|
||||
"sub": "dst = dst - src",
|
||||
"mul": "dst = dst * src (low 32)",
|
||||
"mulhi": "dst = high 32 bits of dst * src",
|
||||
"xor": "dst = dst ^ src",
|
||||
"or": "dst = dst | src",
|
||||
"rotl": "dst = rotl(dst, rot), rot in 1..31",
|
||||
"rotr": "dst = rotr(dst, src & 31)",
|
||||
"mad": "dst = src * src2 + dst",
|
||||
"shfl": "dst = dst ^ (src of lane (lane ^ mask)), mask in {1,2,4,8,16}, within the 32-lane warp",
|
||||
"load": "dst = dst ^ dataset[src & dataset.mask]",
|
||||
"wload": "base = (src of lane 0 & dataset.mask) & ~31; dst = dst ^ dataset[base + lane] (warp-coalesced 128-byte load, lever b, only when --wide-frac > 0)"
|
||||
},
|
||||
"dataset": {
|
||||
"log2_words": 28,
|
||||
"bytes": 1073741824,
|
||||
"mask": "0x0fffffff",
|
||||
"day": "2026-10-03",
|
||||
"day_bytes": "6461792f323032362d31302d3033",
|
||||
"day_words_from": "seed_words_from_bytes(day_bytes)",
|
||||
"d0": "0x3067619f",
|
||||
"d1": "0x3c269176",
|
||||
"mode": "memory-hard",
|
||||
"spec": "proto-metal/MEMHARD.md",
|
||||
"key": ["0x3067619f", "0x3c269176", "0x84a03b03", "0xf8c63294", "0xff977c5b", "0xe60def3e", "0x63630141", "0xb8fbcb58"],
|
||||
"key_derivation": "the 8 words of seed_words_from_bytes(day_bytes); d0, d1 are key[0], key[1]",
|
||||
"cache": {"log2_words": 26, "bytes": 268435456, "line_words": 16, "segment_lines": 64, "segments": 65536, "block": "ChaCha12 core + feed-forward, rotations 16 12 8 7", "sigma": ["0x61707865", "0x3320646e", "0x79622d32", "0x6b206574"], "tag": ["0x49676e65", "0x756d4d48"], "chain": "in_j = prev_line ^ (sigma[0..3] || key[0..7] || seg || j || tag[0..1]); line_j = block(in_j); prev_0 = 0"},
|
||||
"mixer": {"draw": "SplitMix64 seeded with key[0] | key[1] << 32: rot[0..7] = 1 + next() % 31, mul[0..15] = low32(next()) | 1, rc[0..15] = low32(next())", "rot": [20, 20, 19, 4, 26, 3, 3, 27], "mul": ["0x42146205", "0x52cbe0fb", "0x7ecf4a03", "0x6728907f", "0xd81d9751", "0x132952c3", "0xf60de277", "0x05358035", "0xbaf6499d", "0xe4db9667", "0x3e98f45d", "0xd0004edd", "0x2691630d", "0x9beb3bcf", "0xab310379", "0x99cfb423"], "rc": ["0xbab68293", "0xcc162340", "0x6ce151cc", "0xe62b8997", "0xc9c80297", "0xf74a1654", "0x3d704af5", "0x3cf522b7", "0x2b9cac04", "0xa880ac10", "0x13e5dd1d", "0x6fc3e233", "0x2d83eeac", "0x9006e8bf", "0x2c4b5362", "0x31b49ee2"], "round": "for i in 0..15: s[i] = (s[i] ^ (rc[i] + (r+1) * 0x9E3779B9)) * mul[i]; then quarter rounds on columns (0,4,8,12) (1,5,9,13) (2,6,10,14) (3,7,11,15) with rot[0..3] and diagonals (0,5,10,15) (1,6,11,12) (2,7,8,13) (3,4,9,14) with rot[4..7]", "quarter_round": "a += b; d ^= a; d = rotl(d, r1); c += d; b ^= c; b = rotl(b, r2); a += b; d ^= a; d = rotl(d, r3); c += d; b ^= c; b = rotl(b, r4)"},
|
||||
"item": "s[0..7] = key; s[8+i] = t * mul[i] + rc[i] for i in 0..7; for r in 0..7: s = M_r(s); line = s[0] & 0x003fffff; s[i] ^= cache[line * 16 + i]; then s = M_8(s); item(t) = s",
|
||||
"word": "dataset[w] = item(w >> 4)[w & 15]"
|
||||
},
|
||||
"instructions": [
|
||||
{"i": 0, "op": "rotr", "dst": 3, "src": 4, "src2": 3, "imm": "0x33f6fe7b", "imm2": "0xd46e1ac2", "rot": 21, "bit": 9, "mask": 8, "width": 1},
|
||||
{"i": 1, "op": "xor", "dst": 0, "src": 7, "src2": 4, "imm": "0x12e86486", "imm2": "0x1e848be1", "rot": 3, "bit": 7, "mask": 4, "width": 1},
|
||||
{"i": 2, "op": "load", "dst": 1, "src": 0, "src2": 7, "imm": "0x25bf1dfe", "imm2": "0x85cff09c", "rot": 27, "bit": 24, "mask": 4, "width": 16},
|
||||
{"i": 3, "op": "rotl", "dst": 5, "src": 3, "src2": 3, "imm": "0xbfde1d4f", "imm2": "0x098e8aab", "rot": 15, "bit": 30, "mask": 4, "width": 1},
|
||||
{"i": 4, "op": "add", "dst": 2, "src": 3, "src2": 6, "imm": "0xd7a264d9", "imm2": "0xd35e575c", "rot": 7, "bit": 6, "mask": 4, "width": 1},
|
||||
{"i": 5, "op": "shfl", "dst": 5, "src": 2, "src2": 4, "imm": "0x5d5210ad", "imm2": "0xd984eb95", "rot": 27, "bit": 13, "mask": 1, "width": 1},
|
||||
{"i": 6, "op": "mad", "dst": 1, "src": 2, "src2": 5, "imm": "0xb969487c", "imm2": "0x61ea012e", "rot": 26, "bit": 25, "mask": 1, "width": 1},
|
||||
{"i": 7, "op": "or", "dst": 2, "src": 3, "src2": 4, "imm": "0xc1c5d61e", "imm2": "0x50d4e85c", "rot": 19, "bit": 25, "mask": 4, "width": 1},
|
||||
{"i": 8, "op": "xor", "dst": 3, "src": 5, "src2": 2, "imm": "0x33a2e407", "imm2": "0x4c9951f2", "rot": 2, "bit": 24, "mask": 16, "width": 1},
|
||||
{"i": 9, "op": "add", "dst": 0, "src": 3, "src2": 0, "imm": "0x4e543e70", "imm2": "0xd98be6ed", "rot": 4, "bit": 29, "mask": 1, "width": 1},
|
||||
{"i": 10, "op": "rotr", "dst": 5, "src": 1, "src2": 0, "imm": "0x76afe302", "imm2": "0x9eca97e5", "rot": 3, "bit": 20, "mask": 8, "width": 1},
|
||||
{"i": 11, "op": "mul", "dst": 3, "src": 5, "src2": 3, "imm": "0xbfb4e238", "imm2": "0x2746818f", "rot": 9, "bit": 25, "mask": 8, "width": 1},
|
||||
{"i": 12, "op": "xor", "dst": 2, "src": 7, "src2": 3, "imm": "0x29d5f28f", "imm2": "0xab4d8139", "rot": 10, "bit": 4, "mask": 1, "width": 1},
|
||||
{"i": 13, "op": "add", "dst": 1, "src": 6, "src2": 1, "imm": "0xe36f3c9f", "imm2": "0x97a9219c", "rot": 30, "bit": 30, "mask": 2, "width": 1},
|
||||
{"i": 14, "op": "or", "dst": 2, "src": 1, "src2": 0, "imm": "0x3c03e7d3", "imm2": "0xd16859dd", "rot": 15, "bit": 28, "mask": 2, "width": 1},
|
||||
{"i": 15, "op": "or", "dst": 1, "src": 3, "src2": 0, "imm": "0x38a5677d", "imm2": "0xa67fd283", "rot": 29, "bit": 15, "mask": 2, "width": 1},
|
||||
{"i": 16, "op": "mad", "dst": 7, "src": 3, "src2": 7, "imm": "0x78f5e68e", "imm2": "0x9d9644ec", "rot": 25, "bit": 1, "mask": 2, "width": 1},
|
||||
{"i": 17, "op": "add", "dst": 3, "src": 2, "src2": 0, "imm": "0x0c0a7b49", "imm2": "0xf799b153", "rot": 22, "bit": 13, "mask": 8, "width": 1},
|
||||
{"i": 18, "op": "load", "dst": 7, "src": 5, "src2": 6, "imm": "0xf2026981", "imm2": "0x15d47d37", "rot": 28, "bit": 27, "mask": 2, "width": 1},
|
||||
{"i": 19, "op": "load", "dst": 7, "src": 2, "src2": 4, "imm": "0x9d237b38", "imm2": "0x527aa464", "rot": 5, "bit": 22, "mask": 2, "width": 1},
|
||||
{"i": 20, "op": "shfl", "dst": 5, "src": 0, "src2": 0, "imm": "0x102562b7", "imm2": "0xe66dad9b", "rot": 9, "bit": 22, "mask": 8, "width": 1},
|
||||
{"i": 21, "op": "load", "dst": 4, "src": 1, "src2": 5, "imm": "0xe8365586", "imm2": "0x6f13fc63", "rot": 26, "bit": 6, "mask": 8, "width": 1},
|
||||
{"i": 22, "op": "load", "dst": 5, "src": 7, "src2": 2, "imm": "0xacd9154f", "imm2": "0x785e81e4", "rot": 22, "bit": 29, "mask": 1, "width": 1},
|
||||
{"i": 23, "op": "xor", "dst": 4, "src": 2, "src2": 6, "imm": "0x03eb8f2d", "imm2": "0x2f686222", "rot": 30, "bit": 30, "mask": 2, "width": 1},
|
||||
{"i": 24, "op": "add", "dst": 5, "src": 3, "src2": 3, "imm": "0x011f9670", "imm2": "0x26eb8325", "rot": 15, "bit": 14, "mask": 8, "width": 1},
|
||||
{"i": 25, "op": "mul", "dst": 0, "src": 1, "src2": 0, "imm": "0x0cacc6a3", "imm2": "0x28bca959", "rot": 8, "bit": 19, "mask": 2, "width": 1},
|
||||
{"i": 26, "op": "xor", "dst": 4, "src": 7, "src2": 7, "imm": "0x60fc8d5f", "imm2": "0xb8453fd3", "rot": 22, "bit": 3, "mask": 8, "width": 1},
|
||||
{"i": 27, "op": "add", "dst": 7, "src": 5, "src2": 6, "imm": "0x42177757", "imm2": "0xf12a4057", "rot": 15, "bit": 26, "mask": 16, "width": 1},
|
||||
{"i": 28, "op": "mad", "dst": 5, "src": 0, "src2": 7, "imm": "0x0f21b242", "imm2": "0x2fa77c71", "rot": 30, "bit": 20, "mask": 1, "width": 1},
|
||||
{"i": 29, "op": "mul", "dst": 3, "src": 6, "src2": 0, "imm": "0x69e62f8d", "imm2": "0x0037ce73", "rot": 18, "bit": 12, "mask": 2, "width": 1},
|
||||
{"i": 30, "op": "rotl", "dst": 6, "src": 7, "src2": 6, "imm": "0xb259e02f", "imm2": "0x0a33cfdf", "rot": 24, "bit": 12, "mask": 4, "width": 1},
|
||||
{"i": 31, "op": "rotr", "dst": 4, "src": 0, "src2": 6, "imm": "0xa8839588", "imm2": "0xd5af17af", "rot": 18, "bit": 19, "mask": 1, "width": 1},
|
||||
{"i": 32, "op": "load", "dst": 6, "src": 4, "src2": 4, "imm": "0xd7e19199", "imm2": "0xf45eb79a", "rot": 24, "bit": 11, "mask": 2, "width": 1},
|
||||
{"i": 33, "op": "shfl", "dst": 0, "src": 1, "src2": 5, "imm": "0x3e9f25b5", "imm2": "0x405b0189", "rot": 9, "bit": 30, "mask": 1, "width": 1},
|
||||
{"i": 34, "op": "mul", "dst": 4, "src": 5, "src2": 2, "imm": "0x42ed1682", "imm2": "0xdd577015", "rot": 27, "bit": 2, "mask": 8, "width": 1},
|
||||
{"i": 35, "op": "rotl", "dst": 2, "src": 4, "src2": 0, "imm": "0x39954523", "imm2": "0x9d5b1079", "rot": 15, "bit": 13, "mask": 16, "width": 1},
|
||||
{"i": 36, "op": "add", "dst": 7, "src": 3, "src2": 0, "imm": "0xe0ebc725", "imm2": "0xc1b9573f", "rot": 14, "bit": 5, "mask": 2, "width": 1},
|
||||
{"i": 37, "op": "load", "dst": 0, "src": 2, "src2": 5, "imm": "0x921d347e", "imm2": "0x18b83d03", "rot": 27, "bit": 7, "mask": 4, "width": 4},
|
||||
{"i": 38, "op": "mad", "dst": 7, "src": 0, "src2": 2, "imm": "0x211c8e0d", "imm2": "0x963c2eec", "rot": 6, "bit": 23, "mask": 16, "width": 1},
|
||||
{"i": 39, "op": "add", "dst": 0, "src": 7, "src2": 2, "imm": "0xd0b844de", "imm2": "0xde4cd365", "rot": 27, "bit": 16, "mask": 4, "width": 1},
|
||||
{"i": 40, "op": "load", "dst": 7, "src": 6, "src2": 6, "imm": "0x3b8d9718", "imm2": "0x8ab1654a", "rot": 7, "bit": 16, "mask": 16, "width": 16},
|
||||
{"i": 41, "op": "xor", "dst": 0, "src": 1, "src2": 2, "imm": "0x014f5a59", "imm2": "0xc8398216", "rot": 2, "bit": 17, "mask": 2, "width": 1},
|
||||
{"i": 42, "op": "rotl", "dst": 1, "src": 5, "src2": 1, "imm": "0x3bee3d81", "imm2": "0x2ce34bcd", "rot": 19, "bit": 6, "mask": 1, "width": 1},
|
||||
{"i": 43, "op": "xor", "dst": 7, "src": 1, "src2": 1, "imm": "0x27aaf2ee", "imm2": "0xec39fef7", "rot": 9, "bit": 18, "mask": 8, "width": 1},
|
||||
{"i": 44, "op": "mul", "dst": 2, "src": 4, "src2": 3, "imm": "0x1b770975", "imm2": "0xa556f55d", "rot": 4, "bit": 23, "mask": 1, "width": 1},
|
||||
{"i": 45, "op": "load", "dst": 6, "src": 4, "src2": 5, "imm": "0xe6ebfbe4", "imm2": "0x0a9cc201", "rot": 2, "bit": 5, "mask": 4, "width": 16},
|
||||
{"i": 46, "op": "add", "dst": 7, "src": 3, "src2": 7, "imm": "0x7633c48c", "imm2": "0x5d12f1a2", "rot": 10, "bit": 28, "mask": 1, "width": 1},
|
||||
{"i": 47, "op": "load", "dst": 3, "src": 2, "src2": 5, "imm": "0xe92f250d", "imm2": "0x626fb82e", "rot": 27, "bit": 8, "mask": 1, "width": 1},
|
||||
{"i": 48, "op": "load", "dst": 2, "src": 5, "src2": 5, "imm": "0x32ec784c", "imm2": "0x5c40c45a", "rot": 23, "bit": 0, "mask": 4, "width": 16},
|
||||
{"i": 49, "op": "mul", "dst": 7, "src": 5, "src2": 0, "imm": "0x68a298b5", "imm2": "0xded99974", "rot": 31, "bit": 22, "mask": 8, "width": 1},
|
||||
{"i": 50, "op": "mad", "dst": 3, "src": 7, "src2": 0, "imm": "0xf89a028b", "imm2": "0x8ece86f6", "rot": 24, "bit": 20, "mask": 2, "width": 1},
|
||||
{"i": 51, "op": "load", "dst": 3, "src": 2, "src2": 7, "imm": "0xe1a0d923", "imm2": "0xdb8faa0b", "rot": 15, "bit": 23, "mask": 8, "width": 4},
|
||||
{"i": 52, "op": "load", "dst": 4, "src": 7, "src2": 6, "imm": "0x28e50e93", "imm2": "0x965bcc9c", "rot": 25, "bit": 28, "mask": 4, "width": 4},
|
||||
{"i": 53, "op": "mulhi", "dst": 4, "src": 1, "src2": 2, "imm": "0x0065ecaf", "imm2": "0xe870289e", "rot": 8, "bit": 18, "mask": 4, "width": 1},
|
||||
{"i": 54, "op": "add", "dst": 7, "src": 4, "src2": 3, "imm": "0xf64a6e41", "imm2": "0xd8ed09ba", "rot": 14, "bit": 24, "mask": 16, "width": 1},
|
||||
{"i": 55, "op": "mulhi", "dst": 5, "src": 3, "src2": 1, "imm": "0xd12951e6", "imm2": "0xe3ae79fe", "rot": 2, "bit": 0, "mask": 2, "width": 1},
|
||||
{"i": 56, "op": "mul", "dst": 5, "src": 7, "src2": 4, "imm": "0xac8f65d4", "imm2": "0x11401bd1", "rot": 22, "bit": 6, "mask": 2, "width": 1},
|
||||
{"i": 57, "op": "load", "dst": 3, "src": 0, "src2": 1, "imm": "0x2815f83f", "imm2": "0x34b3e25b", "rot": 7, "bit": 27, "mask": 2, "width": 16},
|
||||
{"i": 58, "op": "mulhi", "dst": 5, "src": 2, "src2": 7, "imm": "0xbc696afd", "imm2": "0x488bfc7d", "rot": 24, "bit": 31, "mask": 4, "width": 1},
|
||||
{"i": 59, "op": "mul", "dst": 7, "src": 5, "src2": 7, "imm": "0x0f1bd7bd", "imm2": "0xf3a4c1c8", "rot": 25, "bit": 10, "mask": 4, "width": 1},
|
||||
{"i": 60, "op": "load", "dst": 6, "src": 3, "src2": 1, "imm": "0x2ebad44e", "imm2": "0x6b6fcf95", "rot": 4, "bit": 16, "mask": 8, "width": 16},
|
||||
{"i": 61, "op": "mad", "dst": 7, "src": 1, "src2": 1, "imm": "0xd9791f15", "imm2": "0xdd0cbcb2", "rot": 8, "bit": 14, "mask": 16, "width": 1},
|
||||
{"i": 62, "op": "load", "dst": 0, "src": 7, "src2": 1, "imm": "0x057ced89", "imm2": "0x08fdfbc1", "rot": 20, "bit": 15, "mask": 16, "width": 1},
|
||||
{"i": 63, "op": "mul", "dst": 5, "src": 3, "src2": 4, "imm": "0xbd9f5fdd", "imm2": "0xac802ec9", "rot": 27, "bit": 11, "mask": 2, "width": 1}
|
||||
]
|
||||
}
|
||||
109
proto-cuda/packs-readwidth/mixA-3/program.metal
Normal file
109
proto-cuda/packs-readwidth/mixA-3/program.metal
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
#include <metal_stdlib>
|
||||
using namespace metal;
|
||||
|
||||
#define MASK 0x0fffffffu
|
||||
constant uint SEEDW[8] = { 0x30b957f0u, 0x374e2a95u, 0xf416345eu, 0x7af15ccbu, 0xf0bcabc5u, 0xb5b36f35u, 0xf99641c7u, 0xd0312afeu };
|
||||
|
||||
inline uint splitmix32(uint x) {
|
||||
x ^= x >> 16; x *= 0x7feb352du;
|
||||
x ^= x >> 15; x *= 0x846ca68bu;
|
||||
x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
inline uint rotl_imm(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31
|
||||
inline uint rotr_var(uint x, uint n) { n &= 31u; return (x >> n) | (x << ((32u - n) & 31u)); }
|
||||
inline uint ds_elem(uint i, uint d0, uint d1) {
|
||||
uint x = i ^ d0;
|
||||
x *= 0x9E3779B1u; x ^= x >> 15;
|
||||
x += d1;
|
||||
x *= 0x85EBCA77u; x ^= x >> 13;
|
||||
x *= 0xC2B2AE3Du; x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
|
||||
kernel void igneum_hash(device const uint* dataset [[buffer(0)]],
|
||||
device ulong* out [[buffer(1)]],
|
||||
constant uint& baseNonce [[buffer(2)]],
|
||||
uint gid [[thread_position_in_grid]]) {
|
||||
uint nonce = baseNonce + gid;
|
||||
uint r0, r1, r2, r3, r4, r5, r6, r7;
|
||||
{ uint x = nonce ^ SEEDW[0]; x += 0x9e3779b9u * 1u; x = splitmix32(x); r0 = x ^ SEEDW[1]; }
|
||||
{ uint x = nonce ^ SEEDW[1]; x += 0x9e3779b9u * 2u; x = splitmix32(x); r1 = x ^ SEEDW[2]; }
|
||||
{ uint x = nonce ^ SEEDW[2]; x += 0x9e3779b9u * 3u; x = splitmix32(x); r2 = x ^ SEEDW[3]; }
|
||||
{ uint x = nonce ^ SEEDW[3]; x += 0x9e3779b9u * 4u; x = splitmix32(x); r3 = x ^ SEEDW[4]; }
|
||||
{ uint x = nonce ^ SEEDW[4]; x += 0x9e3779b9u * 5u; x = splitmix32(x); r4 = x ^ SEEDW[5]; }
|
||||
{ uint x = nonce ^ SEEDW[5]; x += 0x9e3779b9u * 6u; x = splitmix32(x); r5 = x ^ SEEDW[6]; }
|
||||
{ uint x = nonce ^ SEEDW[6]; x += 0x9e3779b9u * 7u; x = splitmix32(x); r6 = x ^ SEEDW[7]; }
|
||||
{ uint x = nonce ^ SEEDW[7]; x += 0x9e3779b9u * 8u; x = splitmix32(x); r7 = x ^ SEEDW[0]; }
|
||||
|
||||
for (uint it = 0u; it < 8u; ++it) {
|
||||
uint sel = r0;
|
||||
r3 = rotr_var(r3, r4); // 0
|
||||
r0 = r0 ^ r7; // 1
|
||||
{ uint b_ = (r0 & MASK) & ~15u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint x_ = r1 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r1 = x_; } // 2
|
||||
r5 = rotl_imm(r5, 15u); // 3
|
||||
r2 = r2 + r3 + select(0xd7a264d9u, 0xd35e575cu, ((sel >> 6u) & 1u) != 0u); // 4
|
||||
r5 = r5 ^ simd_shuffle_xor(r2, (ushort)1); // 5
|
||||
r1 = r2 * r5 + r1; // 6
|
||||
r2 = r2 | r3; // 7
|
||||
r3 = r3 ^ r5; // 8
|
||||
r0 = r0 + r3 + select(0x4e543e70u, 0xd98be6edu, ((sel >> 29u) & 1u) != 0u); // 9
|
||||
r5 = rotr_var(r5, r1); // 10
|
||||
r3 = r3 * r5; // 11
|
||||
r2 = r2 ^ r7; // 12
|
||||
r1 = r1 + r6 + select(0xe36f3c9fu, 0x97a9219cu, ((sel >> 30u) & 1u) != 0u); // 13
|
||||
r2 = r2 | r1; // 14
|
||||
r1 = r1 | r3; // 15
|
||||
r7 = r3 * r7 + r7; // 16
|
||||
r3 = r3 + r2 + select(0x0c0a7b49u, 0xf799b153u, ((sel >> 13u) & 1u) != 0u); // 17
|
||||
r7 = r7 ^ dataset[r5 & MASK]; // 18
|
||||
r7 = r7 ^ dataset[r2 & MASK]; // 19
|
||||
r5 = r5 ^ simd_shuffle_xor(r0, (ushort)8); // 20
|
||||
r4 = r4 ^ dataset[r1 & MASK]; // 21
|
||||
r5 = r5 ^ dataset[r7 & MASK]; // 22
|
||||
r4 = r4 ^ r2; // 23
|
||||
r5 = r5 + r3 + select(0x011f9670u, 0x26eb8325u, ((sel >> 14u) & 1u) != 0u); // 24
|
||||
r0 = r0 * r1; // 25
|
||||
r4 = r4 ^ r7; // 26
|
||||
r7 = r7 + r5 + select(0x42177757u, 0xf12a4057u, ((sel >> 26u) & 1u) != 0u); // 27
|
||||
r5 = r0 * r7 + r5; // 28
|
||||
r3 = r3 * r6; // 29
|
||||
r6 = rotl_imm(r6, 24u); // 30
|
||||
r4 = rotr_var(r4, r0); // 31
|
||||
r6 = r6 ^ dataset[r4 & MASK]; // 32
|
||||
r0 = r0 ^ simd_shuffle_xor(r1, (ushort)1); // 33
|
||||
r4 = r4 * r5; // 34
|
||||
r2 = rotl_imm(r2, 15u); // 35
|
||||
r7 = r7 + r3 + select(0xe0ebc725u, 0xc1b9573fu, ((sel >> 5u) & 1u) != 0u); // 36
|
||||
{ uint b_ = (r2 & MASK) & ~3u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint x_ = r0 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r0 = x_; } // 37
|
||||
r7 = r0 * r2 + r7; // 38
|
||||
r0 = r0 + r7 + select(0xd0b844deu, 0xde4cd365u, ((sel >> 16u) & 1u) != 0u); // 39
|
||||
{ uint b_ = (r6 & MASK) & ~15u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint x_ = r7 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r7 = x_; } // 40
|
||||
r0 = r0 ^ r1; // 41
|
||||
r1 = rotl_imm(r1, 19u); // 42
|
||||
r7 = r7 ^ r1; // 43
|
||||
r2 = r2 * r4; // 44
|
||||
{ uint b_ = (r4 & MASK) & ~15u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r6 = x_; } // 45
|
||||
r7 = r7 + r3 + select(0x7633c48cu, 0x5d12f1a2u, ((sel >> 28u) & 1u) != 0u); // 46
|
||||
r3 = r3 ^ dataset[r2 & MASK]; // 47
|
||||
{ uint b_ = (r5 & MASK) & ~15u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint x_ = r2 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r2 = x_; } // 48
|
||||
r7 = r7 * r5; // 49
|
||||
r3 = r7 * r0 + r3; // 50
|
||||
{ uint b_ = (r2 & MASK) & ~3u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r3 = x_; } // 51
|
||||
{ uint b_ = (r7 & MASK) & ~3u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint x_ = r4 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r4 = x_; } // 52
|
||||
r4 = mulhi(r4, r1); // 53
|
||||
r7 = r7 + r4 + select(0xf64a6e41u, 0xd8ed09bau, ((sel >> 24u) & 1u) != 0u); // 54
|
||||
r5 = mulhi(r5, r3); // 55
|
||||
r5 = r5 * r7; // 56
|
||||
{ uint b_ = (r0 & MASK) & ~15u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r3 = x_; } // 57
|
||||
r5 = mulhi(r5, r2); // 58
|
||||
r7 = r7 * r5; // 59
|
||||
{ uint b_ = (r3 & MASK) & ~15u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r6 = x_; } // 60
|
||||
r7 = r1 * r1 + r7; // 61
|
||||
r0 = r0 ^ dataset[r7 & MASK]; // 62
|
||||
r5 = r5 * r3; // 63
|
||||
}
|
||||
uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u);
|
||||
uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u);
|
||||
out[gid] = ((ulong)hi << 32) | (ulong)lo;
|
||||
}
|
||||
111
proto-cuda/packs-readwidth/mixA-3/program_bound.metal
Normal file
111
proto-cuda/packs-readwidth/mixA-3/program_bound.metal
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
#include <metal_stdlib>
|
||||
using namespace metal;
|
||||
|
||||
#define MASK 0x0fffffffu
|
||||
constant uint SEEDW[8] = { 0x30b957f0u, 0x374e2a95u, 0xf416345eu, 0x7af15ccbu, 0xf0bcabc5u, 0xb5b36f35u, 0xf99641c7u, 0xd0312afeu };
|
||||
|
||||
inline uint splitmix32(uint x) {
|
||||
x ^= x >> 16; x *= 0x7feb352du;
|
||||
x ^= x >> 15; x *= 0x846ca68bu;
|
||||
x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
inline uint rotl_imm(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31
|
||||
inline uint rotr_var(uint x, uint n) { n &= 31u; return (x >> n) | (x << ((32u - n) & 31u)); }
|
||||
inline uint ds_elem(uint i, uint d0, uint d1) {
|
||||
uint x = i ^ d0;
|
||||
x *= 0x9E3779B1u; x ^= x >> 15;
|
||||
x += d1;
|
||||
x *= 0x85EBCA77u; x ^= x >> 13;
|
||||
x *= 0xC2B2AE3Du; x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
|
||||
// Header-bound variant: the init words come from buffer 3 (bind.rs), not from SEEDW.
|
||||
kernel void igneum_hash_bound(device const uint* dataset [[buffer(0)]],
|
||||
device ulong* out [[buffer(1)]],
|
||||
constant uint& baseNonce [[buffer(2)]],
|
||||
constant uint* initw [[buffer(3)]],
|
||||
uint gid [[thread_position_in_grid]]) {
|
||||
uint nonce = baseNonce + gid;
|
||||
uint r0, r1, r2, r3, r4, r5, r6, r7;
|
||||
{ uint x = nonce ^ initw[0]; x += 0x9e3779b9u * 1u; x = splitmix32(x); r0 = x ^ initw[1]; }
|
||||
{ uint x = nonce ^ initw[1]; x += 0x9e3779b9u * 2u; x = splitmix32(x); r1 = x ^ initw[2]; }
|
||||
{ uint x = nonce ^ initw[2]; x += 0x9e3779b9u * 3u; x = splitmix32(x); r2 = x ^ initw[3]; }
|
||||
{ uint x = nonce ^ initw[3]; x += 0x9e3779b9u * 4u; x = splitmix32(x); r3 = x ^ initw[4]; }
|
||||
{ uint x = nonce ^ initw[4]; x += 0x9e3779b9u * 5u; x = splitmix32(x); r4 = x ^ initw[5]; }
|
||||
{ uint x = nonce ^ initw[5]; x += 0x9e3779b9u * 6u; x = splitmix32(x); r5 = x ^ initw[6]; }
|
||||
{ uint x = nonce ^ initw[6]; x += 0x9e3779b9u * 7u; x = splitmix32(x); r6 = x ^ initw[7]; }
|
||||
{ uint x = nonce ^ initw[7]; x += 0x9e3779b9u * 8u; x = splitmix32(x); r7 = x ^ initw[0]; }
|
||||
|
||||
for (uint it = 0u; it < 8u; ++it) {
|
||||
uint sel = r0;
|
||||
r3 = rotr_var(r3, r4); // 0
|
||||
r0 = r0 ^ r7; // 1
|
||||
{ uint b_ = (r0 & MASK) & ~15u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint x_ = r1 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r1 = x_; } // 2
|
||||
r5 = rotl_imm(r5, 15u); // 3
|
||||
r2 = r2 + r3 + select(0xd7a264d9u, 0xd35e575cu, ((sel >> 6u) & 1u) != 0u); // 4
|
||||
r5 = r5 ^ simd_shuffle_xor(r2, (ushort)1); // 5
|
||||
r1 = r2 * r5 + r1; // 6
|
||||
r2 = r2 | r3; // 7
|
||||
r3 = r3 ^ r5; // 8
|
||||
r0 = r0 + r3 + select(0x4e543e70u, 0xd98be6edu, ((sel >> 29u) & 1u) != 0u); // 9
|
||||
r5 = rotr_var(r5, r1); // 10
|
||||
r3 = r3 * r5; // 11
|
||||
r2 = r2 ^ r7; // 12
|
||||
r1 = r1 + r6 + select(0xe36f3c9fu, 0x97a9219cu, ((sel >> 30u) & 1u) != 0u); // 13
|
||||
r2 = r2 | r1; // 14
|
||||
r1 = r1 | r3; // 15
|
||||
r7 = r3 * r7 + r7; // 16
|
||||
r3 = r3 + r2 + select(0x0c0a7b49u, 0xf799b153u, ((sel >> 13u) & 1u) != 0u); // 17
|
||||
r7 = r7 ^ dataset[r5 & MASK]; // 18
|
||||
r7 = r7 ^ dataset[r2 & MASK]; // 19
|
||||
r5 = r5 ^ simd_shuffle_xor(r0, (ushort)8); // 20
|
||||
r4 = r4 ^ dataset[r1 & MASK]; // 21
|
||||
r5 = r5 ^ dataset[r7 & MASK]; // 22
|
||||
r4 = r4 ^ r2; // 23
|
||||
r5 = r5 + r3 + select(0x011f9670u, 0x26eb8325u, ((sel >> 14u) & 1u) != 0u); // 24
|
||||
r0 = r0 * r1; // 25
|
||||
r4 = r4 ^ r7; // 26
|
||||
r7 = r7 + r5 + select(0x42177757u, 0xf12a4057u, ((sel >> 26u) & 1u) != 0u); // 27
|
||||
r5 = r0 * r7 + r5; // 28
|
||||
r3 = r3 * r6; // 29
|
||||
r6 = rotl_imm(r6, 24u); // 30
|
||||
r4 = rotr_var(r4, r0); // 31
|
||||
r6 = r6 ^ dataset[r4 & MASK]; // 32
|
||||
r0 = r0 ^ simd_shuffle_xor(r1, (ushort)1); // 33
|
||||
r4 = r4 * r5; // 34
|
||||
r2 = rotl_imm(r2, 15u); // 35
|
||||
r7 = r7 + r3 + select(0xe0ebc725u, 0xc1b9573fu, ((sel >> 5u) & 1u) != 0u); // 36
|
||||
{ uint b_ = (r2 & MASK) & ~3u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint x_ = r0 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r0 = x_; } // 37
|
||||
r7 = r0 * r2 + r7; // 38
|
||||
r0 = r0 + r7 + select(0xd0b844deu, 0xde4cd365u, ((sel >> 16u) & 1u) != 0u); // 39
|
||||
{ uint b_ = (r6 & MASK) & ~15u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint x_ = r7 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r7 = x_; } // 40
|
||||
r0 = r0 ^ r1; // 41
|
||||
r1 = rotl_imm(r1, 19u); // 42
|
||||
r7 = r7 ^ r1; // 43
|
||||
r2 = r2 * r4; // 44
|
||||
{ uint b_ = (r4 & MASK) & ~15u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r6 = x_; } // 45
|
||||
r7 = r7 + r3 + select(0x7633c48cu, 0x5d12f1a2u, ((sel >> 28u) & 1u) != 0u); // 46
|
||||
r3 = r3 ^ dataset[r2 & MASK]; // 47
|
||||
{ uint b_ = (r5 & MASK) & ~15u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint x_ = r2 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r2 = x_; } // 48
|
||||
r7 = r7 * r5; // 49
|
||||
r3 = r7 * r0 + r3; // 50
|
||||
{ uint b_ = (r2 & MASK) & ~3u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r3 = x_; } // 51
|
||||
{ uint b_ = (r7 & MASK) & ~3u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint x_ = r4 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r4 = x_; } // 52
|
||||
r4 = mulhi(r4, r1); // 53
|
||||
r7 = r7 + r4 + select(0xf64a6e41u, 0xd8ed09bau, ((sel >> 24u) & 1u) != 0u); // 54
|
||||
r5 = mulhi(r5, r3); // 55
|
||||
r5 = r5 * r7; // 56
|
||||
{ uint b_ = (r0 & MASK) & ~15u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r3 = x_; } // 57
|
||||
r5 = mulhi(r5, r2); // 58
|
||||
r7 = r7 * r5; // 59
|
||||
{ uint b_ = (r3 & MASK) & ~15u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r6 = x_; } // 60
|
||||
r7 = r1 * r1 + r7; // 61
|
||||
r0 = r0 ^ dataset[r7 & MASK]; // 62
|
||||
r5 = r5 * r3; // 63
|
||||
}
|
||||
uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u);
|
||||
uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u);
|
||||
out[gid] = ((ulong)hi << 32) | (ulong)lo;
|
||||
}
|
||||
57
proto-cuda/packs-readwidth/mixA-3/vectors.h
Normal file
57
proto-cuda/packs-readwidth/mixA-3/vectors.h
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
// Generated by igneum-pow export (generator v2) for seed "igneum-readwidth/A/3". Do not edit by hand.
|
||||
// Expected outputs: igneum-pow (Rust) CPU interpreter, generator v2, memory-hard dataset
|
||||
#pragma once
|
||||
#ifdef __cplusplus
|
||||
#include <cstdint>
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
#define IGNEUM_VEC_WARPS 3
|
||||
static const uint32_t IGNEUM_VEC_BASE[IGNEUM_VEC_WARPS] = { 0u, 4096u, 1000000u };
|
||||
static const uint64_t IGNEUM_VEC_OUT[IGNEUM_VEC_WARPS][32] = {
|
||||
{ // base nonce 0
|
||||
0x828587efbc9cfc52ull, 0xd16fc546d5ec261cull, 0xb8af925838b9e1acull, 0x1fc15054e4659c04ull, 0x93ebf4629d0269bbull, 0x52d88b5a306a4737ull, 0x0831861028fa46deull, 0xa4d101fceb303faaull,
|
||||
0x96e9ddfb6a3af702ull, 0x2684793f4309a5baull, 0x12af0be41555dc8cull, 0xa5a7e5ff81a320abull, 0xa3cdfe85fb3696bfull, 0x2771918e4de403a4ull, 0xd46c364e94b850faull, 0x41f55fd8b9e13547ull,
|
||||
0x31922377a1f64cf8ull, 0x13b1dedfb55abdb7ull, 0xd4d88bf9b5ad332dull, 0xda146417bd74c676ull, 0x360aed886b80ce04ull, 0x82340715236f4d67ull, 0x830d5072d63ffc31ull, 0xd08271eaa0cab2dcull,
|
||||
0x9abe271aec0bd6cfull, 0xc12cb8813051e021ull, 0xc0e2a5765296703aull, 0x40afd7e8bcd7d766ull, 0x8d086fb3a523d08full, 0x2693f50209f3451aull, 0x7efb655d14f1ebeeull, 0x99ee7b1b6c7d4bc1ull
|
||||
},
|
||||
{ // base nonce 4096
|
||||
0xbb4af8028dd1238full, 0xb1d96223fb465f3aull, 0xf6177d3717c5902dull, 0x7eb185cfde7ef8cdull, 0xed4d5f3af5e2455cull, 0x0b27846cbbb73cd6ull, 0x237cfab99f0d5ac0ull, 0xbb1e762688a5fa1full,
|
||||
0xbd0462583cfd0143ull, 0xaa071a547999c287ull, 0x42f373a7cc6b30d0ull, 0xab2f623965cd83c7ull, 0x0ffe1417daac3f15ull, 0x3517ce71179553f4ull, 0xd6a3417bf3cd74e1ull, 0xcb3d43858bc48ff3ull,
|
||||
0xaee5c7ff929e9c42ull, 0x1306f6d212e43830ull, 0x14c859a79eb2dad0ull, 0x8cfab5f11caec5e2ull, 0x2de1093748836118ull, 0xc1fa999644710490ull, 0x7c1afa846083ca13ull, 0x14a3ace55059a23dull,
|
||||
0x0a5624ae684434deull, 0xbad4e3a866d28c00ull, 0x0708afb27b44085aull, 0xea27cfd72bcf1862ull, 0x5c9538461c82d517ull, 0x95e0033bf5d07d57ull, 0x49b334ff88786acfull, 0xade49578b94c594bull
|
||||
},
|
||||
{ // base nonce 1000000
|
||||
0x448bdf6ce862af09ull, 0xb137b3a92e26de3bull, 0xf57d56bf9cdb1ba1ull, 0x60a48fcbd0a34564ull, 0xd4578282342e482aull, 0x09d7d7bd7e7166e1ull, 0xa13ea5faa65a969bull, 0x1c8f45874270eb1bull,
|
||||
0x6c6b1c5799bceaf4ull, 0x11505938be6c01c3ull, 0x46d70f2787f3deaaull, 0xe7546fa4fdf67d02ull, 0x27780d83c95eb515ull, 0x5206a7adfba9f15dull, 0x485504ae37c128e0ull, 0xd442920b668e97dbull,
|
||||
0x56fdc1e95fb2d170ull, 0x09e38ff904a5b56aull, 0xb2ae26db1222f910ull, 0xa19864d4801daf4dull, 0x06a933927c9d1911ull, 0x3dab78408de69705ull, 0x17f568a8f4bf8d07ull, 0x3bc2d52c807a0290ull,
|
||||
0x58626fdb2dac1a6eull, 0x5bf21bfea7756f58ull, 0xd40dc38290489e78ull, 0xa0851f74c4783040ull, 0x9f521fa799d21d1eull, 0x363b3f454f9feef6ull, 0xb383f1a11e51190full, 0x4c83f6eb054d58a8ull
|
||||
}
|
||||
};
|
||||
|
||||
// Dataset self-test: dataset[0..15] and dataset[IGNEUM_MASK] (268435455).
|
||||
static const uint32_t IGNEUM_DS_HEAD[16] = {
|
||||
0xffc3cd94u, 0x5920ccd8u, 0x392f44bbu, 0x5e57f67au, 0x2f2bc2a9u, 0x620b0e36u, 0xbdc09014u, 0x436654bfu,
|
||||
0x311e0b48u, 0x1abd93adu, 0x59cc7ce8u, 0xee5247b2u, 0x86171fe8u, 0x6d874751u, 0xc9f7728fu, 0x7c2a435du
|
||||
};
|
||||
static const uint32_t IGNEUM_DS_LAST_INDEX = 268435455u;
|
||||
static const uint32_t IGNEUM_DS_LAST = 0xa33ada72u;
|
||||
// 64 sampled dataset words (index, value) computed on the Mac.
|
||||
#define IGNEUM_DS_SAMPLES 64
|
||||
static const uint32_t IGNEUM_DS_SAMPLE_INDEX[IGNEUM_DS_SAMPLES] = {
|
||||
59471966u, 217795994u, 208353206u, 42483309u, 172547758u, 148076330u, 183853158u, 214389424u, 267488061u, 169781097u, 184093494u, 153880993u, 84977930u, 46426879u, 3093825u, 225364072u, 44593546u, 260713159u, 168250303u, 52384140u, 223401610u, 45554030u, 95410555u, 175039924u, 79171087u, 267580473u, 24168642u, 37981670u, 171551130u, 195559979u, 204611762u, 140997658u, 138925853u, 86637313u, 20736778u, 219665210u, 160430336u, 264654675u, 8013395u, 228945585u, 213884386u, 104419827u, 44185464u, 142737231u, 99284897u, 132475900u, 61861762u, 132056166u, 262388043u, 91878046u, 117353561u, 124768597u, 71352993u, 190698941u, 46055428u, 55281366u, 165145231u, 106810753u, 171985651u, 232085256u, 159510492u, 40072060u, 209107596u, 39023794u
|
||||
};
|
||||
static const uint32_t IGNEUM_DS_SAMPLE_VALUE[IGNEUM_DS_SAMPLES] = {
|
||||
0xe8b73d94u, 0x337028b5u, 0xafe148c9u, 0xab99f7aeu, 0x434ea619u, 0xd85cb880u, 0x54764c7fu, 0x82c7e420u, 0xedf4cb9eu, 0x9884c959u, 0x223ee793u, 0x3a9ccf69u, 0x81da4fd2u, 0xd6ce8cb9u, 0xe3922dcau, 0x3e7e6bdeu, 0x382a3acau, 0x567e7f7fu, 0x25a0f084u, 0xbfeef128u, 0xe338abfbu, 0x7c3b5280u, 0x909bc5f1u, 0xd8b74b9cu, 0x8e31a22eu, 0x26b5f1d8u, 0x79122c00u, 0xcafc3340u, 0xd5e02ea3u, 0x1aee1afdu, 0xdb090d9au, 0xb049f435u, 0x4954d8bau, 0x03797ba0u, 0x196eefbdu, 0xd153412au, 0xbe5d2c4bu, 0xdaa14f0eu, 0x8e61ed07u, 0x9e9a64c6u, 0x2e29ff36u, 0x392a8589u, 0xb56a5912u, 0xfa6e8b57u, 0xd1a737cbu, 0xb0fa841au, 0xbe1c341fu, 0xe25be0f1u, 0xe937f543u, 0xebab2248u, 0x8e1b607au, 0x202a2fedu, 0x95e2819cu, 0x9c9652d4u, 0x32fedef0u, 0xdecfff82u, 0xcb5d43e5u, 0xb735806au, 0x8905939cu, 0xfbf8472du, 0xada74e5du, 0x7ebdeeeau, 0x0119f2b3u, 0xa9a376b8u
|
||||
};
|
||||
// Cache self-test (memory-hard mode): cache[0..15], the last 16 words, and FNV-1a 64 over all 2^26 words.
|
||||
static const uint32_t IGNEUM_CACHE_HEAD[16] = {
|
||||
0x355a86d2u, 0x7957db1cu, 0xd21772afu, 0x6fc1e09bu, 0xd55ce61du, 0x6e6a278bu, 0xd3f543ceu, 0x223d8e82u,
|
||||
0x143ab337u, 0x2e9f05bdu, 0x2eb389bfu, 0x0c6e449eu, 0x5cfa4222u, 0xba6560feu, 0x8e3e1aa4u, 0xdbcc1d53u
|
||||
};
|
||||
static const uint32_t IGNEUM_CACHE_LAST[16] = {
|
||||
0x41190d91u, 0xbd277957u, 0x22ddbb49u, 0x6986f207u, 0xdf69a4d6u, 0x26401a3au, 0x818230fbu, 0xc417122du,
|
||||
0x3597b211u, 0xb553ce55u, 0xcf39cc0du, 0x3b7fc43au, 0x3fd43b00u, 0x67e1c80eu, 0xffa7ea7du, 0xca2960abu
|
||||
};
|
||||
static const uint64_t IGNEUM_CACHE_FNV64 = 0x48c4f5bf24166b2eull;
|
||||
36
proto-cuda/packs-readwidth/mixA-3/vectors.json
Normal file
36
proto-cuda/packs-readwidth/mixA-3/vectors.json
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
{
|
||||
"seed": "igneum-readwidth/A/3",
|
||||
"day": "2026-10-03",
|
||||
"dataset_mode": "memory-hard",
|
||||
"dataset_log2_words": 28,
|
||||
"mask": "0x0fffffff",
|
||||
"lanes": 32,
|
||||
"source": "igneum-pow (Rust) CPU interpreter, generator v2, memory-hard dataset",
|
||||
"warps": [
|
||||
{"base_nonce": 0, "expected": [
|
||||
"0x828587efbc9cfc52", "0xd16fc546d5ec261c", "0xb8af925838b9e1ac", "0x1fc15054e4659c04", "0x93ebf4629d0269bb", "0x52d88b5a306a4737", "0x0831861028fa46de", "0xa4d101fceb303faa",
|
||||
"0x96e9ddfb6a3af702", "0x2684793f4309a5ba", "0x12af0be41555dc8c", "0xa5a7e5ff81a320ab", "0xa3cdfe85fb3696bf", "0x2771918e4de403a4", "0xd46c364e94b850fa", "0x41f55fd8b9e13547",
|
||||
"0x31922377a1f64cf8", "0x13b1dedfb55abdb7", "0xd4d88bf9b5ad332d", "0xda146417bd74c676", "0x360aed886b80ce04", "0x82340715236f4d67", "0x830d5072d63ffc31", "0xd08271eaa0cab2dc",
|
||||
"0x9abe271aec0bd6cf", "0xc12cb8813051e021", "0xc0e2a5765296703a", "0x40afd7e8bcd7d766", "0x8d086fb3a523d08f", "0x2693f50209f3451a", "0x7efb655d14f1ebee", "0x99ee7b1b6c7d4bc1"
|
||||
]},
|
||||
{"base_nonce": 4096, "expected": [
|
||||
"0xbb4af8028dd1238f", "0xb1d96223fb465f3a", "0xf6177d3717c5902d", "0x7eb185cfde7ef8cd", "0xed4d5f3af5e2455c", "0x0b27846cbbb73cd6", "0x237cfab99f0d5ac0", "0xbb1e762688a5fa1f",
|
||||
"0xbd0462583cfd0143", "0xaa071a547999c287", "0x42f373a7cc6b30d0", "0xab2f623965cd83c7", "0x0ffe1417daac3f15", "0x3517ce71179553f4", "0xd6a3417bf3cd74e1", "0xcb3d43858bc48ff3",
|
||||
"0xaee5c7ff929e9c42", "0x1306f6d212e43830", "0x14c859a79eb2dad0", "0x8cfab5f11caec5e2", "0x2de1093748836118", "0xc1fa999644710490", "0x7c1afa846083ca13", "0x14a3ace55059a23d",
|
||||
"0x0a5624ae684434de", "0xbad4e3a866d28c00", "0x0708afb27b44085a", "0xea27cfd72bcf1862", "0x5c9538461c82d517", "0x95e0033bf5d07d57", "0x49b334ff88786acf", "0xade49578b94c594b"
|
||||
]},
|
||||
{"base_nonce": 1000000, "expected": [
|
||||
"0x448bdf6ce862af09", "0xb137b3a92e26de3b", "0xf57d56bf9cdb1ba1", "0x60a48fcbd0a34564", "0xd4578282342e482a", "0x09d7d7bd7e7166e1", "0xa13ea5faa65a969b", "0x1c8f45874270eb1b",
|
||||
"0x6c6b1c5799bceaf4", "0x11505938be6c01c3", "0x46d70f2787f3deaa", "0xe7546fa4fdf67d02", "0x27780d83c95eb515", "0x5206a7adfba9f15d", "0x485504ae37c128e0", "0xd442920b668e97db",
|
||||
"0x56fdc1e95fb2d170", "0x09e38ff904a5b56a", "0xb2ae26db1222f910", "0xa19864d4801daf4d", "0x06a933927c9d1911", "0x3dab78408de69705", "0x17f568a8f4bf8d07", "0x3bc2d52c807a0290",
|
||||
"0x58626fdb2dac1a6e", "0x5bf21bfea7756f58", "0xd40dc38290489e78", "0xa0851f74c4783040", "0x9f521fa799d21d1e", "0x363b3f454f9feef6", "0xb383f1a11e51190f", "0x4c83f6eb054d58a8"
|
||||
]}
|
||||
],
|
||||
"dataset_head": ["0xffc3cd94", "0x5920ccd8", "0x392f44bb", "0x5e57f67a", "0x2f2bc2a9", "0x620b0e36", "0xbdc09014", "0x436654bf", "0x311e0b48", "0x1abd93ad", "0x59cc7ce8", "0xee5247b2", "0x86171fe8", "0x6d874751", "0xc9f7728f", "0x7c2a435d"],
|
||||
"dataset_last_index": 268435455,
|
||||
"dataset_last": "0xa33ada72",
|
||||
"dataset_samples": [{"index": 59471966, "value": "0xe8b73d94"}, {"index": 217795994, "value": "0x337028b5"}, {"index": 208353206, "value": "0xafe148c9"}, {"index": 42483309, "value": "0xab99f7ae"}, {"index": 172547758, "value": "0x434ea619"}, {"index": 148076330, "value": "0xd85cb880"}, {"index": 183853158, "value": "0x54764c7f"}, {"index": 214389424, "value": "0x82c7e420"}, {"index": 267488061, "value": "0xedf4cb9e"}, {"index": 169781097, "value": "0x9884c959"}, {"index": 184093494, "value": "0x223ee793"}, {"index": 153880993, "value": "0x3a9ccf69"}, {"index": 84977930, "value": "0x81da4fd2"}, {"index": 46426879, "value": "0xd6ce8cb9"}, {"index": 3093825, "value": "0xe3922dca"}, {"index": 225364072, "value": "0x3e7e6bde"}, {"index": 44593546, "value": "0x382a3aca"}, {"index": 260713159, "value": "0x567e7f7f"}, {"index": 168250303, "value": "0x25a0f084"}, {"index": 52384140, "value": "0xbfeef128"}, {"index": 223401610, "value": "0xe338abfb"}, {"index": 45554030, "value": "0x7c3b5280"}, {"index": 95410555, "value": "0x909bc5f1"}, {"index": 175039924, "value": "0xd8b74b9c"}, {"index": 79171087, "value": "0x8e31a22e"}, {"index": 267580473, "value": "0x26b5f1d8"}, {"index": 24168642, "value": "0x79122c00"}, {"index": 37981670, "value": "0xcafc3340"}, {"index": 171551130, "value": "0xd5e02ea3"}, {"index": 195559979, "value": "0x1aee1afd"}, {"index": 204611762, "value": "0xdb090d9a"}, {"index": 140997658, "value": "0xb049f435"}, {"index": 138925853, "value": "0x4954d8ba"}, {"index": 86637313, "value": "0x03797ba0"}, {"index": 20736778, "value": "0x196eefbd"}, {"index": 219665210, "value": "0xd153412a"}, {"index": 160430336, "value": "0xbe5d2c4b"}, {"index": 264654675, "value": "0xdaa14f0e"}, {"index": 8013395, "value": "0x8e61ed07"}, {"index": 228945585, "value": "0x9e9a64c6"}, {"index": 213884386, "value": "0x2e29ff36"}, {"index": 104419827, "value": "0x392a8589"}, {"index": 44185464, "value": "0xb56a5912"}, {"index": 142737231, "value": "0xfa6e8b57"}, {"index": 99284897, "value": "0xd1a737cb"}, {"index": 132475900, "value": "0xb0fa841a"}, {"index": 61861762, "value": "0xbe1c341f"}, {"index": 132056166, "value": "0xe25be0f1"}, {"index": 262388043, "value": "0xe937f543"}, {"index": 91878046, "value": "0xebab2248"}, {"index": 117353561, "value": "0x8e1b607a"}, {"index": 124768597, "value": "0x202a2fed"}, {"index": 71352993, "value": "0x95e2819c"}, {"index": 190698941, "value": "0x9c9652d4"}, {"index": 46055428, "value": "0x32fedef0"}, {"index": 55281366, "value": "0xdecfff82"}, {"index": 165145231, "value": "0xcb5d43e5"}, {"index": 106810753, "value": "0xb735806a"}, {"index": 171985651, "value": "0x8905939c"}, {"index": 232085256, "value": "0xfbf8472d"}, {"index": 159510492, "value": "0xada74e5d"}, {"index": 40072060, "value": "0x7ebdeeea"}, {"index": 209107596, "value": "0x0119f2b3"}, {"index": 39023794, "value": "0xa9a376b8"}],
|
||||
"cache_head": ["0x355a86d2", "0x7957db1c", "0xd21772af", "0x6fc1e09b", "0xd55ce61d", "0x6e6a278b", "0xd3f543ce", "0x223d8e82", "0x143ab337", "0x2e9f05bd", "0x2eb389bf", "0x0c6e449e", "0x5cfa4222", "0xba6560fe", "0x8e3e1aa4", "0xdbcc1d53"],
|
||||
"cache_last_line": ["0x41190d91", "0xbd277957", "0x22ddbb49", "0x6986f207", "0xdf69a4d6", "0x26401a3a", "0x818230fb", "0xc417122d", "0x3597b211", "0xb553ce55", "0xcf39cc0d", "0x3b7fc43a", "0x3fd43b00", "0x67e1c80e", "0xffa7ea7d", "0xca2960ab"],
|
||||
"cache_fnv1a64": "0x48c4f5bf24166b2e"
|
||||
}
|
||||
278
proto-cuda/packs-readwidth/mixA-4/kernel.cl
Normal file
278
proto-cuda/packs-readwidth/mixA-4/kernel.cl
Normal file
|
|
@ -0,0 +1,278 @@
|
|||
// Generated by igneum-pow export (generator v2) for seed "igneum-readwidth/A/5". Do not edit by hand.
|
||||
// OpenCL C twin of the Metal kernel for the same seed (see proto-opencl/README.md, WAVEFRONT.md and program.metal).
|
||||
// Built from source at runtime by proto-opencl/host.c, which passes these defines:
|
||||
// IGNEUM_GROUP work-group size of igneum_hash, a multiple of 32 (default 32: one work-group = one 32-lane unit)
|
||||
// IGNEUM_EXCHANGE 0 = local-memory exchange with a barrier (any device, any wave width; the default)
|
||||
// 1 = sub_group_shuffle_xor (cl_khr_subgroup_shuffle), only with IGNEUM_GROUP 32 and a sub-group size of exactly 32
|
||||
// 2 = intel_sub_group_shuffle_xor (cl_intel_subgroups), same condition
|
||||
// The verification unit is always 32 lanes. A 64-wide hardware wave (AMD GCN/CDNA, RDNA in wave64) runs two units;
|
||||
// the exchange masks are 1, 2, 4, 8, 16, so every partner lane lies inside the lane's own aligned run of 32.
|
||||
#ifndef IGNEUM_GROUP
|
||||
#define IGNEUM_GROUP 32
|
||||
#endif
|
||||
#ifndef IGNEUM_EXCHANGE
|
||||
#define IGNEUM_EXCHANGE 0
|
||||
#endif
|
||||
#ifdef __OPENCL_VERSION__
|
||||
#define IGNEUM_KERNEL_HASH __kernel __attribute__((reqd_work_group_size(IGNEUM_GROUP, 1, 1)))
|
||||
#define IGNEUM_LOCAL_WORDS(name, n) __local uint name[n]
|
||||
#if IGNEUM_EXCHANGE == 1
|
||||
#ifdef cl_khr_subgroups
|
||||
#pragma OPENCL EXTENSION cl_khr_subgroups : enable
|
||||
#endif
|
||||
#ifdef cl_khr_subgroup_shuffle
|
||||
#pragma OPENCL EXTENSION cl_khr_subgroup_shuffle : enable
|
||||
#endif
|
||||
#elif IGNEUM_EXCHANGE == 2
|
||||
#pragma OPENCL EXTENSION cl_intel_subgroups : enable
|
||||
#endif
|
||||
#else
|
||||
// Not an OpenCL compiler: proto-opencl/emu compiles this file as C++ and supplies the built-ins and these two macros.
|
||||
#include "emu_opencl.h"
|
||||
#endif
|
||||
|
||||
#if IGNEUM_EXCHANGE == 1
|
||||
#define IGNEUM_SHFL_XOR(dst, a, m) dst = sub_group_shuffle_xor((a), (uint)(m))
|
||||
#define IGNEUM_BCAST0(dst, a) dst = sub_group_broadcast((a), 0u)
|
||||
#elif IGNEUM_EXCHANGE == 2
|
||||
#define IGNEUM_SHFL_XOR(dst, a, m) dst = intel_sub_group_shuffle_xor((a), (uint)(m))
|
||||
#define IGNEUM_BCAST0(dst, a) dst = sub_group_broadcast((a), 0u)
|
||||
#else
|
||||
// Local-memory exchange. Two buffers of IGNEUM_GROUP words alternate (xk counts exchanges), so one barrier per
|
||||
// exchange is enough: a lane can only overwrite buffer b at exchange k+2 after passing barrier k+1, and every lane
|
||||
// reaches barrier k+1 only after its read of buffer b at exchange k. The partner lid ^ m stays inside the lane's
|
||||
// aligned run of 32 because m < 32. Control flow is uniform, so every work-item reaches every barrier.
|
||||
#define IGNEUM_SHFL_XOR(dst, a, m) { xch[(xk & 1u) * IGNEUM_GROUP + lid] = (a); barrier(CLK_LOCAL_MEM_FENCE); dst = xch[(xk & 1u) * IGNEUM_GROUP + (lid ^ (uint)(m))]; xk += 1u; }
|
||||
#define IGNEUM_BCAST0(dst, a) { xch[(xk & 1u) * IGNEUM_GROUP + lid] = (a); barrier(CLK_LOCAL_MEM_FENCE); dst = xch[(xk & 1u) * IGNEUM_GROUP + (lid & ~31u)]; xk += 1u; }
|
||||
#endif
|
||||
|
||||
static inline uint splitmix32(uint x) {
|
||||
x ^= x >> 16; x *= 0x7feb352du;
|
||||
x ^= x >> 15; x *= 0x846ca68bu;
|
||||
x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
// n is a literal in 1..31 at every call site. OpenCL rotate() rotates left by n modulo 32.
|
||||
static inline uint rotl_imm(uint x, uint n) { return rotate(x, n); }
|
||||
// Right rotation by n modulo 32 as a left rotation by (32 - n) modulo 32; n == 0 gives x.
|
||||
static inline uint rotr_var(uint x, uint n) { return rotate(x, (0u - n) & 31u); }
|
||||
static inline uint ds_elem(uint i, uint d0, uint d1) {
|
||||
uint x = i ^ d0;
|
||||
x *= 0x9E3779B1u; x ^= x >> 15;
|
||||
x += d1;
|
||||
x *= 0x85EBCA77u; x ^= x >> 13;
|
||||
x *= 0xC2B2AE3Du; x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
|
||||
// Memory-hard dataset core (MEMHARD.md). Cache: 2^26 words in 2^16 segments of 64 chained ChaCha12 lines.
|
||||
// Item: 8 rounds of seed-parameterised mixer + one 64-byte cache read, then a final mixer. All parameters are literals.
|
||||
#define MH_CACHE_LINE_MASK 0x003fffffu
|
||||
#define MH_SEGMENT_LINES 64u
|
||||
#define MH_QR(a, b, c, d, r1, r2, r3, r4) { a += b; d ^= a; d = mh_rotl(d, r1); c += d; b ^= c; b = mh_rotl(b, r2); a += b; d ^= a; d = mh_rotl(d, r3); c += d; b ^= c; b = mh_rotl(b, r4); }
|
||||
static inline uint mh_rotl(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 at every call site
|
||||
|
||||
// y = ChaCha12 core(x) + x
|
||||
static inline void mh_chacha_block(const uint* x, uint* y) {
|
||||
for (uint i = 0u; i < 16u; ++i) y[i] = x[i];
|
||||
for (uint r = 0u; r < 6u; ++r) {
|
||||
MH_QR(y[0], y[4], y[8], y[12], 16u, 12u, 8u, 7u) MH_QR(y[1], y[5], y[9], y[13], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[2], y[6], y[10], y[14], 16u, 12u, 8u, 7u) MH_QR(y[3], y[7], y[11], y[15], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[0], y[5], y[10], y[15], 16u, 12u, 8u, 7u) MH_QR(y[1], y[6], y[11], y[12], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[2], y[7], y[8], y[13], 16u, 12u, 8u, 7u) MH_QR(y[3], y[4], y[9], y[14], 16u, 12u, 8u, 7u)
|
||||
}
|
||||
for (uint i = 0u; i < 16u; ++i) y[i] += x[i];
|
||||
}
|
||||
|
||||
// One cache segment: 64 chained lines written at cache[seg * 1024]. in_j = prev ^ (sigma || K || seg || j || tag), prev_0 = 0.
|
||||
static inline void mh_cache_segment(__global uint* cache, uint seg) {
|
||||
uint prev[16]; uint x[16]; uint y[16];
|
||||
for (uint i = 0u; i < 16u; ++i) prev[i] = 0u;
|
||||
for (uint j = 0u; j < MH_SEGMENT_LINES; ++j) {
|
||||
x[0] = 0x61707865u ^ prev[0]; x[1] = 0x3320646eu ^ prev[1]; x[2] = 0x79622d32u ^ prev[2]; x[3] = 0x6b206574u ^ prev[3];
|
||||
x[4] = 0x3067619fu ^ prev[4];
|
||||
x[5] = 0x3c269176u ^ prev[5];
|
||||
x[6] = 0x84a03b03u ^ prev[6];
|
||||
x[7] = 0xf8c63294u ^ prev[7];
|
||||
x[8] = 0xff977c5bu ^ prev[8];
|
||||
x[9] = 0xe60def3eu ^ prev[9];
|
||||
x[10] = 0x63630141u ^ prev[10];
|
||||
x[11] = 0xb8fbcb58u ^ prev[11];
|
||||
x[12] = seg ^ prev[12]; x[13] = j ^ prev[13]; x[14] = 0x49676e65u ^ prev[14]; x[15] = 0x756d4d48u ^ prev[15];
|
||||
mh_chacha_block(x, y);
|
||||
__global uint* line = cache + ((seg * MH_SEGMENT_LINES + j) * 16u);
|
||||
for (uint i = 0u; i < 16u; ++i) { line[i] = y[i]; prev[i] = y[i]; }
|
||||
}
|
||||
}
|
||||
|
||||
// M_r: per word (s ^ (RC + rk)) * MUL, then a column round and a diagonal round with the seed-drawn rotations.
|
||||
static inline void mh_mixer(uint* s, uint rk) {
|
||||
s[0] = (s[0] ^ (0xbab68293u + rk)) * 0x42146205u;
|
||||
s[1] = (s[1] ^ (0xcc162340u + rk)) * 0x52cbe0fbu;
|
||||
s[2] = (s[2] ^ (0x6ce151ccu + rk)) * 0x7ecf4a03u;
|
||||
s[3] = (s[3] ^ (0xe62b8997u + rk)) * 0x6728907fu;
|
||||
s[4] = (s[4] ^ (0xc9c80297u + rk)) * 0xd81d9751u;
|
||||
s[5] = (s[5] ^ (0xf74a1654u + rk)) * 0x132952c3u;
|
||||
s[6] = (s[6] ^ (0x3d704af5u + rk)) * 0xf60de277u;
|
||||
s[7] = (s[7] ^ (0x3cf522b7u + rk)) * 0x05358035u;
|
||||
s[8] = (s[8] ^ (0x2b9cac04u + rk)) * 0xbaf6499du;
|
||||
s[9] = (s[9] ^ (0xa880ac10u + rk)) * 0xe4db9667u;
|
||||
s[10] = (s[10] ^ (0x13e5dd1du + rk)) * 0x3e98f45du;
|
||||
s[11] = (s[11] ^ (0x6fc3e233u + rk)) * 0xd0004eddu;
|
||||
s[12] = (s[12] ^ (0x2d83eeacu + rk)) * 0x2691630du;
|
||||
s[13] = (s[13] ^ (0x9006e8bfu + rk)) * 0x9beb3bcfu;
|
||||
s[14] = (s[14] ^ (0x2c4b5362u + rk)) * 0xab310379u;
|
||||
s[15] = (s[15] ^ (0x31b49ee2u + rk)) * 0x99cfb423u;
|
||||
MH_QR(s[0], s[4], s[8], s[12], 20u, 20u, 19u, 4u) MH_QR(s[1], s[5], s[9], s[13], 20u, 20u, 19u, 4u)
|
||||
MH_QR(s[2], s[6], s[10], s[14], 20u, 20u, 19u, 4u) MH_QR(s[3], s[7], s[11], s[15], 20u, 20u, 19u, 4u)
|
||||
MH_QR(s[0], s[5], s[10], s[15], 26u, 3u, 3u, 27u) MH_QR(s[1], s[6], s[11], s[12], 26u, 3u, 3u, 27u)
|
||||
MH_QR(s[2], s[7], s[8], s[13], 26u, 3u, 3u, 27u) MH_QR(s[3], s[4], s[9], s[14], 26u, 3u, 3u, 27u)
|
||||
}
|
||||
|
||||
// Item t: 16 words. s = (K, t * MUL[i] + RC[i]); 8 rounds of mixer + cache line s[0] & mask; final mixer.
|
||||
static inline void mh_item(__global const uint* cache, uint t, uint* s) {
|
||||
s[0] = 0x3067619fu;
|
||||
s[1] = 0x3c269176u;
|
||||
s[2] = 0x84a03b03u;
|
||||
s[3] = 0xf8c63294u;
|
||||
s[4] = 0xff977c5bu;
|
||||
s[5] = 0xe60def3eu;
|
||||
s[6] = 0x63630141u;
|
||||
s[7] = 0xb8fbcb58u;
|
||||
s[8] = t * 0x42146205u + 0xbab68293u;
|
||||
s[9] = t * 0x52cbe0fbu + 0xcc162340u;
|
||||
s[10] = t * 0x7ecf4a03u + 0x6ce151ccu;
|
||||
s[11] = t * 0x6728907fu + 0xe62b8997u;
|
||||
s[12] = t * 0xd81d9751u + 0xc9c80297u;
|
||||
s[13] = t * 0x132952c3u + 0xf74a1654u;
|
||||
s[14] = t * 0xf60de277u + 0x3d704af5u;
|
||||
s[15] = t * 0x05358035u + 0x3cf522b7u;
|
||||
for (uint r = 0u; r < 8u; ++r) {
|
||||
mh_mixer(s, 0x9E3779B9u * (r + 1u));
|
||||
__global const uint* line = cache + ((s[0] & MH_CACHE_LINE_MASK) * 16u);
|
||||
for (uint i = 0u; i < 16u; ++i) s[i] ^= line[i];
|
||||
}
|
||||
mh_mixer(s, 0x9E3779B9u * 9u);
|
||||
}
|
||||
// dataset[w] without the dataset: derive item w >> 4 and take word w & 15.
|
||||
static inline uint mh_word(__global const uint* cache, uint w) { uint s[16]; mh_item(cache, w >> 4u, s); return s[w & 15u]; }
|
||||
|
||||
// Memory-hard dataset (MEMHARD.md). One work-item per cache segment; one work-item per 64-byte dataset item.
|
||||
// The same constants as memhard.h in this pack (one emitter, three dialects).
|
||||
__kernel void igneum_cache_fill(__global uint* cache, uint nSegments) {
|
||||
uint seg = (uint)get_global_id(0);
|
||||
if (seg < nSegments) mh_cache_segment(cache, seg);
|
||||
}
|
||||
__kernel void igneum_build(__global uint* ds, __global const uint* cache, uint nItems) {
|
||||
uint t = (uint)get_global_id(0);
|
||||
if (t < nItems) {
|
||||
uint s[16];
|
||||
mh_item(cache, t, s);
|
||||
__global uint* d = ds + ((ulong)t * 16u);
|
||||
for (uint i = 0u; i < 16u; ++i) d[i] = s[i];
|
||||
}
|
||||
}
|
||||
|
||||
// One hash per work-item. IGNEUM_GROUP is a multiple of 32; lane = lid & 31 and every exchange stays inside the
|
||||
// lane's own aligned run of 32 work-items, exactly like simd_shuffle_xor inside a 32-wide Metal SIMD group and
|
||||
// __shfl_xor_sync inside a CUDA warp. Control flow is uniform (no branches at all).
|
||||
IGNEUM_KERNEL_HASH void igneum_hash(__global const uint* ds, __global ulong* out, uint baseNonce, uint mask) {
|
||||
uint gid = (uint)get_global_id(0);
|
||||
uint lid = (uint)get_local_id(0);
|
||||
uint nonce = baseNonce + gid;
|
||||
uint r0, r1, r2, r3, r4, r5, r6, r7;
|
||||
#if IGNEUM_EXCHANGE == 0
|
||||
IGNEUM_LOCAL_WORDS(xch, 2 * IGNEUM_GROUP);
|
||||
uint xk = 0u;
|
||||
#else
|
||||
(void)lid;
|
||||
#endif
|
||||
{ uint x = nonce ^ 0xc255b2bfu; x += 0x9e3779b9u; x = splitmix32(x); r0 = x ^ 0xdba9d396u; } // SEEDW[0], 0x9e3779b9u * 1u, SEEDW[1]
|
||||
{ uint x = nonce ^ 0xdba9d396u; x += 0x3c6ef372u; x = splitmix32(x); r1 = x ^ 0x6ea527e4u; } // SEEDW[1], 0x9e3779b9u * 2u, SEEDW[2]
|
||||
{ uint x = nonce ^ 0x6ea527e4u; x += 0xdaa66d2bu; x = splitmix32(x); r2 = x ^ 0x05f1866au; } // SEEDW[2], 0x9e3779b9u * 3u, SEEDW[3]
|
||||
{ uint x = nonce ^ 0x05f1866au; x += 0x78dde6e4u; x = splitmix32(x); r3 = x ^ 0x2947e02eu; } // SEEDW[3], 0x9e3779b9u * 4u, SEEDW[4]
|
||||
{ uint x = nonce ^ 0x2947e02eu; x += 0x1715609du; x = splitmix32(x); r4 = x ^ 0x0ecc5c6fu; } // SEEDW[4], 0x9e3779b9u * 5u, SEEDW[5]
|
||||
{ uint x = nonce ^ 0x0ecc5c6fu; x += 0xb54cda56u; x = splitmix32(x); r5 = x ^ 0xc3b7068du; } // SEEDW[5], 0x9e3779b9u * 6u, SEEDW[6]
|
||||
{ uint x = nonce ^ 0xc3b7068du; x += 0x5384540fu; x = splitmix32(x); r6 = x ^ 0x282d1c2eu; } // SEEDW[6], 0x9e3779b9u * 7u, SEEDW[7]
|
||||
{ uint x = nonce ^ 0x282d1c2eu; x += 0xf1bbcdc8u; x = splitmix32(x); r7 = x ^ 0xc255b2bfu; } // SEEDW[7], 0x9e3779b9u * 8u, SEEDW[0]
|
||||
|
||||
for (uint it = 0u; it < 8u; ++it) {
|
||||
uint sel = r0;
|
||||
r3 = rotl_imm(r3, 26u); // 0 rotl
|
||||
r2 = rotr_var(r2, r0); // 1 rotr
|
||||
r0 = r0 ^ r7; // 2 xor
|
||||
r4 = r4 ^ r7; // 3 xor
|
||||
r2 = r2 ^ ds[r4 & mask]; // 4 load
|
||||
{ uint b_ = (r2 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r3 = x_; } // 5 load
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r7, 4u); r0 = r0 ^ t_; } // 6 shfl
|
||||
r6 = rotl_imm(r6, 31u); // 7 rotl
|
||||
r1 = r4 * r2 + r1; // 8 mad
|
||||
r1 = r7 * r0 + r1; // 9 mad
|
||||
r4 = r4 ^ ds[r1 & mask]; // 10 load
|
||||
r6 = r7 * r0 + r6; // 11 mad
|
||||
r2 = r2 * r6; // 12 mul
|
||||
{ uint b_ = (r2 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r0 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r0 = x_; } // 13 load
|
||||
r2 = r2 + r7 + ((((sel >> 22u) & 1u) != 0u) ? 0x4a3db5a5u : 0x5df3957du); // 14 add
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r7, 1u); r5 = r5 ^ t_; } // 15 shfl
|
||||
r3 = r5 * r6 + r3; // 16 mad
|
||||
r2 = r2 * r5; // 17 mul
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r5, 1u); r1 = r1 ^ t_; } // 18 shfl
|
||||
r0 = r0 - r1; // 19 sub
|
||||
r4 = r6 * r4 + r4; // 20 mad
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r0, 16u); r3 = r3 ^ t_; } // 21 shfl
|
||||
r1 = rotl_imm(r1, 24u); // 22 rotl
|
||||
r1 = r1 + r0 + ((((sel >> 22u) & 1u) != 0u) ? 0xfc07c54cu : 0x5c141117u); // 23 add
|
||||
r2 = r2 ^ ds[r0 & mask]; // 24 load
|
||||
r0 = r0 ^ r1; // 25 xor
|
||||
r3 = r3 ^ r7; // 26 xor
|
||||
{ uint b_ = (r3 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r2 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r2 = x_; } // 27 load
|
||||
r0 = r0 ^ r6; // 28 xor
|
||||
r4 = r4 ^ r1; // 29 xor
|
||||
r6 = r6 * r3; // 30 mul
|
||||
r3 = rotl_imm(r3, 23u); // 31 rotl
|
||||
r7 = rotr_var(r7, r1); // 32 rotr
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r2, 2u); r6 = r6 ^ t_; } // 33 shfl
|
||||
{ uint b_ = (r0 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r5 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r5 = x_; } // 34 load
|
||||
r6 = r6 + r3 + ((((sel >> 29u) & 1u) != 0u) ? 0x0b74657bu : 0xfb55c58du); // 35 add
|
||||
{ uint b_ = (r5 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r6 = x_; } // 36 load
|
||||
r1 = r1 ^ ds[r4 & mask]; // 37 load
|
||||
{ uint b_ = (r3 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r6 = x_; } // 38 load
|
||||
r4 = r4 ^ ds[r7 & mask]; // 39 load
|
||||
r7 = mul_hi(r7, r3); // 40 mulhi
|
||||
r0 = r0 | r6; // 41 or
|
||||
r0 = r3 * r0 + r0; // 42 mad
|
||||
{ uint b_ = (r6 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r4 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r4 = x_; } // 43 load
|
||||
r2 = r4 * r0 + r2; // 44 mad
|
||||
r2 = r4 * r2 + r2; // 45 mad
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r5, 16u); r7 = r7 ^ t_; } // 46 shfl
|
||||
r6 = r1 * r4 + r6; // 47 mad
|
||||
r7 = r7 ^ ds[r1 & mask]; // 48 load
|
||||
r6 = mul_hi(r6, r5); // 49 mulhi
|
||||
r5 = mul_hi(r5, r0); // 50 mulhi
|
||||
{ uint b_ = (r6 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r1 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r1 = x_; } // 51 load
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r3, 1u); r7 = r7 ^ t_; } // 52 shfl
|
||||
r2 = r2 ^ r5; // 53 xor
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r6, 4u); r0 = r0 ^ t_; } // 54 shfl
|
||||
r2 = r2 * r5; // 55 mul
|
||||
r5 = r5 * r6; // 56 mul
|
||||
{ uint b_ = (r4 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r6 = x_; } // 57 load
|
||||
r4 = r7 * r7 + r4; // 58 mad
|
||||
r2 = r2 ^ ds[r1 & mask]; // 59 load
|
||||
r1 = r1 * r4; // 60 mul
|
||||
r3 = r3 * r4; // 61 mul
|
||||
r6 = r6 ^ r4; // 62 xor
|
||||
r3 = rotr_var(r3, r1); // 63 rotr
|
||||
}
|
||||
uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u);
|
||||
uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u);
|
||||
out[gid] = ((ulong)hi << 32) | (ulong)lo;
|
||||
}
|
||||
|
||||
#if IGNEUM_EXCHANGE != 0
|
||||
// Reports the sub-group size this device uses for a work-group of IGNEUM_GROUP items. host.c runs it only when the
|
||||
// per-kernel query (clGetKernelSubGroupInfoKHR on igneum_hash) is unavailable; that query is preferred because a
|
||||
// compiler may pick a different wave width per kernel (RDNA: wave32 or wave64). See WAVEFRONT.md.
|
||||
IGNEUM_KERNEL_HASH void igneum_probe_subgroup(__global uint* out) {
|
||||
if (get_local_id(0) == 0u) { out[0] = get_sub_group_size(); out[1] = get_num_sub_groups(); }
|
||||
}
|
||||
#endif
|
||||
164
proto-cuda/packs-readwidth/mixA-4/kernel.cu
Normal file
164
proto-cuda/packs-readwidth/mixA-4/kernel.cu
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
// Generated by igneum-pow export (generator v2) for seed "igneum-readwidth/A/5". Do not edit by hand.
|
||||
// Bit-exact twin of the Metal kernel for the same seed (see proto-cuda/CHECKLIST.md and program.metal).
|
||||
// Compiled ahead of time by nvcc together with proto-cuda/host.cu. No NVRTC.
|
||||
#include <cuda_runtime.h>
|
||||
#include <cstdint>
|
||||
#include "program.h"
|
||||
#include "memhard.h"
|
||||
|
||||
__device__ __forceinline__ uint32_t splitmix32(uint32_t x) {
|
||||
x ^= x >> 16; x *= 0x7feb352du;
|
||||
x ^= x >> 15; x *= 0x846ca68bu;
|
||||
x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
// n is a literal in 1..31 at every call site, so both shift amounts are in 1..31.
|
||||
__device__ __forceinline__ uint32_t rotl_imm(uint32_t x, uint32_t n) { return (x << n) | (x >> (32u - n)); }
|
||||
// n is masked to 0..31; the second shift amount is masked too, so n == 0 gives x.
|
||||
__device__ __forceinline__ uint32_t rotr_var(uint32_t x, uint32_t n) { n &= 31u; return (x >> n) | (x << ((32u - n) & 31u)); }
|
||||
__device__ __forceinline__ uint32_t ds_elem(uint32_t i, uint32_t d0, uint32_t d1) {
|
||||
uint32_t x = i ^ d0;
|
||||
x *= 0x9E3779B1u; x ^= x >> 15;
|
||||
x += d1;
|
||||
x *= 0x85EBCA77u; x ^= x >> 13;
|
||||
x *= 0xC2B2AE3Du; x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
|
||||
// Memory-hard dataset (MEMHARD.md). One thread per cache segment; one thread per 64-byte dataset item.
|
||||
// The core functions (mh_cache_segment, mh_item) are in memhard.h and are also compiled for the host.
|
||||
__global__ void igneum_cache_fill(uint32_t* cache, uint32_t nSegments) {
|
||||
uint32_t seg = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
if (seg < nSegments) mh_cache_segment(cache, seg);
|
||||
}
|
||||
__global__ void igneum_build(uint32_t* ds, const uint32_t* cache, uint32_t nItems) {
|
||||
uint32_t t = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
if (t < nItems) {
|
||||
uint32_t s[16];
|
||||
mh_item(cache, t, s);
|
||||
uint32_t* d = ds + (size_t)t * 16u;
|
||||
for (uint32_t i = 0u; i < 16u; ++i) d[i] = s[i];
|
||||
}
|
||||
}
|
||||
|
||||
// One hash per thread. blockDim.x is a multiple of 32; lane = threadIdx.x & 31 and every
|
||||
// __shfl_xor_sync stays inside the lane's own warp, exactly like simd_shuffle_xor inside a
|
||||
// 32-wide Metal SIMD group. Control flow is uniform, so the full 0xffffffff member mask is valid.
|
||||
__global__ void igneum_hash(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask) {
|
||||
uint32_t gid = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
uint32_t nonce = baseNonce + gid;
|
||||
uint32_t r0, r1, r2, r3, r4, r5, r6, r7;
|
||||
{ uint32_t x = nonce ^ 0xc255b2bfu; x += 0x9e3779b9u; x = splitmix32(x); r0 = x ^ 0xdba9d396u; } // SEEDW[0], 0x9e3779b9u * 1u, SEEDW[1]
|
||||
{ uint32_t x = nonce ^ 0xdba9d396u; x += 0x3c6ef372u; x = splitmix32(x); r1 = x ^ 0x6ea527e4u; } // SEEDW[1], 0x9e3779b9u * 2u, SEEDW[2]
|
||||
{ uint32_t x = nonce ^ 0x6ea527e4u; x += 0xdaa66d2bu; x = splitmix32(x); r2 = x ^ 0x05f1866au; } // SEEDW[2], 0x9e3779b9u * 3u, SEEDW[3]
|
||||
{ uint32_t x = nonce ^ 0x05f1866au; x += 0x78dde6e4u; x = splitmix32(x); r3 = x ^ 0x2947e02eu; } // SEEDW[3], 0x9e3779b9u * 4u, SEEDW[4]
|
||||
{ uint32_t x = nonce ^ 0x2947e02eu; x += 0x1715609du; x = splitmix32(x); r4 = x ^ 0x0ecc5c6fu; } // SEEDW[4], 0x9e3779b9u * 5u, SEEDW[5]
|
||||
{ uint32_t x = nonce ^ 0x0ecc5c6fu; x += 0xb54cda56u; x = splitmix32(x); r5 = x ^ 0xc3b7068du; } // SEEDW[5], 0x9e3779b9u * 6u, SEEDW[6]
|
||||
{ uint32_t x = nonce ^ 0xc3b7068du; x += 0x5384540fu; x = splitmix32(x); r6 = x ^ 0x282d1c2eu; } // SEEDW[6], 0x9e3779b9u * 7u, SEEDW[7]
|
||||
{ uint32_t x = nonce ^ 0x282d1c2eu; x += 0xf1bbcdc8u; x = splitmix32(x); r7 = x ^ 0xc255b2bfu; } // SEEDW[7], 0x9e3779b9u * 8u, SEEDW[0]
|
||||
|
||||
for (uint32_t it = 0u; it < 8u; ++it) {
|
||||
uint32_t sel = r0;
|
||||
r3 = rotl_imm(r3, 26u); // 0 rotl
|
||||
r2 = rotr_var(r2, r0); // 1 rotr
|
||||
r0 = r0 ^ r7; // 2 xor
|
||||
r4 = r4 ^ r7; // 3 xor
|
||||
r2 = r2 ^ ds[r4 & mask]; // 4 load
|
||||
{ uint32_t b_ = (r2 & mask) & ~3u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint32_t x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r3 = x_; } // 5 load
|
||||
r0 = r0 ^ __shfl_xor_sync(0xffffffffu, r7, 4); // 6 shfl
|
||||
r6 = rotl_imm(r6, 31u); // 7 rotl
|
||||
r1 = r4 * r2 + r1; // 8 mad
|
||||
r1 = r7 * r0 + r1; // 9 mad
|
||||
r4 = r4 ^ ds[r1 & mask]; // 10 load
|
||||
r6 = r7 * r0 + r6; // 11 mad
|
||||
r2 = r2 * r6; // 12 mul
|
||||
{ uint32_t b_ = (r2 & mask) & ~3u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint32_t x_ = r0 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r0 = x_; } // 13 load
|
||||
r2 = r2 + r7 + ((((sel >> 22u) & 1u) != 0u) ? 0x4a3db5a5u : 0x5df3957du); // 14 add
|
||||
r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r7, 1); // 15 shfl
|
||||
r3 = r5 * r6 + r3; // 16 mad
|
||||
r2 = r2 * r5; // 17 mul
|
||||
r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r5, 1); // 18 shfl
|
||||
r0 = r0 - r1; // 19 sub
|
||||
r4 = r6 * r4 + r4; // 20 mad
|
||||
r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r0, 16); // 21 shfl
|
||||
r1 = rotl_imm(r1, 24u); // 22 rotl
|
||||
r1 = r1 + r0 + ((((sel >> 22u) & 1u) != 0u) ? 0xfc07c54cu : 0x5c141117u); // 23 add
|
||||
r2 = r2 ^ ds[r0 & mask]; // 24 load
|
||||
r0 = r0 ^ r1; // 25 xor
|
||||
r3 = r3 ^ r7; // 26 xor
|
||||
{ uint32_t b_ = (r3 & mask) & ~3u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint32_t x_ = r2 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r2 = x_; } // 27 load
|
||||
r0 = r0 ^ r6; // 28 xor
|
||||
r4 = r4 ^ r1; // 29 xor
|
||||
r6 = r6 * r3; // 30 mul
|
||||
r3 = rotl_imm(r3, 23u); // 31 rotl
|
||||
r7 = rotr_var(r7, r1); // 32 rotr
|
||||
r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r2, 2); // 33 shfl
|
||||
{ uint32_t b_ = (r0 & mask) & ~15u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint32_t x_ = r5 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r5 = x_; } // 34 load
|
||||
r6 = r6 + r3 + ((((sel >> 29u) & 1u) != 0u) ? 0x0b74657bu : 0xfb55c58du); // 35 add
|
||||
{ uint32_t b_ = (r5 & mask) & ~15u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint32_t x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r6 = x_; } // 36 load
|
||||
r1 = r1 ^ ds[r4 & mask]; // 37 load
|
||||
{ uint32_t b_ = (r3 & mask) & ~3u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint32_t x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r6 = x_; } // 38 load
|
||||
r4 = r4 ^ ds[r7 & mask]; // 39 load
|
||||
r7 = __umulhi(r7, r3); // 40 mulhi
|
||||
r0 = r0 | r6; // 41 or
|
||||
r0 = r3 * r0 + r0; // 42 mad
|
||||
{ uint32_t b_ = (r6 & mask) & ~15u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint32_t x_ = r4 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r4 = x_; } // 43 load
|
||||
r2 = r4 * r0 + r2; // 44 mad
|
||||
r2 = r4 * r2 + r2; // 45 mad
|
||||
r7 = r7 ^ __shfl_xor_sync(0xffffffffu, r5, 16); // 46 shfl
|
||||
r6 = r1 * r4 + r6; // 47 mad
|
||||
r7 = r7 ^ ds[r1 & mask]; // 48 load
|
||||
r6 = __umulhi(r6, r5); // 49 mulhi
|
||||
r5 = __umulhi(r5, r0); // 50 mulhi
|
||||
{ uint32_t b_ = (r6 & mask) & ~3u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint32_t x_ = r1 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r1 = x_; } // 51 load
|
||||
r7 = r7 ^ __shfl_xor_sync(0xffffffffu, r3, 1); // 52 shfl
|
||||
r2 = r2 ^ r5; // 53 xor
|
||||
r0 = r0 ^ __shfl_xor_sync(0xffffffffu, r6, 4); // 54 shfl
|
||||
r2 = r2 * r5; // 55 mul
|
||||
r5 = r5 * r6; // 56 mul
|
||||
{ uint32_t b_ = (r4 & mask) & ~3u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint32_t x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r6 = x_; } // 57 load
|
||||
r4 = r7 * r7 + r4; // 58 mad
|
||||
r2 = r2 ^ ds[r1 & mask]; // 59 load
|
||||
r1 = r1 * r4; // 60 mul
|
||||
r3 = r3 * r4; // 61 mul
|
||||
r6 = r6 ^ r4; // 62 xor
|
||||
r3 = rotr_var(r3, r1); // 63 rotr
|
||||
}
|
||||
uint32_t lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u);
|
||||
uint32_t hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u);
|
||||
out[gid] = ((uint64_t)hi << 32) | (uint64_t)lo;
|
||||
}
|
||||
|
||||
// Host-side launch wrappers. Declared in program.h, called from host.cu.
|
||||
cudaError_t igneum_launch_cache_fill(uint32_t* cache, uint32_t nSegments) {
|
||||
if (nSegments == 0u) return cudaErrorInvalidValue;
|
||||
uint32_t block = 256u;
|
||||
uint32_t grid = (nSegments + block - 1u) / block;
|
||||
igneum_cache_fill<<<grid, block>>>(cache, nSegments);
|
||||
return cudaGetLastError();
|
||||
}
|
||||
|
||||
cudaError_t igneum_launch_build(uint32_t* ds, const uint32_t* cache, uint32_t nItems) {
|
||||
if (nItems == 0u) return cudaErrorInvalidValue;
|
||||
uint32_t block = 256u;
|
||||
uint32_t grid = (nItems + block - 1u) / block;
|
||||
igneum_build<<<grid, block>>>(ds, cache, nItems);
|
||||
return cudaGetLastError();
|
||||
}
|
||||
|
||||
cudaError_t igneum_launch_hash(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask,
|
||||
uint32_t nonces, uint32_t blockWarps) {
|
||||
if (blockWarps == 0u || blockWarps > 32u) return cudaErrorInvalidValue;
|
||||
uint32_t block = 32u * blockWarps;
|
||||
if (nonces == 0u || (nonces % block) != 0u) return cudaErrorInvalidValue;
|
||||
igneum_hash<<<nonces / block, block>>>(ds, out, baseNonce, mask);
|
||||
return cudaGetLastError();
|
||||
}
|
||||
|
||||
cudaError_t igneum_hash_info(int* numRegs, int* blocksPerSM, uint32_t blockWarps) {
|
||||
cudaFuncAttributes attr;
|
||||
cudaError_t e = cudaFuncGetAttributes(&attr, igneum_hash);
|
||||
if (e != cudaSuccess) return e;
|
||||
*numRegs = attr.numRegs;
|
||||
return cudaOccupancyMaxActiveBlocksPerMultiprocessor(blocksPerSM, igneum_hash, (int)(32u * blockWarps), 0);
|
||||
}
|
||||
372
proto-cuda/packs-readwidth/mixA-4/kernel_bound.cl
Normal file
372
proto-cuda/packs-readwidth/mixA-4/kernel_bound.cl
Normal file
|
|
@ -0,0 +1,372 @@
|
|||
// Generated by igneum-pow export (generator v2) for seed "igneum-readwidth/A/5". Do not edit by hand.
|
||||
// OpenCL C twin of the Metal kernel for the same seed (see proto-opencl/README.md, WAVEFRONT.md and program.metal).
|
||||
// Built from source at runtime by proto-opencl/host.c, which passes these defines:
|
||||
// IGNEUM_GROUP work-group size of igneum_hash, a multiple of 32 (default 32: one work-group = one 32-lane unit)
|
||||
// IGNEUM_EXCHANGE 0 = local-memory exchange with a barrier (any device, any wave width; the default)
|
||||
// 1 = sub_group_shuffle_xor (cl_khr_subgroup_shuffle), only with IGNEUM_GROUP 32 and a sub-group size of exactly 32
|
||||
// 2 = intel_sub_group_shuffle_xor (cl_intel_subgroups), same condition
|
||||
// The verification unit is always 32 lanes. A 64-wide hardware wave (AMD GCN/CDNA, RDNA in wave64) runs two units;
|
||||
// the exchange masks are 1, 2, 4, 8, 16, so every partner lane lies inside the lane's own aligned run of 32.
|
||||
#ifndef IGNEUM_GROUP
|
||||
#define IGNEUM_GROUP 32
|
||||
#endif
|
||||
#ifndef IGNEUM_EXCHANGE
|
||||
#define IGNEUM_EXCHANGE 0
|
||||
#endif
|
||||
#ifdef __OPENCL_VERSION__
|
||||
#define IGNEUM_KERNEL_HASH __kernel __attribute__((reqd_work_group_size(IGNEUM_GROUP, 1, 1)))
|
||||
#define IGNEUM_LOCAL_WORDS(name, n) __local uint name[n]
|
||||
#if IGNEUM_EXCHANGE == 1
|
||||
#ifdef cl_khr_subgroups
|
||||
#pragma OPENCL EXTENSION cl_khr_subgroups : enable
|
||||
#endif
|
||||
#ifdef cl_khr_subgroup_shuffle
|
||||
#pragma OPENCL EXTENSION cl_khr_subgroup_shuffle : enable
|
||||
#endif
|
||||
#elif IGNEUM_EXCHANGE == 2
|
||||
#pragma OPENCL EXTENSION cl_intel_subgroups : enable
|
||||
#endif
|
||||
#else
|
||||
// Not an OpenCL compiler: proto-opencl/emu compiles this file as C++ and supplies the built-ins and these two macros.
|
||||
#include "emu_opencl.h"
|
||||
#endif
|
||||
|
||||
#if IGNEUM_EXCHANGE == 1
|
||||
#define IGNEUM_SHFL_XOR(dst, a, m) dst = sub_group_shuffle_xor((a), (uint)(m))
|
||||
#define IGNEUM_BCAST0(dst, a) dst = sub_group_broadcast((a), 0u)
|
||||
#elif IGNEUM_EXCHANGE == 2
|
||||
#define IGNEUM_SHFL_XOR(dst, a, m) dst = intel_sub_group_shuffle_xor((a), (uint)(m))
|
||||
#define IGNEUM_BCAST0(dst, a) dst = sub_group_broadcast((a), 0u)
|
||||
#else
|
||||
// Local-memory exchange. Two buffers of IGNEUM_GROUP words alternate (xk counts exchanges), so one barrier per
|
||||
// exchange is enough: a lane can only overwrite buffer b at exchange k+2 after passing barrier k+1, and every lane
|
||||
// reaches barrier k+1 only after its read of buffer b at exchange k. The partner lid ^ m stays inside the lane's
|
||||
// aligned run of 32 because m < 32. Control flow is uniform, so every work-item reaches every barrier.
|
||||
#define IGNEUM_SHFL_XOR(dst, a, m) { xch[(xk & 1u) * IGNEUM_GROUP + lid] = (a); barrier(CLK_LOCAL_MEM_FENCE); dst = xch[(xk & 1u) * IGNEUM_GROUP + (lid ^ (uint)(m))]; xk += 1u; }
|
||||
#define IGNEUM_BCAST0(dst, a) { xch[(xk & 1u) * IGNEUM_GROUP + lid] = (a); barrier(CLK_LOCAL_MEM_FENCE); dst = xch[(xk & 1u) * IGNEUM_GROUP + (lid & ~31u)]; xk += 1u; }
|
||||
#endif
|
||||
|
||||
static inline uint splitmix32(uint x) {
|
||||
x ^= x >> 16; x *= 0x7feb352du;
|
||||
x ^= x >> 15; x *= 0x846ca68bu;
|
||||
x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
// n is a literal in 1..31 at every call site. OpenCL rotate() rotates left by n modulo 32.
|
||||
static inline uint rotl_imm(uint x, uint n) { return rotate(x, n); }
|
||||
// Right rotation by n modulo 32 as a left rotation by (32 - n) modulo 32; n == 0 gives x.
|
||||
static inline uint rotr_var(uint x, uint n) { return rotate(x, (0u - n) & 31u); }
|
||||
static inline uint ds_elem(uint i, uint d0, uint d1) {
|
||||
uint x = i ^ d0;
|
||||
x *= 0x9E3779B1u; x ^= x >> 15;
|
||||
x += d1;
|
||||
x *= 0x85EBCA77u; x ^= x >> 13;
|
||||
x *= 0xC2B2AE3Du; x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
|
||||
// Memory-hard dataset core (MEMHARD.md). Cache: 2^26 words in 2^16 segments of 64 chained ChaCha12 lines.
|
||||
// Item: 8 rounds of seed-parameterised mixer + one 64-byte cache read, then a final mixer. All parameters are literals.
|
||||
#define MH_CACHE_LINE_MASK 0x003fffffu
|
||||
#define MH_SEGMENT_LINES 64u
|
||||
#define MH_QR(a, b, c, d, r1, r2, r3, r4) { a += b; d ^= a; d = mh_rotl(d, r1); c += d; b ^= c; b = mh_rotl(b, r2); a += b; d ^= a; d = mh_rotl(d, r3); c += d; b ^= c; b = mh_rotl(b, r4); }
|
||||
static inline uint mh_rotl(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 at every call site
|
||||
|
||||
// y = ChaCha12 core(x) + x
|
||||
static inline void mh_chacha_block(const uint* x, uint* y) {
|
||||
for (uint i = 0u; i < 16u; ++i) y[i] = x[i];
|
||||
for (uint r = 0u; r < 6u; ++r) {
|
||||
MH_QR(y[0], y[4], y[8], y[12], 16u, 12u, 8u, 7u) MH_QR(y[1], y[5], y[9], y[13], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[2], y[6], y[10], y[14], 16u, 12u, 8u, 7u) MH_QR(y[3], y[7], y[11], y[15], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[0], y[5], y[10], y[15], 16u, 12u, 8u, 7u) MH_QR(y[1], y[6], y[11], y[12], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[2], y[7], y[8], y[13], 16u, 12u, 8u, 7u) MH_QR(y[3], y[4], y[9], y[14], 16u, 12u, 8u, 7u)
|
||||
}
|
||||
for (uint i = 0u; i < 16u; ++i) y[i] += x[i];
|
||||
}
|
||||
|
||||
// One cache segment: 64 chained lines written at cache[seg * 1024]. in_j = prev ^ (sigma || K || seg || j || tag), prev_0 = 0.
|
||||
static inline void mh_cache_segment(__global uint* cache, uint seg) {
|
||||
uint prev[16]; uint x[16]; uint y[16];
|
||||
for (uint i = 0u; i < 16u; ++i) prev[i] = 0u;
|
||||
for (uint j = 0u; j < MH_SEGMENT_LINES; ++j) {
|
||||
x[0] = 0x61707865u ^ prev[0]; x[1] = 0x3320646eu ^ prev[1]; x[2] = 0x79622d32u ^ prev[2]; x[3] = 0x6b206574u ^ prev[3];
|
||||
x[4] = 0x3067619fu ^ prev[4];
|
||||
x[5] = 0x3c269176u ^ prev[5];
|
||||
x[6] = 0x84a03b03u ^ prev[6];
|
||||
x[7] = 0xf8c63294u ^ prev[7];
|
||||
x[8] = 0xff977c5bu ^ prev[8];
|
||||
x[9] = 0xe60def3eu ^ prev[9];
|
||||
x[10] = 0x63630141u ^ prev[10];
|
||||
x[11] = 0xb8fbcb58u ^ prev[11];
|
||||
x[12] = seg ^ prev[12]; x[13] = j ^ prev[13]; x[14] = 0x49676e65u ^ prev[14]; x[15] = 0x756d4d48u ^ prev[15];
|
||||
mh_chacha_block(x, y);
|
||||
__global uint* line = cache + ((seg * MH_SEGMENT_LINES + j) * 16u);
|
||||
for (uint i = 0u; i < 16u; ++i) { line[i] = y[i]; prev[i] = y[i]; }
|
||||
}
|
||||
}
|
||||
|
||||
// M_r: per word (s ^ (RC + rk)) * MUL, then a column round and a diagonal round with the seed-drawn rotations.
|
||||
static inline void mh_mixer(uint* s, uint rk) {
|
||||
s[0] = (s[0] ^ (0xbab68293u + rk)) * 0x42146205u;
|
||||
s[1] = (s[1] ^ (0xcc162340u + rk)) * 0x52cbe0fbu;
|
||||
s[2] = (s[2] ^ (0x6ce151ccu + rk)) * 0x7ecf4a03u;
|
||||
s[3] = (s[3] ^ (0xe62b8997u + rk)) * 0x6728907fu;
|
||||
s[4] = (s[4] ^ (0xc9c80297u + rk)) * 0xd81d9751u;
|
||||
s[5] = (s[5] ^ (0xf74a1654u + rk)) * 0x132952c3u;
|
||||
s[6] = (s[6] ^ (0x3d704af5u + rk)) * 0xf60de277u;
|
||||
s[7] = (s[7] ^ (0x3cf522b7u + rk)) * 0x05358035u;
|
||||
s[8] = (s[8] ^ (0x2b9cac04u + rk)) * 0xbaf6499du;
|
||||
s[9] = (s[9] ^ (0xa880ac10u + rk)) * 0xe4db9667u;
|
||||
s[10] = (s[10] ^ (0x13e5dd1du + rk)) * 0x3e98f45du;
|
||||
s[11] = (s[11] ^ (0x6fc3e233u + rk)) * 0xd0004eddu;
|
||||
s[12] = (s[12] ^ (0x2d83eeacu + rk)) * 0x2691630du;
|
||||
s[13] = (s[13] ^ (0x9006e8bfu + rk)) * 0x9beb3bcfu;
|
||||
s[14] = (s[14] ^ (0x2c4b5362u + rk)) * 0xab310379u;
|
||||
s[15] = (s[15] ^ (0x31b49ee2u + rk)) * 0x99cfb423u;
|
||||
MH_QR(s[0], s[4], s[8], s[12], 20u, 20u, 19u, 4u) MH_QR(s[1], s[5], s[9], s[13], 20u, 20u, 19u, 4u)
|
||||
MH_QR(s[2], s[6], s[10], s[14], 20u, 20u, 19u, 4u) MH_QR(s[3], s[7], s[11], s[15], 20u, 20u, 19u, 4u)
|
||||
MH_QR(s[0], s[5], s[10], s[15], 26u, 3u, 3u, 27u) MH_QR(s[1], s[6], s[11], s[12], 26u, 3u, 3u, 27u)
|
||||
MH_QR(s[2], s[7], s[8], s[13], 26u, 3u, 3u, 27u) MH_QR(s[3], s[4], s[9], s[14], 26u, 3u, 3u, 27u)
|
||||
}
|
||||
|
||||
// Item t: 16 words. s = (K, t * MUL[i] + RC[i]); 8 rounds of mixer + cache line s[0] & mask; final mixer.
|
||||
static inline void mh_item(__global const uint* cache, uint t, uint* s) {
|
||||
s[0] = 0x3067619fu;
|
||||
s[1] = 0x3c269176u;
|
||||
s[2] = 0x84a03b03u;
|
||||
s[3] = 0xf8c63294u;
|
||||
s[4] = 0xff977c5bu;
|
||||
s[5] = 0xe60def3eu;
|
||||
s[6] = 0x63630141u;
|
||||
s[7] = 0xb8fbcb58u;
|
||||
s[8] = t * 0x42146205u + 0xbab68293u;
|
||||
s[9] = t * 0x52cbe0fbu + 0xcc162340u;
|
||||
s[10] = t * 0x7ecf4a03u + 0x6ce151ccu;
|
||||
s[11] = t * 0x6728907fu + 0xe62b8997u;
|
||||
s[12] = t * 0xd81d9751u + 0xc9c80297u;
|
||||
s[13] = t * 0x132952c3u + 0xf74a1654u;
|
||||
s[14] = t * 0xf60de277u + 0x3d704af5u;
|
||||
s[15] = t * 0x05358035u + 0x3cf522b7u;
|
||||
for (uint r = 0u; r < 8u; ++r) {
|
||||
mh_mixer(s, 0x9E3779B9u * (r + 1u));
|
||||
__global const uint* line = cache + ((s[0] & MH_CACHE_LINE_MASK) * 16u);
|
||||
for (uint i = 0u; i < 16u; ++i) s[i] ^= line[i];
|
||||
}
|
||||
mh_mixer(s, 0x9E3779B9u * 9u);
|
||||
}
|
||||
// dataset[w] without the dataset: derive item w >> 4 and take word w & 15.
|
||||
static inline uint mh_word(__global const uint* cache, uint w) { uint s[16]; mh_item(cache, w >> 4u, s); return s[w & 15u]; }
|
||||
|
||||
// Memory-hard dataset (MEMHARD.md). One work-item per cache segment; one work-item per 64-byte dataset item.
|
||||
// The same constants as memhard.h in this pack (one emitter, three dialects).
|
||||
__kernel void igneum_cache_fill(__global uint* cache, uint nSegments) {
|
||||
uint seg = (uint)get_global_id(0);
|
||||
if (seg < nSegments) mh_cache_segment(cache, seg);
|
||||
}
|
||||
__kernel void igneum_build(__global uint* ds, __global const uint* cache, uint nItems) {
|
||||
uint t = (uint)get_global_id(0);
|
||||
if (t < nItems) {
|
||||
uint s[16];
|
||||
mh_item(cache, t, s);
|
||||
__global uint* d = ds + ((ulong)t * 16u);
|
||||
for (uint i = 0u; i < 16u; ++i) d[i] = s[i];
|
||||
}
|
||||
}
|
||||
|
||||
// One hash per work-item. IGNEUM_GROUP is a multiple of 32; lane = lid & 31 and every exchange stays inside the
|
||||
// lane's own aligned run of 32 work-items, exactly like simd_shuffle_xor inside a 32-wide Metal SIMD group and
|
||||
// __shfl_xor_sync inside a CUDA warp. Control flow is uniform (no branches at all).
|
||||
IGNEUM_KERNEL_HASH void igneum_hash(__global const uint* ds, __global ulong* out, uint baseNonce, uint mask) {
|
||||
uint gid = (uint)get_global_id(0);
|
||||
uint lid = (uint)get_local_id(0);
|
||||
uint nonce = baseNonce + gid;
|
||||
uint r0, r1, r2, r3, r4, r5, r6, r7;
|
||||
#if IGNEUM_EXCHANGE == 0
|
||||
IGNEUM_LOCAL_WORDS(xch, 2 * IGNEUM_GROUP);
|
||||
uint xk = 0u;
|
||||
#else
|
||||
(void)lid;
|
||||
#endif
|
||||
{ uint x = nonce ^ 0xc255b2bfu; x += 0x9e3779b9u; x = splitmix32(x); r0 = x ^ 0xdba9d396u; } // SEEDW[0], 0x9e3779b9u * 1u, SEEDW[1]
|
||||
{ uint x = nonce ^ 0xdba9d396u; x += 0x3c6ef372u; x = splitmix32(x); r1 = x ^ 0x6ea527e4u; } // SEEDW[1], 0x9e3779b9u * 2u, SEEDW[2]
|
||||
{ uint x = nonce ^ 0x6ea527e4u; x += 0xdaa66d2bu; x = splitmix32(x); r2 = x ^ 0x05f1866au; } // SEEDW[2], 0x9e3779b9u * 3u, SEEDW[3]
|
||||
{ uint x = nonce ^ 0x05f1866au; x += 0x78dde6e4u; x = splitmix32(x); r3 = x ^ 0x2947e02eu; } // SEEDW[3], 0x9e3779b9u * 4u, SEEDW[4]
|
||||
{ uint x = nonce ^ 0x2947e02eu; x += 0x1715609du; x = splitmix32(x); r4 = x ^ 0x0ecc5c6fu; } // SEEDW[4], 0x9e3779b9u * 5u, SEEDW[5]
|
||||
{ uint x = nonce ^ 0x0ecc5c6fu; x += 0xb54cda56u; x = splitmix32(x); r5 = x ^ 0xc3b7068du; } // SEEDW[5], 0x9e3779b9u * 6u, SEEDW[6]
|
||||
{ uint x = nonce ^ 0xc3b7068du; x += 0x5384540fu; x = splitmix32(x); r6 = x ^ 0x282d1c2eu; } // SEEDW[6], 0x9e3779b9u * 7u, SEEDW[7]
|
||||
{ uint x = nonce ^ 0x282d1c2eu; x += 0xf1bbcdc8u; x = splitmix32(x); r7 = x ^ 0xc255b2bfu; } // SEEDW[7], 0x9e3779b9u * 8u, SEEDW[0]
|
||||
|
||||
for (uint it = 0u; it < 8u; ++it) {
|
||||
uint sel = r0;
|
||||
r3 = rotl_imm(r3, 26u); // 0 rotl
|
||||
r2 = rotr_var(r2, r0); // 1 rotr
|
||||
r0 = r0 ^ r7; // 2 xor
|
||||
r4 = r4 ^ r7; // 3 xor
|
||||
r2 = r2 ^ ds[r4 & mask]; // 4 load
|
||||
{ uint b_ = (r2 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r3 = x_; } // 5 load
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r7, 4u); r0 = r0 ^ t_; } // 6 shfl
|
||||
r6 = rotl_imm(r6, 31u); // 7 rotl
|
||||
r1 = r4 * r2 + r1; // 8 mad
|
||||
r1 = r7 * r0 + r1; // 9 mad
|
||||
r4 = r4 ^ ds[r1 & mask]; // 10 load
|
||||
r6 = r7 * r0 + r6; // 11 mad
|
||||
r2 = r2 * r6; // 12 mul
|
||||
{ uint b_ = (r2 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r0 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r0 = x_; } // 13 load
|
||||
r2 = r2 + r7 + ((((sel >> 22u) & 1u) != 0u) ? 0x4a3db5a5u : 0x5df3957du); // 14 add
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r7, 1u); r5 = r5 ^ t_; } // 15 shfl
|
||||
r3 = r5 * r6 + r3; // 16 mad
|
||||
r2 = r2 * r5; // 17 mul
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r5, 1u); r1 = r1 ^ t_; } // 18 shfl
|
||||
r0 = r0 - r1; // 19 sub
|
||||
r4 = r6 * r4 + r4; // 20 mad
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r0, 16u); r3 = r3 ^ t_; } // 21 shfl
|
||||
r1 = rotl_imm(r1, 24u); // 22 rotl
|
||||
r1 = r1 + r0 + ((((sel >> 22u) & 1u) != 0u) ? 0xfc07c54cu : 0x5c141117u); // 23 add
|
||||
r2 = r2 ^ ds[r0 & mask]; // 24 load
|
||||
r0 = r0 ^ r1; // 25 xor
|
||||
r3 = r3 ^ r7; // 26 xor
|
||||
{ uint b_ = (r3 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r2 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r2 = x_; } // 27 load
|
||||
r0 = r0 ^ r6; // 28 xor
|
||||
r4 = r4 ^ r1; // 29 xor
|
||||
r6 = r6 * r3; // 30 mul
|
||||
r3 = rotl_imm(r3, 23u); // 31 rotl
|
||||
r7 = rotr_var(r7, r1); // 32 rotr
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r2, 2u); r6 = r6 ^ t_; } // 33 shfl
|
||||
{ uint b_ = (r0 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r5 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r5 = x_; } // 34 load
|
||||
r6 = r6 + r3 + ((((sel >> 29u) & 1u) != 0u) ? 0x0b74657bu : 0xfb55c58du); // 35 add
|
||||
{ uint b_ = (r5 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r6 = x_; } // 36 load
|
||||
r1 = r1 ^ ds[r4 & mask]; // 37 load
|
||||
{ uint b_ = (r3 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r6 = x_; } // 38 load
|
||||
r4 = r4 ^ ds[r7 & mask]; // 39 load
|
||||
r7 = mul_hi(r7, r3); // 40 mulhi
|
||||
r0 = r0 | r6; // 41 or
|
||||
r0 = r3 * r0 + r0; // 42 mad
|
||||
{ uint b_ = (r6 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r4 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r4 = x_; } // 43 load
|
||||
r2 = r4 * r0 + r2; // 44 mad
|
||||
r2 = r4 * r2 + r2; // 45 mad
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r5, 16u); r7 = r7 ^ t_; } // 46 shfl
|
||||
r6 = r1 * r4 + r6; // 47 mad
|
||||
r7 = r7 ^ ds[r1 & mask]; // 48 load
|
||||
r6 = mul_hi(r6, r5); // 49 mulhi
|
||||
r5 = mul_hi(r5, r0); // 50 mulhi
|
||||
{ uint b_ = (r6 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r1 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r1 = x_; } // 51 load
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r3, 1u); r7 = r7 ^ t_; } // 52 shfl
|
||||
r2 = r2 ^ r5; // 53 xor
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r6, 4u); r0 = r0 ^ t_; } // 54 shfl
|
||||
r2 = r2 * r5; // 55 mul
|
||||
r5 = r5 * r6; // 56 mul
|
||||
{ uint b_ = (r4 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r6 = x_; } // 57 load
|
||||
r4 = r7 * r7 + r4; // 58 mad
|
||||
r2 = r2 ^ ds[r1 & mask]; // 59 load
|
||||
r1 = r1 * r4; // 60 mul
|
||||
r3 = r3 * r4; // 61 mul
|
||||
r6 = r6 ^ r4; // 62 xor
|
||||
r3 = rotr_var(r3, r1); // 63 rotr
|
||||
}
|
||||
uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u);
|
||||
uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u);
|
||||
out[gid] = ((ulong)hi << 32) | (ulong)lo;
|
||||
}
|
||||
|
||||
#if IGNEUM_EXCHANGE != 0
|
||||
// Reports the sub-group size this device uses for a work-group of IGNEUM_GROUP items. host.c runs it only when the
|
||||
// per-kernel query (clGetKernelSubGroupInfoKHR on igneum_hash) is unavailable; that query is preferred because a
|
||||
// compiler may pick a different wave width per kernel (RDNA: wave32 or wave64). See WAVEFRONT.md.
|
||||
IGNEUM_KERNEL_HASH void igneum_probe_subgroup(__global uint* out) {
|
||||
if (get_local_id(0) == 0u) { out[0] = get_sub_group_size(); out[1] = get_num_sub_groups(); }
|
||||
}
|
||||
#endif
|
||||
|
||||
// Header-bound variant (bind.rs): the init words come from initw, not SEEDW. Same body as igneum_hash.
|
||||
IGNEUM_KERNEL_HASH void igneum_hash_bound(__global const uint* ds, __global ulong* out, uint baseNonce, uint mask, __global const uint* initw) {
|
||||
uint gid = (uint)get_global_id(0);
|
||||
uint lid = (uint)get_local_id(0);
|
||||
uint nonce = baseNonce + gid;
|
||||
uint r0, r1, r2, r3, r4, r5, r6, r7;
|
||||
uint iw0 = initw[0], iw1 = initw[1], iw2 = initw[2], iw3 = initw[3], iw4 = initw[4], iw5 = initw[5], iw6 = initw[6], iw7 = initw[7];
|
||||
#if IGNEUM_EXCHANGE == 0
|
||||
IGNEUM_LOCAL_WORDS(xch, 2 * IGNEUM_GROUP);
|
||||
uint xk = 0u;
|
||||
#else
|
||||
(void)lid;
|
||||
#endif
|
||||
{ uint x = nonce ^ iw0; x += 0x9e3779b9u * 1u; x = splitmix32(x); r0 = x ^ iw1; }
|
||||
{ uint x = nonce ^ iw1; x += 0x9e3779b9u * 2u; x = splitmix32(x); r1 = x ^ iw2; }
|
||||
{ uint x = nonce ^ iw2; x += 0x9e3779b9u * 3u; x = splitmix32(x); r2 = x ^ iw3; }
|
||||
{ uint x = nonce ^ iw3; x += 0x9e3779b9u * 4u; x = splitmix32(x); r3 = x ^ iw4; }
|
||||
{ uint x = nonce ^ iw4; x += 0x9e3779b9u * 5u; x = splitmix32(x); r4 = x ^ iw5; }
|
||||
{ uint x = nonce ^ iw5; x += 0x9e3779b9u * 6u; x = splitmix32(x); r5 = x ^ iw6; }
|
||||
{ uint x = nonce ^ iw6; x += 0x9e3779b9u * 7u; x = splitmix32(x); r6 = x ^ iw7; }
|
||||
{ uint x = nonce ^ iw7; x += 0x9e3779b9u * 8u; x = splitmix32(x); r7 = x ^ iw0; }
|
||||
|
||||
for (uint it = 0u; it < 8u; ++it) {
|
||||
uint sel = r0;
|
||||
r3 = rotl_imm(r3, 26u); // 0 rotl
|
||||
r2 = rotr_var(r2, r0); // 1 rotr
|
||||
r0 = r0 ^ r7; // 2 xor
|
||||
r4 = r4 ^ r7; // 3 xor
|
||||
r2 = r2 ^ ds[r4 & mask]; // 4 load
|
||||
{ uint b_ = (r2 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r3 = x_; } // 5 load
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r7, 4u); r0 = r0 ^ t_; } // 6 shfl
|
||||
r6 = rotl_imm(r6, 31u); // 7 rotl
|
||||
r1 = r4 * r2 + r1; // 8 mad
|
||||
r1 = r7 * r0 + r1; // 9 mad
|
||||
r4 = r4 ^ ds[r1 & mask]; // 10 load
|
||||
r6 = r7 * r0 + r6; // 11 mad
|
||||
r2 = r2 * r6; // 12 mul
|
||||
{ uint b_ = (r2 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r0 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r0 = x_; } // 13 load
|
||||
r2 = r2 + r7 + ((((sel >> 22u) & 1u) != 0u) ? 0x4a3db5a5u : 0x5df3957du); // 14 add
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r7, 1u); r5 = r5 ^ t_; } // 15 shfl
|
||||
r3 = r5 * r6 + r3; // 16 mad
|
||||
r2 = r2 * r5; // 17 mul
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r5, 1u); r1 = r1 ^ t_; } // 18 shfl
|
||||
r0 = r0 - r1; // 19 sub
|
||||
r4 = r6 * r4 + r4; // 20 mad
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r0, 16u); r3 = r3 ^ t_; } // 21 shfl
|
||||
r1 = rotl_imm(r1, 24u); // 22 rotl
|
||||
r1 = r1 + r0 + ((((sel >> 22u) & 1u) != 0u) ? 0xfc07c54cu : 0x5c141117u); // 23 add
|
||||
r2 = r2 ^ ds[r0 & mask]; // 24 load
|
||||
r0 = r0 ^ r1; // 25 xor
|
||||
r3 = r3 ^ r7; // 26 xor
|
||||
{ uint b_ = (r3 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r2 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r2 = x_; } // 27 load
|
||||
r0 = r0 ^ r6; // 28 xor
|
||||
r4 = r4 ^ r1; // 29 xor
|
||||
r6 = r6 * r3; // 30 mul
|
||||
r3 = rotl_imm(r3, 23u); // 31 rotl
|
||||
r7 = rotr_var(r7, r1); // 32 rotr
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r2, 2u); r6 = r6 ^ t_; } // 33 shfl
|
||||
{ uint b_ = (r0 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r5 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r5 = x_; } // 34 load
|
||||
r6 = r6 + r3 + ((((sel >> 29u) & 1u) != 0u) ? 0x0b74657bu : 0xfb55c58du); // 35 add
|
||||
{ uint b_ = (r5 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r6 = x_; } // 36 load
|
||||
r1 = r1 ^ ds[r4 & mask]; // 37 load
|
||||
{ uint b_ = (r3 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r6 = x_; } // 38 load
|
||||
r4 = r4 ^ ds[r7 & mask]; // 39 load
|
||||
r7 = mul_hi(r7, r3); // 40 mulhi
|
||||
r0 = r0 | r6; // 41 or
|
||||
r0 = r3 * r0 + r0; // 42 mad
|
||||
{ uint b_ = (r6 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r4 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r4 = x_; } // 43 load
|
||||
r2 = r4 * r0 + r2; // 44 mad
|
||||
r2 = r4 * r2 + r2; // 45 mad
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r5, 16u); r7 = r7 ^ t_; } // 46 shfl
|
||||
r6 = r1 * r4 + r6; // 47 mad
|
||||
r7 = r7 ^ ds[r1 & mask]; // 48 load
|
||||
r6 = mul_hi(r6, r5); // 49 mulhi
|
||||
r5 = mul_hi(r5, r0); // 50 mulhi
|
||||
{ uint b_ = (r6 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r1 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r1 = x_; } // 51 load
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r3, 1u); r7 = r7 ^ t_; } // 52 shfl
|
||||
r2 = r2 ^ r5; // 53 xor
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r6, 4u); r0 = r0 ^ t_; } // 54 shfl
|
||||
r2 = r2 * r5; // 55 mul
|
||||
r5 = r5 * r6; // 56 mul
|
||||
{ uint b_ = (r4 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r6 = x_; } // 57 load
|
||||
r4 = r7 * r7 + r4; // 58 mad
|
||||
r2 = r2 ^ ds[r1 & mask]; // 59 load
|
||||
r1 = r1 * r4; // 60 mul
|
||||
r3 = r3 * r4; // 61 mul
|
||||
r6 = r6 ^ r4; // 62 xor
|
||||
r3 = rotr_var(r3, r1); // 63 rotr
|
||||
}
|
||||
uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u);
|
||||
uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u);
|
||||
out[gid] = ((ulong)hi << 32) | (ulong)lo;
|
||||
}
|
||||
123
proto-cuda/packs-readwidth/mixA-4/kernel_bound.cu
Normal file
123
proto-cuda/packs-readwidth/mixA-4/kernel_bound.cu
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
// Generated by igneum-pow export (generator v2) for seed "igneum-readwidth/A/5". Do not edit by hand.
|
||||
// Header-bound twin of igneum_hash in kernel.cu: the init words come from a kernel argument, not SEEDW.
|
||||
// Host declarations (also in program_bound.h if present):
|
||||
// struct IgneumInitWords { uint32_t w[8]; };
|
||||
// cudaError_t igneum_launch_hash_bound(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask,
|
||||
// IgneumInitWords iw, uint32_t nonces, uint32_t blockWarps);
|
||||
// cudaError_t igneum_hash_bound_info(int* numRegs, int* blocksPerSM, uint32_t blockWarps);
|
||||
#include <cuda_runtime.h>
|
||||
#include <cstdint>
|
||||
#include "program.h"
|
||||
|
||||
struct IgneumInitWords { uint32_t w[8]; };
|
||||
|
||||
__device__ __forceinline__ uint32_t splitmix32(uint32_t x) {
|
||||
x ^= x >> 16; x *= 0x7feb352du;
|
||||
x ^= x >> 15; x *= 0x846ca68bu;
|
||||
x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
__device__ __forceinline__ uint32_t rotl_imm(uint32_t x, uint32_t n) { return (x << n) | (x >> (32u - n)); }
|
||||
__device__ __forceinline__ uint32_t rotr_var(uint32_t x, uint32_t n) { n &= 31u; return (x >> n) | (x << ((32u - n) & 31u)); }
|
||||
|
||||
__global__ void igneum_hash_bound(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask, IgneumInitWords iw) {
|
||||
uint32_t gid = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
uint32_t nonce = baseNonce + gid;
|
||||
uint32_t r0, r1, r2, r3, r4, r5, r6, r7;
|
||||
{ uint32_t x = nonce ^ iw.w[0]; x += 0x9e3779b9u * 1u; x = splitmix32(x); r0 = x ^ iw.w[1]; }
|
||||
{ uint32_t x = nonce ^ iw.w[1]; x += 0x9e3779b9u * 2u; x = splitmix32(x); r1 = x ^ iw.w[2]; }
|
||||
{ uint32_t x = nonce ^ iw.w[2]; x += 0x9e3779b9u * 3u; x = splitmix32(x); r2 = x ^ iw.w[3]; }
|
||||
{ uint32_t x = nonce ^ iw.w[3]; x += 0x9e3779b9u * 4u; x = splitmix32(x); r3 = x ^ iw.w[4]; }
|
||||
{ uint32_t x = nonce ^ iw.w[4]; x += 0x9e3779b9u * 5u; x = splitmix32(x); r4 = x ^ iw.w[5]; }
|
||||
{ uint32_t x = nonce ^ iw.w[5]; x += 0x9e3779b9u * 6u; x = splitmix32(x); r5 = x ^ iw.w[6]; }
|
||||
{ uint32_t x = nonce ^ iw.w[6]; x += 0x9e3779b9u * 7u; x = splitmix32(x); r6 = x ^ iw.w[7]; }
|
||||
{ uint32_t x = nonce ^ iw.w[7]; x += 0x9e3779b9u * 8u; x = splitmix32(x); r7 = x ^ iw.w[0]; }
|
||||
|
||||
for (uint32_t it = 0u; it < 8u; ++it) {
|
||||
uint32_t sel = r0;
|
||||
r3 = rotl_imm(r3, 26u); // 0 rotl
|
||||
r2 = rotr_var(r2, r0); // 1 rotr
|
||||
r0 = r0 ^ r7; // 2 xor
|
||||
r4 = r4 ^ r7; // 3 xor
|
||||
r2 = r2 ^ ds[r4 & mask]; // 4 load
|
||||
{ uint32_t b_ = (r2 & mask) & ~3u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint32_t x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r3 = x_; } // 5 load
|
||||
r0 = r0 ^ __shfl_xor_sync(0xffffffffu, r7, 4); // 6 shfl
|
||||
r6 = rotl_imm(r6, 31u); // 7 rotl
|
||||
r1 = r4 * r2 + r1; // 8 mad
|
||||
r1 = r7 * r0 + r1; // 9 mad
|
||||
r4 = r4 ^ ds[r1 & mask]; // 10 load
|
||||
r6 = r7 * r0 + r6; // 11 mad
|
||||
r2 = r2 * r6; // 12 mul
|
||||
{ uint32_t b_ = (r2 & mask) & ~3u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint32_t x_ = r0 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r0 = x_; } // 13 load
|
||||
r2 = r2 + r7 + ((((sel >> 22u) & 1u) != 0u) ? 0x4a3db5a5u : 0x5df3957du); // 14 add
|
||||
r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r7, 1); // 15 shfl
|
||||
r3 = r5 * r6 + r3; // 16 mad
|
||||
r2 = r2 * r5; // 17 mul
|
||||
r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r5, 1); // 18 shfl
|
||||
r0 = r0 - r1; // 19 sub
|
||||
r4 = r6 * r4 + r4; // 20 mad
|
||||
r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r0, 16); // 21 shfl
|
||||
r1 = rotl_imm(r1, 24u); // 22 rotl
|
||||
r1 = r1 + r0 + ((((sel >> 22u) & 1u) != 0u) ? 0xfc07c54cu : 0x5c141117u); // 23 add
|
||||
r2 = r2 ^ ds[r0 & mask]; // 24 load
|
||||
r0 = r0 ^ r1; // 25 xor
|
||||
r3 = r3 ^ r7; // 26 xor
|
||||
{ uint32_t b_ = (r3 & mask) & ~3u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint32_t x_ = r2 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r2 = x_; } // 27 load
|
||||
r0 = r0 ^ r6; // 28 xor
|
||||
r4 = r4 ^ r1; // 29 xor
|
||||
r6 = r6 * r3; // 30 mul
|
||||
r3 = rotl_imm(r3, 23u); // 31 rotl
|
||||
r7 = rotr_var(r7, r1); // 32 rotr
|
||||
r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r2, 2); // 33 shfl
|
||||
{ uint32_t b_ = (r0 & mask) & ~15u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint32_t x_ = r5 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r5 = x_; } // 34 load
|
||||
r6 = r6 + r3 + ((((sel >> 29u) & 1u) != 0u) ? 0x0b74657bu : 0xfb55c58du); // 35 add
|
||||
{ uint32_t b_ = (r5 & mask) & ~15u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint32_t x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r6 = x_; } // 36 load
|
||||
r1 = r1 ^ ds[r4 & mask]; // 37 load
|
||||
{ uint32_t b_ = (r3 & mask) & ~3u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint32_t x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r6 = x_; } // 38 load
|
||||
r4 = r4 ^ ds[r7 & mask]; // 39 load
|
||||
r7 = __umulhi(r7, r3); // 40 mulhi
|
||||
r0 = r0 | r6; // 41 or
|
||||
r0 = r3 * r0 + r0; // 42 mad
|
||||
{ uint32_t b_ = (r6 & mask) & ~15u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint32_t x_ = r4 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r4 = x_; } // 43 load
|
||||
r2 = r4 * r0 + r2; // 44 mad
|
||||
r2 = r4 * r2 + r2; // 45 mad
|
||||
r7 = r7 ^ __shfl_xor_sync(0xffffffffu, r5, 16); // 46 shfl
|
||||
r6 = r1 * r4 + r6; // 47 mad
|
||||
r7 = r7 ^ ds[r1 & mask]; // 48 load
|
||||
r6 = __umulhi(r6, r5); // 49 mulhi
|
||||
r5 = __umulhi(r5, r0); // 50 mulhi
|
||||
{ uint32_t b_ = (r6 & mask) & ~3u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint32_t x_ = r1 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r1 = x_; } // 51 load
|
||||
r7 = r7 ^ __shfl_xor_sync(0xffffffffu, r3, 1); // 52 shfl
|
||||
r2 = r2 ^ r5; // 53 xor
|
||||
r0 = r0 ^ __shfl_xor_sync(0xffffffffu, r6, 4); // 54 shfl
|
||||
r2 = r2 * r5; // 55 mul
|
||||
r5 = r5 * r6; // 56 mul
|
||||
{ uint32_t b_ = (r4 & mask) & ~3u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint32_t x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r6 = x_; } // 57 load
|
||||
r4 = r7 * r7 + r4; // 58 mad
|
||||
r2 = r2 ^ ds[r1 & mask]; // 59 load
|
||||
r1 = r1 * r4; // 60 mul
|
||||
r3 = r3 * r4; // 61 mul
|
||||
r6 = r6 ^ r4; // 62 xor
|
||||
r3 = rotr_var(r3, r1); // 63 rotr
|
||||
}
|
||||
uint32_t lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u);
|
||||
uint32_t hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u);
|
||||
out[gid] = ((uint64_t)hi << 32) | (uint64_t)lo;
|
||||
}
|
||||
|
||||
cudaError_t igneum_launch_hash_bound(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask,
|
||||
IgneumInitWords iw, uint32_t nonces, uint32_t blockWarps) {
|
||||
if (blockWarps == 0u || blockWarps > 32u) return cudaErrorInvalidValue;
|
||||
uint32_t block = 32u * blockWarps;
|
||||
if (nonces == 0u || (nonces % block) != 0u) return cudaErrorInvalidValue;
|
||||
igneum_hash_bound<<<nonces / block, block>>>(ds, out, baseNonce, mask, iw);
|
||||
return cudaGetLastError();
|
||||
}
|
||||
|
||||
cudaError_t igneum_hash_bound_info(int* numRegs, int* blocksPerSM, uint32_t blockWarps) {
|
||||
cudaFuncAttributes attr;
|
||||
cudaError_t e = cudaFuncGetAttributes(&attr, igneum_hash_bound);
|
||||
if (e != cudaSuccess) return e;
|
||||
*numRegs = attr.numRegs;
|
||||
return cudaOccupancyMaxActiveBlocksPerMultiprocessor(blocksPerSM, igneum_hash_bound, (int)(32u * blockWarps), 0);
|
||||
}
|
||||
108
proto-cuda/packs-readwidth/mixA-4/memhard.h
Normal file
108
proto-cuda/packs-readwidth/mixA-4/memhard.h
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
// Generated by igneum-pow export (generator v2) for seed "igneum-readwidth/A/5". Do not edit by hand.
|
||||
// Memory-hard dataset core, the same text that the Mac's Metal kernels and CPU verifier were checked against.
|
||||
// Included by kernel.cu (device), host.cu (host reference) and proto-opencl/host.c (C99 host reference).
|
||||
// See proto-metal/MEMHARD.md for the construction. kernel.cl carries the same text in OpenCL C.
|
||||
#pragma once
|
||||
#ifdef __cplusplus
|
||||
#include <cstdint>
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
#if defined(__CUDACC__)
|
||||
#define IGNEUM_HD __host__ __device__ __forceinline__
|
||||
#elif defined(_MSC_VER) && !defined(__cplusplus)
|
||||
#define IGNEUM_HD static __inline
|
||||
#else
|
||||
#define IGNEUM_HD static inline
|
||||
#endif
|
||||
// Memory-hard dataset core (MEMHARD.md). Cache: 2^26 words in 2^16 segments of 64 chained ChaCha12 lines.
|
||||
// Item: 8 rounds of seed-parameterised mixer + one 64-byte cache read, then a final mixer. All parameters are literals.
|
||||
#define MH_CACHE_LINE_MASK 0x003fffffu
|
||||
#define MH_SEGMENT_LINES 64u
|
||||
#define MH_QR(a, b, c, d, r1, r2, r3, r4) { a += b; d ^= a; d = mh_rotl(d, r1); c += d; b ^= c; b = mh_rotl(b, r2); a += b; d ^= a; d = mh_rotl(d, r3); c += d; b ^= c; b = mh_rotl(b, r4); }
|
||||
IGNEUM_HD uint32_t mh_rotl(uint32_t x, uint32_t n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 at every call site
|
||||
|
||||
// y = ChaCha12 core(x) + x
|
||||
IGNEUM_HD void mh_chacha_block(const uint32_t* x, uint32_t* y) {
|
||||
for (uint32_t i = 0u; i < 16u; ++i) y[i] = x[i];
|
||||
for (uint32_t r = 0u; r < 6u; ++r) {
|
||||
MH_QR(y[0], y[4], y[8], y[12], 16u, 12u, 8u, 7u) MH_QR(y[1], y[5], y[9], y[13], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[2], y[6], y[10], y[14], 16u, 12u, 8u, 7u) MH_QR(y[3], y[7], y[11], y[15], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[0], y[5], y[10], y[15], 16u, 12u, 8u, 7u) MH_QR(y[1], y[6], y[11], y[12], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[2], y[7], y[8], y[13], 16u, 12u, 8u, 7u) MH_QR(y[3], y[4], y[9], y[14], 16u, 12u, 8u, 7u)
|
||||
}
|
||||
for (uint32_t i = 0u; i < 16u; ++i) y[i] += x[i];
|
||||
}
|
||||
|
||||
// One cache segment: 64 chained lines written at cache[seg * 1024]. in_j = prev ^ (sigma || K || seg || j || tag), prev_0 = 0.
|
||||
IGNEUM_HD void mh_cache_segment(uint32_t* cache, uint32_t seg) {
|
||||
uint32_t prev[16]; uint32_t x[16]; uint32_t y[16];
|
||||
for (uint32_t i = 0u; i < 16u; ++i) prev[i] = 0u;
|
||||
for (uint32_t j = 0u; j < MH_SEGMENT_LINES; ++j) {
|
||||
x[0] = 0x61707865u ^ prev[0]; x[1] = 0x3320646eu ^ prev[1]; x[2] = 0x79622d32u ^ prev[2]; x[3] = 0x6b206574u ^ prev[3];
|
||||
x[4] = 0x3067619fu ^ prev[4];
|
||||
x[5] = 0x3c269176u ^ prev[5];
|
||||
x[6] = 0x84a03b03u ^ prev[6];
|
||||
x[7] = 0xf8c63294u ^ prev[7];
|
||||
x[8] = 0xff977c5bu ^ prev[8];
|
||||
x[9] = 0xe60def3eu ^ prev[9];
|
||||
x[10] = 0x63630141u ^ prev[10];
|
||||
x[11] = 0xb8fbcb58u ^ prev[11];
|
||||
x[12] = seg ^ prev[12]; x[13] = j ^ prev[13]; x[14] = 0x49676e65u ^ prev[14]; x[15] = 0x756d4d48u ^ prev[15];
|
||||
mh_chacha_block(x, y);
|
||||
uint32_t* line = cache + ((seg * MH_SEGMENT_LINES + j) * 16u);
|
||||
for (uint32_t i = 0u; i < 16u; ++i) { line[i] = y[i]; prev[i] = y[i]; }
|
||||
}
|
||||
}
|
||||
|
||||
// M_r: per word (s ^ (RC + rk)) * MUL, then a column round and a diagonal round with the seed-drawn rotations.
|
||||
IGNEUM_HD void mh_mixer(uint32_t* s, uint32_t rk) {
|
||||
s[0] = (s[0] ^ (0xbab68293u + rk)) * 0x42146205u;
|
||||
s[1] = (s[1] ^ (0xcc162340u + rk)) * 0x52cbe0fbu;
|
||||
s[2] = (s[2] ^ (0x6ce151ccu + rk)) * 0x7ecf4a03u;
|
||||
s[3] = (s[3] ^ (0xe62b8997u + rk)) * 0x6728907fu;
|
||||
s[4] = (s[4] ^ (0xc9c80297u + rk)) * 0xd81d9751u;
|
||||
s[5] = (s[5] ^ (0xf74a1654u + rk)) * 0x132952c3u;
|
||||
s[6] = (s[6] ^ (0x3d704af5u + rk)) * 0xf60de277u;
|
||||
s[7] = (s[7] ^ (0x3cf522b7u + rk)) * 0x05358035u;
|
||||
s[8] = (s[8] ^ (0x2b9cac04u + rk)) * 0xbaf6499du;
|
||||
s[9] = (s[9] ^ (0xa880ac10u + rk)) * 0xe4db9667u;
|
||||
s[10] = (s[10] ^ (0x13e5dd1du + rk)) * 0x3e98f45du;
|
||||
s[11] = (s[11] ^ (0x6fc3e233u + rk)) * 0xd0004eddu;
|
||||
s[12] = (s[12] ^ (0x2d83eeacu + rk)) * 0x2691630du;
|
||||
s[13] = (s[13] ^ (0x9006e8bfu + rk)) * 0x9beb3bcfu;
|
||||
s[14] = (s[14] ^ (0x2c4b5362u + rk)) * 0xab310379u;
|
||||
s[15] = (s[15] ^ (0x31b49ee2u + rk)) * 0x99cfb423u;
|
||||
MH_QR(s[0], s[4], s[8], s[12], 20u, 20u, 19u, 4u) MH_QR(s[1], s[5], s[9], s[13], 20u, 20u, 19u, 4u)
|
||||
MH_QR(s[2], s[6], s[10], s[14], 20u, 20u, 19u, 4u) MH_QR(s[3], s[7], s[11], s[15], 20u, 20u, 19u, 4u)
|
||||
MH_QR(s[0], s[5], s[10], s[15], 26u, 3u, 3u, 27u) MH_QR(s[1], s[6], s[11], s[12], 26u, 3u, 3u, 27u)
|
||||
MH_QR(s[2], s[7], s[8], s[13], 26u, 3u, 3u, 27u) MH_QR(s[3], s[4], s[9], s[14], 26u, 3u, 3u, 27u)
|
||||
}
|
||||
|
||||
// Item t: 16 words. s = (K, t * MUL[i] + RC[i]); 8 rounds of mixer + cache line s[0] & mask; final mixer.
|
||||
IGNEUM_HD void mh_item(const uint32_t* cache, uint32_t t, uint32_t* s) {
|
||||
s[0] = 0x3067619fu;
|
||||
s[1] = 0x3c269176u;
|
||||
s[2] = 0x84a03b03u;
|
||||
s[3] = 0xf8c63294u;
|
||||
s[4] = 0xff977c5bu;
|
||||
s[5] = 0xe60def3eu;
|
||||
s[6] = 0x63630141u;
|
||||
s[7] = 0xb8fbcb58u;
|
||||
s[8] = t * 0x42146205u + 0xbab68293u;
|
||||
s[9] = t * 0x52cbe0fbu + 0xcc162340u;
|
||||
s[10] = t * 0x7ecf4a03u + 0x6ce151ccu;
|
||||
s[11] = t * 0x6728907fu + 0xe62b8997u;
|
||||
s[12] = t * 0xd81d9751u + 0xc9c80297u;
|
||||
s[13] = t * 0x132952c3u + 0xf74a1654u;
|
||||
s[14] = t * 0xf60de277u + 0x3d704af5u;
|
||||
s[15] = t * 0x05358035u + 0x3cf522b7u;
|
||||
for (uint32_t r = 0u; r < 8u; ++r) {
|
||||
mh_mixer(s, 0x9E3779B9u * (r + 1u));
|
||||
const uint32_t* line = cache + ((s[0] & MH_CACHE_LINE_MASK) * 16u);
|
||||
for (uint32_t i = 0u; i < 16u; ++i) s[i] ^= line[i];
|
||||
}
|
||||
mh_mixer(s, 0x9E3779B9u * 9u);
|
||||
}
|
||||
// dataset[w] without the dataset: derive item w >> 4 and take word w & 15.
|
||||
IGNEUM_HD uint32_t mh_word(const uint32_t* cache, uint32_t w) { uint32_t s[16]; mh_item(cache, w >> 4u, s); return s[w & 15u]; }
|
||||
106
proto-cuda/packs-readwidth/mixA-4/memhard.metal
Normal file
106
proto-cuda/packs-readwidth/mixA-4/memhard.metal
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
#include <metal_stdlib>
|
||||
using namespace metal;
|
||||
// Memory-hard dataset core (MEMHARD.md). Cache: 2^26 words in 2^16 segments of 64 chained ChaCha12 lines.
|
||||
// Item: 8 rounds of seed-parameterised mixer + one 64-byte cache read, then a final mixer. All parameters are literals.
|
||||
#define MH_CACHE_LINE_MASK 0x003fffffu
|
||||
#define MH_SEGMENT_LINES 64u
|
||||
#define MH_QR(a, b, c, d, r1, r2, r3, r4) { a += b; d ^= a; d = mh_rotl(d, r1); c += d; b ^= c; b = mh_rotl(b, r2); a += b; d ^= a; d = mh_rotl(d, r3); c += d; b ^= c; b = mh_rotl(b, r4); }
|
||||
inline uint mh_rotl(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 at every call site
|
||||
|
||||
// y = ChaCha12 core(x) + x
|
||||
inline void mh_chacha_block(const thread uint* x, thread uint* y) {
|
||||
for (uint i = 0u; i < 16u; ++i) y[i] = x[i];
|
||||
for (uint r = 0u; r < 6u; ++r) {
|
||||
MH_QR(y[0], y[4], y[8], y[12], 16u, 12u, 8u, 7u) MH_QR(y[1], y[5], y[9], y[13], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[2], y[6], y[10], y[14], 16u, 12u, 8u, 7u) MH_QR(y[3], y[7], y[11], y[15], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[0], y[5], y[10], y[15], 16u, 12u, 8u, 7u) MH_QR(y[1], y[6], y[11], y[12], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[2], y[7], y[8], y[13], 16u, 12u, 8u, 7u) MH_QR(y[3], y[4], y[9], y[14], 16u, 12u, 8u, 7u)
|
||||
}
|
||||
for (uint i = 0u; i < 16u; ++i) y[i] += x[i];
|
||||
}
|
||||
|
||||
// One cache segment: 64 chained lines written at cache[seg * 1024]. in_j = prev ^ (sigma || K || seg || j || tag), prev_0 = 0.
|
||||
inline void mh_cache_segment(device uint* cache, uint seg) {
|
||||
uint prev[16]; uint x[16]; uint y[16];
|
||||
for (uint i = 0u; i < 16u; ++i) prev[i] = 0u;
|
||||
for (uint j = 0u; j < MH_SEGMENT_LINES; ++j) {
|
||||
x[0] = 0x61707865u ^ prev[0]; x[1] = 0x3320646eu ^ prev[1]; x[2] = 0x79622d32u ^ prev[2]; x[3] = 0x6b206574u ^ prev[3];
|
||||
x[4] = 0x3067619fu ^ prev[4];
|
||||
x[5] = 0x3c269176u ^ prev[5];
|
||||
x[6] = 0x84a03b03u ^ prev[6];
|
||||
x[7] = 0xf8c63294u ^ prev[7];
|
||||
x[8] = 0xff977c5bu ^ prev[8];
|
||||
x[9] = 0xe60def3eu ^ prev[9];
|
||||
x[10] = 0x63630141u ^ prev[10];
|
||||
x[11] = 0xb8fbcb58u ^ prev[11];
|
||||
x[12] = seg ^ prev[12]; x[13] = j ^ prev[13]; x[14] = 0x49676e65u ^ prev[14]; x[15] = 0x756d4d48u ^ prev[15];
|
||||
mh_chacha_block(x, y);
|
||||
device uint* line = cache + ((seg * MH_SEGMENT_LINES + j) * 16u);
|
||||
for (uint i = 0u; i < 16u; ++i) { line[i] = y[i]; prev[i] = y[i]; }
|
||||
}
|
||||
}
|
||||
|
||||
// M_r: per word (s ^ (RC + rk)) * MUL, then a column round and a diagonal round with the seed-drawn rotations.
|
||||
inline void mh_mixer(thread uint* s, uint rk) {
|
||||
s[0] = (s[0] ^ (0xbab68293u + rk)) * 0x42146205u;
|
||||
s[1] = (s[1] ^ (0xcc162340u + rk)) * 0x52cbe0fbu;
|
||||
s[2] = (s[2] ^ (0x6ce151ccu + rk)) * 0x7ecf4a03u;
|
||||
s[3] = (s[3] ^ (0xe62b8997u + rk)) * 0x6728907fu;
|
||||
s[4] = (s[4] ^ (0xc9c80297u + rk)) * 0xd81d9751u;
|
||||
s[5] = (s[5] ^ (0xf74a1654u + rk)) * 0x132952c3u;
|
||||
s[6] = (s[6] ^ (0x3d704af5u + rk)) * 0xf60de277u;
|
||||
s[7] = (s[7] ^ (0x3cf522b7u + rk)) * 0x05358035u;
|
||||
s[8] = (s[8] ^ (0x2b9cac04u + rk)) * 0xbaf6499du;
|
||||
s[9] = (s[9] ^ (0xa880ac10u + rk)) * 0xe4db9667u;
|
||||
s[10] = (s[10] ^ (0x13e5dd1du + rk)) * 0x3e98f45du;
|
||||
s[11] = (s[11] ^ (0x6fc3e233u + rk)) * 0xd0004eddu;
|
||||
s[12] = (s[12] ^ (0x2d83eeacu + rk)) * 0x2691630du;
|
||||
s[13] = (s[13] ^ (0x9006e8bfu + rk)) * 0x9beb3bcfu;
|
||||
s[14] = (s[14] ^ (0x2c4b5362u + rk)) * 0xab310379u;
|
||||
s[15] = (s[15] ^ (0x31b49ee2u + rk)) * 0x99cfb423u;
|
||||
MH_QR(s[0], s[4], s[8], s[12], 20u, 20u, 19u, 4u) MH_QR(s[1], s[5], s[9], s[13], 20u, 20u, 19u, 4u)
|
||||
MH_QR(s[2], s[6], s[10], s[14], 20u, 20u, 19u, 4u) MH_QR(s[3], s[7], s[11], s[15], 20u, 20u, 19u, 4u)
|
||||
MH_QR(s[0], s[5], s[10], s[15], 26u, 3u, 3u, 27u) MH_QR(s[1], s[6], s[11], s[12], 26u, 3u, 3u, 27u)
|
||||
MH_QR(s[2], s[7], s[8], s[13], 26u, 3u, 3u, 27u) MH_QR(s[3], s[4], s[9], s[14], 26u, 3u, 3u, 27u)
|
||||
}
|
||||
|
||||
// Item t: 16 words. s = (K, t * MUL[i] + RC[i]); 8 rounds of mixer + cache line s[0] & mask; final mixer.
|
||||
inline void mh_item(device const uint* cache, uint t, thread uint* s) {
|
||||
s[0] = 0x3067619fu;
|
||||
s[1] = 0x3c269176u;
|
||||
s[2] = 0x84a03b03u;
|
||||
s[3] = 0xf8c63294u;
|
||||
s[4] = 0xff977c5bu;
|
||||
s[5] = 0xe60def3eu;
|
||||
s[6] = 0x63630141u;
|
||||
s[7] = 0xb8fbcb58u;
|
||||
s[8] = t * 0x42146205u + 0xbab68293u;
|
||||
s[9] = t * 0x52cbe0fbu + 0xcc162340u;
|
||||
s[10] = t * 0x7ecf4a03u + 0x6ce151ccu;
|
||||
s[11] = t * 0x6728907fu + 0xe62b8997u;
|
||||
s[12] = t * 0xd81d9751u + 0xc9c80297u;
|
||||
s[13] = t * 0x132952c3u + 0xf74a1654u;
|
||||
s[14] = t * 0xf60de277u + 0x3d704af5u;
|
||||
s[15] = t * 0x05358035u + 0x3cf522b7u;
|
||||
for (uint r = 0u; r < 8u; ++r) {
|
||||
mh_mixer(s, 0x9E3779B9u * (r + 1u));
|
||||
device const uint* line = cache + ((s[0] & MH_CACHE_LINE_MASK) * 16u);
|
||||
for (uint i = 0u; i < 16u; ++i) s[i] ^= line[i];
|
||||
}
|
||||
mh_mixer(s, 0x9E3779B9u * 9u);
|
||||
}
|
||||
// dataset[w] without the dataset: derive item w >> 4 and take word w & 15.
|
||||
inline uint mh_word(device const uint* cache, uint w) { uint s[16]; mh_item(cache, w >> 4u, s); return s[w & 15u]; }
|
||||
|
||||
// One thread per segment (2^16 threads).
|
||||
kernel void igneum_cache_fill(device uint* cache [[buffer(0)]], uint gid [[thread_position_in_grid]]) {
|
||||
mh_cache_segment(cache, gid);
|
||||
}
|
||||
// One thread per 64-byte item (dataset words / 16 threads).
|
||||
kernel void igneum_build(device const uint* cache [[buffer(0)]], device uint* dataset [[buffer(1)]],
|
||||
uint gid [[thread_position_in_grid]]) {
|
||||
uint s[16];
|
||||
mh_item(cache, gid, s);
|
||||
device uint* d = dataset + gid * 16u;
|
||||
for (uint i = 0u; i < 16u; ++i) d[i] = s[i];
|
||||
}
|
||||
60
proto-cuda/packs-readwidth/mixA-4/program.h
Normal file
60
proto-cuda/packs-readwidth/mixA-4/program.h
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
// Generated by igneum-pow export (generator v2) for seed "igneum-readwidth/A/5". Do not edit by hand.
|
||||
// Program metadata for host.cu plus the launch wrappers defined in kernel.cu.
|
||||
// Also included by proto-opencl/host.c (C99), which defines IGNEUM_NO_CUDA first and reads only the macros.
|
||||
#pragma once
|
||||
#ifdef __cplusplus
|
||||
#include <cstdint>
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
#ifndef IGNEUM_NO_CUDA
|
||||
#include <cuda_runtime.h>
|
||||
#endif
|
||||
|
||||
#define IGNEUM_SEED_STRING "igneum-readwidth/A/5"
|
||||
#define IGNEUM_SEED_BYTES_HEX "69676e65756d2d7265616477696474682f412f35"
|
||||
#define IGNEUM_GENERATOR 2
|
||||
#define IGNEUM_PROGRAM_ATTEMPT 0
|
||||
#define IGNEUM_PROGRAM_ID 0x8c7f626ae00b8a7cull
|
||||
#define IGNEUM_DAY_STRING "2026-10-03"
|
||||
#define IGNEUM_DAY_BYTES_HEX "6461792f323032362d31302d3033"
|
||||
#define IGNEUM_DAY0 0x3067619fu
|
||||
#define IGNEUM_DAY1 0x3c269176u
|
||||
#define IGNEUM_DATASET_LOG2 28
|
||||
#define IGNEUM_MASK 0x0fffffffu
|
||||
#define IGNEUM_LANES 32
|
||||
#define IGNEUM_ITERATIONS 8
|
||||
#define IGNEUM_INSTR_COUNT 64
|
||||
#define IGNEUM_LOADS_PER_HASH 128
|
||||
#define IGNEUM_WIDE_LOADS_PER_HASH 0
|
||||
#define IGNEUM_OP_MIX "load=16 mad=10 shfl=8 xor=8 mul=7 rotl=4 add=3 mulhi=3 rotr=3 or=1 sub=1"
|
||||
// Read-width experiment (5 October 2026, docs/plans/read-width.md): NOT the lottery hash. A load of W words reads
|
||||
// the W-word-aligned address and folds every word into dst: x = dst ^ w[0]; x = (rotl(x, 11) * 0x9e3779b1) ^ w[j]; dst = x.
|
||||
#define IGNEUM_LOAD_CLASS "mix50-35-15"
|
||||
#define IGNEUM_LOAD_SLOTS 16
|
||||
#define IGNEUM_LOAD_MIX { 50, 35, 15 }
|
||||
#define IGNEUM_LOAD_WIDTH_COUNTS { 7, 6, 3 } // loads of 4, 16, 64 bytes per program
|
||||
#define IGNEUM_BYTES_PER_HASH 2528
|
||||
#define IGNEUM_FOLD_ROT 11
|
||||
#define IGNEUM_FOLD_MUL 0x9e3779b1u
|
||||
// 0 = closed-form dataset (ds_elem), 1 = memory-hard cache construction (MEMHARD.md, memhard.h)
|
||||
#define IGNEUM_DATASET_MODE 1
|
||||
|
||||
#define IGNEUM_SEEDW_INIT { 0xc255b2bfu, 0xdba9d396u, 0x6ea527e4u, 0x05f1866au, 0x2947e02eu, 0x0ecc5c6fu, 0xc3b7068du, 0x282d1c2eu }
|
||||
#define IGNEUM_KEY_INIT { 0x3067619fu, 0x3c269176u, 0x84a03b03u, 0xf8c63294u, 0xff977c5bu, 0xe60def3eu, 0x63630141u, 0xb8fbcb58u }
|
||||
#define IGNEUM_CACHE_LOG2_WORDS 26
|
||||
#define IGNEUM_CACHE_SEGMENT_LOG2_LINES 6
|
||||
#define IGNEUM_CACHE_SEGMENTS 65536u
|
||||
#define IGNEUM_ITEM_ROUNDS 8
|
||||
#define IGNEUM_MIX_ROT_INIT { 20u, 20u, 19u, 4u, 26u, 3u, 3u, 27u }
|
||||
#define IGNEUM_MIX_MUL_INIT { 0x42146205u, 0x52cbe0fbu, 0x7ecf4a03u, 0x6728907fu, 0xd81d9751u, 0x132952c3u, 0xf60de277u, 0x05358035u, 0xbaf6499du, 0xe4db9667u, 0x3e98f45du, 0xd0004eddu, 0x2691630du, 0x9beb3bcfu, 0xab310379u, 0x99cfb423u }
|
||||
#define IGNEUM_MIX_RC_INIT { 0xbab68293u, 0xcc162340u, 0x6ce151ccu, 0xe62b8997u, 0xc9c80297u, 0xf74a1654u, 0x3d704af5u, 0x3cf522b7u, 0x2b9cac04u, 0xa880ac10u, 0x13e5dd1du, 0x6fc3e233u, 0x2d83eeacu, 0x9006e8bfu, 0x2c4b5362u, 0x31b49ee2u }
|
||||
|
||||
#ifndef IGNEUM_NO_CUDA
|
||||
// Defined in kernel.cu. All launch on the default stream and return cudaGetLastError().
|
||||
cudaError_t igneum_launch_cache_fill(uint32_t* cache, uint32_t nSegments);
|
||||
cudaError_t igneum_launch_build(uint32_t* ds, const uint32_t* cache, uint32_t nItems);
|
||||
cudaError_t igneum_launch_hash(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask,
|
||||
uint32_t nonces, uint32_t blockWarps);
|
||||
cudaError_t igneum_hash_info(int* numRegs, int* blocksPerSM, uint32_t blockWarps);
|
||||
#endif
|
||||
127
proto-cuda/packs-readwidth/mixA-4/program.json
Normal file
127
proto-cuda/packs-readwidth/mixA-4/program.json
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
{
|
||||
"format": "igneum-program-pack-3",
|
||||
"generator": 2,
|
||||
"attempt": 0,
|
||||
"program_id": "0x8c7f626ae00b8a7c",
|
||||
"program_id_derivation": "FNV-1a 64 over 'igneum-program/' || generator_le32 || seed_words as little-endian bytes || attempt_le32",
|
||||
"dataset_mode": "memory-hard",
|
||||
"seed": "igneum-readwidth/A/5",
|
||||
"seed_bytes": "69676e65756d2d7265616477696474682f412f35",
|
||||
"seed_words": ["0xc255b2bf", "0xdba9d396", "0x6ea527e4", "0x05f1866a", "0x2947e02e", "0x0ecc5c6f", "0xc3b7068d", "0x282d1c2e"],
|
||||
"seed_derivation": "seed_words = FNV-1a 64 over seed_bytes (attempt 0) or seed_bytes || attempt_le32 (attempt k >= 1), basis ^ (salt * 0x9E3779B97F4A7C15) for salt 0..3, then h ^= h>>33; h *= 0xff51afd7ed558ccd; h ^= h>>33; words[2*salt] = low 32, words[2*salt+1] = high 32",
|
||||
"generator_rule": "version 2: exactly 16 load slots drawn first from instructions 1..63 (partial Fisher-Yates), the other 48 ops from the ten non-load weights (sum 75); a load's source is drawn from the registers other than dst written by an earlier instruction and not read by a load since; the candidate must pass the acceptance rule of spec 01 section 1.4.6 (static: no cyclically stale load source, every register has an injecting write; dynamic: 64 units on the seed-keyed closed-form dataset with no constant register bit, no lane-constant load site, under 164 saturated final values, every output bit within 136 of 1024, distinct addresses above 245760), else the next attempt of the seed is tried",
|
||||
"lanes": 32,
|
||||
"registers": 8,
|
||||
"iterations": 8,
|
||||
"instruction_count": 64,
|
||||
"loads_per_hash": 128,
|
||||
"load_class": "mix50-35-15",
|
||||
"load_slots": 16,
|
||||
"load_mix_percent_4_16_64": [50, 35, 15],
|
||||
"load_width_counts_4_16_64": [7, 6, 3],
|
||||
"bytes_per_hash": 2528,
|
||||
"wide_load": "read-width experiment (5 October 2026, docs/plans/read-width.md), NOT the lottery hash: a load of W words (width field, 4 or 16) reads dataset[b .. b + W) with b = (src & mask) & ~(W - 1) and folds every word into dst: x = dst ^ w[0]; for j in 1..W: x = (rotl(x, 11) * 0x9e3779b1) ^ w[j]; dst = x; width 1 is the plain load; the width is drawn per instruction from the class mix with one extra below(100) draw after the nine of version 2, and the program id is FNV-1a 64 over 'igneum-program-rw/' || generator_le32 || seed words || attempt_le32 || mix[3] || load_slots",
|
||||
"op_mix": {"load": 16, "mad": 10, "shfl": 8, "xor": 8, "mul": 7, "rotl": 4, "add": 3, "mulhi": 3, "rotr": 3, "or": 1, "sub": 1},
|
||||
"register_init": "for i in 0..7: x = nonce ^ seed_words[i]; x += 0x9e3779b9 * (i+1) (mod 2^32); x = splitmix32(x); r[i] = x ^ seed_words[(i+1) & 7]",
|
||||
"splitmix32": "x ^= x>>16; x *= 0x7feb352d; x ^= x>>15; x *= 0x846ca68b; x ^= x>>16",
|
||||
"iteration": "sel = r0 sampled once at the top of each iteration, then all instructions in order",
|
||||
"output": "lo = r0 ^ rotl(r1,7) ^ rotl(r2,14) ^ rotl(r3,21); hi = r4 ^ rotl(r5,9) ^ rotl(r6,18) ^ rotl(r7,27); out = (hi << 32) | lo",
|
||||
"op_semantics": {
|
||||
"add": "dst = dst + src + (bit `bit` of sel ? imm2 : imm)",
|
||||
"sub": "dst = dst - src",
|
||||
"mul": "dst = dst * src (low 32)",
|
||||
"mulhi": "dst = high 32 bits of dst * src",
|
||||
"xor": "dst = dst ^ src",
|
||||
"or": "dst = dst | src",
|
||||
"rotl": "dst = rotl(dst, rot), rot in 1..31",
|
||||
"rotr": "dst = rotr(dst, src & 31)",
|
||||
"mad": "dst = src * src2 + dst",
|
||||
"shfl": "dst = dst ^ (src of lane (lane ^ mask)), mask in {1,2,4,8,16}, within the 32-lane warp",
|
||||
"load": "dst = dst ^ dataset[src & dataset.mask]",
|
||||
"wload": "base = (src of lane 0 & dataset.mask) & ~31; dst = dst ^ dataset[base + lane] (warp-coalesced 128-byte load, lever b, only when --wide-frac > 0)"
|
||||
},
|
||||
"dataset": {
|
||||
"log2_words": 28,
|
||||
"bytes": 1073741824,
|
||||
"mask": "0x0fffffff",
|
||||
"day": "2026-10-03",
|
||||
"day_bytes": "6461792f323032362d31302d3033",
|
||||
"day_words_from": "seed_words_from_bytes(day_bytes)",
|
||||
"d0": "0x3067619f",
|
||||
"d1": "0x3c269176",
|
||||
"mode": "memory-hard",
|
||||
"spec": "proto-metal/MEMHARD.md",
|
||||
"key": ["0x3067619f", "0x3c269176", "0x84a03b03", "0xf8c63294", "0xff977c5b", "0xe60def3e", "0x63630141", "0xb8fbcb58"],
|
||||
"key_derivation": "the 8 words of seed_words_from_bytes(day_bytes); d0, d1 are key[0], key[1]",
|
||||
"cache": {"log2_words": 26, "bytes": 268435456, "line_words": 16, "segment_lines": 64, "segments": 65536, "block": "ChaCha12 core + feed-forward, rotations 16 12 8 7", "sigma": ["0x61707865", "0x3320646e", "0x79622d32", "0x6b206574"], "tag": ["0x49676e65", "0x756d4d48"], "chain": "in_j = prev_line ^ (sigma[0..3] || key[0..7] || seg || j || tag[0..1]); line_j = block(in_j); prev_0 = 0"},
|
||||
"mixer": {"draw": "SplitMix64 seeded with key[0] | key[1] << 32: rot[0..7] = 1 + next() % 31, mul[0..15] = low32(next()) | 1, rc[0..15] = low32(next())", "rot": [20, 20, 19, 4, 26, 3, 3, 27], "mul": ["0x42146205", "0x52cbe0fb", "0x7ecf4a03", "0x6728907f", "0xd81d9751", "0x132952c3", "0xf60de277", "0x05358035", "0xbaf6499d", "0xe4db9667", "0x3e98f45d", "0xd0004edd", "0x2691630d", "0x9beb3bcf", "0xab310379", "0x99cfb423"], "rc": ["0xbab68293", "0xcc162340", "0x6ce151cc", "0xe62b8997", "0xc9c80297", "0xf74a1654", "0x3d704af5", "0x3cf522b7", "0x2b9cac04", "0xa880ac10", "0x13e5dd1d", "0x6fc3e233", "0x2d83eeac", "0x9006e8bf", "0x2c4b5362", "0x31b49ee2"], "round": "for i in 0..15: s[i] = (s[i] ^ (rc[i] + (r+1) * 0x9E3779B9)) * mul[i]; then quarter rounds on columns (0,4,8,12) (1,5,9,13) (2,6,10,14) (3,7,11,15) with rot[0..3] and diagonals (0,5,10,15) (1,6,11,12) (2,7,8,13) (3,4,9,14) with rot[4..7]", "quarter_round": "a += b; d ^= a; d = rotl(d, r1); c += d; b ^= c; b = rotl(b, r2); a += b; d ^= a; d = rotl(d, r3); c += d; b ^= c; b = rotl(b, r4)"},
|
||||
"item": "s[0..7] = key; s[8+i] = t * mul[i] + rc[i] for i in 0..7; for r in 0..7: s = M_r(s); line = s[0] & 0x003fffff; s[i] ^= cache[line * 16 + i]; then s = M_8(s); item(t) = s",
|
||||
"word": "dataset[w] = item(w >> 4)[w & 15]"
|
||||
},
|
||||
"instructions": [
|
||||
{"i": 0, "op": "rotl", "dst": 3, "src": 5, "src2": 6, "imm": "0x7e513467", "imm2": "0x0fed3e98", "rot": 26, "bit": 29, "mask": 8, "width": 1},
|
||||
{"i": 1, "op": "rotr", "dst": 2, "src": 0, "src2": 1, "imm": "0x944f466f", "imm2": "0xbbb1d985", "rot": 17, "bit": 20, "mask": 1, "width": 1},
|
||||
{"i": 2, "op": "xor", "dst": 0, "src": 7, "src2": 4, "imm": "0x42d344ab", "imm2": "0xc4fa2084", "rot": 29, "bit": 10, "mask": 4, "width": 1},
|
||||
{"i": 3, "op": "xor", "dst": 4, "src": 7, "src2": 2, "imm": "0x6a558d6d", "imm2": "0x21feb6e9", "rot": 31, "bit": 0, "mask": 8, "width": 1},
|
||||
{"i": 4, "op": "load", "dst": 2, "src": 4, "src2": 4, "imm": "0xe6c6b0d6", "imm2": "0xf7ff31ee", "rot": 25, "bit": 21, "mask": 4, "width": 1},
|
||||
{"i": 5, "op": "load", "dst": 3, "src": 2, "src2": 0, "imm": "0x8c1b23b2", "imm2": "0x7db0b535", "rot": 16, "bit": 1, "mask": 1, "width": 4},
|
||||
{"i": 6, "op": "shfl", "dst": 0, "src": 7, "src2": 4, "imm": "0x9d7e34c0", "imm2": "0xf15d4662", "rot": 4, "bit": 16, "mask": 4, "width": 1},
|
||||
{"i": 7, "op": "rotl", "dst": 6, "src": 5, "src2": 1, "imm": "0x8981adb9", "imm2": "0x4bb830b4", "rot": 31, "bit": 24, "mask": 4, "width": 1},
|
||||
{"i": 8, "op": "mad", "dst": 1, "src": 4, "src2": 2, "imm": "0xcb805ebd", "imm2": "0xde933f7d", "rot": 29, "bit": 27, "mask": 8, "width": 1},
|
||||
{"i": 9, "op": "mad", "dst": 1, "src": 7, "src2": 0, "imm": "0x66835a74", "imm2": "0xde14a90d", "rot": 30, "bit": 29, "mask": 4, "width": 1},
|
||||
{"i": 10, "op": "load", "dst": 4, "src": 1, "src2": 3, "imm": "0x0e0ff63d", "imm2": "0x848393fd", "rot": 20, "bit": 13, "mask": 4, "width": 1},
|
||||
{"i": 11, "op": "mad", "dst": 6, "src": 7, "src2": 0, "imm": "0x54b20c82", "imm2": "0x6be278b9", "rot": 27, "bit": 25, "mask": 4, "width": 1},
|
||||
{"i": 12, "op": "mul", "dst": 2, "src": 6, "src2": 4, "imm": "0x152bfc86", "imm2": "0x403f65d5", "rot": 31, "bit": 12, "mask": 8, "width": 1},
|
||||
{"i": 13, "op": "load", "dst": 0, "src": 2, "src2": 5, "imm": "0x0c3b44ce", "imm2": "0x03bbe6be", "rot": 13, "bit": 27, "mask": 4, "width": 4},
|
||||
{"i": 14, "op": "add", "dst": 2, "src": 7, "src2": 2, "imm": "0x5df3957d", "imm2": "0x4a3db5a5", "rot": 19, "bit": 22, "mask": 16, "width": 1},
|
||||
{"i": 15, "op": "shfl", "dst": 5, "src": 7, "src2": 2, "imm": "0x62602275", "imm2": "0x8dd64d3c", "rot": 14, "bit": 1, "mask": 1, "width": 1},
|
||||
{"i": 16, "op": "mad", "dst": 3, "src": 5, "src2": 6, "imm": "0xdcbd85e9", "imm2": "0x6aa7c473", "rot": 3, "bit": 30, "mask": 8, "width": 1},
|
||||
{"i": 17, "op": "mul", "dst": 2, "src": 5, "src2": 0, "imm": "0xbc049a58", "imm2": "0x65f78542", "rot": 22, "bit": 28, "mask": 8, "width": 1},
|
||||
{"i": 18, "op": "shfl", "dst": 1, "src": 5, "src2": 3, "imm": "0x1381d2fa", "imm2": "0xb37a6855", "rot": 22, "bit": 29, "mask": 1, "width": 1},
|
||||
{"i": 19, "op": "sub", "dst": 0, "src": 1, "src2": 3, "imm": "0x0975c87d", "imm2": "0xcf931617", "rot": 10, "bit": 22, "mask": 8, "width": 1},
|
||||
{"i": 20, "op": "mad", "dst": 4, "src": 6, "src2": 4, "imm": "0x10759307", "imm2": "0x3eae5571", "rot": 15, "bit": 7, "mask": 8, "width": 1},
|
||||
{"i": 21, "op": "shfl", "dst": 3, "src": 0, "src2": 0, "imm": "0x047b824d", "imm2": "0xf79c23a1", "rot": 28, "bit": 5, "mask": 16, "width": 1},
|
||||
{"i": 22, "op": "rotl", "dst": 1, "src": 3, "src2": 3, "imm": "0x6ebf5dd2", "imm2": "0xcc6928a6", "rot": 24, "bit": 0, "mask": 1, "width": 1},
|
||||
{"i": 23, "op": "add", "dst": 1, "src": 0, "src2": 2, "imm": "0x5c141117", "imm2": "0xfc07c54c", "rot": 6, "bit": 22, "mask": 4, "width": 1},
|
||||
{"i": 24, "op": "load", "dst": 2, "src": 0, "src2": 0, "imm": "0x4ca5dd93", "imm2": "0x50f7ea7a", "rot": 15, "bit": 21, "mask": 16, "width": 1},
|
||||
{"i": 25, "op": "xor", "dst": 0, "src": 1, "src2": 0, "imm": "0xb02c8523", "imm2": "0xc20cbd93", "rot": 8, "bit": 14, "mask": 4, "width": 1},
|
||||
{"i": 26, "op": "xor", "dst": 3, "src": 7, "src2": 6, "imm": "0x4ac5aa82", "imm2": "0xd0a3b8ca", "rot": 1, "bit": 22, "mask": 16, "width": 1},
|
||||
{"i": 27, "op": "load", "dst": 2, "src": 3, "src2": 0, "imm": "0xc7cb167e", "imm2": "0xe604db1b", "rot": 3, "bit": 1, "mask": 16, "width": 4},
|
||||
{"i": 28, "op": "xor", "dst": 0, "src": 6, "src2": 5, "imm": "0x68319ac4", "imm2": "0x1d0fc6ef", "rot": 31, "bit": 13, "mask": 8, "width": 1},
|
||||
{"i": 29, "op": "xor", "dst": 4, "src": 1, "src2": 4, "imm": "0x46e6b295", "imm2": "0x279187a0", "rot": 22, "bit": 6, "mask": 4, "width": 1},
|
||||
{"i": 30, "op": "mul", "dst": 6, "src": 3, "src2": 6, "imm": "0x087009f4", "imm2": "0x69bd5f06", "rot": 17, "bit": 13, "mask": 1, "width": 1},
|
||||
{"i": 31, "op": "rotl", "dst": 3, "src": 0, "src2": 3, "imm": "0x96261bd7", "imm2": "0x2304582f", "rot": 23, "bit": 31, "mask": 4, "width": 1},
|
||||
{"i": 32, "op": "rotr", "dst": 7, "src": 1, "src2": 1, "imm": "0x975e5e73", "imm2": "0x7382921b", "rot": 11, "bit": 21, "mask": 2, "width": 1},
|
||||
{"i": 33, "op": "shfl", "dst": 6, "src": 2, "src2": 2, "imm": "0xfc64a106", "imm2": "0xfa7eb90c", "rot": 1, "bit": 16, "mask": 2, "width": 1},
|
||||
{"i": 34, "op": "load", "dst": 5, "src": 0, "src2": 7, "imm": "0xe536f810", "imm2": "0xe44d2045", "rot": 4, "bit": 9, "mask": 8, "width": 16},
|
||||
{"i": 35, "op": "add", "dst": 6, "src": 3, "src2": 6, "imm": "0xfb55c58d", "imm2": "0x0b74657b", "rot": 25, "bit": 29, "mask": 8, "width": 1},
|
||||
{"i": 36, "op": "load", "dst": 6, "src": 5, "src2": 1, "imm": "0x85c5e518", "imm2": "0xdf4f27ed", "rot": 10, "bit": 6, "mask": 2, "width": 16},
|
||||
{"i": 37, "op": "load", "dst": 1, "src": 4, "src2": 6, "imm": "0xd47ed295", "imm2": "0x062102da", "rot": 1, "bit": 15, "mask": 16, "width": 1},
|
||||
{"i": 38, "op": "load", "dst": 6, "src": 3, "src2": 7, "imm": "0x07c3080a", "imm2": "0x2f4b3801", "rot": 8, "bit": 10, "mask": 4, "width": 4},
|
||||
{"i": 39, "op": "load", "dst": 4, "src": 7, "src2": 5, "imm": "0x1beb83e7", "imm2": "0x90d4963d", "rot": 16, "bit": 31, "mask": 4, "width": 1},
|
||||
{"i": 40, "op": "mulhi", "dst": 7, "src": 3, "src2": 7, "imm": "0x42b300c8", "imm2": "0x05b01fcb", "rot": 5, "bit": 17, "mask": 1, "width": 1},
|
||||
{"i": 41, "op": "or", "dst": 0, "src": 6, "src2": 5, "imm": "0xd6d93d15", "imm2": "0xcef78983", "rot": 31, "bit": 6, "mask": 1, "width": 1},
|
||||
{"i": 42, "op": "mad", "dst": 0, "src": 3, "src2": 0, "imm": "0xd14e02da", "imm2": "0x72d866a4", "rot": 9, "bit": 29, "mask": 4, "width": 1},
|
||||
{"i": 43, "op": "load", "dst": 4, "src": 6, "src2": 6, "imm": "0x84684f5c", "imm2": "0x396d612e", "rot": 2, "bit": 7, "mask": 2, "width": 16},
|
||||
{"i": 44, "op": "mad", "dst": 2, "src": 4, "src2": 0, "imm": "0x0a129ff8", "imm2": "0x8dbb8864", "rot": 20, "bit": 29, "mask": 8, "width": 1},
|
||||
{"i": 45, "op": "mad", "dst": 2, "src": 4, "src2": 2, "imm": "0x8e8de36b", "imm2": "0x5f1ad032", "rot": 11, "bit": 7, "mask": 2, "width": 1},
|
||||
{"i": 46, "op": "shfl", "dst": 7, "src": 5, "src2": 0, "imm": "0x395fb2f0", "imm2": "0x1f8120ba", "rot": 13, "bit": 25, "mask": 16, "width": 1},
|
||||
{"i": 47, "op": "mad", "dst": 6, "src": 1, "src2": 4, "imm": "0x46dd77ef", "imm2": "0x3344daf3", "rot": 24, "bit": 26, "mask": 4, "width": 1},
|
||||
{"i": 48, "op": "load", "dst": 7, "src": 1, "src2": 5, "imm": "0x72e62a51", "imm2": "0x6887cd34", "rot": 28, "bit": 6, "mask": 4, "width": 1},
|
||||
{"i": 49, "op": "mulhi", "dst": 6, "src": 5, "src2": 6, "imm": "0x15785a34", "imm2": "0x4cd4815d", "rot": 18, "bit": 22, "mask": 1, "width": 1},
|
||||
{"i": 50, "op": "mulhi", "dst": 5, "src": 0, "src2": 3, "imm": "0xf4adde36", "imm2": "0x3a596180", "rot": 28, "bit": 11, "mask": 2, "width": 1},
|
||||
{"i": 51, "op": "load", "dst": 1, "src": 6, "src2": 0, "imm": "0xbe0a1ce3", "imm2": "0xa67b98b2", "rot": 19, "bit": 12, "mask": 8, "width": 4},
|
||||
{"i": 52, "op": "shfl", "dst": 7, "src": 3, "src2": 2, "imm": "0xde71a6c7", "imm2": "0x089678f0", "rot": 11, "bit": 22, "mask": 1, "width": 1},
|
||||
{"i": 53, "op": "xor", "dst": 2, "src": 5, "src2": 6, "imm": "0x25e0b714", "imm2": "0xc498694f", "rot": 31, "bit": 20, "mask": 2, "width": 1},
|
||||
{"i": 54, "op": "shfl", "dst": 0, "src": 6, "src2": 5, "imm": "0x4f08890f", "imm2": "0x9214703e", "rot": 1, "bit": 23, "mask": 4, "width": 1},
|
||||
{"i": 55, "op": "mul", "dst": 2, "src": 5, "src2": 3, "imm": "0x3c2cb502", "imm2": "0xd2b3be81", "rot": 31, "bit": 18, "mask": 1, "width": 1},
|
||||
{"i": 56, "op": "mul", "dst": 5, "src": 6, "src2": 3, "imm": "0x856a28d5", "imm2": "0xd0a711af", "rot": 24, "bit": 0, "mask": 1, "width": 1},
|
||||
{"i": 57, "op": "load", "dst": 6, "src": 4, "src2": 7, "imm": "0xf0c439cf", "imm2": "0x36507133", "rot": 14, "bit": 2, "mask": 4, "width": 4},
|
||||
{"i": 58, "op": "mad", "dst": 4, "src": 7, "src2": 7, "imm": "0x1df01e69", "imm2": "0xae8c4b8e", "rot": 28, "bit": 17, "mask": 2, "width": 1},
|
||||
{"i": 59, "op": "load", "dst": 2, "src": 1, "src2": 6, "imm": "0x3796e56b", "imm2": "0x4b519b72", "rot": 30, "bit": 31, "mask": 2, "width": 1},
|
||||
{"i": 60, "op": "mul", "dst": 1, "src": 4, "src2": 2, "imm": "0x4c165ca5", "imm2": "0xd4c97f2a", "rot": 18, "bit": 20, "mask": 1, "width": 1},
|
||||
{"i": 61, "op": "mul", "dst": 3, "src": 4, "src2": 1, "imm": "0x5d55a322", "imm2": "0xdde0b168", "rot": 1, "bit": 27, "mask": 4, "width": 1},
|
||||
{"i": 62, "op": "xor", "dst": 6, "src": 4, "src2": 5, "imm": "0x82cf3c97", "imm2": "0x7c368d65", "rot": 26, "bit": 17, "mask": 4, "width": 1},
|
||||
{"i": 63, "op": "rotr", "dst": 3, "src": 1, "src2": 2, "imm": "0x53bbae08", "imm2": "0x223ccdc5", "rot": 28, "bit": 16, "mask": 4, "width": 1}
|
||||
]
|
||||
}
|
||||
109
proto-cuda/packs-readwidth/mixA-4/program.metal
Normal file
109
proto-cuda/packs-readwidth/mixA-4/program.metal
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
#include <metal_stdlib>
|
||||
using namespace metal;
|
||||
|
||||
#define MASK 0x0fffffffu
|
||||
constant uint SEEDW[8] = { 0xc255b2bfu, 0xdba9d396u, 0x6ea527e4u, 0x05f1866au, 0x2947e02eu, 0x0ecc5c6fu, 0xc3b7068du, 0x282d1c2eu };
|
||||
|
||||
inline uint splitmix32(uint x) {
|
||||
x ^= x >> 16; x *= 0x7feb352du;
|
||||
x ^= x >> 15; x *= 0x846ca68bu;
|
||||
x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
inline uint rotl_imm(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31
|
||||
inline uint rotr_var(uint x, uint n) { n &= 31u; return (x >> n) | (x << ((32u - n) & 31u)); }
|
||||
inline uint ds_elem(uint i, uint d0, uint d1) {
|
||||
uint x = i ^ d0;
|
||||
x *= 0x9E3779B1u; x ^= x >> 15;
|
||||
x += d1;
|
||||
x *= 0x85EBCA77u; x ^= x >> 13;
|
||||
x *= 0xC2B2AE3Du; x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
|
||||
kernel void igneum_hash(device const uint* dataset [[buffer(0)]],
|
||||
device ulong* out [[buffer(1)]],
|
||||
constant uint& baseNonce [[buffer(2)]],
|
||||
uint gid [[thread_position_in_grid]]) {
|
||||
uint nonce = baseNonce + gid;
|
||||
uint r0, r1, r2, r3, r4, r5, r6, r7;
|
||||
{ uint x = nonce ^ SEEDW[0]; x += 0x9e3779b9u * 1u; x = splitmix32(x); r0 = x ^ SEEDW[1]; }
|
||||
{ uint x = nonce ^ SEEDW[1]; x += 0x9e3779b9u * 2u; x = splitmix32(x); r1 = x ^ SEEDW[2]; }
|
||||
{ uint x = nonce ^ SEEDW[2]; x += 0x9e3779b9u * 3u; x = splitmix32(x); r2 = x ^ SEEDW[3]; }
|
||||
{ uint x = nonce ^ SEEDW[3]; x += 0x9e3779b9u * 4u; x = splitmix32(x); r3 = x ^ SEEDW[4]; }
|
||||
{ uint x = nonce ^ SEEDW[4]; x += 0x9e3779b9u * 5u; x = splitmix32(x); r4 = x ^ SEEDW[5]; }
|
||||
{ uint x = nonce ^ SEEDW[5]; x += 0x9e3779b9u * 6u; x = splitmix32(x); r5 = x ^ SEEDW[6]; }
|
||||
{ uint x = nonce ^ SEEDW[6]; x += 0x9e3779b9u * 7u; x = splitmix32(x); r6 = x ^ SEEDW[7]; }
|
||||
{ uint x = nonce ^ SEEDW[7]; x += 0x9e3779b9u * 8u; x = splitmix32(x); r7 = x ^ SEEDW[0]; }
|
||||
|
||||
for (uint it = 0u; it < 8u; ++it) {
|
||||
uint sel = r0;
|
||||
r3 = rotl_imm(r3, 26u); // 0
|
||||
r2 = rotr_var(r2, r0); // 1
|
||||
r0 = r0 ^ r7; // 2
|
||||
r4 = r4 ^ r7; // 3
|
||||
r2 = r2 ^ dataset[r4 & MASK]; // 4
|
||||
{ uint b_ = (r2 & MASK) & ~3u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r3 = x_; } // 5
|
||||
r0 = r0 ^ simd_shuffle_xor(r7, (ushort)4); // 6
|
||||
r6 = rotl_imm(r6, 31u); // 7
|
||||
r1 = r4 * r2 + r1; // 8
|
||||
r1 = r7 * r0 + r1; // 9
|
||||
r4 = r4 ^ dataset[r1 & MASK]; // 10
|
||||
r6 = r7 * r0 + r6; // 11
|
||||
r2 = r2 * r6; // 12
|
||||
{ uint b_ = (r2 & MASK) & ~3u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint x_ = r0 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r0 = x_; } // 13
|
||||
r2 = r2 + r7 + select(0x5df3957du, 0x4a3db5a5u, ((sel >> 22u) & 1u) != 0u); // 14
|
||||
r5 = r5 ^ simd_shuffle_xor(r7, (ushort)1); // 15
|
||||
r3 = r5 * r6 + r3; // 16
|
||||
r2 = r2 * r5; // 17
|
||||
r1 = r1 ^ simd_shuffle_xor(r5, (ushort)1); // 18
|
||||
r0 = r0 - r1; // 19
|
||||
r4 = r6 * r4 + r4; // 20
|
||||
r3 = r3 ^ simd_shuffle_xor(r0, (ushort)16); // 21
|
||||
r1 = rotl_imm(r1, 24u); // 22
|
||||
r1 = r1 + r0 + select(0x5c141117u, 0xfc07c54cu, ((sel >> 22u) & 1u) != 0u); // 23
|
||||
r2 = r2 ^ dataset[r0 & MASK]; // 24
|
||||
r0 = r0 ^ r1; // 25
|
||||
r3 = r3 ^ r7; // 26
|
||||
{ uint b_ = (r3 & MASK) & ~3u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint x_ = r2 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r2 = x_; } // 27
|
||||
r0 = r0 ^ r6; // 28
|
||||
r4 = r4 ^ r1; // 29
|
||||
r6 = r6 * r3; // 30
|
||||
r3 = rotl_imm(r3, 23u); // 31
|
||||
r7 = rotr_var(r7, r1); // 32
|
||||
r6 = r6 ^ simd_shuffle_xor(r2, (ushort)2); // 33
|
||||
{ uint b_ = (r0 & MASK) & ~15u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint x_ = r5 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r5 = x_; } // 34
|
||||
r6 = r6 + r3 + select(0xfb55c58du, 0x0b74657bu, ((sel >> 29u) & 1u) != 0u); // 35
|
||||
{ uint b_ = (r5 & MASK) & ~15u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r6 = x_; } // 36
|
||||
r1 = r1 ^ dataset[r4 & MASK]; // 37
|
||||
{ uint b_ = (r3 & MASK) & ~3u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r6 = x_; } // 38
|
||||
r4 = r4 ^ dataset[r7 & MASK]; // 39
|
||||
r7 = mulhi(r7, r3); // 40
|
||||
r0 = r0 | r6; // 41
|
||||
r0 = r3 * r0 + r0; // 42
|
||||
{ uint b_ = (r6 & MASK) & ~15u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint x_ = r4 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r4 = x_; } // 43
|
||||
r2 = r4 * r0 + r2; // 44
|
||||
r2 = r4 * r2 + r2; // 45
|
||||
r7 = r7 ^ simd_shuffle_xor(r5, (ushort)16); // 46
|
||||
r6 = r1 * r4 + r6; // 47
|
||||
r7 = r7 ^ dataset[r1 & MASK]; // 48
|
||||
r6 = mulhi(r6, r5); // 49
|
||||
r5 = mulhi(r5, r0); // 50
|
||||
{ uint b_ = (r6 & MASK) & ~3u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint x_ = r1 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r1 = x_; } // 51
|
||||
r7 = r7 ^ simd_shuffle_xor(r3, (ushort)1); // 52
|
||||
r2 = r2 ^ r5; // 53
|
||||
r0 = r0 ^ simd_shuffle_xor(r6, (ushort)4); // 54
|
||||
r2 = r2 * r5; // 55
|
||||
r5 = r5 * r6; // 56
|
||||
{ uint b_ = (r4 & MASK) & ~3u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r6 = x_; } // 57
|
||||
r4 = r7 * r7 + r4; // 58
|
||||
r2 = r2 ^ dataset[r1 & MASK]; // 59
|
||||
r1 = r1 * r4; // 60
|
||||
r3 = r3 * r4; // 61
|
||||
r6 = r6 ^ r4; // 62
|
||||
r3 = rotr_var(r3, r1); // 63
|
||||
}
|
||||
uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u);
|
||||
uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u);
|
||||
out[gid] = ((ulong)hi << 32) | (ulong)lo;
|
||||
}
|
||||
111
proto-cuda/packs-readwidth/mixA-4/program_bound.metal
Normal file
111
proto-cuda/packs-readwidth/mixA-4/program_bound.metal
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
#include <metal_stdlib>
|
||||
using namespace metal;
|
||||
|
||||
#define MASK 0x0fffffffu
|
||||
constant uint SEEDW[8] = { 0xc255b2bfu, 0xdba9d396u, 0x6ea527e4u, 0x05f1866au, 0x2947e02eu, 0x0ecc5c6fu, 0xc3b7068du, 0x282d1c2eu };
|
||||
|
||||
inline uint splitmix32(uint x) {
|
||||
x ^= x >> 16; x *= 0x7feb352du;
|
||||
x ^= x >> 15; x *= 0x846ca68bu;
|
||||
x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
inline uint rotl_imm(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31
|
||||
inline uint rotr_var(uint x, uint n) { n &= 31u; return (x >> n) | (x << ((32u - n) & 31u)); }
|
||||
inline uint ds_elem(uint i, uint d0, uint d1) {
|
||||
uint x = i ^ d0;
|
||||
x *= 0x9E3779B1u; x ^= x >> 15;
|
||||
x += d1;
|
||||
x *= 0x85EBCA77u; x ^= x >> 13;
|
||||
x *= 0xC2B2AE3Du; x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
|
||||
// Header-bound variant: the init words come from buffer 3 (bind.rs), not from SEEDW.
|
||||
kernel void igneum_hash_bound(device const uint* dataset [[buffer(0)]],
|
||||
device ulong* out [[buffer(1)]],
|
||||
constant uint& baseNonce [[buffer(2)]],
|
||||
constant uint* initw [[buffer(3)]],
|
||||
uint gid [[thread_position_in_grid]]) {
|
||||
uint nonce = baseNonce + gid;
|
||||
uint r0, r1, r2, r3, r4, r5, r6, r7;
|
||||
{ uint x = nonce ^ initw[0]; x += 0x9e3779b9u * 1u; x = splitmix32(x); r0 = x ^ initw[1]; }
|
||||
{ uint x = nonce ^ initw[1]; x += 0x9e3779b9u * 2u; x = splitmix32(x); r1 = x ^ initw[2]; }
|
||||
{ uint x = nonce ^ initw[2]; x += 0x9e3779b9u * 3u; x = splitmix32(x); r2 = x ^ initw[3]; }
|
||||
{ uint x = nonce ^ initw[3]; x += 0x9e3779b9u * 4u; x = splitmix32(x); r3 = x ^ initw[4]; }
|
||||
{ uint x = nonce ^ initw[4]; x += 0x9e3779b9u * 5u; x = splitmix32(x); r4 = x ^ initw[5]; }
|
||||
{ uint x = nonce ^ initw[5]; x += 0x9e3779b9u * 6u; x = splitmix32(x); r5 = x ^ initw[6]; }
|
||||
{ uint x = nonce ^ initw[6]; x += 0x9e3779b9u * 7u; x = splitmix32(x); r6 = x ^ initw[7]; }
|
||||
{ uint x = nonce ^ initw[7]; x += 0x9e3779b9u * 8u; x = splitmix32(x); r7 = x ^ initw[0]; }
|
||||
|
||||
for (uint it = 0u; it < 8u; ++it) {
|
||||
uint sel = r0;
|
||||
r3 = rotl_imm(r3, 26u); // 0
|
||||
r2 = rotr_var(r2, r0); // 1
|
||||
r0 = r0 ^ r7; // 2
|
||||
r4 = r4 ^ r7; // 3
|
||||
r2 = r2 ^ dataset[r4 & MASK]; // 4
|
||||
{ uint b_ = (r2 & MASK) & ~3u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r3 = x_; } // 5
|
||||
r0 = r0 ^ simd_shuffle_xor(r7, (ushort)4); // 6
|
||||
r6 = rotl_imm(r6, 31u); // 7
|
||||
r1 = r4 * r2 + r1; // 8
|
||||
r1 = r7 * r0 + r1; // 9
|
||||
r4 = r4 ^ dataset[r1 & MASK]; // 10
|
||||
r6 = r7 * r0 + r6; // 11
|
||||
r2 = r2 * r6; // 12
|
||||
{ uint b_ = (r2 & MASK) & ~3u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint x_ = r0 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r0 = x_; } // 13
|
||||
r2 = r2 + r7 + select(0x5df3957du, 0x4a3db5a5u, ((sel >> 22u) & 1u) != 0u); // 14
|
||||
r5 = r5 ^ simd_shuffle_xor(r7, (ushort)1); // 15
|
||||
r3 = r5 * r6 + r3; // 16
|
||||
r2 = r2 * r5; // 17
|
||||
r1 = r1 ^ simd_shuffle_xor(r5, (ushort)1); // 18
|
||||
r0 = r0 - r1; // 19
|
||||
r4 = r6 * r4 + r4; // 20
|
||||
r3 = r3 ^ simd_shuffle_xor(r0, (ushort)16); // 21
|
||||
r1 = rotl_imm(r1, 24u); // 22
|
||||
r1 = r1 + r0 + select(0x5c141117u, 0xfc07c54cu, ((sel >> 22u) & 1u) != 0u); // 23
|
||||
r2 = r2 ^ dataset[r0 & MASK]; // 24
|
||||
r0 = r0 ^ r1; // 25
|
||||
r3 = r3 ^ r7; // 26
|
||||
{ uint b_ = (r3 & MASK) & ~3u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint x_ = r2 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r2 = x_; } // 27
|
||||
r0 = r0 ^ r6; // 28
|
||||
r4 = r4 ^ r1; // 29
|
||||
r6 = r6 * r3; // 30
|
||||
r3 = rotl_imm(r3, 23u); // 31
|
||||
r7 = rotr_var(r7, r1); // 32
|
||||
r6 = r6 ^ simd_shuffle_xor(r2, (ushort)2); // 33
|
||||
{ uint b_ = (r0 & MASK) & ~15u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint x_ = r5 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r5 = x_; } // 34
|
||||
r6 = r6 + r3 + select(0xfb55c58du, 0x0b74657bu, ((sel >> 29u) & 1u) != 0u); // 35
|
||||
{ uint b_ = (r5 & MASK) & ~15u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r6 = x_; } // 36
|
||||
r1 = r1 ^ dataset[r4 & MASK]; // 37
|
||||
{ uint b_ = (r3 & MASK) & ~3u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r6 = x_; } // 38
|
||||
r4 = r4 ^ dataset[r7 & MASK]; // 39
|
||||
r7 = mulhi(r7, r3); // 40
|
||||
r0 = r0 | r6; // 41
|
||||
r0 = r3 * r0 + r0; // 42
|
||||
{ uint b_ = (r6 & MASK) & ~15u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint x_ = r4 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r4 = x_; } // 43
|
||||
r2 = r4 * r0 + r2; // 44
|
||||
r2 = r4 * r2 + r2; // 45
|
||||
r7 = r7 ^ simd_shuffle_xor(r5, (ushort)16); // 46
|
||||
r6 = r1 * r4 + r6; // 47
|
||||
r7 = r7 ^ dataset[r1 & MASK]; // 48
|
||||
r6 = mulhi(r6, r5); // 49
|
||||
r5 = mulhi(r5, r0); // 50
|
||||
{ uint b_ = (r6 & MASK) & ~3u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint x_ = r1 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r1 = x_; } // 51
|
||||
r7 = r7 ^ simd_shuffle_xor(r3, (ushort)1); // 52
|
||||
r2 = r2 ^ r5; // 53
|
||||
r0 = r0 ^ simd_shuffle_xor(r6, (ushort)4); // 54
|
||||
r2 = r2 * r5; // 55
|
||||
r5 = r5 * r6; // 56
|
||||
{ uint b_ = (r4 & MASK) & ~3u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r6 = x_; } // 57
|
||||
r4 = r7 * r7 + r4; // 58
|
||||
r2 = r2 ^ dataset[r1 & MASK]; // 59
|
||||
r1 = r1 * r4; // 60
|
||||
r3 = r3 * r4; // 61
|
||||
r6 = r6 ^ r4; // 62
|
||||
r3 = rotr_var(r3, r1); // 63
|
||||
}
|
||||
uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u);
|
||||
uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u);
|
||||
out[gid] = ((ulong)hi << 32) | (ulong)lo;
|
||||
}
|
||||
57
proto-cuda/packs-readwidth/mixA-4/vectors.h
Normal file
57
proto-cuda/packs-readwidth/mixA-4/vectors.h
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
// Generated by igneum-pow export (generator v2) for seed "igneum-readwidth/A/5". Do not edit by hand.
|
||||
// Expected outputs: igneum-pow (Rust) CPU interpreter, generator v2, memory-hard dataset
|
||||
#pragma once
|
||||
#ifdef __cplusplus
|
||||
#include <cstdint>
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
#define IGNEUM_VEC_WARPS 3
|
||||
static const uint32_t IGNEUM_VEC_BASE[IGNEUM_VEC_WARPS] = { 0u, 4096u, 1000000u };
|
||||
static const uint64_t IGNEUM_VEC_OUT[IGNEUM_VEC_WARPS][32] = {
|
||||
{ // base nonce 0
|
||||
0xeaee437d9c4bba42ull, 0xa89fc64fb516d23bull, 0xf50c45c711918300ull, 0x7f02b33440a1ee24ull, 0x2010bc3f907d5040ull, 0x74d0198a4fbd6269ull, 0xe6248af74a39174eull, 0x1eb569508ef6c62bull,
|
||||
0xa33d857ed5fe79beull, 0x373c29561fbc6793ull, 0xf085a877af1bb6e8ull, 0x642c45f3214b4d6dull, 0xe1ad911edc598629ull, 0xff3e0523b7834ed3ull, 0x7c8752e2db521931ull, 0xe14314ca7f3637bcull,
|
||||
0x325b4f284dcc8f53ull, 0x4d2d6b6e3dd0acc0ull, 0x435670a68d505a3dull, 0x719f3f336a843deeull, 0x101662b22c52db66ull, 0x4467ce7e0020e5deull, 0xef2031f7841e1b86ull, 0xccac3386fc48adbdull,
|
||||
0x0634a7aa079c7fcfull, 0x5139e023bceb13d3ull, 0xc114f6be02fd1befull, 0x3401895eb20ff261ull, 0xf1e3dcf94fa94b59ull, 0xa4af930f43a9a6e7ull, 0xcf2a8f7bc60fd349ull, 0x3cf48986c94c816cull
|
||||
},
|
||||
{ // base nonce 4096
|
||||
0x81fc83f13ff4be40ull, 0x7c42d114d8e674fbull, 0x816154766b564cccull, 0xb7bf2a4a3d544d2eull, 0x7de35c931f18d8c9ull, 0x1d3829de6e647586ull, 0x76a8d92d75a87fc4ull, 0x2308825663bba9b7ull,
|
||||
0xe6d226a37785ffa1ull, 0xdeef0eed55374e0full, 0xde5cfde59a1a53ecull, 0xc4799ac83c5a0602ull, 0xaab7dada14aa7c47ull, 0x7e5eacebfb6ec92cull, 0x2c99a69019e48570ull, 0xae065fa5a54b586aull,
|
||||
0x23cb704f5a33e2caull, 0xf0bdea48e2c03edbull, 0xe150785d233211ceull, 0xb45388e11497f6bbull, 0xf862683cde4568bcull, 0x2e4e81f9fafef5c2ull, 0x8e6aef8b82861379ull, 0x7883eea61e6b6cbdull,
|
||||
0xcc89c8ea28a7a715ull, 0x4adb824fc1302fc7ull, 0x0b99a18825cf092cull, 0xac0f0a2a901bc59aull, 0xef5e0f0bf1c9b8aeull, 0x2220f11e1b69bc0aull, 0x3e9695b77c69892cull, 0xbfe252bff26b14fcull
|
||||
},
|
||||
{ // base nonce 1000000
|
||||
0xb2cc4dc245d1522dull, 0x3f89483adcc726bcull, 0x3df0f900a0027a6cull, 0xa47b69fe239ee7dcull, 0xff539ee62e5ffa98ull, 0x622a019529ba3cc4ull, 0xf92f75b66deb9f43ull, 0x5bdb07bf6d151978ull,
|
||||
0xc6b6ee7fb2350d3aull, 0x0d47d76e37088cc7ull, 0xc662723c083ae26dull, 0x68ddb8f6849ffa3cull, 0x5439d7ce29a28ac0ull, 0x59ffe6543a643d07ull, 0xec4286570ff0b04cull, 0xef042881c63fdda4ull,
|
||||
0xf8185da0349a2894ull, 0xdc4e87d0650fe7a1ull, 0x7df286ee2777a93full, 0x4c2b743817f1a427ull, 0x1b7aef4be8cf3bb3ull, 0xfb64afb73c0fbab8ull, 0x365b83541877755dull, 0x59872f36106c4827ull,
|
||||
0x452e18f12aa47c59ull, 0xed37e59b230c5ad7ull, 0x383768d545312f62ull, 0x30c548bee141f5f5ull, 0x073494619104a4c4ull, 0x0ba09ddfc99ee224ull, 0x0a371f34ea9b52a4ull, 0xe3c763c14c3e2f38ull
|
||||
}
|
||||
};
|
||||
|
||||
// Dataset self-test: dataset[0..15] and dataset[IGNEUM_MASK] (268435455).
|
||||
static const uint32_t IGNEUM_DS_HEAD[16] = {
|
||||
0xffc3cd94u, 0x5920ccd8u, 0x392f44bbu, 0x5e57f67au, 0x2f2bc2a9u, 0x620b0e36u, 0xbdc09014u, 0x436654bfu,
|
||||
0x311e0b48u, 0x1abd93adu, 0x59cc7ce8u, 0xee5247b2u, 0x86171fe8u, 0x6d874751u, 0xc9f7728fu, 0x7c2a435du
|
||||
};
|
||||
static const uint32_t IGNEUM_DS_LAST_INDEX = 268435455u;
|
||||
static const uint32_t IGNEUM_DS_LAST = 0xa33ada72u;
|
||||
// 64 sampled dataset words (index, value) computed on the Mac.
|
||||
#define IGNEUM_DS_SAMPLES 64
|
||||
static const uint32_t IGNEUM_DS_SAMPLE_INDEX[IGNEUM_DS_SAMPLES] = {
|
||||
59471966u, 217795994u, 208353206u, 42483309u, 172547758u, 148076330u, 183853158u, 214389424u, 267488061u, 169781097u, 184093494u, 153880993u, 84977930u, 46426879u, 3093825u, 225364072u, 44593546u, 260713159u, 168250303u, 52384140u, 223401610u, 45554030u, 95410555u, 175039924u, 79171087u, 267580473u, 24168642u, 37981670u, 171551130u, 195559979u, 204611762u, 140997658u, 138925853u, 86637313u, 20736778u, 219665210u, 160430336u, 264654675u, 8013395u, 228945585u, 213884386u, 104419827u, 44185464u, 142737231u, 99284897u, 132475900u, 61861762u, 132056166u, 262388043u, 91878046u, 117353561u, 124768597u, 71352993u, 190698941u, 46055428u, 55281366u, 165145231u, 106810753u, 171985651u, 232085256u, 159510492u, 40072060u, 209107596u, 39023794u
|
||||
};
|
||||
static const uint32_t IGNEUM_DS_SAMPLE_VALUE[IGNEUM_DS_SAMPLES] = {
|
||||
0xe8b73d94u, 0x337028b5u, 0xafe148c9u, 0xab99f7aeu, 0x434ea619u, 0xd85cb880u, 0x54764c7fu, 0x82c7e420u, 0xedf4cb9eu, 0x9884c959u, 0x223ee793u, 0x3a9ccf69u, 0x81da4fd2u, 0xd6ce8cb9u, 0xe3922dcau, 0x3e7e6bdeu, 0x382a3acau, 0x567e7f7fu, 0x25a0f084u, 0xbfeef128u, 0xe338abfbu, 0x7c3b5280u, 0x909bc5f1u, 0xd8b74b9cu, 0x8e31a22eu, 0x26b5f1d8u, 0x79122c00u, 0xcafc3340u, 0xd5e02ea3u, 0x1aee1afdu, 0xdb090d9au, 0xb049f435u, 0x4954d8bau, 0x03797ba0u, 0x196eefbdu, 0xd153412au, 0xbe5d2c4bu, 0xdaa14f0eu, 0x8e61ed07u, 0x9e9a64c6u, 0x2e29ff36u, 0x392a8589u, 0xb56a5912u, 0xfa6e8b57u, 0xd1a737cbu, 0xb0fa841au, 0xbe1c341fu, 0xe25be0f1u, 0xe937f543u, 0xebab2248u, 0x8e1b607au, 0x202a2fedu, 0x95e2819cu, 0x9c9652d4u, 0x32fedef0u, 0xdecfff82u, 0xcb5d43e5u, 0xb735806au, 0x8905939cu, 0xfbf8472du, 0xada74e5du, 0x7ebdeeeau, 0x0119f2b3u, 0xa9a376b8u
|
||||
};
|
||||
// Cache self-test (memory-hard mode): cache[0..15], the last 16 words, and FNV-1a 64 over all 2^26 words.
|
||||
static const uint32_t IGNEUM_CACHE_HEAD[16] = {
|
||||
0x355a86d2u, 0x7957db1cu, 0xd21772afu, 0x6fc1e09bu, 0xd55ce61du, 0x6e6a278bu, 0xd3f543ceu, 0x223d8e82u,
|
||||
0x143ab337u, 0x2e9f05bdu, 0x2eb389bfu, 0x0c6e449eu, 0x5cfa4222u, 0xba6560feu, 0x8e3e1aa4u, 0xdbcc1d53u
|
||||
};
|
||||
static const uint32_t IGNEUM_CACHE_LAST[16] = {
|
||||
0x41190d91u, 0xbd277957u, 0x22ddbb49u, 0x6986f207u, 0xdf69a4d6u, 0x26401a3au, 0x818230fbu, 0xc417122du,
|
||||
0x3597b211u, 0xb553ce55u, 0xcf39cc0du, 0x3b7fc43au, 0x3fd43b00u, 0x67e1c80eu, 0xffa7ea7du, 0xca2960abu
|
||||
};
|
||||
static const uint64_t IGNEUM_CACHE_FNV64 = 0x48c4f5bf24166b2eull;
|
||||
36
proto-cuda/packs-readwidth/mixA-4/vectors.json
Normal file
36
proto-cuda/packs-readwidth/mixA-4/vectors.json
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
{
|
||||
"seed": "igneum-readwidth/A/5",
|
||||
"day": "2026-10-03",
|
||||
"dataset_mode": "memory-hard",
|
||||
"dataset_log2_words": 28,
|
||||
"mask": "0x0fffffff",
|
||||
"lanes": 32,
|
||||
"source": "igneum-pow (Rust) CPU interpreter, generator v2, memory-hard dataset",
|
||||
"warps": [
|
||||
{"base_nonce": 0, "expected": [
|
||||
"0xeaee437d9c4bba42", "0xa89fc64fb516d23b", "0xf50c45c711918300", "0x7f02b33440a1ee24", "0x2010bc3f907d5040", "0x74d0198a4fbd6269", "0xe6248af74a39174e", "0x1eb569508ef6c62b",
|
||||
"0xa33d857ed5fe79be", "0x373c29561fbc6793", "0xf085a877af1bb6e8", "0x642c45f3214b4d6d", "0xe1ad911edc598629", "0xff3e0523b7834ed3", "0x7c8752e2db521931", "0xe14314ca7f3637bc",
|
||||
"0x325b4f284dcc8f53", "0x4d2d6b6e3dd0acc0", "0x435670a68d505a3d", "0x719f3f336a843dee", "0x101662b22c52db66", "0x4467ce7e0020e5de", "0xef2031f7841e1b86", "0xccac3386fc48adbd",
|
||||
"0x0634a7aa079c7fcf", "0x5139e023bceb13d3", "0xc114f6be02fd1bef", "0x3401895eb20ff261", "0xf1e3dcf94fa94b59", "0xa4af930f43a9a6e7", "0xcf2a8f7bc60fd349", "0x3cf48986c94c816c"
|
||||
]},
|
||||
{"base_nonce": 4096, "expected": [
|
||||
"0x81fc83f13ff4be40", "0x7c42d114d8e674fb", "0x816154766b564ccc", "0xb7bf2a4a3d544d2e", "0x7de35c931f18d8c9", "0x1d3829de6e647586", "0x76a8d92d75a87fc4", "0x2308825663bba9b7",
|
||||
"0xe6d226a37785ffa1", "0xdeef0eed55374e0f", "0xde5cfde59a1a53ec", "0xc4799ac83c5a0602", "0xaab7dada14aa7c47", "0x7e5eacebfb6ec92c", "0x2c99a69019e48570", "0xae065fa5a54b586a",
|
||||
"0x23cb704f5a33e2ca", "0xf0bdea48e2c03edb", "0xe150785d233211ce", "0xb45388e11497f6bb", "0xf862683cde4568bc", "0x2e4e81f9fafef5c2", "0x8e6aef8b82861379", "0x7883eea61e6b6cbd",
|
||||
"0xcc89c8ea28a7a715", "0x4adb824fc1302fc7", "0x0b99a18825cf092c", "0xac0f0a2a901bc59a", "0xef5e0f0bf1c9b8ae", "0x2220f11e1b69bc0a", "0x3e9695b77c69892c", "0xbfe252bff26b14fc"
|
||||
]},
|
||||
{"base_nonce": 1000000, "expected": [
|
||||
"0xb2cc4dc245d1522d", "0x3f89483adcc726bc", "0x3df0f900a0027a6c", "0xa47b69fe239ee7dc", "0xff539ee62e5ffa98", "0x622a019529ba3cc4", "0xf92f75b66deb9f43", "0x5bdb07bf6d151978",
|
||||
"0xc6b6ee7fb2350d3a", "0x0d47d76e37088cc7", "0xc662723c083ae26d", "0x68ddb8f6849ffa3c", "0x5439d7ce29a28ac0", "0x59ffe6543a643d07", "0xec4286570ff0b04c", "0xef042881c63fdda4",
|
||||
"0xf8185da0349a2894", "0xdc4e87d0650fe7a1", "0x7df286ee2777a93f", "0x4c2b743817f1a427", "0x1b7aef4be8cf3bb3", "0xfb64afb73c0fbab8", "0x365b83541877755d", "0x59872f36106c4827",
|
||||
"0x452e18f12aa47c59", "0xed37e59b230c5ad7", "0x383768d545312f62", "0x30c548bee141f5f5", "0x073494619104a4c4", "0x0ba09ddfc99ee224", "0x0a371f34ea9b52a4", "0xe3c763c14c3e2f38"
|
||||
]}
|
||||
],
|
||||
"dataset_head": ["0xffc3cd94", "0x5920ccd8", "0x392f44bb", "0x5e57f67a", "0x2f2bc2a9", "0x620b0e36", "0xbdc09014", "0x436654bf", "0x311e0b48", "0x1abd93ad", "0x59cc7ce8", "0xee5247b2", "0x86171fe8", "0x6d874751", "0xc9f7728f", "0x7c2a435d"],
|
||||
"dataset_last_index": 268435455,
|
||||
"dataset_last": "0xa33ada72",
|
||||
"dataset_samples": [{"index": 59471966, "value": "0xe8b73d94"}, {"index": 217795994, "value": "0x337028b5"}, {"index": 208353206, "value": "0xafe148c9"}, {"index": 42483309, "value": "0xab99f7ae"}, {"index": 172547758, "value": "0x434ea619"}, {"index": 148076330, "value": "0xd85cb880"}, {"index": 183853158, "value": "0x54764c7f"}, {"index": 214389424, "value": "0x82c7e420"}, {"index": 267488061, "value": "0xedf4cb9e"}, {"index": 169781097, "value": "0x9884c959"}, {"index": 184093494, "value": "0x223ee793"}, {"index": 153880993, "value": "0x3a9ccf69"}, {"index": 84977930, "value": "0x81da4fd2"}, {"index": 46426879, "value": "0xd6ce8cb9"}, {"index": 3093825, "value": "0xe3922dca"}, {"index": 225364072, "value": "0x3e7e6bde"}, {"index": 44593546, "value": "0x382a3aca"}, {"index": 260713159, "value": "0x567e7f7f"}, {"index": 168250303, "value": "0x25a0f084"}, {"index": 52384140, "value": "0xbfeef128"}, {"index": 223401610, "value": "0xe338abfb"}, {"index": 45554030, "value": "0x7c3b5280"}, {"index": 95410555, "value": "0x909bc5f1"}, {"index": 175039924, "value": "0xd8b74b9c"}, {"index": 79171087, "value": "0x8e31a22e"}, {"index": 267580473, "value": "0x26b5f1d8"}, {"index": 24168642, "value": "0x79122c00"}, {"index": 37981670, "value": "0xcafc3340"}, {"index": 171551130, "value": "0xd5e02ea3"}, {"index": 195559979, "value": "0x1aee1afd"}, {"index": 204611762, "value": "0xdb090d9a"}, {"index": 140997658, "value": "0xb049f435"}, {"index": 138925853, "value": "0x4954d8ba"}, {"index": 86637313, "value": "0x03797ba0"}, {"index": 20736778, "value": "0x196eefbd"}, {"index": 219665210, "value": "0xd153412a"}, {"index": 160430336, "value": "0xbe5d2c4b"}, {"index": 264654675, "value": "0xdaa14f0e"}, {"index": 8013395, "value": "0x8e61ed07"}, {"index": 228945585, "value": "0x9e9a64c6"}, {"index": 213884386, "value": "0x2e29ff36"}, {"index": 104419827, "value": "0x392a8589"}, {"index": 44185464, "value": "0xb56a5912"}, {"index": 142737231, "value": "0xfa6e8b57"}, {"index": 99284897, "value": "0xd1a737cb"}, {"index": 132475900, "value": "0xb0fa841a"}, {"index": 61861762, "value": "0xbe1c341f"}, {"index": 132056166, "value": "0xe25be0f1"}, {"index": 262388043, "value": "0xe937f543"}, {"index": 91878046, "value": "0xebab2248"}, {"index": 117353561, "value": "0x8e1b607a"}, {"index": 124768597, "value": "0x202a2fed"}, {"index": 71352993, "value": "0x95e2819c"}, {"index": 190698941, "value": "0x9c9652d4"}, {"index": 46055428, "value": "0x32fedef0"}, {"index": 55281366, "value": "0xdecfff82"}, {"index": 165145231, "value": "0xcb5d43e5"}, {"index": 106810753, "value": "0xb735806a"}, {"index": 171985651, "value": "0x8905939c"}, {"index": 232085256, "value": "0xfbf8472d"}, {"index": 159510492, "value": "0xada74e5d"}, {"index": 40072060, "value": "0x7ebdeeea"}, {"index": 209107596, "value": "0x0119f2b3"}, {"index": 39023794, "value": "0xa9a376b8"}],
|
||||
"cache_head": ["0x355a86d2", "0x7957db1c", "0xd21772af", "0x6fc1e09b", "0xd55ce61d", "0x6e6a278b", "0xd3f543ce", "0x223d8e82", "0x143ab337", "0x2e9f05bd", "0x2eb389bf", "0x0c6e449e", "0x5cfa4222", "0xba6560fe", "0x8e3e1aa4", "0xdbcc1d53"],
|
||||
"cache_last_line": ["0x41190d91", "0xbd277957", "0x22ddbb49", "0x6986f207", "0xdf69a4d6", "0x26401a3a", "0x818230fb", "0xc417122d", "0x3597b211", "0xb553ce55", "0xcf39cc0d", "0x3b7fc43a", "0x3fd43b00", "0x67e1c80e", "0xffa7ea7d", "0xca2960ab"],
|
||||
"cache_fnv1a64": "0x48c4f5bf24166b2e"
|
||||
}
|
||||
278
proto-cuda/packs-readwidth/mixA-5/kernel.cl
Normal file
278
proto-cuda/packs-readwidth/mixA-5/kernel.cl
Normal file
|
|
@ -0,0 +1,278 @@
|
|||
// Generated by igneum-pow export (generator v2) for seed "igneum-readwidth/A/6". Do not edit by hand.
|
||||
// OpenCL C twin of the Metal kernel for the same seed (see proto-opencl/README.md, WAVEFRONT.md and program.metal).
|
||||
// Built from source at runtime by proto-opencl/host.c, which passes these defines:
|
||||
// IGNEUM_GROUP work-group size of igneum_hash, a multiple of 32 (default 32: one work-group = one 32-lane unit)
|
||||
// IGNEUM_EXCHANGE 0 = local-memory exchange with a barrier (any device, any wave width; the default)
|
||||
// 1 = sub_group_shuffle_xor (cl_khr_subgroup_shuffle), only with IGNEUM_GROUP 32 and a sub-group size of exactly 32
|
||||
// 2 = intel_sub_group_shuffle_xor (cl_intel_subgroups), same condition
|
||||
// The verification unit is always 32 lanes. A 64-wide hardware wave (AMD GCN/CDNA, RDNA in wave64) runs two units;
|
||||
// the exchange masks are 1, 2, 4, 8, 16, so every partner lane lies inside the lane's own aligned run of 32.
|
||||
#ifndef IGNEUM_GROUP
|
||||
#define IGNEUM_GROUP 32
|
||||
#endif
|
||||
#ifndef IGNEUM_EXCHANGE
|
||||
#define IGNEUM_EXCHANGE 0
|
||||
#endif
|
||||
#ifdef __OPENCL_VERSION__
|
||||
#define IGNEUM_KERNEL_HASH __kernel __attribute__((reqd_work_group_size(IGNEUM_GROUP, 1, 1)))
|
||||
#define IGNEUM_LOCAL_WORDS(name, n) __local uint name[n]
|
||||
#if IGNEUM_EXCHANGE == 1
|
||||
#ifdef cl_khr_subgroups
|
||||
#pragma OPENCL EXTENSION cl_khr_subgroups : enable
|
||||
#endif
|
||||
#ifdef cl_khr_subgroup_shuffle
|
||||
#pragma OPENCL EXTENSION cl_khr_subgroup_shuffle : enable
|
||||
#endif
|
||||
#elif IGNEUM_EXCHANGE == 2
|
||||
#pragma OPENCL EXTENSION cl_intel_subgroups : enable
|
||||
#endif
|
||||
#else
|
||||
// Not an OpenCL compiler: proto-opencl/emu compiles this file as C++ and supplies the built-ins and these two macros.
|
||||
#include "emu_opencl.h"
|
||||
#endif
|
||||
|
||||
#if IGNEUM_EXCHANGE == 1
|
||||
#define IGNEUM_SHFL_XOR(dst, a, m) dst = sub_group_shuffle_xor((a), (uint)(m))
|
||||
#define IGNEUM_BCAST0(dst, a) dst = sub_group_broadcast((a), 0u)
|
||||
#elif IGNEUM_EXCHANGE == 2
|
||||
#define IGNEUM_SHFL_XOR(dst, a, m) dst = intel_sub_group_shuffle_xor((a), (uint)(m))
|
||||
#define IGNEUM_BCAST0(dst, a) dst = sub_group_broadcast((a), 0u)
|
||||
#else
|
||||
// Local-memory exchange. Two buffers of IGNEUM_GROUP words alternate (xk counts exchanges), so one barrier per
|
||||
// exchange is enough: a lane can only overwrite buffer b at exchange k+2 after passing barrier k+1, and every lane
|
||||
// reaches barrier k+1 only after its read of buffer b at exchange k. The partner lid ^ m stays inside the lane's
|
||||
// aligned run of 32 because m < 32. Control flow is uniform, so every work-item reaches every barrier.
|
||||
#define IGNEUM_SHFL_XOR(dst, a, m) { xch[(xk & 1u) * IGNEUM_GROUP + lid] = (a); barrier(CLK_LOCAL_MEM_FENCE); dst = xch[(xk & 1u) * IGNEUM_GROUP + (lid ^ (uint)(m))]; xk += 1u; }
|
||||
#define IGNEUM_BCAST0(dst, a) { xch[(xk & 1u) * IGNEUM_GROUP + lid] = (a); barrier(CLK_LOCAL_MEM_FENCE); dst = xch[(xk & 1u) * IGNEUM_GROUP + (lid & ~31u)]; xk += 1u; }
|
||||
#endif
|
||||
|
||||
static inline uint splitmix32(uint x) {
|
||||
x ^= x >> 16; x *= 0x7feb352du;
|
||||
x ^= x >> 15; x *= 0x846ca68bu;
|
||||
x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
// n is a literal in 1..31 at every call site. OpenCL rotate() rotates left by n modulo 32.
|
||||
static inline uint rotl_imm(uint x, uint n) { return rotate(x, n); }
|
||||
// Right rotation by n modulo 32 as a left rotation by (32 - n) modulo 32; n == 0 gives x.
|
||||
static inline uint rotr_var(uint x, uint n) { return rotate(x, (0u - n) & 31u); }
|
||||
static inline uint ds_elem(uint i, uint d0, uint d1) {
|
||||
uint x = i ^ d0;
|
||||
x *= 0x9E3779B1u; x ^= x >> 15;
|
||||
x += d1;
|
||||
x *= 0x85EBCA77u; x ^= x >> 13;
|
||||
x *= 0xC2B2AE3Du; x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
|
||||
// Memory-hard dataset core (MEMHARD.md). Cache: 2^26 words in 2^16 segments of 64 chained ChaCha12 lines.
|
||||
// Item: 8 rounds of seed-parameterised mixer + one 64-byte cache read, then a final mixer. All parameters are literals.
|
||||
#define MH_CACHE_LINE_MASK 0x003fffffu
|
||||
#define MH_SEGMENT_LINES 64u
|
||||
#define MH_QR(a, b, c, d, r1, r2, r3, r4) { a += b; d ^= a; d = mh_rotl(d, r1); c += d; b ^= c; b = mh_rotl(b, r2); a += b; d ^= a; d = mh_rotl(d, r3); c += d; b ^= c; b = mh_rotl(b, r4); }
|
||||
static inline uint mh_rotl(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 at every call site
|
||||
|
||||
// y = ChaCha12 core(x) + x
|
||||
static inline void mh_chacha_block(const uint* x, uint* y) {
|
||||
for (uint i = 0u; i < 16u; ++i) y[i] = x[i];
|
||||
for (uint r = 0u; r < 6u; ++r) {
|
||||
MH_QR(y[0], y[4], y[8], y[12], 16u, 12u, 8u, 7u) MH_QR(y[1], y[5], y[9], y[13], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[2], y[6], y[10], y[14], 16u, 12u, 8u, 7u) MH_QR(y[3], y[7], y[11], y[15], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[0], y[5], y[10], y[15], 16u, 12u, 8u, 7u) MH_QR(y[1], y[6], y[11], y[12], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[2], y[7], y[8], y[13], 16u, 12u, 8u, 7u) MH_QR(y[3], y[4], y[9], y[14], 16u, 12u, 8u, 7u)
|
||||
}
|
||||
for (uint i = 0u; i < 16u; ++i) y[i] += x[i];
|
||||
}
|
||||
|
||||
// One cache segment: 64 chained lines written at cache[seg * 1024]. in_j = prev ^ (sigma || K || seg || j || tag), prev_0 = 0.
|
||||
static inline void mh_cache_segment(__global uint* cache, uint seg) {
|
||||
uint prev[16]; uint x[16]; uint y[16];
|
||||
for (uint i = 0u; i < 16u; ++i) prev[i] = 0u;
|
||||
for (uint j = 0u; j < MH_SEGMENT_LINES; ++j) {
|
||||
x[0] = 0x61707865u ^ prev[0]; x[1] = 0x3320646eu ^ prev[1]; x[2] = 0x79622d32u ^ prev[2]; x[3] = 0x6b206574u ^ prev[3];
|
||||
x[4] = 0x3067619fu ^ prev[4];
|
||||
x[5] = 0x3c269176u ^ prev[5];
|
||||
x[6] = 0x84a03b03u ^ prev[6];
|
||||
x[7] = 0xf8c63294u ^ prev[7];
|
||||
x[8] = 0xff977c5bu ^ prev[8];
|
||||
x[9] = 0xe60def3eu ^ prev[9];
|
||||
x[10] = 0x63630141u ^ prev[10];
|
||||
x[11] = 0xb8fbcb58u ^ prev[11];
|
||||
x[12] = seg ^ prev[12]; x[13] = j ^ prev[13]; x[14] = 0x49676e65u ^ prev[14]; x[15] = 0x756d4d48u ^ prev[15];
|
||||
mh_chacha_block(x, y);
|
||||
__global uint* line = cache + ((seg * MH_SEGMENT_LINES + j) * 16u);
|
||||
for (uint i = 0u; i < 16u; ++i) { line[i] = y[i]; prev[i] = y[i]; }
|
||||
}
|
||||
}
|
||||
|
||||
// M_r: per word (s ^ (RC + rk)) * MUL, then a column round and a diagonal round with the seed-drawn rotations.
|
||||
static inline void mh_mixer(uint* s, uint rk) {
|
||||
s[0] = (s[0] ^ (0xbab68293u + rk)) * 0x42146205u;
|
||||
s[1] = (s[1] ^ (0xcc162340u + rk)) * 0x52cbe0fbu;
|
||||
s[2] = (s[2] ^ (0x6ce151ccu + rk)) * 0x7ecf4a03u;
|
||||
s[3] = (s[3] ^ (0xe62b8997u + rk)) * 0x6728907fu;
|
||||
s[4] = (s[4] ^ (0xc9c80297u + rk)) * 0xd81d9751u;
|
||||
s[5] = (s[5] ^ (0xf74a1654u + rk)) * 0x132952c3u;
|
||||
s[6] = (s[6] ^ (0x3d704af5u + rk)) * 0xf60de277u;
|
||||
s[7] = (s[7] ^ (0x3cf522b7u + rk)) * 0x05358035u;
|
||||
s[8] = (s[8] ^ (0x2b9cac04u + rk)) * 0xbaf6499du;
|
||||
s[9] = (s[9] ^ (0xa880ac10u + rk)) * 0xe4db9667u;
|
||||
s[10] = (s[10] ^ (0x13e5dd1du + rk)) * 0x3e98f45du;
|
||||
s[11] = (s[11] ^ (0x6fc3e233u + rk)) * 0xd0004eddu;
|
||||
s[12] = (s[12] ^ (0x2d83eeacu + rk)) * 0x2691630du;
|
||||
s[13] = (s[13] ^ (0x9006e8bfu + rk)) * 0x9beb3bcfu;
|
||||
s[14] = (s[14] ^ (0x2c4b5362u + rk)) * 0xab310379u;
|
||||
s[15] = (s[15] ^ (0x31b49ee2u + rk)) * 0x99cfb423u;
|
||||
MH_QR(s[0], s[4], s[8], s[12], 20u, 20u, 19u, 4u) MH_QR(s[1], s[5], s[9], s[13], 20u, 20u, 19u, 4u)
|
||||
MH_QR(s[2], s[6], s[10], s[14], 20u, 20u, 19u, 4u) MH_QR(s[3], s[7], s[11], s[15], 20u, 20u, 19u, 4u)
|
||||
MH_QR(s[0], s[5], s[10], s[15], 26u, 3u, 3u, 27u) MH_QR(s[1], s[6], s[11], s[12], 26u, 3u, 3u, 27u)
|
||||
MH_QR(s[2], s[7], s[8], s[13], 26u, 3u, 3u, 27u) MH_QR(s[3], s[4], s[9], s[14], 26u, 3u, 3u, 27u)
|
||||
}
|
||||
|
||||
// Item t: 16 words. s = (K, t * MUL[i] + RC[i]); 8 rounds of mixer + cache line s[0] & mask; final mixer.
|
||||
static inline void mh_item(__global const uint* cache, uint t, uint* s) {
|
||||
s[0] = 0x3067619fu;
|
||||
s[1] = 0x3c269176u;
|
||||
s[2] = 0x84a03b03u;
|
||||
s[3] = 0xf8c63294u;
|
||||
s[4] = 0xff977c5bu;
|
||||
s[5] = 0xe60def3eu;
|
||||
s[6] = 0x63630141u;
|
||||
s[7] = 0xb8fbcb58u;
|
||||
s[8] = t * 0x42146205u + 0xbab68293u;
|
||||
s[9] = t * 0x52cbe0fbu + 0xcc162340u;
|
||||
s[10] = t * 0x7ecf4a03u + 0x6ce151ccu;
|
||||
s[11] = t * 0x6728907fu + 0xe62b8997u;
|
||||
s[12] = t * 0xd81d9751u + 0xc9c80297u;
|
||||
s[13] = t * 0x132952c3u + 0xf74a1654u;
|
||||
s[14] = t * 0xf60de277u + 0x3d704af5u;
|
||||
s[15] = t * 0x05358035u + 0x3cf522b7u;
|
||||
for (uint r = 0u; r < 8u; ++r) {
|
||||
mh_mixer(s, 0x9E3779B9u * (r + 1u));
|
||||
__global const uint* line = cache + ((s[0] & MH_CACHE_LINE_MASK) * 16u);
|
||||
for (uint i = 0u; i < 16u; ++i) s[i] ^= line[i];
|
||||
}
|
||||
mh_mixer(s, 0x9E3779B9u * 9u);
|
||||
}
|
||||
// dataset[w] without the dataset: derive item w >> 4 and take word w & 15.
|
||||
static inline uint mh_word(__global const uint* cache, uint w) { uint s[16]; mh_item(cache, w >> 4u, s); return s[w & 15u]; }
|
||||
|
||||
// Memory-hard dataset (MEMHARD.md). One work-item per cache segment; one work-item per 64-byte dataset item.
|
||||
// The same constants as memhard.h in this pack (one emitter, three dialects).
|
||||
__kernel void igneum_cache_fill(__global uint* cache, uint nSegments) {
|
||||
uint seg = (uint)get_global_id(0);
|
||||
if (seg < nSegments) mh_cache_segment(cache, seg);
|
||||
}
|
||||
__kernel void igneum_build(__global uint* ds, __global const uint* cache, uint nItems) {
|
||||
uint t = (uint)get_global_id(0);
|
||||
if (t < nItems) {
|
||||
uint s[16];
|
||||
mh_item(cache, t, s);
|
||||
__global uint* d = ds + ((ulong)t * 16u);
|
||||
for (uint i = 0u; i < 16u; ++i) d[i] = s[i];
|
||||
}
|
||||
}
|
||||
|
||||
// One hash per work-item. IGNEUM_GROUP is a multiple of 32; lane = lid & 31 and every exchange stays inside the
|
||||
// lane's own aligned run of 32 work-items, exactly like simd_shuffle_xor inside a 32-wide Metal SIMD group and
|
||||
// __shfl_xor_sync inside a CUDA warp. Control flow is uniform (no branches at all).
|
||||
IGNEUM_KERNEL_HASH void igneum_hash(__global const uint* ds, __global ulong* out, uint baseNonce, uint mask) {
|
||||
uint gid = (uint)get_global_id(0);
|
||||
uint lid = (uint)get_local_id(0);
|
||||
uint nonce = baseNonce + gid;
|
||||
uint r0, r1, r2, r3, r4, r5, r6, r7;
|
||||
#if IGNEUM_EXCHANGE == 0
|
||||
IGNEUM_LOCAL_WORDS(xch, 2 * IGNEUM_GROUP);
|
||||
uint xk = 0u;
|
||||
#else
|
||||
(void)lid;
|
||||
#endif
|
||||
{ uint x = nonce ^ 0x2a53aad4u; x += 0x9e3779b9u; x = splitmix32(x); r0 = x ^ 0x37fcb6e2u; } // SEEDW[0], 0x9e3779b9u * 1u, SEEDW[1]
|
||||
{ uint x = nonce ^ 0x37fcb6e2u; x += 0x3c6ef372u; x = splitmix32(x); r1 = x ^ 0x25d66a27u; } // SEEDW[1], 0x9e3779b9u * 2u, SEEDW[2]
|
||||
{ uint x = nonce ^ 0x25d66a27u; x += 0xdaa66d2bu; x = splitmix32(x); r2 = x ^ 0xf5249e5eu; } // SEEDW[2], 0x9e3779b9u * 3u, SEEDW[3]
|
||||
{ uint x = nonce ^ 0xf5249e5eu; x += 0x78dde6e4u; x = splitmix32(x); r3 = x ^ 0x15f86a59u; } // SEEDW[3], 0x9e3779b9u * 4u, SEEDW[4]
|
||||
{ uint x = nonce ^ 0x15f86a59u; x += 0x1715609du; x = splitmix32(x); r4 = x ^ 0x8144559au; } // SEEDW[4], 0x9e3779b9u * 5u, SEEDW[5]
|
||||
{ uint x = nonce ^ 0x8144559au; x += 0xb54cda56u; x = splitmix32(x); r5 = x ^ 0xcad741a6u; } // SEEDW[5], 0x9e3779b9u * 6u, SEEDW[6]
|
||||
{ uint x = nonce ^ 0xcad741a6u; x += 0x5384540fu; x = splitmix32(x); r6 = x ^ 0xcb961373u; } // SEEDW[6], 0x9e3779b9u * 7u, SEEDW[7]
|
||||
{ uint x = nonce ^ 0xcb961373u; x += 0xf1bbcdc8u; x = splitmix32(x); r7 = x ^ 0x2a53aad4u; } // SEEDW[7], 0x9e3779b9u * 8u, SEEDW[0]
|
||||
|
||||
for (uint it = 0u; it < 8u; ++it) {
|
||||
uint sel = r0;
|
||||
r0 = rotl_imm(r0, 10u); // 0 rotl
|
||||
r5 = r3 * r1 + r5; // 1 mad
|
||||
{ uint b_ = (r0 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r5 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r5 = x_; } // 2 load
|
||||
{ uint b_ = (r5 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r6 = x_; } // 3 load
|
||||
r5 = r2 * r2 + r5; // 4 mad
|
||||
r4 = r4 + r3 + ((((sel >> 10u) & 1u) != 0u) ? 0x4edf355au : 0xbd587d10u); // 5 add
|
||||
r3 = r3 ^ r2; // 6 xor
|
||||
r5 = r5 ^ r3; // 7 xor
|
||||
r7 = r6 * r2 + r7; // 8 mad
|
||||
r7 = r6 * r3 + r7; // 9 mad
|
||||
{ uint b_ = (r5 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r3 = x_; } // 10 load
|
||||
r1 = mul_hi(r1, r4); // 11 mulhi
|
||||
r1 = r1 ^ r6; // 12 xor
|
||||
r2 = mul_hi(r2, r1); // 13 mulhi
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r7, 4u); r6 = r6 ^ t_; } // 14 shfl
|
||||
r4 = r6 * r4 + r4; // 15 mad
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r0, 8u); r1 = r1 ^ t_; } // 16 shfl
|
||||
r5 = r5 ^ r4; // 17 xor
|
||||
r0 = r0 * r2; // 18 mul
|
||||
r6 = r6 ^ ds[r3 & mask]; // 19 load
|
||||
r6 = mul_hi(r6, r2); // 20 mulhi
|
||||
r7 = r2 * r6 + r7; // 21 mad
|
||||
r4 = r4 * r5; // 22 mul
|
||||
r3 = r3 * r5; // 23 mul
|
||||
r6 = r6 * r4; // 24 mul
|
||||
r3 = r3 ^ ds[r7 & mask]; // 25 load
|
||||
r2 = rotr_var(r2, r5); // 26 rotr
|
||||
r5 = r5 | r6; // 27 or
|
||||
{ uint b_ = (r2 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r4 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r4 = x_; } // 28 load
|
||||
r6 = r6 | r0; // 29 or
|
||||
r0 = r0 + r3 + ((((sel >> 2u) & 1u) != 0u) ? 0xdca976acu : 0x5faa0547u); // 30 add
|
||||
r6 = mul_hi(r6, r0); // 31 mulhi
|
||||
r3 = rotr_var(r3, r7); // 32 rotr
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r4, 4u); r0 = r0 ^ t_; } // 33 shfl
|
||||
r2 = rotl_imm(r2, 17u); // 34 rotl
|
||||
r7 = mul_hi(r7, r6); // 35 mulhi
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r2, 2u); r3 = r3 ^ t_; } // 36 shfl
|
||||
r6 = r6 ^ ds[r0 & mask]; // 37 load
|
||||
{ uint b_ = (r6 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r0 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r0 = x_; } // 38 load
|
||||
r1 = r1 ^ r0; // 39 xor
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r1, 2u); r3 = r3 ^ t_; } // 40 shfl
|
||||
r1 = r1 ^ ds[r5 & mask]; // 41 load
|
||||
r3 = r3 * r2; // 42 mul
|
||||
r2 = r2 ^ ds[r7 & mask]; // 43 load
|
||||
r7 = r7 + r3 + ((((sel >> 7u) & 1u) != 0u) ? 0x610bd3c2u : 0xe28c457cu); // 44 add
|
||||
r7 = mul_hi(r7, r6); // 45 mulhi
|
||||
r3 = r3 ^ r4; // 46 xor
|
||||
r3 = r3 ^ ds[r7 & mask]; // 47 load
|
||||
r7 = mul_hi(r7, r2); // 48 mulhi
|
||||
r6 = mul_hi(r6, r3); // 49 mulhi
|
||||
{ uint b_ = (r1 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r2 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r2 = x_; } // 50 load
|
||||
{ uint b_ = (r3 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r6 = x_; } // 51 load
|
||||
r5 = r5 ^ r3; // 52 xor
|
||||
r5 = r5 + r7 + ((((sel >> 31u) & 1u) != 0u) ? 0xcca8fa7cu : 0xd6457f6eu); // 53 add
|
||||
r7 = rotr_var(r7, r1); // 54 rotr
|
||||
r6 = r6 + r7 + ((((sel >> 12u) & 1u) != 0u) ? 0x826cb755u : 0xf3e1301cu); // 55 add
|
||||
{ uint b_ = (r0 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r3 = x_; } // 56 load
|
||||
r1 = rotr_var(r1, r5); // 57 rotr
|
||||
{ uint b_ = (r6 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r2 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r2 = x_; } // 58 load
|
||||
r3 = r3 - r7; // 59 sub
|
||||
r1 = r4 * r6 + r1; // 60 mad
|
||||
r2 = r1 * r2 + r2; // 61 mad
|
||||
r4 = r4 ^ r3; // 62 xor
|
||||
r2 = r2 ^ ds[r4 & mask]; // 63 load
|
||||
}
|
||||
uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u);
|
||||
uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u);
|
||||
out[gid] = ((ulong)hi << 32) | (ulong)lo;
|
||||
}
|
||||
|
||||
#if IGNEUM_EXCHANGE != 0
|
||||
// Reports the sub-group size this device uses for a work-group of IGNEUM_GROUP items. host.c runs it only when the
|
||||
// per-kernel query (clGetKernelSubGroupInfoKHR on igneum_hash) is unavailable; that query is preferred because a
|
||||
// compiler may pick a different wave width per kernel (RDNA: wave32 or wave64). See WAVEFRONT.md.
|
||||
IGNEUM_KERNEL_HASH void igneum_probe_subgroup(__global uint* out) {
|
||||
if (get_local_id(0) == 0u) { out[0] = get_sub_group_size(); out[1] = get_num_sub_groups(); }
|
||||
}
|
||||
#endif
|
||||
164
proto-cuda/packs-readwidth/mixA-5/kernel.cu
Normal file
164
proto-cuda/packs-readwidth/mixA-5/kernel.cu
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
// Generated by igneum-pow export (generator v2) for seed "igneum-readwidth/A/6". Do not edit by hand.
|
||||
// Bit-exact twin of the Metal kernel for the same seed (see proto-cuda/CHECKLIST.md and program.metal).
|
||||
// Compiled ahead of time by nvcc together with proto-cuda/host.cu. No NVRTC.
|
||||
#include <cuda_runtime.h>
|
||||
#include <cstdint>
|
||||
#include "program.h"
|
||||
#include "memhard.h"
|
||||
|
||||
__device__ __forceinline__ uint32_t splitmix32(uint32_t x) {
|
||||
x ^= x >> 16; x *= 0x7feb352du;
|
||||
x ^= x >> 15; x *= 0x846ca68bu;
|
||||
x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
// n is a literal in 1..31 at every call site, so both shift amounts are in 1..31.
|
||||
__device__ __forceinline__ uint32_t rotl_imm(uint32_t x, uint32_t n) { return (x << n) | (x >> (32u - n)); }
|
||||
// n is masked to 0..31; the second shift amount is masked too, so n == 0 gives x.
|
||||
__device__ __forceinline__ uint32_t rotr_var(uint32_t x, uint32_t n) { n &= 31u; return (x >> n) | (x << ((32u - n) & 31u)); }
|
||||
__device__ __forceinline__ uint32_t ds_elem(uint32_t i, uint32_t d0, uint32_t d1) {
|
||||
uint32_t x = i ^ d0;
|
||||
x *= 0x9E3779B1u; x ^= x >> 15;
|
||||
x += d1;
|
||||
x *= 0x85EBCA77u; x ^= x >> 13;
|
||||
x *= 0xC2B2AE3Du; x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
|
||||
// Memory-hard dataset (MEMHARD.md). One thread per cache segment; one thread per 64-byte dataset item.
|
||||
// The core functions (mh_cache_segment, mh_item) are in memhard.h and are also compiled for the host.
|
||||
__global__ void igneum_cache_fill(uint32_t* cache, uint32_t nSegments) {
|
||||
uint32_t seg = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
if (seg < nSegments) mh_cache_segment(cache, seg);
|
||||
}
|
||||
__global__ void igneum_build(uint32_t* ds, const uint32_t* cache, uint32_t nItems) {
|
||||
uint32_t t = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
if (t < nItems) {
|
||||
uint32_t s[16];
|
||||
mh_item(cache, t, s);
|
||||
uint32_t* d = ds + (size_t)t * 16u;
|
||||
for (uint32_t i = 0u; i < 16u; ++i) d[i] = s[i];
|
||||
}
|
||||
}
|
||||
|
||||
// One hash per thread. blockDim.x is a multiple of 32; lane = threadIdx.x & 31 and every
|
||||
// __shfl_xor_sync stays inside the lane's own warp, exactly like simd_shuffle_xor inside a
|
||||
// 32-wide Metal SIMD group. Control flow is uniform, so the full 0xffffffff member mask is valid.
|
||||
__global__ void igneum_hash(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask) {
|
||||
uint32_t gid = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
uint32_t nonce = baseNonce + gid;
|
||||
uint32_t r0, r1, r2, r3, r4, r5, r6, r7;
|
||||
{ uint32_t x = nonce ^ 0x2a53aad4u; x += 0x9e3779b9u; x = splitmix32(x); r0 = x ^ 0x37fcb6e2u; } // SEEDW[0], 0x9e3779b9u * 1u, SEEDW[1]
|
||||
{ uint32_t x = nonce ^ 0x37fcb6e2u; x += 0x3c6ef372u; x = splitmix32(x); r1 = x ^ 0x25d66a27u; } // SEEDW[1], 0x9e3779b9u * 2u, SEEDW[2]
|
||||
{ uint32_t x = nonce ^ 0x25d66a27u; x += 0xdaa66d2bu; x = splitmix32(x); r2 = x ^ 0xf5249e5eu; } // SEEDW[2], 0x9e3779b9u * 3u, SEEDW[3]
|
||||
{ uint32_t x = nonce ^ 0xf5249e5eu; x += 0x78dde6e4u; x = splitmix32(x); r3 = x ^ 0x15f86a59u; } // SEEDW[3], 0x9e3779b9u * 4u, SEEDW[4]
|
||||
{ uint32_t x = nonce ^ 0x15f86a59u; x += 0x1715609du; x = splitmix32(x); r4 = x ^ 0x8144559au; } // SEEDW[4], 0x9e3779b9u * 5u, SEEDW[5]
|
||||
{ uint32_t x = nonce ^ 0x8144559au; x += 0xb54cda56u; x = splitmix32(x); r5 = x ^ 0xcad741a6u; } // SEEDW[5], 0x9e3779b9u * 6u, SEEDW[6]
|
||||
{ uint32_t x = nonce ^ 0xcad741a6u; x += 0x5384540fu; x = splitmix32(x); r6 = x ^ 0xcb961373u; } // SEEDW[6], 0x9e3779b9u * 7u, SEEDW[7]
|
||||
{ uint32_t x = nonce ^ 0xcb961373u; x += 0xf1bbcdc8u; x = splitmix32(x); r7 = x ^ 0x2a53aad4u; } // SEEDW[7], 0x9e3779b9u * 8u, SEEDW[0]
|
||||
|
||||
for (uint32_t it = 0u; it < 8u; ++it) {
|
||||
uint32_t sel = r0;
|
||||
r0 = rotl_imm(r0, 10u); // 0 rotl
|
||||
r5 = r3 * r1 + r5; // 1 mad
|
||||
{ uint32_t b_ = (r0 & mask) & ~15u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint32_t x_ = r5 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r5 = x_; } // 2 load
|
||||
{ uint32_t b_ = (r5 & mask) & ~3u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint32_t x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r6 = x_; } // 3 load
|
||||
r5 = r2 * r2 + r5; // 4 mad
|
||||
r4 = r4 + r3 + ((((sel >> 10u) & 1u) != 0u) ? 0x4edf355au : 0xbd587d10u); // 5 add
|
||||
r3 = r3 ^ r2; // 6 xor
|
||||
r5 = r5 ^ r3; // 7 xor
|
||||
r7 = r6 * r2 + r7; // 8 mad
|
||||
r7 = r6 * r3 + r7; // 9 mad
|
||||
{ uint32_t b_ = (r5 & mask) & ~15u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint32_t x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r3 = x_; } // 10 load
|
||||
r1 = __umulhi(r1, r4); // 11 mulhi
|
||||
r1 = r1 ^ r6; // 12 xor
|
||||
r2 = __umulhi(r2, r1); // 13 mulhi
|
||||
r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r7, 4); // 14 shfl
|
||||
r4 = r6 * r4 + r4; // 15 mad
|
||||
r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r0, 8); // 16 shfl
|
||||
r5 = r5 ^ r4; // 17 xor
|
||||
r0 = r0 * r2; // 18 mul
|
||||
r6 = r6 ^ ds[r3 & mask]; // 19 load
|
||||
r6 = __umulhi(r6, r2); // 20 mulhi
|
||||
r7 = r2 * r6 + r7; // 21 mad
|
||||
r4 = r4 * r5; // 22 mul
|
||||
r3 = r3 * r5; // 23 mul
|
||||
r6 = r6 * r4; // 24 mul
|
||||
r3 = r3 ^ ds[r7 & mask]; // 25 load
|
||||
r2 = rotr_var(r2, r5); // 26 rotr
|
||||
r5 = r5 | r6; // 27 or
|
||||
{ uint32_t b_ = (r2 & mask) & ~3u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint32_t x_ = r4 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r4 = x_; } // 28 load
|
||||
r6 = r6 | r0; // 29 or
|
||||
r0 = r0 + r3 + ((((sel >> 2u) & 1u) != 0u) ? 0xdca976acu : 0x5faa0547u); // 30 add
|
||||
r6 = __umulhi(r6, r0); // 31 mulhi
|
||||
r3 = rotr_var(r3, r7); // 32 rotr
|
||||
r0 = r0 ^ __shfl_xor_sync(0xffffffffu, r4, 4); // 33 shfl
|
||||
r2 = rotl_imm(r2, 17u); // 34 rotl
|
||||
r7 = __umulhi(r7, r6); // 35 mulhi
|
||||
r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r2, 2); // 36 shfl
|
||||
r6 = r6 ^ ds[r0 & mask]; // 37 load
|
||||
{ uint32_t b_ = (r6 & mask) & ~15u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint32_t x_ = r0 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r0 = x_; } // 38 load
|
||||
r1 = r1 ^ r0; // 39 xor
|
||||
r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r1, 2); // 40 shfl
|
||||
r1 = r1 ^ ds[r5 & mask]; // 41 load
|
||||
r3 = r3 * r2; // 42 mul
|
||||
r2 = r2 ^ ds[r7 & mask]; // 43 load
|
||||
r7 = r7 + r3 + ((((sel >> 7u) & 1u) != 0u) ? 0x610bd3c2u : 0xe28c457cu); // 44 add
|
||||
r7 = __umulhi(r7, r6); // 45 mulhi
|
||||
r3 = r3 ^ r4; // 46 xor
|
||||
r3 = r3 ^ ds[r7 & mask]; // 47 load
|
||||
r7 = __umulhi(r7, r2); // 48 mulhi
|
||||
r6 = __umulhi(r6, r3); // 49 mulhi
|
||||
{ uint32_t b_ = (r1 & mask) & ~15u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint32_t x_ = r2 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r2 = x_; } // 50 load
|
||||
{ uint32_t b_ = (r3 & mask) & ~15u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint32_t x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r6 = x_; } // 51 load
|
||||
r5 = r5 ^ r3; // 52 xor
|
||||
r5 = r5 + r7 + ((((sel >> 31u) & 1u) != 0u) ? 0xcca8fa7cu : 0xd6457f6eu); // 53 add
|
||||
r7 = rotr_var(r7, r1); // 54 rotr
|
||||
r6 = r6 + r7 + ((((sel >> 12u) & 1u) != 0u) ? 0x826cb755u : 0xf3e1301cu); // 55 add
|
||||
{ uint32_t b_ = (r0 & mask) & ~15u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint32_t x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r3 = x_; } // 56 load
|
||||
r1 = rotr_var(r1, r5); // 57 rotr
|
||||
{ uint32_t b_ = (r6 & mask) & ~3u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint32_t x_ = r2 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r2 = x_; } // 58 load
|
||||
r3 = r3 - r7; // 59 sub
|
||||
r1 = r4 * r6 + r1; // 60 mad
|
||||
r2 = r1 * r2 + r2; // 61 mad
|
||||
r4 = r4 ^ r3; // 62 xor
|
||||
r2 = r2 ^ ds[r4 & mask]; // 63 load
|
||||
}
|
||||
uint32_t lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u);
|
||||
uint32_t hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u);
|
||||
out[gid] = ((uint64_t)hi << 32) | (uint64_t)lo;
|
||||
}
|
||||
|
||||
// Host-side launch wrappers. Declared in program.h, called from host.cu.
|
||||
cudaError_t igneum_launch_cache_fill(uint32_t* cache, uint32_t nSegments) {
|
||||
if (nSegments == 0u) return cudaErrorInvalidValue;
|
||||
uint32_t block = 256u;
|
||||
uint32_t grid = (nSegments + block - 1u) / block;
|
||||
igneum_cache_fill<<<grid, block>>>(cache, nSegments);
|
||||
return cudaGetLastError();
|
||||
}
|
||||
|
||||
cudaError_t igneum_launch_build(uint32_t* ds, const uint32_t* cache, uint32_t nItems) {
|
||||
if (nItems == 0u) return cudaErrorInvalidValue;
|
||||
uint32_t block = 256u;
|
||||
uint32_t grid = (nItems + block - 1u) / block;
|
||||
igneum_build<<<grid, block>>>(ds, cache, nItems);
|
||||
return cudaGetLastError();
|
||||
}
|
||||
|
||||
cudaError_t igneum_launch_hash(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask,
|
||||
uint32_t nonces, uint32_t blockWarps) {
|
||||
if (blockWarps == 0u || blockWarps > 32u) return cudaErrorInvalidValue;
|
||||
uint32_t block = 32u * blockWarps;
|
||||
if (nonces == 0u || (nonces % block) != 0u) return cudaErrorInvalidValue;
|
||||
igneum_hash<<<nonces / block, block>>>(ds, out, baseNonce, mask);
|
||||
return cudaGetLastError();
|
||||
}
|
||||
|
||||
cudaError_t igneum_hash_info(int* numRegs, int* blocksPerSM, uint32_t blockWarps) {
|
||||
cudaFuncAttributes attr;
|
||||
cudaError_t e = cudaFuncGetAttributes(&attr, igneum_hash);
|
||||
if (e != cudaSuccess) return e;
|
||||
*numRegs = attr.numRegs;
|
||||
return cudaOccupancyMaxActiveBlocksPerMultiprocessor(blocksPerSM, igneum_hash, (int)(32u * blockWarps), 0);
|
||||
}
|
||||
372
proto-cuda/packs-readwidth/mixA-5/kernel_bound.cl
Normal file
372
proto-cuda/packs-readwidth/mixA-5/kernel_bound.cl
Normal file
|
|
@ -0,0 +1,372 @@
|
|||
// Generated by igneum-pow export (generator v2) for seed "igneum-readwidth/A/6". Do not edit by hand.
|
||||
// OpenCL C twin of the Metal kernel for the same seed (see proto-opencl/README.md, WAVEFRONT.md and program.metal).
|
||||
// Built from source at runtime by proto-opencl/host.c, which passes these defines:
|
||||
// IGNEUM_GROUP work-group size of igneum_hash, a multiple of 32 (default 32: one work-group = one 32-lane unit)
|
||||
// IGNEUM_EXCHANGE 0 = local-memory exchange with a barrier (any device, any wave width; the default)
|
||||
// 1 = sub_group_shuffle_xor (cl_khr_subgroup_shuffle), only with IGNEUM_GROUP 32 and a sub-group size of exactly 32
|
||||
// 2 = intel_sub_group_shuffle_xor (cl_intel_subgroups), same condition
|
||||
// The verification unit is always 32 lanes. A 64-wide hardware wave (AMD GCN/CDNA, RDNA in wave64) runs two units;
|
||||
// the exchange masks are 1, 2, 4, 8, 16, so every partner lane lies inside the lane's own aligned run of 32.
|
||||
#ifndef IGNEUM_GROUP
|
||||
#define IGNEUM_GROUP 32
|
||||
#endif
|
||||
#ifndef IGNEUM_EXCHANGE
|
||||
#define IGNEUM_EXCHANGE 0
|
||||
#endif
|
||||
#ifdef __OPENCL_VERSION__
|
||||
#define IGNEUM_KERNEL_HASH __kernel __attribute__((reqd_work_group_size(IGNEUM_GROUP, 1, 1)))
|
||||
#define IGNEUM_LOCAL_WORDS(name, n) __local uint name[n]
|
||||
#if IGNEUM_EXCHANGE == 1
|
||||
#ifdef cl_khr_subgroups
|
||||
#pragma OPENCL EXTENSION cl_khr_subgroups : enable
|
||||
#endif
|
||||
#ifdef cl_khr_subgroup_shuffle
|
||||
#pragma OPENCL EXTENSION cl_khr_subgroup_shuffle : enable
|
||||
#endif
|
||||
#elif IGNEUM_EXCHANGE == 2
|
||||
#pragma OPENCL EXTENSION cl_intel_subgroups : enable
|
||||
#endif
|
||||
#else
|
||||
// Not an OpenCL compiler: proto-opencl/emu compiles this file as C++ and supplies the built-ins and these two macros.
|
||||
#include "emu_opencl.h"
|
||||
#endif
|
||||
|
||||
#if IGNEUM_EXCHANGE == 1
|
||||
#define IGNEUM_SHFL_XOR(dst, a, m) dst = sub_group_shuffle_xor((a), (uint)(m))
|
||||
#define IGNEUM_BCAST0(dst, a) dst = sub_group_broadcast((a), 0u)
|
||||
#elif IGNEUM_EXCHANGE == 2
|
||||
#define IGNEUM_SHFL_XOR(dst, a, m) dst = intel_sub_group_shuffle_xor((a), (uint)(m))
|
||||
#define IGNEUM_BCAST0(dst, a) dst = sub_group_broadcast((a), 0u)
|
||||
#else
|
||||
// Local-memory exchange. Two buffers of IGNEUM_GROUP words alternate (xk counts exchanges), so one barrier per
|
||||
// exchange is enough: a lane can only overwrite buffer b at exchange k+2 after passing barrier k+1, and every lane
|
||||
// reaches barrier k+1 only after its read of buffer b at exchange k. The partner lid ^ m stays inside the lane's
|
||||
// aligned run of 32 because m < 32. Control flow is uniform, so every work-item reaches every barrier.
|
||||
#define IGNEUM_SHFL_XOR(dst, a, m) { xch[(xk & 1u) * IGNEUM_GROUP + lid] = (a); barrier(CLK_LOCAL_MEM_FENCE); dst = xch[(xk & 1u) * IGNEUM_GROUP + (lid ^ (uint)(m))]; xk += 1u; }
|
||||
#define IGNEUM_BCAST0(dst, a) { xch[(xk & 1u) * IGNEUM_GROUP + lid] = (a); barrier(CLK_LOCAL_MEM_FENCE); dst = xch[(xk & 1u) * IGNEUM_GROUP + (lid & ~31u)]; xk += 1u; }
|
||||
#endif
|
||||
|
||||
static inline uint splitmix32(uint x) {
|
||||
x ^= x >> 16; x *= 0x7feb352du;
|
||||
x ^= x >> 15; x *= 0x846ca68bu;
|
||||
x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
// n is a literal in 1..31 at every call site. OpenCL rotate() rotates left by n modulo 32.
|
||||
static inline uint rotl_imm(uint x, uint n) { return rotate(x, n); }
|
||||
// Right rotation by n modulo 32 as a left rotation by (32 - n) modulo 32; n == 0 gives x.
|
||||
static inline uint rotr_var(uint x, uint n) { return rotate(x, (0u - n) & 31u); }
|
||||
static inline uint ds_elem(uint i, uint d0, uint d1) {
|
||||
uint x = i ^ d0;
|
||||
x *= 0x9E3779B1u; x ^= x >> 15;
|
||||
x += d1;
|
||||
x *= 0x85EBCA77u; x ^= x >> 13;
|
||||
x *= 0xC2B2AE3Du; x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
|
||||
// Memory-hard dataset core (MEMHARD.md). Cache: 2^26 words in 2^16 segments of 64 chained ChaCha12 lines.
|
||||
// Item: 8 rounds of seed-parameterised mixer + one 64-byte cache read, then a final mixer. All parameters are literals.
|
||||
#define MH_CACHE_LINE_MASK 0x003fffffu
|
||||
#define MH_SEGMENT_LINES 64u
|
||||
#define MH_QR(a, b, c, d, r1, r2, r3, r4) { a += b; d ^= a; d = mh_rotl(d, r1); c += d; b ^= c; b = mh_rotl(b, r2); a += b; d ^= a; d = mh_rotl(d, r3); c += d; b ^= c; b = mh_rotl(b, r4); }
|
||||
static inline uint mh_rotl(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 at every call site
|
||||
|
||||
// y = ChaCha12 core(x) + x
|
||||
static inline void mh_chacha_block(const uint* x, uint* y) {
|
||||
for (uint i = 0u; i < 16u; ++i) y[i] = x[i];
|
||||
for (uint r = 0u; r < 6u; ++r) {
|
||||
MH_QR(y[0], y[4], y[8], y[12], 16u, 12u, 8u, 7u) MH_QR(y[1], y[5], y[9], y[13], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[2], y[6], y[10], y[14], 16u, 12u, 8u, 7u) MH_QR(y[3], y[7], y[11], y[15], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[0], y[5], y[10], y[15], 16u, 12u, 8u, 7u) MH_QR(y[1], y[6], y[11], y[12], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[2], y[7], y[8], y[13], 16u, 12u, 8u, 7u) MH_QR(y[3], y[4], y[9], y[14], 16u, 12u, 8u, 7u)
|
||||
}
|
||||
for (uint i = 0u; i < 16u; ++i) y[i] += x[i];
|
||||
}
|
||||
|
||||
// One cache segment: 64 chained lines written at cache[seg * 1024]. in_j = prev ^ (sigma || K || seg || j || tag), prev_0 = 0.
|
||||
static inline void mh_cache_segment(__global uint* cache, uint seg) {
|
||||
uint prev[16]; uint x[16]; uint y[16];
|
||||
for (uint i = 0u; i < 16u; ++i) prev[i] = 0u;
|
||||
for (uint j = 0u; j < MH_SEGMENT_LINES; ++j) {
|
||||
x[0] = 0x61707865u ^ prev[0]; x[1] = 0x3320646eu ^ prev[1]; x[2] = 0x79622d32u ^ prev[2]; x[3] = 0x6b206574u ^ prev[3];
|
||||
x[4] = 0x3067619fu ^ prev[4];
|
||||
x[5] = 0x3c269176u ^ prev[5];
|
||||
x[6] = 0x84a03b03u ^ prev[6];
|
||||
x[7] = 0xf8c63294u ^ prev[7];
|
||||
x[8] = 0xff977c5bu ^ prev[8];
|
||||
x[9] = 0xe60def3eu ^ prev[9];
|
||||
x[10] = 0x63630141u ^ prev[10];
|
||||
x[11] = 0xb8fbcb58u ^ prev[11];
|
||||
x[12] = seg ^ prev[12]; x[13] = j ^ prev[13]; x[14] = 0x49676e65u ^ prev[14]; x[15] = 0x756d4d48u ^ prev[15];
|
||||
mh_chacha_block(x, y);
|
||||
__global uint* line = cache + ((seg * MH_SEGMENT_LINES + j) * 16u);
|
||||
for (uint i = 0u; i < 16u; ++i) { line[i] = y[i]; prev[i] = y[i]; }
|
||||
}
|
||||
}
|
||||
|
||||
// M_r: per word (s ^ (RC + rk)) * MUL, then a column round and a diagonal round with the seed-drawn rotations.
|
||||
static inline void mh_mixer(uint* s, uint rk) {
|
||||
s[0] = (s[0] ^ (0xbab68293u + rk)) * 0x42146205u;
|
||||
s[1] = (s[1] ^ (0xcc162340u + rk)) * 0x52cbe0fbu;
|
||||
s[2] = (s[2] ^ (0x6ce151ccu + rk)) * 0x7ecf4a03u;
|
||||
s[3] = (s[3] ^ (0xe62b8997u + rk)) * 0x6728907fu;
|
||||
s[4] = (s[4] ^ (0xc9c80297u + rk)) * 0xd81d9751u;
|
||||
s[5] = (s[5] ^ (0xf74a1654u + rk)) * 0x132952c3u;
|
||||
s[6] = (s[6] ^ (0x3d704af5u + rk)) * 0xf60de277u;
|
||||
s[7] = (s[7] ^ (0x3cf522b7u + rk)) * 0x05358035u;
|
||||
s[8] = (s[8] ^ (0x2b9cac04u + rk)) * 0xbaf6499du;
|
||||
s[9] = (s[9] ^ (0xa880ac10u + rk)) * 0xe4db9667u;
|
||||
s[10] = (s[10] ^ (0x13e5dd1du + rk)) * 0x3e98f45du;
|
||||
s[11] = (s[11] ^ (0x6fc3e233u + rk)) * 0xd0004eddu;
|
||||
s[12] = (s[12] ^ (0x2d83eeacu + rk)) * 0x2691630du;
|
||||
s[13] = (s[13] ^ (0x9006e8bfu + rk)) * 0x9beb3bcfu;
|
||||
s[14] = (s[14] ^ (0x2c4b5362u + rk)) * 0xab310379u;
|
||||
s[15] = (s[15] ^ (0x31b49ee2u + rk)) * 0x99cfb423u;
|
||||
MH_QR(s[0], s[4], s[8], s[12], 20u, 20u, 19u, 4u) MH_QR(s[1], s[5], s[9], s[13], 20u, 20u, 19u, 4u)
|
||||
MH_QR(s[2], s[6], s[10], s[14], 20u, 20u, 19u, 4u) MH_QR(s[3], s[7], s[11], s[15], 20u, 20u, 19u, 4u)
|
||||
MH_QR(s[0], s[5], s[10], s[15], 26u, 3u, 3u, 27u) MH_QR(s[1], s[6], s[11], s[12], 26u, 3u, 3u, 27u)
|
||||
MH_QR(s[2], s[7], s[8], s[13], 26u, 3u, 3u, 27u) MH_QR(s[3], s[4], s[9], s[14], 26u, 3u, 3u, 27u)
|
||||
}
|
||||
|
||||
// Item t: 16 words. s = (K, t * MUL[i] + RC[i]); 8 rounds of mixer + cache line s[0] & mask; final mixer.
|
||||
static inline void mh_item(__global const uint* cache, uint t, uint* s) {
|
||||
s[0] = 0x3067619fu;
|
||||
s[1] = 0x3c269176u;
|
||||
s[2] = 0x84a03b03u;
|
||||
s[3] = 0xf8c63294u;
|
||||
s[4] = 0xff977c5bu;
|
||||
s[5] = 0xe60def3eu;
|
||||
s[6] = 0x63630141u;
|
||||
s[7] = 0xb8fbcb58u;
|
||||
s[8] = t * 0x42146205u + 0xbab68293u;
|
||||
s[9] = t * 0x52cbe0fbu + 0xcc162340u;
|
||||
s[10] = t * 0x7ecf4a03u + 0x6ce151ccu;
|
||||
s[11] = t * 0x6728907fu + 0xe62b8997u;
|
||||
s[12] = t * 0xd81d9751u + 0xc9c80297u;
|
||||
s[13] = t * 0x132952c3u + 0xf74a1654u;
|
||||
s[14] = t * 0xf60de277u + 0x3d704af5u;
|
||||
s[15] = t * 0x05358035u + 0x3cf522b7u;
|
||||
for (uint r = 0u; r < 8u; ++r) {
|
||||
mh_mixer(s, 0x9E3779B9u * (r + 1u));
|
||||
__global const uint* line = cache + ((s[0] & MH_CACHE_LINE_MASK) * 16u);
|
||||
for (uint i = 0u; i < 16u; ++i) s[i] ^= line[i];
|
||||
}
|
||||
mh_mixer(s, 0x9E3779B9u * 9u);
|
||||
}
|
||||
// dataset[w] without the dataset: derive item w >> 4 and take word w & 15.
|
||||
static inline uint mh_word(__global const uint* cache, uint w) { uint s[16]; mh_item(cache, w >> 4u, s); return s[w & 15u]; }
|
||||
|
||||
// Memory-hard dataset (MEMHARD.md). One work-item per cache segment; one work-item per 64-byte dataset item.
|
||||
// The same constants as memhard.h in this pack (one emitter, three dialects).
|
||||
__kernel void igneum_cache_fill(__global uint* cache, uint nSegments) {
|
||||
uint seg = (uint)get_global_id(0);
|
||||
if (seg < nSegments) mh_cache_segment(cache, seg);
|
||||
}
|
||||
__kernel void igneum_build(__global uint* ds, __global const uint* cache, uint nItems) {
|
||||
uint t = (uint)get_global_id(0);
|
||||
if (t < nItems) {
|
||||
uint s[16];
|
||||
mh_item(cache, t, s);
|
||||
__global uint* d = ds + ((ulong)t * 16u);
|
||||
for (uint i = 0u; i < 16u; ++i) d[i] = s[i];
|
||||
}
|
||||
}
|
||||
|
||||
// One hash per work-item. IGNEUM_GROUP is a multiple of 32; lane = lid & 31 and every exchange stays inside the
|
||||
// lane's own aligned run of 32 work-items, exactly like simd_shuffle_xor inside a 32-wide Metal SIMD group and
|
||||
// __shfl_xor_sync inside a CUDA warp. Control flow is uniform (no branches at all).
|
||||
IGNEUM_KERNEL_HASH void igneum_hash(__global const uint* ds, __global ulong* out, uint baseNonce, uint mask) {
|
||||
uint gid = (uint)get_global_id(0);
|
||||
uint lid = (uint)get_local_id(0);
|
||||
uint nonce = baseNonce + gid;
|
||||
uint r0, r1, r2, r3, r4, r5, r6, r7;
|
||||
#if IGNEUM_EXCHANGE == 0
|
||||
IGNEUM_LOCAL_WORDS(xch, 2 * IGNEUM_GROUP);
|
||||
uint xk = 0u;
|
||||
#else
|
||||
(void)lid;
|
||||
#endif
|
||||
{ uint x = nonce ^ 0x2a53aad4u; x += 0x9e3779b9u; x = splitmix32(x); r0 = x ^ 0x37fcb6e2u; } // SEEDW[0], 0x9e3779b9u * 1u, SEEDW[1]
|
||||
{ uint x = nonce ^ 0x37fcb6e2u; x += 0x3c6ef372u; x = splitmix32(x); r1 = x ^ 0x25d66a27u; } // SEEDW[1], 0x9e3779b9u * 2u, SEEDW[2]
|
||||
{ uint x = nonce ^ 0x25d66a27u; x += 0xdaa66d2bu; x = splitmix32(x); r2 = x ^ 0xf5249e5eu; } // SEEDW[2], 0x9e3779b9u * 3u, SEEDW[3]
|
||||
{ uint x = nonce ^ 0xf5249e5eu; x += 0x78dde6e4u; x = splitmix32(x); r3 = x ^ 0x15f86a59u; } // SEEDW[3], 0x9e3779b9u * 4u, SEEDW[4]
|
||||
{ uint x = nonce ^ 0x15f86a59u; x += 0x1715609du; x = splitmix32(x); r4 = x ^ 0x8144559au; } // SEEDW[4], 0x9e3779b9u * 5u, SEEDW[5]
|
||||
{ uint x = nonce ^ 0x8144559au; x += 0xb54cda56u; x = splitmix32(x); r5 = x ^ 0xcad741a6u; } // SEEDW[5], 0x9e3779b9u * 6u, SEEDW[6]
|
||||
{ uint x = nonce ^ 0xcad741a6u; x += 0x5384540fu; x = splitmix32(x); r6 = x ^ 0xcb961373u; } // SEEDW[6], 0x9e3779b9u * 7u, SEEDW[7]
|
||||
{ uint x = nonce ^ 0xcb961373u; x += 0xf1bbcdc8u; x = splitmix32(x); r7 = x ^ 0x2a53aad4u; } // SEEDW[7], 0x9e3779b9u * 8u, SEEDW[0]
|
||||
|
||||
for (uint it = 0u; it < 8u; ++it) {
|
||||
uint sel = r0;
|
||||
r0 = rotl_imm(r0, 10u); // 0 rotl
|
||||
r5 = r3 * r1 + r5; // 1 mad
|
||||
{ uint b_ = (r0 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r5 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r5 = x_; } // 2 load
|
||||
{ uint b_ = (r5 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r6 = x_; } // 3 load
|
||||
r5 = r2 * r2 + r5; // 4 mad
|
||||
r4 = r4 + r3 + ((((sel >> 10u) & 1u) != 0u) ? 0x4edf355au : 0xbd587d10u); // 5 add
|
||||
r3 = r3 ^ r2; // 6 xor
|
||||
r5 = r5 ^ r3; // 7 xor
|
||||
r7 = r6 * r2 + r7; // 8 mad
|
||||
r7 = r6 * r3 + r7; // 9 mad
|
||||
{ uint b_ = (r5 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r3 = x_; } // 10 load
|
||||
r1 = mul_hi(r1, r4); // 11 mulhi
|
||||
r1 = r1 ^ r6; // 12 xor
|
||||
r2 = mul_hi(r2, r1); // 13 mulhi
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r7, 4u); r6 = r6 ^ t_; } // 14 shfl
|
||||
r4 = r6 * r4 + r4; // 15 mad
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r0, 8u); r1 = r1 ^ t_; } // 16 shfl
|
||||
r5 = r5 ^ r4; // 17 xor
|
||||
r0 = r0 * r2; // 18 mul
|
||||
r6 = r6 ^ ds[r3 & mask]; // 19 load
|
||||
r6 = mul_hi(r6, r2); // 20 mulhi
|
||||
r7 = r2 * r6 + r7; // 21 mad
|
||||
r4 = r4 * r5; // 22 mul
|
||||
r3 = r3 * r5; // 23 mul
|
||||
r6 = r6 * r4; // 24 mul
|
||||
r3 = r3 ^ ds[r7 & mask]; // 25 load
|
||||
r2 = rotr_var(r2, r5); // 26 rotr
|
||||
r5 = r5 | r6; // 27 or
|
||||
{ uint b_ = (r2 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r4 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r4 = x_; } // 28 load
|
||||
r6 = r6 | r0; // 29 or
|
||||
r0 = r0 + r3 + ((((sel >> 2u) & 1u) != 0u) ? 0xdca976acu : 0x5faa0547u); // 30 add
|
||||
r6 = mul_hi(r6, r0); // 31 mulhi
|
||||
r3 = rotr_var(r3, r7); // 32 rotr
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r4, 4u); r0 = r0 ^ t_; } // 33 shfl
|
||||
r2 = rotl_imm(r2, 17u); // 34 rotl
|
||||
r7 = mul_hi(r7, r6); // 35 mulhi
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r2, 2u); r3 = r3 ^ t_; } // 36 shfl
|
||||
r6 = r6 ^ ds[r0 & mask]; // 37 load
|
||||
{ uint b_ = (r6 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r0 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r0 = x_; } // 38 load
|
||||
r1 = r1 ^ r0; // 39 xor
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r1, 2u); r3 = r3 ^ t_; } // 40 shfl
|
||||
r1 = r1 ^ ds[r5 & mask]; // 41 load
|
||||
r3 = r3 * r2; // 42 mul
|
||||
r2 = r2 ^ ds[r7 & mask]; // 43 load
|
||||
r7 = r7 + r3 + ((((sel >> 7u) & 1u) != 0u) ? 0x610bd3c2u : 0xe28c457cu); // 44 add
|
||||
r7 = mul_hi(r7, r6); // 45 mulhi
|
||||
r3 = r3 ^ r4; // 46 xor
|
||||
r3 = r3 ^ ds[r7 & mask]; // 47 load
|
||||
r7 = mul_hi(r7, r2); // 48 mulhi
|
||||
r6 = mul_hi(r6, r3); // 49 mulhi
|
||||
{ uint b_ = (r1 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r2 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r2 = x_; } // 50 load
|
||||
{ uint b_ = (r3 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r6 = x_; } // 51 load
|
||||
r5 = r5 ^ r3; // 52 xor
|
||||
r5 = r5 + r7 + ((((sel >> 31u) & 1u) != 0u) ? 0xcca8fa7cu : 0xd6457f6eu); // 53 add
|
||||
r7 = rotr_var(r7, r1); // 54 rotr
|
||||
r6 = r6 + r7 + ((((sel >> 12u) & 1u) != 0u) ? 0x826cb755u : 0xf3e1301cu); // 55 add
|
||||
{ uint b_ = (r0 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r3 = x_; } // 56 load
|
||||
r1 = rotr_var(r1, r5); // 57 rotr
|
||||
{ uint b_ = (r6 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r2 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r2 = x_; } // 58 load
|
||||
r3 = r3 - r7; // 59 sub
|
||||
r1 = r4 * r6 + r1; // 60 mad
|
||||
r2 = r1 * r2 + r2; // 61 mad
|
||||
r4 = r4 ^ r3; // 62 xor
|
||||
r2 = r2 ^ ds[r4 & mask]; // 63 load
|
||||
}
|
||||
uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u);
|
||||
uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u);
|
||||
out[gid] = ((ulong)hi << 32) | (ulong)lo;
|
||||
}
|
||||
|
||||
#if IGNEUM_EXCHANGE != 0
|
||||
// Reports the sub-group size this device uses for a work-group of IGNEUM_GROUP items. host.c runs it only when the
|
||||
// per-kernel query (clGetKernelSubGroupInfoKHR on igneum_hash) is unavailable; that query is preferred because a
|
||||
// compiler may pick a different wave width per kernel (RDNA: wave32 or wave64). See WAVEFRONT.md.
|
||||
IGNEUM_KERNEL_HASH void igneum_probe_subgroup(__global uint* out) {
|
||||
if (get_local_id(0) == 0u) { out[0] = get_sub_group_size(); out[1] = get_num_sub_groups(); }
|
||||
}
|
||||
#endif
|
||||
|
||||
// Header-bound variant (bind.rs): the init words come from initw, not SEEDW. Same body as igneum_hash.
|
||||
IGNEUM_KERNEL_HASH void igneum_hash_bound(__global const uint* ds, __global ulong* out, uint baseNonce, uint mask, __global const uint* initw) {
|
||||
uint gid = (uint)get_global_id(0);
|
||||
uint lid = (uint)get_local_id(0);
|
||||
uint nonce = baseNonce + gid;
|
||||
uint r0, r1, r2, r3, r4, r5, r6, r7;
|
||||
uint iw0 = initw[0], iw1 = initw[1], iw2 = initw[2], iw3 = initw[3], iw4 = initw[4], iw5 = initw[5], iw6 = initw[6], iw7 = initw[7];
|
||||
#if IGNEUM_EXCHANGE == 0
|
||||
IGNEUM_LOCAL_WORDS(xch, 2 * IGNEUM_GROUP);
|
||||
uint xk = 0u;
|
||||
#else
|
||||
(void)lid;
|
||||
#endif
|
||||
{ uint x = nonce ^ iw0; x += 0x9e3779b9u * 1u; x = splitmix32(x); r0 = x ^ iw1; }
|
||||
{ uint x = nonce ^ iw1; x += 0x9e3779b9u * 2u; x = splitmix32(x); r1 = x ^ iw2; }
|
||||
{ uint x = nonce ^ iw2; x += 0x9e3779b9u * 3u; x = splitmix32(x); r2 = x ^ iw3; }
|
||||
{ uint x = nonce ^ iw3; x += 0x9e3779b9u * 4u; x = splitmix32(x); r3 = x ^ iw4; }
|
||||
{ uint x = nonce ^ iw4; x += 0x9e3779b9u * 5u; x = splitmix32(x); r4 = x ^ iw5; }
|
||||
{ uint x = nonce ^ iw5; x += 0x9e3779b9u * 6u; x = splitmix32(x); r5 = x ^ iw6; }
|
||||
{ uint x = nonce ^ iw6; x += 0x9e3779b9u * 7u; x = splitmix32(x); r6 = x ^ iw7; }
|
||||
{ uint x = nonce ^ iw7; x += 0x9e3779b9u * 8u; x = splitmix32(x); r7 = x ^ iw0; }
|
||||
|
||||
for (uint it = 0u; it < 8u; ++it) {
|
||||
uint sel = r0;
|
||||
r0 = rotl_imm(r0, 10u); // 0 rotl
|
||||
r5 = r3 * r1 + r5; // 1 mad
|
||||
{ uint b_ = (r0 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r5 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r5 = x_; } // 2 load
|
||||
{ uint b_ = (r5 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r6 = x_; } // 3 load
|
||||
r5 = r2 * r2 + r5; // 4 mad
|
||||
r4 = r4 + r3 + ((((sel >> 10u) & 1u) != 0u) ? 0x4edf355au : 0xbd587d10u); // 5 add
|
||||
r3 = r3 ^ r2; // 6 xor
|
||||
r5 = r5 ^ r3; // 7 xor
|
||||
r7 = r6 * r2 + r7; // 8 mad
|
||||
r7 = r6 * r3 + r7; // 9 mad
|
||||
{ uint b_ = (r5 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r3 = x_; } // 10 load
|
||||
r1 = mul_hi(r1, r4); // 11 mulhi
|
||||
r1 = r1 ^ r6; // 12 xor
|
||||
r2 = mul_hi(r2, r1); // 13 mulhi
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r7, 4u); r6 = r6 ^ t_; } // 14 shfl
|
||||
r4 = r6 * r4 + r4; // 15 mad
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r0, 8u); r1 = r1 ^ t_; } // 16 shfl
|
||||
r5 = r5 ^ r4; // 17 xor
|
||||
r0 = r0 * r2; // 18 mul
|
||||
r6 = r6 ^ ds[r3 & mask]; // 19 load
|
||||
r6 = mul_hi(r6, r2); // 20 mulhi
|
||||
r7 = r2 * r6 + r7; // 21 mad
|
||||
r4 = r4 * r5; // 22 mul
|
||||
r3 = r3 * r5; // 23 mul
|
||||
r6 = r6 * r4; // 24 mul
|
||||
r3 = r3 ^ ds[r7 & mask]; // 25 load
|
||||
r2 = rotr_var(r2, r5); // 26 rotr
|
||||
r5 = r5 | r6; // 27 or
|
||||
{ uint b_ = (r2 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r4 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r4 = x_; } // 28 load
|
||||
r6 = r6 | r0; // 29 or
|
||||
r0 = r0 + r3 + ((((sel >> 2u) & 1u) != 0u) ? 0xdca976acu : 0x5faa0547u); // 30 add
|
||||
r6 = mul_hi(r6, r0); // 31 mulhi
|
||||
r3 = rotr_var(r3, r7); // 32 rotr
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r4, 4u); r0 = r0 ^ t_; } // 33 shfl
|
||||
r2 = rotl_imm(r2, 17u); // 34 rotl
|
||||
r7 = mul_hi(r7, r6); // 35 mulhi
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r2, 2u); r3 = r3 ^ t_; } // 36 shfl
|
||||
r6 = r6 ^ ds[r0 & mask]; // 37 load
|
||||
{ uint b_ = (r6 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r0 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r0 = x_; } // 38 load
|
||||
r1 = r1 ^ r0; // 39 xor
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r1, 2u); r3 = r3 ^ t_; } // 40 shfl
|
||||
r1 = r1 ^ ds[r5 & mask]; // 41 load
|
||||
r3 = r3 * r2; // 42 mul
|
||||
r2 = r2 ^ ds[r7 & mask]; // 43 load
|
||||
r7 = r7 + r3 + ((((sel >> 7u) & 1u) != 0u) ? 0x610bd3c2u : 0xe28c457cu); // 44 add
|
||||
r7 = mul_hi(r7, r6); // 45 mulhi
|
||||
r3 = r3 ^ r4; // 46 xor
|
||||
r3 = r3 ^ ds[r7 & mask]; // 47 load
|
||||
r7 = mul_hi(r7, r2); // 48 mulhi
|
||||
r6 = mul_hi(r6, r3); // 49 mulhi
|
||||
{ uint b_ = (r1 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r2 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r2 = x_; } // 50 load
|
||||
{ uint b_ = (r3 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r6 = x_; } // 51 load
|
||||
r5 = r5 ^ r3; // 52 xor
|
||||
r5 = r5 + r7 + ((((sel >> 31u) & 1u) != 0u) ? 0xcca8fa7cu : 0xd6457f6eu); // 53 add
|
||||
r7 = rotr_var(r7, r1); // 54 rotr
|
||||
r6 = r6 + r7 + ((((sel >> 12u) & 1u) != 0u) ? 0x826cb755u : 0xf3e1301cu); // 55 add
|
||||
{ uint b_ = (r0 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r3 = x_; } // 56 load
|
||||
r1 = rotr_var(r1, r5); // 57 rotr
|
||||
{ uint b_ = (r6 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r2 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r2 = x_; } // 58 load
|
||||
r3 = r3 - r7; // 59 sub
|
||||
r1 = r4 * r6 + r1; // 60 mad
|
||||
r2 = r1 * r2 + r2; // 61 mad
|
||||
r4 = r4 ^ r3; // 62 xor
|
||||
r2 = r2 ^ ds[r4 & mask]; // 63 load
|
||||
}
|
||||
uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u);
|
||||
uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u);
|
||||
out[gid] = ((ulong)hi << 32) | (ulong)lo;
|
||||
}
|
||||
123
proto-cuda/packs-readwidth/mixA-5/kernel_bound.cu
Normal file
123
proto-cuda/packs-readwidth/mixA-5/kernel_bound.cu
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
// Generated by igneum-pow export (generator v2) for seed "igneum-readwidth/A/6". Do not edit by hand.
|
||||
// Header-bound twin of igneum_hash in kernel.cu: the init words come from a kernel argument, not SEEDW.
|
||||
// Host declarations (also in program_bound.h if present):
|
||||
// struct IgneumInitWords { uint32_t w[8]; };
|
||||
// cudaError_t igneum_launch_hash_bound(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask,
|
||||
// IgneumInitWords iw, uint32_t nonces, uint32_t blockWarps);
|
||||
// cudaError_t igneum_hash_bound_info(int* numRegs, int* blocksPerSM, uint32_t blockWarps);
|
||||
#include <cuda_runtime.h>
|
||||
#include <cstdint>
|
||||
#include "program.h"
|
||||
|
||||
struct IgneumInitWords { uint32_t w[8]; };
|
||||
|
||||
__device__ __forceinline__ uint32_t splitmix32(uint32_t x) {
|
||||
x ^= x >> 16; x *= 0x7feb352du;
|
||||
x ^= x >> 15; x *= 0x846ca68bu;
|
||||
x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
__device__ __forceinline__ uint32_t rotl_imm(uint32_t x, uint32_t n) { return (x << n) | (x >> (32u - n)); }
|
||||
__device__ __forceinline__ uint32_t rotr_var(uint32_t x, uint32_t n) { n &= 31u; return (x >> n) | (x << ((32u - n) & 31u)); }
|
||||
|
||||
__global__ void igneum_hash_bound(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask, IgneumInitWords iw) {
|
||||
uint32_t gid = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
uint32_t nonce = baseNonce + gid;
|
||||
uint32_t r0, r1, r2, r3, r4, r5, r6, r7;
|
||||
{ uint32_t x = nonce ^ iw.w[0]; x += 0x9e3779b9u * 1u; x = splitmix32(x); r0 = x ^ iw.w[1]; }
|
||||
{ uint32_t x = nonce ^ iw.w[1]; x += 0x9e3779b9u * 2u; x = splitmix32(x); r1 = x ^ iw.w[2]; }
|
||||
{ uint32_t x = nonce ^ iw.w[2]; x += 0x9e3779b9u * 3u; x = splitmix32(x); r2 = x ^ iw.w[3]; }
|
||||
{ uint32_t x = nonce ^ iw.w[3]; x += 0x9e3779b9u * 4u; x = splitmix32(x); r3 = x ^ iw.w[4]; }
|
||||
{ uint32_t x = nonce ^ iw.w[4]; x += 0x9e3779b9u * 5u; x = splitmix32(x); r4 = x ^ iw.w[5]; }
|
||||
{ uint32_t x = nonce ^ iw.w[5]; x += 0x9e3779b9u * 6u; x = splitmix32(x); r5 = x ^ iw.w[6]; }
|
||||
{ uint32_t x = nonce ^ iw.w[6]; x += 0x9e3779b9u * 7u; x = splitmix32(x); r6 = x ^ iw.w[7]; }
|
||||
{ uint32_t x = nonce ^ iw.w[7]; x += 0x9e3779b9u * 8u; x = splitmix32(x); r7 = x ^ iw.w[0]; }
|
||||
|
||||
for (uint32_t it = 0u; it < 8u; ++it) {
|
||||
uint32_t sel = r0;
|
||||
r0 = rotl_imm(r0, 10u); // 0 rotl
|
||||
r5 = r3 * r1 + r5; // 1 mad
|
||||
{ uint32_t b_ = (r0 & mask) & ~15u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint32_t x_ = r5 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r5 = x_; } // 2 load
|
||||
{ uint32_t b_ = (r5 & mask) & ~3u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint32_t x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r6 = x_; } // 3 load
|
||||
r5 = r2 * r2 + r5; // 4 mad
|
||||
r4 = r4 + r3 + ((((sel >> 10u) & 1u) != 0u) ? 0x4edf355au : 0xbd587d10u); // 5 add
|
||||
r3 = r3 ^ r2; // 6 xor
|
||||
r5 = r5 ^ r3; // 7 xor
|
||||
r7 = r6 * r2 + r7; // 8 mad
|
||||
r7 = r6 * r3 + r7; // 9 mad
|
||||
{ uint32_t b_ = (r5 & mask) & ~15u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint32_t x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r3 = x_; } // 10 load
|
||||
r1 = __umulhi(r1, r4); // 11 mulhi
|
||||
r1 = r1 ^ r6; // 12 xor
|
||||
r2 = __umulhi(r2, r1); // 13 mulhi
|
||||
r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r7, 4); // 14 shfl
|
||||
r4 = r6 * r4 + r4; // 15 mad
|
||||
r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r0, 8); // 16 shfl
|
||||
r5 = r5 ^ r4; // 17 xor
|
||||
r0 = r0 * r2; // 18 mul
|
||||
r6 = r6 ^ ds[r3 & mask]; // 19 load
|
||||
r6 = __umulhi(r6, r2); // 20 mulhi
|
||||
r7 = r2 * r6 + r7; // 21 mad
|
||||
r4 = r4 * r5; // 22 mul
|
||||
r3 = r3 * r5; // 23 mul
|
||||
r6 = r6 * r4; // 24 mul
|
||||
r3 = r3 ^ ds[r7 & mask]; // 25 load
|
||||
r2 = rotr_var(r2, r5); // 26 rotr
|
||||
r5 = r5 | r6; // 27 or
|
||||
{ uint32_t b_ = (r2 & mask) & ~3u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint32_t x_ = r4 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r4 = x_; } // 28 load
|
||||
r6 = r6 | r0; // 29 or
|
||||
r0 = r0 + r3 + ((((sel >> 2u) & 1u) != 0u) ? 0xdca976acu : 0x5faa0547u); // 30 add
|
||||
r6 = __umulhi(r6, r0); // 31 mulhi
|
||||
r3 = rotr_var(r3, r7); // 32 rotr
|
||||
r0 = r0 ^ __shfl_xor_sync(0xffffffffu, r4, 4); // 33 shfl
|
||||
r2 = rotl_imm(r2, 17u); // 34 rotl
|
||||
r7 = __umulhi(r7, r6); // 35 mulhi
|
||||
r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r2, 2); // 36 shfl
|
||||
r6 = r6 ^ ds[r0 & mask]; // 37 load
|
||||
{ uint32_t b_ = (r6 & mask) & ~15u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint32_t x_ = r0 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r0 = x_; } // 38 load
|
||||
r1 = r1 ^ r0; // 39 xor
|
||||
r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r1, 2); // 40 shfl
|
||||
r1 = r1 ^ ds[r5 & mask]; // 41 load
|
||||
r3 = r3 * r2; // 42 mul
|
||||
r2 = r2 ^ ds[r7 & mask]; // 43 load
|
||||
r7 = r7 + r3 + ((((sel >> 7u) & 1u) != 0u) ? 0x610bd3c2u : 0xe28c457cu); // 44 add
|
||||
r7 = __umulhi(r7, r6); // 45 mulhi
|
||||
r3 = r3 ^ r4; // 46 xor
|
||||
r3 = r3 ^ ds[r7 & mask]; // 47 load
|
||||
r7 = __umulhi(r7, r2); // 48 mulhi
|
||||
r6 = __umulhi(r6, r3); // 49 mulhi
|
||||
{ uint32_t b_ = (r1 & mask) & ~15u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint32_t x_ = r2 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r2 = x_; } // 50 load
|
||||
{ uint32_t b_ = (r3 & mask) & ~15u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint32_t x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r6 = x_; } // 51 load
|
||||
r5 = r5 ^ r3; // 52 xor
|
||||
r5 = r5 + r7 + ((((sel >> 31u) & 1u) != 0u) ? 0xcca8fa7cu : 0xd6457f6eu); // 53 add
|
||||
r7 = rotr_var(r7, r1); // 54 rotr
|
||||
r6 = r6 + r7 + ((((sel >> 12u) & 1u) != 0u) ? 0x826cb755u : 0xf3e1301cu); // 55 add
|
||||
{ uint32_t b_ = (r0 & mask) & ~15u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint32_t x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r3 = x_; } // 56 load
|
||||
r1 = rotr_var(r1, r5); // 57 rotr
|
||||
{ uint32_t b_ = (r6 & mask) & ~3u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint32_t x_ = r2 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r2 = x_; } // 58 load
|
||||
r3 = r3 - r7; // 59 sub
|
||||
r1 = r4 * r6 + r1; // 60 mad
|
||||
r2 = r1 * r2 + r2; // 61 mad
|
||||
r4 = r4 ^ r3; // 62 xor
|
||||
r2 = r2 ^ ds[r4 & mask]; // 63 load
|
||||
}
|
||||
uint32_t lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u);
|
||||
uint32_t hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u);
|
||||
out[gid] = ((uint64_t)hi << 32) | (uint64_t)lo;
|
||||
}
|
||||
|
||||
cudaError_t igneum_launch_hash_bound(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask,
|
||||
IgneumInitWords iw, uint32_t nonces, uint32_t blockWarps) {
|
||||
if (blockWarps == 0u || blockWarps > 32u) return cudaErrorInvalidValue;
|
||||
uint32_t block = 32u * blockWarps;
|
||||
if (nonces == 0u || (nonces % block) != 0u) return cudaErrorInvalidValue;
|
||||
igneum_hash_bound<<<nonces / block, block>>>(ds, out, baseNonce, mask, iw);
|
||||
return cudaGetLastError();
|
||||
}
|
||||
|
||||
cudaError_t igneum_hash_bound_info(int* numRegs, int* blocksPerSM, uint32_t blockWarps) {
|
||||
cudaFuncAttributes attr;
|
||||
cudaError_t e = cudaFuncGetAttributes(&attr, igneum_hash_bound);
|
||||
if (e != cudaSuccess) return e;
|
||||
*numRegs = attr.numRegs;
|
||||
return cudaOccupancyMaxActiveBlocksPerMultiprocessor(blocksPerSM, igneum_hash_bound, (int)(32u * blockWarps), 0);
|
||||
}
|
||||
108
proto-cuda/packs-readwidth/mixA-5/memhard.h
Normal file
108
proto-cuda/packs-readwidth/mixA-5/memhard.h
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
// Generated by igneum-pow export (generator v2) for seed "igneum-readwidth/A/6". Do not edit by hand.
|
||||
// Memory-hard dataset core, the same text that the Mac's Metal kernels and CPU verifier were checked against.
|
||||
// Included by kernel.cu (device), host.cu (host reference) and proto-opencl/host.c (C99 host reference).
|
||||
// See proto-metal/MEMHARD.md for the construction. kernel.cl carries the same text in OpenCL C.
|
||||
#pragma once
|
||||
#ifdef __cplusplus
|
||||
#include <cstdint>
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
#if defined(__CUDACC__)
|
||||
#define IGNEUM_HD __host__ __device__ __forceinline__
|
||||
#elif defined(_MSC_VER) && !defined(__cplusplus)
|
||||
#define IGNEUM_HD static __inline
|
||||
#else
|
||||
#define IGNEUM_HD static inline
|
||||
#endif
|
||||
// Memory-hard dataset core (MEMHARD.md). Cache: 2^26 words in 2^16 segments of 64 chained ChaCha12 lines.
|
||||
// Item: 8 rounds of seed-parameterised mixer + one 64-byte cache read, then a final mixer. All parameters are literals.
|
||||
#define MH_CACHE_LINE_MASK 0x003fffffu
|
||||
#define MH_SEGMENT_LINES 64u
|
||||
#define MH_QR(a, b, c, d, r1, r2, r3, r4) { a += b; d ^= a; d = mh_rotl(d, r1); c += d; b ^= c; b = mh_rotl(b, r2); a += b; d ^= a; d = mh_rotl(d, r3); c += d; b ^= c; b = mh_rotl(b, r4); }
|
||||
IGNEUM_HD uint32_t mh_rotl(uint32_t x, uint32_t n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 at every call site
|
||||
|
||||
// y = ChaCha12 core(x) + x
|
||||
IGNEUM_HD void mh_chacha_block(const uint32_t* x, uint32_t* y) {
|
||||
for (uint32_t i = 0u; i < 16u; ++i) y[i] = x[i];
|
||||
for (uint32_t r = 0u; r < 6u; ++r) {
|
||||
MH_QR(y[0], y[4], y[8], y[12], 16u, 12u, 8u, 7u) MH_QR(y[1], y[5], y[9], y[13], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[2], y[6], y[10], y[14], 16u, 12u, 8u, 7u) MH_QR(y[3], y[7], y[11], y[15], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[0], y[5], y[10], y[15], 16u, 12u, 8u, 7u) MH_QR(y[1], y[6], y[11], y[12], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[2], y[7], y[8], y[13], 16u, 12u, 8u, 7u) MH_QR(y[3], y[4], y[9], y[14], 16u, 12u, 8u, 7u)
|
||||
}
|
||||
for (uint32_t i = 0u; i < 16u; ++i) y[i] += x[i];
|
||||
}
|
||||
|
||||
// One cache segment: 64 chained lines written at cache[seg * 1024]. in_j = prev ^ (sigma || K || seg || j || tag), prev_0 = 0.
|
||||
IGNEUM_HD void mh_cache_segment(uint32_t* cache, uint32_t seg) {
|
||||
uint32_t prev[16]; uint32_t x[16]; uint32_t y[16];
|
||||
for (uint32_t i = 0u; i < 16u; ++i) prev[i] = 0u;
|
||||
for (uint32_t j = 0u; j < MH_SEGMENT_LINES; ++j) {
|
||||
x[0] = 0x61707865u ^ prev[0]; x[1] = 0x3320646eu ^ prev[1]; x[2] = 0x79622d32u ^ prev[2]; x[3] = 0x6b206574u ^ prev[3];
|
||||
x[4] = 0x3067619fu ^ prev[4];
|
||||
x[5] = 0x3c269176u ^ prev[5];
|
||||
x[6] = 0x84a03b03u ^ prev[6];
|
||||
x[7] = 0xf8c63294u ^ prev[7];
|
||||
x[8] = 0xff977c5bu ^ prev[8];
|
||||
x[9] = 0xe60def3eu ^ prev[9];
|
||||
x[10] = 0x63630141u ^ prev[10];
|
||||
x[11] = 0xb8fbcb58u ^ prev[11];
|
||||
x[12] = seg ^ prev[12]; x[13] = j ^ prev[13]; x[14] = 0x49676e65u ^ prev[14]; x[15] = 0x756d4d48u ^ prev[15];
|
||||
mh_chacha_block(x, y);
|
||||
uint32_t* line = cache + ((seg * MH_SEGMENT_LINES + j) * 16u);
|
||||
for (uint32_t i = 0u; i < 16u; ++i) { line[i] = y[i]; prev[i] = y[i]; }
|
||||
}
|
||||
}
|
||||
|
||||
// M_r: per word (s ^ (RC + rk)) * MUL, then a column round and a diagonal round with the seed-drawn rotations.
|
||||
IGNEUM_HD void mh_mixer(uint32_t* s, uint32_t rk) {
|
||||
s[0] = (s[0] ^ (0xbab68293u + rk)) * 0x42146205u;
|
||||
s[1] = (s[1] ^ (0xcc162340u + rk)) * 0x52cbe0fbu;
|
||||
s[2] = (s[2] ^ (0x6ce151ccu + rk)) * 0x7ecf4a03u;
|
||||
s[3] = (s[3] ^ (0xe62b8997u + rk)) * 0x6728907fu;
|
||||
s[4] = (s[4] ^ (0xc9c80297u + rk)) * 0xd81d9751u;
|
||||
s[5] = (s[5] ^ (0xf74a1654u + rk)) * 0x132952c3u;
|
||||
s[6] = (s[6] ^ (0x3d704af5u + rk)) * 0xf60de277u;
|
||||
s[7] = (s[7] ^ (0x3cf522b7u + rk)) * 0x05358035u;
|
||||
s[8] = (s[8] ^ (0x2b9cac04u + rk)) * 0xbaf6499du;
|
||||
s[9] = (s[9] ^ (0xa880ac10u + rk)) * 0xe4db9667u;
|
||||
s[10] = (s[10] ^ (0x13e5dd1du + rk)) * 0x3e98f45du;
|
||||
s[11] = (s[11] ^ (0x6fc3e233u + rk)) * 0xd0004eddu;
|
||||
s[12] = (s[12] ^ (0x2d83eeacu + rk)) * 0x2691630du;
|
||||
s[13] = (s[13] ^ (0x9006e8bfu + rk)) * 0x9beb3bcfu;
|
||||
s[14] = (s[14] ^ (0x2c4b5362u + rk)) * 0xab310379u;
|
||||
s[15] = (s[15] ^ (0x31b49ee2u + rk)) * 0x99cfb423u;
|
||||
MH_QR(s[0], s[4], s[8], s[12], 20u, 20u, 19u, 4u) MH_QR(s[1], s[5], s[9], s[13], 20u, 20u, 19u, 4u)
|
||||
MH_QR(s[2], s[6], s[10], s[14], 20u, 20u, 19u, 4u) MH_QR(s[3], s[7], s[11], s[15], 20u, 20u, 19u, 4u)
|
||||
MH_QR(s[0], s[5], s[10], s[15], 26u, 3u, 3u, 27u) MH_QR(s[1], s[6], s[11], s[12], 26u, 3u, 3u, 27u)
|
||||
MH_QR(s[2], s[7], s[8], s[13], 26u, 3u, 3u, 27u) MH_QR(s[3], s[4], s[9], s[14], 26u, 3u, 3u, 27u)
|
||||
}
|
||||
|
||||
// Item t: 16 words. s = (K, t * MUL[i] + RC[i]); 8 rounds of mixer + cache line s[0] & mask; final mixer.
|
||||
IGNEUM_HD void mh_item(const uint32_t* cache, uint32_t t, uint32_t* s) {
|
||||
s[0] = 0x3067619fu;
|
||||
s[1] = 0x3c269176u;
|
||||
s[2] = 0x84a03b03u;
|
||||
s[3] = 0xf8c63294u;
|
||||
s[4] = 0xff977c5bu;
|
||||
s[5] = 0xe60def3eu;
|
||||
s[6] = 0x63630141u;
|
||||
s[7] = 0xb8fbcb58u;
|
||||
s[8] = t * 0x42146205u + 0xbab68293u;
|
||||
s[9] = t * 0x52cbe0fbu + 0xcc162340u;
|
||||
s[10] = t * 0x7ecf4a03u + 0x6ce151ccu;
|
||||
s[11] = t * 0x6728907fu + 0xe62b8997u;
|
||||
s[12] = t * 0xd81d9751u + 0xc9c80297u;
|
||||
s[13] = t * 0x132952c3u + 0xf74a1654u;
|
||||
s[14] = t * 0xf60de277u + 0x3d704af5u;
|
||||
s[15] = t * 0x05358035u + 0x3cf522b7u;
|
||||
for (uint32_t r = 0u; r < 8u; ++r) {
|
||||
mh_mixer(s, 0x9E3779B9u * (r + 1u));
|
||||
const uint32_t* line = cache + ((s[0] & MH_CACHE_LINE_MASK) * 16u);
|
||||
for (uint32_t i = 0u; i < 16u; ++i) s[i] ^= line[i];
|
||||
}
|
||||
mh_mixer(s, 0x9E3779B9u * 9u);
|
||||
}
|
||||
// dataset[w] without the dataset: derive item w >> 4 and take word w & 15.
|
||||
IGNEUM_HD uint32_t mh_word(const uint32_t* cache, uint32_t w) { uint32_t s[16]; mh_item(cache, w >> 4u, s); return s[w & 15u]; }
|
||||
106
proto-cuda/packs-readwidth/mixA-5/memhard.metal
Normal file
106
proto-cuda/packs-readwidth/mixA-5/memhard.metal
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
#include <metal_stdlib>
|
||||
using namespace metal;
|
||||
// Memory-hard dataset core (MEMHARD.md). Cache: 2^26 words in 2^16 segments of 64 chained ChaCha12 lines.
|
||||
// Item: 8 rounds of seed-parameterised mixer + one 64-byte cache read, then a final mixer. All parameters are literals.
|
||||
#define MH_CACHE_LINE_MASK 0x003fffffu
|
||||
#define MH_SEGMENT_LINES 64u
|
||||
#define MH_QR(a, b, c, d, r1, r2, r3, r4) { a += b; d ^= a; d = mh_rotl(d, r1); c += d; b ^= c; b = mh_rotl(b, r2); a += b; d ^= a; d = mh_rotl(d, r3); c += d; b ^= c; b = mh_rotl(b, r4); }
|
||||
inline uint mh_rotl(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 at every call site
|
||||
|
||||
// y = ChaCha12 core(x) + x
|
||||
inline void mh_chacha_block(const thread uint* x, thread uint* y) {
|
||||
for (uint i = 0u; i < 16u; ++i) y[i] = x[i];
|
||||
for (uint r = 0u; r < 6u; ++r) {
|
||||
MH_QR(y[0], y[4], y[8], y[12], 16u, 12u, 8u, 7u) MH_QR(y[1], y[5], y[9], y[13], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[2], y[6], y[10], y[14], 16u, 12u, 8u, 7u) MH_QR(y[3], y[7], y[11], y[15], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[0], y[5], y[10], y[15], 16u, 12u, 8u, 7u) MH_QR(y[1], y[6], y[11], y[12], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[2], y[7], y[8], y[13], 16u, 12u, 8u, 7u) MH_QR(y[3], y[4], y[9], y[14], 16u, 12u, 8u, 7u)
|
||||
}
|
||||
for (uint i = 0u; i < 16u; ++i) y[i] += x[i];
|
||||
}
|
||||
|
||||
// One cache segment: 64 chained lines written at cache[seg * 1024]. in_j = prev ^ (sigma || K || seg || j || tag), prev_0 = 0.
|
||||
inline void mh_cache_segment(device uint* cache, uint seg) {
|
||||
uint prev[16]; uint x[16]; uint y[16];
|
||||
for (uint i = 0u; i < 16u; ++i) prev[i] = 0u;
|
||||
for (uint j = 0u; j < MH_SEGMENT_LINES; ++j) {
|
||||
x[0] = 0x61707865u ^ prev[0]; x[1] = 0x3320646eu ^ prev[1]; x[2] = 0x79622d32u ^ prev[2]; x[3] = 0x6b206574u ^ prev[3];
|
||||
x[4] = 0x3067619fu ^ prev[4];
|
||||
x[5] = 0x3c269176u ^ prev[5];
|
||||
x[6] = 0x84a03b03u ^ prev[6];
|
||||
x[7] = 0xf8c63294u ^ prev[7];
|
||||
x[8] = 0xff977c5bu ^ prev[8];
|
||||
x[9] = 0xe60def3eu ^ prev[9];
|
||||
x[10] = 0x63630141u ^ prev[10];
|
||||
x[11] = 0xb8fbcb58u ^ prev[11];
|
||||
x[12] = seg ^ prev[12]; x[13] = j ^ prev[13]; x[14] = 0x49676e65u ^ prev[14]; x[15] = 0x756d4d48u ^ prev[15];
|
||||
mh_chacha_block(x, y);
|
||||
device uint* line = cache + ((seg * MH_SEGMENT_LINES + j) * 16u);
|
||||
for (uint i = 0u; i < 16u; ++i) { line[i] = y[i]; prev[i] = y[i]; }
|
||||
}
|
||||
}
|
||||
|
||||
// M_r: per word (s ^ (RC + rk)) * MUL, then a column round and a diagonal round with the seed-drawn rotations.
|
||||
inline void mh_mixer(thread uint* s, uint rk) {
|
||||
s[0] = (s[0] ^ (0xbab68293u + rk)) * 0x42146205u;
|
||||
s[1] = (s[1] ^ (0xcc162340u + rk)) * 0x52cbe0fbu;
|
||||
s[2] = (s[2] ^ (0x6ce151ccu + rk)) * 0x7ecf4a03u;
|
||||
s[3] = (s[3] ^ (0xe62b8997u + rk)) * 0x6728907fu;
|
||||
s[4] = (s[4] ^ (0xc9c80297u + rk)) * 0xd81d9751u;
|
||||
s[5] = (s[5] ^ (0xf74a1654u + rk)) * 0x132952c3u;
|
||||
s[6] = (s[6] ^ (0x3d704af5u + rk)) * 0xf60de277u;
|
||||
s[7] = (s[7] ^ (0x3cf522b7u + rk)) * 0x05358035u;
|
||||
s[8] = (s[8] ^ (0x2b9cac04u + rk)) * 0xbaf6499du;
|
||||
s[9] = (s[9] ^ (0xa880ac10u + rk)) * 0xe4db9667u;
|
||||
s[10] = (s[10] ^ (0x13e5dd1du + rk)) * 0x3e98f45du;
|
||||
s[11] = (s[11] ^ (0x6fc3e233u + rk)) * 0xd0004eddu;
|
||||
s[12] = (s[12] ^ (0x2d83eeacu + rk)) * 0x2691630du;
|
||||
s[13] = (s[13] ^ (0x9006e8bfu + rk)) * 0x9beb3bcfu;
|
||||
s[14] = (s[14] ^ (0x2c4b5362u + rk)) * 0xab310379u;
|
||||
s[15] = (s[15] ^ (0x31b49ee2u + rk)) * 0x99cfb423u;
|
||||
MH_QR(s[0], s[4], s[8], s[12], 20u, 20u, 19u, 4u) MH_QR(s[1], s[5], s[9], s[13], 20u, 20u, 19u, 4u)
|
||||
MH_QR(s[2], s[6], s[10], s[14], 20u, 20u, 19u, 4u) MH_QR(s[3], s[7], s[11], s[15], 20u, 20u, 19u, 4u)
|
||||
MH_QR(s[0], s[5], s[10], s[15], 26u, 3u, 3u, 27u) MH_QR(s[1], s[6], s[11], s[12], 26u, 3u, 3u, 27u)
|
||||
MH_QR(s[2], s[7], s[8], s[13], 26u, 3u, 3u, 27u) MH_QR(s[3], s[4], s[9], s[14], 26u, 3u, 3u, 27u)
|
||||
}
|
||||
|
||||
// Item t: 16 words. s = (K, t * MUL[i] + RC[i]); 8 rounds of mixer + cache line s[0] & mask; final mixer.
|
||||
inline void mh_item(device const uint* cache, uint t, thread uint* s) {
|
||||
s[0] = 0x3067619fu;
|
||||
s[1] = 0x3c269176u;
|
||||
s[2] = 0x84a03b03u;
|
||||
s[3] = 0xf8c63294u;
|
||||
s[4] = 0xff977c5bu;
|
||||
s[5] = 0xe60def3eu;
|
||||
s[6] = 0x63630141u;
|
||||
s[7] = 0xb8fbcb58u;
|
||||
s[8] = t * 0x42146205u + 0xbab68293u;
|
||||
s[9] = t * 0x52cbe0fbu + 0xcc162340u;
|
||||
s[10] = t * 0x7ecf4a03u + 0x6ce151ccu;
|
||||
s[11] = t * 0x6728907fu + 0xe62b8997u;
|
||||
s[12] = t * 0xd81d9751u + 0xc9c80297u;
|
||||
s[13] = t * 0x132952c3u + 0xf74a1654u;
|
||||
s[14] = t * 0xf60de277u + 0x3d704af5u;
|
||||
s[15] = t * 0x05358035u + 0x3cf522b7u;
|
||||
for (uint r = 0u; r < 8u; ++r) {
|
||||
mh_mixer(s, 0x9E3779B9u * (r + 1u));
|
||||
device const uint* line = cache + ((s[0] & MH_CACHE_LINE_MASK) * 16u);
|
||||
for (uint i = 0u; i < 16u; ++i) s[i] ^= line[i];
|
||||
}
|
||||
mh_mixer(s, 0x9E3779B9u * 9u);
|
||||
}
|
||||
// dataset[w] without the dataset: derive item w >> 4 and take word w & 15.
|
||||
inline uint mh_word(device const uint* cache, uint w) { uint s[16]; mh_item(cache, w >> 4u, s); return s[w & 15u]; }
|
||||
|
||||
// One thread per segment (2^16 threads).
|
||||
kernel void igneum_cache_fill(device uint* cache [[buffer(0)]], uint gid [[thread_position_in_grid]]) {
|
||||
mh_cache_segment(cache, gid);
|
||||
}
|
||||
// One thread per 64-byte item (dataset words / 16 threads).
|
||||
kernel void igneum_build(device const uint* cache [[buffer(0)]], device uint* dataset [[buffer(1)]],
|
||||
uint gid [[thread_position_in_grid]]) {
|
||||
uint s[16];
|
||||
mh_item(cache, gid, s);
|
||||
device uint* d = dataset + gid * 16u;
|
||||
for (uint i = 0u; i < 16u; ++i) d[i] = s[i];
|
||||
}
|
||||
60
proto-cuda/packs-readwidth/mixA-5/program.h
Normal file
60
proto-cuda/packs-readwidth/mixA-5/program.h
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
// Generated by igneum-pow export (generator v2) for seed "igneum-readwidth/A/6". Do not edit by hand.
|
||||
// Program metadata for host.cu plus the launch wrappers defined in kernel.cu.
|
||||
// Also included by proto-opencl/host.c (C99), which defines IGNEUM_NO_CUDA first and reads only the macros.
|
||||
#pragma once
|
||||
#ifdef __cplusplus
|
||||
#include <cstdint>
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
#ifndef IGNEUM_NO_CUDA
|
||||
#include <cuda_runtime.h>
|
||||
#endif
|
||||
|
||||
#define IGNEUM_SEED_STRING "igneum-readwidth/A/6"
|
||||
#define IGNEUM_SEED_BYTES_HEX "69676e65756d2d7265616477696474682f412f36"
|
||||
#define IGNEUM_GENERATOR 2
|
||||
#define IGNEUM_PROGRAM_ATTEMPT 0
|
||||
#define IGNEUM_PROGRAM_ID 0xd9bea03c18e5b8d6ull
|
||||
#define IGNEUM_DAY_STRING "2026-10-03"
|
||||
#define IGNEUM_DAY_BYTES_HEX "6461792f323032362d31302d3033"
|
||||
#define IGNEUM_DAY0 0x3067619fu
|
||||
#define IGNEUM_DAY1 0x3c269176u
|
||||
#define IGNEUM_DATASET_LOG2 28
|
||||
#define IGNEUM_MASK 0x0fffffffu
|
||||
#define IGNEUM_LANES 32
|
||||
#define IGNEUM_ITERATIONS 8
|
||||
#define IGNEUM_INSTR_COUNT 64
|
||||
#define IGNEUM_LOADS_PER_HASH 128
|
||||
#define IGNEUM_WIDE_LOADS_PER_HASH 0
|
||||
#define IGNEUM_OP_MIX "load=16 mad=8 mulhi=8 xor=8 add=5 mul=5 shfl=5 rotr=4 or=2 rotl=2 sub=1"
|
||||
// Read-width experiment (5 October 2026, docs/plans/read-width.md): NOT the lottery hash. A load of W words reads
|
||||
// the W-word-aligned address and folds every word into dst: x = dst ^ w[0]; x = (rotl(x, 11) * 0x9e3779b1) ^ w[j]; dst = x.
|
||||
#define IGNEUM_LOAD_CLASS "mix50-35-15"
|
||||
#define IGNEUM_LOAD_SLOTS 16
|
||||
#define IGNEUM_LOAD_MIX { 50, 35, 15 }
|
||||
#define IGNEUM_LOAD_WIDTH_COUNTS { 7, 3, 6 } // loads of 4, 16, 64 bytes per program
|
||||
#define IGNEUM_BYTES_PER_HASH 3680
|
||||
#define IGNEUM_FOLD_ROT 11
|
||||
#define IGNEUM_FOLD_MUL 0x9e3779b1u
|
||||
// 0 = closed-form dataset (ds_elem), 1 = memory-hard cache construction (MEMHARD.md, memhard.h)
|
||||
#define IGNEUM_DATASET_MODE 1
|
||||
|
||||
#define IGNEUM_SEEDW_INIT { 0x2a53aad4u, 0x37fcb6e2u, 0x25d66a27u, 0xf5249e5eu, 0x15f86a59u, 0x8144559au, 0xcad741a6u, 0xcb961373u }
|
||||
#define IGNEUM_KEY_INIT { 0x3067619fu, 0x3c269176u, 0x84a03b03u, 0xf8c63294u, 0xff977c5bu, 0xe60def3eu, 0x63630141u, 0xb8fbcb58u }
|
||||
#define IGNEUM_CACHE_LOG2_WORDS 26
|
||||
#define IGNEUM_CACHE_SEGMENT_LOG2_LINES 6
|
||||
#define IGNEUM_CACHE_SEGMENTS 65536u
|
||||
#define IGNEUM_ITEM_ROUNDS 8
|
||||
#define IGNEUM_MIX_ROT_INIT { 20u, 20u, 19u, 4u, 26u, 3u, 3u, 27u }
|
||||
#define IGNEUM_MIX_MUL_INIT { 0x42146205u, 0x52cbe0fbu, 0x7ecf4a03u, 0x6728907fu, 0xd81d9751u, 0x132952c3u, 0xf60de277u, 0x05358035u, 0xbaf6499du, 0xe4db9667u, 0x3e98f45du, 0xd0004eddu, 0x2691630du, 0x9beb3bcfu, 0xab310379u, 0x99cfb423u }
|
||||
#define IGNEUM_MIX_RC_INIT { 0xbab68293u, 0xcc162340u, 0x6ce151ccu, 0xe62b8997u, 0xc9c80297u, 0xf74a1654u, 0x3d704af5u, 0x3cf522b7u, 0x2b9cac04u, 0xa880ac10u, 0x13e5dd1du, 0x6fc3e233u, 0x2d83eeacu, 0x9006e8bfu, 0x2c4b5362u, 0x31b49ee2u }
|
||||
|
||||
#ifndef IGNEUM_NO_CUDA
|
||||
// Defined in kernel.cu. All launch on the default stream and return cudaGetLastError().
|
||||
cudaError_t igneum_launch_cache_fill(uint32_t* cache, uint32_t nSegments);
|
||||
cudaError_t igneum_launch_build(uint32_t* ds, const uint32_t* cache, uint32_t nItems);
|
||||
cudaError_t igneum_launch_hash(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask,
|
||||
uint32_t nonces, uint32_t blockWarps);
|
||||
cudaError_t igneum_hash_info(int* numRegs, int* blocksPerSM, uint32_t blockWarps);
|
||||
#endif
|
||||
127
proto-cuda/packs-readwidth/mixA-5/program.json
Normal file
127
proto-cuda/packs-readwidth/mixA-5/program.json
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
{
|
||||
"format": "igneum-program-pack-3",
|
||||
"generator": 2,
|
||||
"attempt": 0,
|
||||
"program_id": "0xd9bea03c18e5b8d6",
|
||||
"program_id_derivation": "FNV-1a 64 over 'igneum-program/' || generator_le32 || seed_words as little-endian bytes || attempt_le32",
|
||||
"dataset_mode": "memory-hard",
|
||||
"seed": "igneum-readwidth/A/6",
|
||||
"seed_bytes": "69676e65756d2d7265616477696474682f412f36",
|
||||
"seed_words": ["0x2a53aad4", "0x37fcb6e2", "0x25d66a27", "0xf5249e5e", "0x15f86a59", "0x8144559a", "0xcad741a6", "0xcb961373"],
|
||||
"seed_derivation": "seed_words = FNV-1a 64 over seed_bytes (attempt 0) or seed_bytes || attempt_le32 (attempt k >= 1), basis ^ (salt * 0x9E3779B97F4A7C15) for salt 0..3, then h ^= h>>33; h *= 0xff51afd7ed558ccd; h ^= h>>33; words[2*salt] = low 32, words[2*salt+1] = high 32",
|
||||
"generator_rule": "version 2: exactly 16 load slots drawn first from instructions 1..63 (partial Fisher-Yates), the other 48 ops from the ten non-load weights (sum 75); a load's source is drawn from the registers other than dst written by an earlier instruction and not read by a load since; the candidate must pass the acceptance rule of spec 01 section 1.4.6 (static: no cyclically stale load source, every register has an injecting write; dynamic: 64 units on the seed-keyed closed-form dataset with no constant register bit, no lane-constant load site, under 164 saturated final values, every output bit within 136 of 1024, distinct addresses above 245760), else the next attempt of the seed is tried",
|
||||
"lanes": 32,
|
||||
"registers": 8,
|
||||
"iterations": 8,
|
||||
"instruction_count": 64,
|
||||
"loads_per_hash": 128,
|
||||
"load_class": "mix50-35-15",
|
||||
"load_slots": 16,
|
||||
"load_mix_percent_4_16_64": [50, 35, 15],
|
||||
"load_width_counts_4_16_64": [7, 3, 6],
|
||||
"bytes_per_hash": 3680,
|
||||
"wide_load": "read-width experiment (5 October 2026, docs/plans/read-width.md), NOT the lottery hash: a load of W words (width field, 4 or 16) reads dataset[b .. b + W) with b = (src & mask) & ~(W - 1) and folds every word into dst: x = dst ^ w[0]; for j in 1..W: x = (rotl(x, 11) * 0x9e3779b1) ^ w[j]; dst = x; width 1 is the plain load; the width is drawn per instruction from the class mix with one extra below(100) draw after the nine of version 2, and the program id is FNV-1a 64 over 'igneum-program-rw/' || generator_le32 || seed words || attempt_le32 || mix[3] || load_slots",
|
||||
"op_mix": {"load": 16, "mad": 8, "mulhi": 8, "xor": 8, "add": 5, "mul": 5, "shfl": 5, "rotr": 4, "or": 2, "rotl": 2, "sub": 1},
|
||||
"register_init": "for i in 0..7: x = nonce ^ seed_words[i]; x += 0x9e3779b9 * (i+1) (mod 2^32); x = splitmix32(x); r[i] = x ^ seed_words[(i+1) & 7]",
|
||||
"splitmix32": "x ^= x>>16; x *= 0x7feb352d; x ^= x>>15; x *= 0x846ca68b; x ^= x>>16",
|
||||
"iteration": "sel = r0 sampled once at the top of each iteration, then all instructions in order",
|
||||
"output": "lo = r0 ^ rotl(r1,7) ^ rotl(r2,14) ^ rotl(r3,21); hi = r4 ^ rotl(r5,9) ^ rotl(r6,18) ^ rotl(r7,27); out = (hi << 32) | lo",
|
||||
"op_semantics": {
|
||||
"add": "dst = dst + src + (bit `bit` of sel ? imm2 : imm)",
|
||||
"sub": "dst = dst - src",
|
||||
"mul": "dst = dst * src (low 32)",
|
||||
"mulhi": "dst = high 32 bits of dst * src",
|
||||
"xor": "dst = dst ^ src",
|
||||
"or": "dst = dst | src",
|
||||
"rotl": "dst = rotl(dst, rot), rot in 1..31",
|
||||
"rotr": "dst = rotr(dst, src & 31)",
|
||||
"mad": "dst = src * src2 + dst",
|
||||
"shfl": "dst = dst ^ (src of lane (lane ^ mask)), mask in {1,2,4,8,16}, within the 32-lane warp",
|
||||
"load": "dst = dst ^ dataset[src & dataset.mask]",
|
||||
"wload": "base = (src of lane 0 & dataset.mask) & ~31; dst = dst ^ dataset[base + lane] (warp-coalesced 128-byte load, lever b, only when --wide-frac > 0)"
|
||||
},
|
||||
"dataset": {
|
||||
"log2_words": 28,
|
||||
"bytes": 1073741824,
|
||||
"mask": "0x0fffffff",
|
||||
"day": "2026-10-03",
|
||||
"day_bytes": "6461792f323032362d31302d3033",
|
||||
"day_words_from": "seed_words_from_bytes(day_bytes)",
|
||||
"d0": "0x3067619f",
|
||||
"d1": "0x3c269176",
|
||||
"mode": "memory-hard",
|
||||
"spec": "proto-metal/MEMHARD.md",
|
||||
"key": ["0x3067619f", "0x3c269176", "0x84a03b03", "0xf8c63294", "0xff977c5b", "0xe60def3e", "0x63630141", "0xb8fbcb58"],
|
||||
"key_derivation": "the 8 words of seed_words_from_bytes(day_bytes); d0, d1 are key[0], key[1]",
|
||||
"cache": {"log2_words": 26, "bytes": 268435456, "line_words": 16, "segment_lines": 64, "segments": 65536, "block": "ChaCha12 core + feed-forward, rotations 16 12 8 7", "sigma": ["0x61707865", "0x3320646e", "0x79622d32", "0x6b206574"], "tag": ["0x49676e65", "0x756d4d48"], "chain": "in_j = prev_line ^ (sigma[0..3] || key[0..7] || seg || j || tag[0..1]); line_j = block(in_j); prev_0 = 0"},
|
||||
"mixer": {"draw": "SplitMix64 seeded with key[0] | key[1] << 32: rot[0..7] = 1 + next() % 31, mul[0..15] = low32(next()) | 1, rc[0..15] = low32(next())", "rot": [20, 20, 19, 4, 26, 3, 3, 27], "mul": ["0x42146205", "0x52cbe0fb", "0x7ecf4a03", "0x6728907f", "0xd81d9751", "0x132952c3", "0xf60de277", "0x05358035", "0xbaf6499d", "0xe4db9667", "0x3e98f45d", "0xd0004edd", "0x2691630d", "0x9beb3bcf", "0xab310379", "0x99cfb423"], "rc": ["0xbab68293", "0xcc162340", "0x6ce151cc", "0xe62b8997", "0xc9c80297", "0xf74a1654", "0x3d704af5", "0x3cf522b7", "0x2b9cac04", "0xa880ac10", "0x13e5dd1d", "0x6fc3e233", "0x2d83eeac", "0x9006e8bf", "0x2c4b5362", "0x31b49ee2"], "round": "for i in 0..15: s[i] = (s[i] ^ (rc[i] + (r+1) * 0x9E3779B9)) * mul[i]; then quarter rounds on columns (0,4,8,12) (1,5,9,13) (2,6,10,14) (3,7,11,15) with rot[0..3] and diagonals (0,5,10,15) (1,6,11,12) (2,7,8,13) (3,4,9,14) with rot[4..7]", "quarter_round": "a += b; d ^= a; d = rotl(d, r1); c += d; b ^= c; b = rotl(b, r2); a += b; d ^= a; d = rotl(d, r3); c += d; b ^= c; b = rotl(b, r4)"},
|
||||
"item": "s[0..7] = key; s[8+i] = t * mul[i] + rc[i] for i in 0..7; for r in 0..7: s = M_r(s); line = s[0] & 0x003fffff; s[i] ^= cache[line * 16 + i]; then s = M_8(s); item(t) = s",
|
||||
"word": "dataset[w] = item(w >> 4)[w & 15]"
|
||||
},
|
||||
"instructions": [
|
||||
{"i": 0, "op": "rotl", "dst": 0, "src": 7, "src2": 6, "imm": "0x2237bb81", "imm2": "0xb069b9f1", "rot": 10, "bit": 18, "mask": 2, "width": 1},
|
||||
{"i": 1, "op": "mad", "dst": 5, "src": 3, "src2": 1, "imm": "0x4fd258fa", "imm2": "0x918a4f37", "rot": 1, "bit": 23, "mask": 16, "width": 1},
|
||||
{"i": 2, "op": "load", "dst": 5, "src": 0, "src2": 2, "imm": "0xbf959e37", "imm2": "0x365cef9c", "rot": 27, "bit": 21, "mask": 16, "width": 16},
|
||||
{"i": 3, "op": "load", "dst": 6, "src": 5, "src2": 5, "imm": "0x48715ea5", "imm2": "0x70bc4e9a", "rot": 21, "bit": 7, "mask": 8, "width": 4},
|
||||
{"i": 4, "op": "mad", "dst": 5, "src": 2, "src2": 2, "imm": "0x84131e0c", "imm2": "0xd3744459", "rot": 24, "bit": 28, "mask": 2, "width": 1},
|
||||
{"i": 5, "op": "add", "dst": 4, "src": 3, "src2": 4, "imm": "0xbd587d10", "imm2": "0x4edf355a", "rot": 18, "bit": 10, "mask": 8, "width": 1},
|
||||
{"i": 6, "op": "xor", "dst": 3, "src": 2, "src2": 3, "imm": "0x41f40748", "imm2": "0x6cfe9987", "rot": 14, "bit": 6, "mask": 16, "width": 1},
|
||||
{"i": 7, "op": "xor", "dst": 5, "src": 3, "src2": 4, "imm": "0x2c14f9c9", "imm2": "0x4f37fd66", "rot": 3, "bit": 1, "mask": 1, "width": 1},
|
||||
{"i": 8, "op": "mad", "dst": 7, "src": 6, "src2": 2, "imm": "0xcb0b8c69", "imm2": "0x451450b3", "rot": 21, "bit": 7, "mask": 16, "width": 1},
|
||||
{"i": 9, "op": "mad", "dst": 7, "src": 6, "src2": 3, "imm": "0x5d258713", "imm2": "0x9822328d", "rot": 30, "bit": 31, "mask": 16, "width": 1},
|
||||
{"i": 10, "op": "load", "dst": 3, "src": 5, "src2": 4, "imm": "0x61b87fba", "imm2": "0x51702831", "rot": 20, "bit": 30, "mask": 8, "width": 16},
|
||||
{"i": 11, "op": "mulhi", "dst": 1, "src": 4, "src2": 7, "imm": "0xc9e85411", "imm2": "0xe89df827", "rot": 26, "bit": 23, "mask": 8, "width": 1},
|
||||
{"i": 12, "op": "xor", "dst": 1, "src": 6, "src2": 6, "imm": "0x1ceb672f", "imm2": "0xf15040b7", "rot": 27, "bit": 19, "mask": 16, "width": 1},
|
||||
{"i": 13, "op": "mulhi", "dst": 2, "src": 1, "src2": 3, "imm": "0xe2dcec46", "imm2": "0x6f243314", "rot": 1, "bit": 3, "mask": 4, "width": 1},
|
||||
{"i": 14, "op": "shfl", "dst": 6, "src": 7, "src2": 5, "imm": "0x8bac3c39", "imm2": "0x55595cd3", "rot": 1, "bit": 28, "mask": 4, "width": 1},
|
||||
{"i": 15, "op": "mad", "dst": 4, "src": 6, "src2": 4, "imm": "0x6d3cc858", "imm2": "0x3c5576ea", "rot": 2, "bit": 21, "mask": 1, "width": 1},
|
||||
{"i": 16, "op": "shfl", "dst": 1, "src": 0, "src2": 1, "imm": "0xdd571938", "imm2": "0x044350f3", "rot": 5, "bit": 5, "mask": 8, "width": 1},
|
||||
{"i": 17, "op": "xor", "dst": 5, "src": 4, "src2": 4, "imm": "0x2c2d15da", "imm2": "0xb15a5c88", "rot": 31, "bit": 19, "mask": 16, "width": 1},
|
||||
{"i": 18, "op": "mul", "dst": 0, "src": 2, "src2": 3, "imm": "0x033348a5", "imm2": "0xd44c3d67", "rot": 1, "bit": 10, "mask": 16, "width": 1},
|
||||
{"i": 19, "op": "load", "dst": 6, "src": 3, "src2": 1, "imm": "0x0dda22a1", "imm2": "0x1ae5993b", "rot": 8, "bit": 4, "mask": 2, "width": 1},
|
||||
{"i": 20, "op": "mulhi", "dst": 6, "src": 2, "src2": 7, "imm": "0xd48e8694", "imm2": "0x11ed9b7b", "rot": 24, "bit": 19, "mask": 16, "width": 1},
|
||||
{"i": 21, "op": "mad", "dst": 7, "src": 2, "src2": 6, "imm": "0x44beb2fe", "imm2": "0x044aa951", "rot": 28, "bit": 22, "mask": 1, "width": 1},
|
||||
{"i": 22, "op": "mul", "dst": 4, "src": 5, "src2": 0, "imm": "0xa0256d05", "imm2": "0xd61f8a1a", "rot": 1, "bit": 0, "mask": 16, "width": 1},
|
||||
{"i": 23, "op": "mul", "dst": 3, "src": 5, "src2": 3, "imm": "0x0b79eb26", "imm2": "0x7f479e48", "rot": 3, "bit": 0, "mask": 8, "width": 1},
|
||||
{"i": 24, "op": "mul", "dst": 6, "src": 4, "src2": 4, "imm": "0x91742ca1", "imm2": "0x9f369d2a", "rot": 19, "bit": 2, "mask": 1, "width": 1},
|
||||
{"i": 25, "op": "load", "dst": 3, "src": 7, "src2": 6, "imm": "0x820853df", "imm2": "0xb288d5cd", "rot": 3, "bit": 23, "mask": 8, "width": 1},
|
||||
{"i": 26, "op": "rotr", "dst": 2, "src": 5, "src2": 7, "imm": "0x65a24fb5", "imm2": "0xfaaf9fca", "rot": 19, "bit": 12, "mask": 8, "width": 1},
|
||||
{"i": 27, "op": "or", "dst": 5, "src": 6, "src2": 4, "imm": "0xb8dc6cbb", "imm2": "0xcac9d5a4", "rot": 8, "bit": 2, "mask": 8, "width": 1},
|
||||
{"i": 28, "op": "load", "dst": 4, "src": 2, "src2": 1, "imm": "0x98a93309", "imm2": "0x235dc454", "rot": 31, "bit": 16, "mask": 4, "width": 4},
|
||||
{"i": 29, "op": "or", "dst": 6, "src": 0, "src2": 0, "imm": "0xc9dc1885", "imm2": "0xade1c24e", "rot": 9, "bit": 20, "mask": 16, "width": 1},
|
||||
{"i": 30, "op": "add", "dst": 0, "src": 3, "src2": 4, "imm": "0x5faa0547", "imm2": "0xdca976ac", "rot": 2, "bit": 2, "mask": 8, "width": 1},
|
||||
{"i": 31, "op": "mulhi", "dst": 6, "src": 0, "src2": 7, "imm": "0xec8a588f", "imm2": "0x7e280eb3", "rot": 12, "bit": 19, "mask": 2, "width": 1},
|
||||
{"i": 32, "op": "rotr", "dst": 3, "src": 7, "src2": 2, "imm": "0x6deb6b1d", "imm2": "0x79c4c05a", "rot": 25, "bit": 22, "mask": 2, "width": 1},
|
||||
{"i": 33, "op": "shfl", "dst": 0, "src": 4, "src2": 4, "imm": "0x3e652de8", "imm2": "0x3a967830", "rot": 31, "bit": 5, "mask": 4, "width": 1},
|
||||
{"i": 34, "op": "rotl", "dst": 2, "src": 0, "src2": 7, "imm": "0xd524262b", "imm2": "0xb65f15f3", "rot": 17, "bit": 2, "mask": 4, "width": 1},
|
||||
{"i": 35, "op": "mulhi", "dst": 7, "src": 6, "src2": 5, "imm": "0x9c455c39", "imm2": "0x7241afc1", "rot": 9, "bit": 20, "mask": 8, "width": 1},
|
||||
{"i": 36, "op": "shfl", "dst": 3, "src": 2, "src2": 4, "imm": "0x78d91acc", "imm2": "0x4efaf581", "rot": 17, "bit": 6, "mask": 2, "width": 1},
|
||||
{"i": 37, "op": "load", "dst": 6, "src": 0, "src2": 1, "imm": "0x45f26b60", "imm2": "0xad134516", "rot": 19, "bit": 4, "mask": 4, "width": 1},
|
||||
{"i": 38, "op": "load", "dst": 0, "src": 6, "src2": 3, "imm": "0x1798a61a", "imm2": "0xc40c58c6", "rot": 21, "bit": 28, "mask": 4, "width": 16},
|
||||
{"i": 39, "op": "xor", "dst": 1, "src": 0, "src2": 4, "imm": "0x862680d2", "imm2": "0x92df77ec", "rot": 12, "bit": 9, "mask": 1, "width": 1},
|
||||
{"i": 40, "op": "shfl", "dst": 3, "src": 1, "src2": 4, "imm": "0x44316a4c", "imm2": "0x843d6213", "rot": 6, "bit": 24, "mask": 2, "width": 1},
|
||||
{"i": 41, "op": "load", "dst": 1, "src": 5, "src2": 1, "imm": "0xeaeb2a04", "imm2": "0xc4cba010", "rot": 7, "bit": 23, "mask": 16, "width": 1},
|
||||
{"i": 42, "op": "mul", "dst": 3, "src": 2, "src2": 5, "imm": "0xe108d4b1", "imm2": "0xf65c52e5", "rot": 3, "bit": 30, "mask": 16, "width": 1},
|
||||
{"i": 43, "op": "load", "dst": 2, "src": 7, "src2": 5, "imm": "0x940d6ee3", "imm2": "0x9d6e3a8f", "rot": 27, "bit": 28, "mask": 1, "width": 1},
|
||||
{"i": 44, "op": "add", "dst": 7, "src": 3, "src2": 0, "imm": "0xe28c457c", "imm2": "0x610bd3c2", "rot": 9, "bit": 7, "mask": 4, "width": 1},
|
||||
{"i": 45, "op": "mulhi", "dst": 7, "src": 6, "src2": 3, "imm": "0xec2679c5", "imm2": "0x522fb2f8", "rot": 4, "bit": 17, "mask": 16, "width": 1},
|
||||
{"i": 46, "op": "xor", "dst": 3, "src": 4, "src2": 5, "imm": "0xce5dce0b", "imm2": "0x5447f7da", "rot": 5, "bit": 28, "mask": 2, "width": 1},
|
||||
{"i": 47, "op": "load", "dst": 3, "src": 7, "src2": 4, "imm": "0x1be86e58", "imm2": "0xe9e1afb9", "rot": 4, "bit": 17, "mask": 2, "width": 1},
|
||||
{"i": 48, "op": "mulhi", "dst": 7, "src": 2, "src2": 1, "imm": "0x26aea9a4", "imm2": "0xa5fa94ce", "rot": 22, "bit": 22, "mask": 16, "width": 1},
|
||||
{"i": 49, "op": "mulhi", "dst": 6, "src": 3, "src2": 2, "imm": "0xc25a3528", "imm2": "0x7a974c09", "rot": 31, "bit": 31, "mask": 8, "width": 1},
|
||||
{"i": 50, "op": "load", "dst": 2, "src": 1, "src2": 0, "imm": "0x3abaf4ef", "imm2": "0x38d75b93", "rot": 26, "bit": 22, "mask": 16, "width": 16},
|
||||
{"i": 51, "op": "load", "dst": 6, "src": 3, "src2": 0, "imm": "0x8b41ee85", "imm2": "0x9171a667", "rot": 19, "bit": 18, "mask": 2, "width": 16},
|
||||
{"i": 52, "op": "xor", "dst": 5, "src": 3, "src2": 7, "imm": "0x9c7de4ed", "imm2": "0x72e1df1d", "rot": 18, "bit": 5, "mask": 2, "width": 1},
|
||||
{"i": 53, "op": "add", "dst": 5, "src": 7, "src2": 6, "imm": "0xd6457f6e", "imm2": "0xcca8fa7c", "rot": 11, "bit": 31, "mask": 4, "width": 1},
|
||||
{"i": 54, "op": "rotr", "dst": 7, "src": 1, "src2": 2, "imm": "0x5ad54c6e", "imm2": "0x0bf13a74", "rot": 2, "bit": 19, "mask": 4, "width": 1},
|
||||
{"i": 55, "op": "add", "dst": 6, "src": 7, "src2": 5, "imm": "0xf3e1301c", "imm2": "0x826cb755", "rot": 18, "bit": 12, "mask": 1, "width": 1},
|
||||
{"i": 56, "op": "load", "dst": 3, "src": 0, "src2": 6, "imm": "0x68c04498", "imm2": "0x09d73293", "rot": 31, "bit": 9, "mask": 16, "width": 16},
|
||||
{"i": 57, "op": "rotr", "dst": 1, "src": 5, "src2": 0, "imm": "0x6ae5f1c4", "imm2": "0x4acb3d16", "rot": 2, "bit": 25, "mask": 2, "width": 1},
|
||||
{"i": 58, "op": "load", "dst": 2, "src": 6, "src2": 3, "imm": "0x908dad61", "imm2": "0x3caa6b5c", "rot": 26, "bit": 23, "mask": 8, "width": 4},
|
||||
{"i": 59, "op": "sub", "dst": 3, "src": 7, "src2": 4, "imm": "0xf497693d", "imm2": "0x12a59627", "rot": 6, "bit": 15, "mask": 16, "width": 1},
|
||||
{"i": 60, "op": "mad", "dst": 1, "src": 4, "src2": 6, "imm": "0x87197b1e", "imm2": "0x9fe5c5a6", "rot": 5, "bit": 18, "mask": 1, "width": 1},
|
||||
{"i": 61, "op": "mad", "dst": 2, "src": 1, "src2": 2, "imm": "0x7ffc05da", "imm2": "0xdd4b88aa", "rot": 15, "bit": 8, "mask": 2, "width": 1},
|
||||
{"i": 62, "op": "xor", "dst": 4, "src": 3, "src2": 0, "imm": "0x660f3bb9", "imm2": "0x48d985a9", "rot": 2, "bit": 27, "mask": 1, "width": 1},
|
||||
{"i": 63, "op": "load", "dst": 2, "src": 4, "src2": 4, "imm": "0x45650a4c", "imm2": "0x4d838ea4", "rot": 15, "bit": 13, "mask": 1, "width": 1}
|
||||
]
|
||||
}
|
||||
109
proto-cuda/packs-readwidth/mixA-5/program.metal
Normal file
109
proto-cuda/packs-readwidth/mixA-5/program.metal
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
#include <metal_stdlib>
|
||||
using namespace metal;
|
||||
|
||||
#define MASK 0x0fffffffu
|
||||
constant uint SEEDW[8] = { 0x2a53aad4u, 0x37fcb6e2u, 0x25d66a27u, 0xf5249e5eu, 0x15f86a59u, 0x8144559au, 0xcad741a6u, 0xcb961373u };
|
||||
|
||||
inline uint splitmix32(uint x) {
|
||||
x ^= x >> 16; x *= 0x7feb352du;
|
||||
x ^= x >> 15; x *= 0x846ca68bu;
|
||||
x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
inline uint rotl_imm(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31
|
||||
inline uint rotr_var(uint x, uint n) { n &= 31u; return (x >> n) | (x << ((32u - n) & 31u)); }
|
||||
inline uint ds_elem(uint i, uint d0, uint d1) {
|
||||
uint x = i ^ d0;
|
||||
x *= 0x9E3779B1u; x ^= x >> 15;
|
||||
x += d1;
|
||||
x *= 0x85EBCA77u; x ^= x >> 13;
|
||||
x *= 0xC2B2AE3Du; x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
|
||||
kernel void igneum_hash(device const uint* dataset [[buffer(0)]],
|
||||
device ulong* out [[buffer(1)]],
|
||||
constant uint& baseNonce [[buffer(2)]],
|
||||
uint gid [[thread_position_in_grid]]) {
|
||||
uint nonce = baseNonce + gid;
|
||||
uint r0, r1, r2, r3, r4, r5, r6, r7;
|
||||
{ uint x = nonce ^ SEEDW[0]; x += 0x9e3779b9u * 1u; x = splitmix32(x); r0 = x ^ SEEDW[1]; }
|
||||
{ uint x = nonce ^ SEEDW[1]; x += 0x9e3779b9u * 2u; x = splitmix32(x); r1 = x ^ SEEDW[2]; }
|
||||
{ uint x = nonce ^ SEEDW[2]; x += 0x9e3779b9u * 3u; x = splitmix32(x); r2 = x ^ SEEDW[3]; }
|
||||
{ uint x = nonce ^ SEEDW[3]; x += 0x9e3779b9u * 4u; x = splitmix32(x); r3 = x ^ SEEDW[4]; }
|
||||
{ uint x = nonce ^ SEEDW[4]; x += 0x9e3779b9u * 5u; x = splitmix32(x); r4 = x ^ SEEDW[5]; }
|
||||
{ uint x = nonce ^ SEEDW[5]; x += 0x9e3779b9u * 6u; x = splitmix32(x); r5 = x ^ SEEDW[6]; }
|
||||
{ uint x = nonce ^ SEEDW[6]; x += 0x9e3779b9u * 7u; x = splitmix32(x); r6 = x ^ SEEDW[7]; }
|
||||
{ uint x = nonce ^ SEEDW[7]; x += 0x9e3779b9u * 8u; x = splitmix32(x); r7 = x ^ SEEDW[0]; }
|
||||
|
||||
for (uint it = 0u; it < 8u; ++it) {
|
||||
uint sel = r0;
|
||||
r0 = rotl_imm(r0, 10u); // 0
|
||||
r5 = r3 * r1 + r5; // 1
|
||||
{ uint b_ = (r0 & MASK) & ~15u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint x_ = r5 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r5 = x_; } // 2
|
||||
{ uint b_ = (r5 & MASK) & ~3u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r6 = x_; } // 3
|
||||
r5 = r2 * r2 + r5; // 4
|
||||
r4 = r4 + r3 + select(0xbd587d10u, 0x4edf355au, ((sel >> 10u) & 1u) != 0u); // 5
|
||||
r3 = r3 ^ r2; // 6
|
||||
r5 = r5 ^ r3; // 7
|
||||
r7 = r6 * r2 + r7; // 8
|
||||
r7 = r6 * r3 + r7; // 9
|
||||
{ uint b_ = (r5 & MASK) & ~15u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r3 = x_; } // 10
|
||||
r1 = mulhi(r1, r4); // 11
|
||||
r1 = r1 ^ r6; // 12
|
||||
r2 = mulhi(r2, r1); // 13
|
||||
r6 = r6 ^ simd_shuffle_xor(r7, (ushort)4); // 14
|
||||
r4 = r6 * r4 + r4; // 15
|
||||
r1 = r1 ^ simd_shuffle_xor(r0, (ushort)8); // 16
|
||||
r5 = r5 ^ r4; // 17
|
||||
r0 = r0 * r2; // 18
|
||||
r6 = r6 ^ dataset[r3 & MASK]; // 19
|
||||
r6 = mulhi(r6, r2); // 20
|
||||
r7 = r2 * r6 + r7; // 21
|
||||
r4 = r4 * r5; // 22
|
||||
r3 = r3 * r5; // 23
|
||||
r6 = r6 * r4; // 24
|
||||
r3 = r3 ^ dataset[r7 & MASK]; // 25
|
||||
r2 = rotr_var(r2, r5); // 26
|
||||
r5 = r5 | r6; // 27
|
||||
{ uint b_ = (r2 & MASK) & ~3u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint x_ = r4 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r4 = x_; } // 28
|
||||
r6 = r6 | r0; // 29
|
||||
r0 = r0 + r3 + select(0x5faa0547u, 0xdca976acu, ((sel >> 2u) & 1u) != 0u); // 30
|
||||
r6 = mulhi(r6, r0); // 31
|
||||
r3 = rotr_var(r3, r7); // 32
|
||||
r0 = r0 ^ simd_shuffle_xor(r4, (ushort)4); // 33
|
||||
r2 = rotl_imm(r2, 17u); // 34
|
||||
r7 = mulhi(r7, r6); // 35
|
||||
r3 = r3 ^ simd_shuffle_xor(r2, (ushort)2); // 36
|
||||
r6 = r6 ^ dataset[r0 & MASK]; // 37
|
||||
{ uint b_ = (r6 & MASK) & ~15u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint x_ = r0 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r0 = x_; } // 38
|
||||
r1 = r1 ^ r0; // 39
|
||||
r3 = r3 ^ simd_shuffle_xor(r1, (ushort)2); // 40
|
||||
r1 = r1 ^ dataset[r5 & MASK]; // 41
|
||||
r3 = r3 * r2; // 42
|
||||
r2 = r2 ^ dataset[r7 & MASK]; // 43
|
||||
r7 = r7 + r3 + select(0xe28c457cu, 0x610bd3c2u, ((sel >> 7u) & 1u) != 0u); // 44
|
||||
r7 = mulhi(r7, r6); // 45
|
||||
r3 = r3 ^ r4; // 46
|
||||
r3 = r3 ^ dataset[r7 & MASK]; // 47
|
||||
r7 = mulhi(r7, r2); // 48
|
||||
r6 = mulhi(r6, r3); // 49
|
||||
{ uint b_ = (r1 & MASK) & ~15u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint x_ = r2 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r2 = x_; } // 50
|
||||
{ uint b_ = (r3 & MASK) & ~15u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r6 = x_; } // 51
|
||||
r5 = r5 ^ r3; // 52
|
||||
r5 = r5 + r7 + select(0xd6457f6eu, 0xcca8fa7cu, ((sel >> 31u) & 1u) != 0u); // 53
|
||||
r7 = rotr_var(r7, r1); // 54
|
||||
r6 = r6 + r7 + select(0xf3e1301cu, 0x826cb755u, ((sel >> 12u) & 1u) != 0u); // 55
|
||||
{ uint b_ = (r0 & MASK) & ~15u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r3 = x_; } // 56
|
||||
r1 = rotr_var(r1, r5); // 57
|
||||
{ uint b_ = (r6 & MASK) & ~3u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint x_ = r2 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r2 = x_; } // 58
|
||||
r3 = r3 - r7; // 59
|
||||
r1 = r4 * r6 + r1; // 60
|
||||
r2 = r1 * r2 + r2; // 61
|
||||
r4 = r4 ^ r3; // 62
|
||||
r2 = r2 ^ dataset[r4 & MASK]; // 63
|
||||
}
|
||||
uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u);
|
||||
uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u);
|
||||
out[gid] = ((ulong)hi << 32) | (ulong)lo;
|
||||
}
|
||||
111
proto-cuda/packs-readwidth/mixA-5/program_bound.metal
Normal file
111
proto-cuda/packs-readwidth/mixA-5/program_bound.metal
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
#include <metal_stdlib>
|
||||
using namespace metal;
|
||||
|
||||
#define MASK 0x0fffffffu
|
||||
constant uint SEEDW[8] = { 0x2a53aad4u, 0x37fcb6e2u, 0x25d66a27u, 0xf5249e5eu, 0x15f86a59u, 0x8144559au, 0xcad741a6u, 0xcb961373u };
|
||||
|
||||
inline uint splitmix32(uint x) {
|
||||
x ^= x >> 16; x *= 0x7feb352du;
|
||||
x ^= x >> 15; x *= 0x846ca68bu;
|
||||
x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
inline uint rotl_imm(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31
|
||||
inline uint rotr_var(uint x, uint n) { n &= 31u; return (x >> n) | (x << ((32u - n) & 31u)); }
|
||||
inline uint ds_elem(uint i, uint d0, uint d1) {
|
||||
uint x = i ^ d0;
|
||||
x *= 0x9E3779B1u; x ^= x >> 15;
|
||||
x += d1;
|
||||
x *= 0x85EBCA77u; x ^= x >> 13;
|
||||
x *= 0xC2B2AE3Du; x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
|
||||
// Header-bound variant: the init words come from buffer 3 (bind.rs), not from SEEDW.
|
||||
kernel void igneum_hash_bound(device const uint* dataset [[buffer(0)]],
|
||||
device ulong* out [[buffer(1)]],
|
||||
constant uint& baseNonce [[buffer(2)]],
|
||||
constant uint* initw [[buffer(3)]],
|
||||
uint gid [[thread_position_in_grid]]) {
|
||||
uint nonce = baseNonce + gid;
|
||||
uint r0, r1, r2, r3, r4, r5, r6, r7;
|
||||
{ uint x = nonce ^ initw[0]; x += 0x9e3779b9u * 1u; x = splitmix32(x); r0 = x ^ initw[1]; }
|
||||
{ uint x = nonce ^ initw[1]; x += 0x9e3779b9u * 2u; x = splitmix32(x); r1 = x ^ initw[2]; }
|
||||
{ uint x = nonce ^ initw[2]; x += 0x9e3779b9u * 3u; x = splitmix32(x); r2 = x ^ initw[3]; }
|
||||
{ uint x = nonce ^ initw[3]; x += 0x9e3779b9u * 4u; x = splitmix32(x); r3 = x ^ initw[4]; }
|
||||
{ uint x = nonce ^ initw[4]; x += 0x9e3779b9u * 5u; x = splitmix32(x); r4 = x ^ initw[5]; }
|
||||
{ uint x = nonce ^ initw[5]; x += 0x9e3779b9u * 6u; x = splitmix32(x); r5 = x ^ initw[6]; }
|
||||
{ uint x = nonce ^ initw[6]; x += 0x9e3779b9u * 7u; x = splitmix32(x); r6 = x ^ initw[7]; }
|
||||
{ uint x = nonce ^ initw[7]; x += 0x9e3779b9u * 8u; x = splitmix32(x); r7 = x ^ initw[0]; }
|
||||
|
||||
for (uint it = 0u; it < 8u; ++it) {
|
||||
uint sel = r0;
|
||||
r0 = rotl_imm(r0, 10u); // 0
|
||||
r5 = r3 * r1 + r5; // 1
|
||||
{ uint b_ = (r0 & MASK) & ~15u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint x_ = r5 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r5 = x_; } // 2
|
||||
{ uint b_ = (r5 & MASK) & ~3u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r6 = x_; } // 3
|
||||
r5 = r2 * r2 + r5; // 4
|
||||
r4 = r4 + r3 + select(0xbd587d10u, 0x4edf355au, ((sel >> 10u) & 1u) != 0u); // 5
|
||||
r3 = r3 ^ r2; // 6
|
||||
r5 = r5 ^ r3; // 7
|
||||
r7 = r6 * r2 + r7; // 8
|
||||
r7 = r6 * r3 + r7; // 9
|
||||
{ uint b_ = (r5 & MASK) & ~15u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r3 = x_; } // 10
|
||||
r1 = mulhi(r1, r4); // 11
|
||||
r1 = r1 ^ r6; // 12
|
||||
r2 = mulhi(r2, r1); // 13
|
||||
r6 = r6 ^ simd_shuffle_xor(r7, (ushort)4); // 14
|
||||
r4 = r6 * r4 + r4; // 15
|
||||
r1 = r1 ^ simd_shuffle_xor(r0, (ushort)8); // 16
|
||||
r5 = r5 ^ r4; // 17
|
||||
r0 = r0 * r2; // 18
|
||||
r6 = r6 ^ dataset[r3 & MASK]; // 19
|
||||
r6 = mulhi(r6, r2); // 20
|
||||
r7 = r2 * r6 + r7; // 21
|
||||
r4 = r4 * r5; // 22
|
||||
r3 = r3 * r5; // 23
|
||||
r6 = r6 * r4; // 24
|
||||
r3 = r3 ^ dataset[r7 & MASK]; // 25
|
||||
r2 = rotr_var(r2, r5); // 26
|
||||
r5 = r5 | r6; // 27
|
||||
{ uint b_ = (r2 & MASK) & ~3u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint x_ = r4 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r4 = x_; } // 28
|
||||
r6 = r6 | r0; // 29
|
||||
r0 = r0 + r3 + select(0x5faa0547u, 0xdca976acu, ((sel >> 2u) & 1u) != 0u); // 30
|
||||
r6 = mulhi(r6, r0); // 31
|
||||
r3 = rotr_var(r3, r7); // 32
|
||||
r0 = r0 ^ simd_shuffle_xor(r4, (ushort)4); // 33
|
||||
r2 = rotl_imm(r2, 17u); // 34
|
||||
r7 = mulhi(r7, r6); // 35
|
||||
r3 = r3 ^ simd_shuffle_xor(r2, (ushort)2); // 36
|
||||
r6 = r6 ^ dataset[r0 & MASK]; // 37
|
||||
{ uint b_ = (r6 & MASK) & ~15u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint x_ = r0 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r0 = x_; } // 38
|
||||
r1 = r1 ^ r0; // 39
|
||||
r3 = r3 ^ simd_shuffle_xor(r1, (ushort)2); // 40
|
||||
r1 = r1 ^ dataset[r5 & MASK]; // 41
|
||||
r3 = r3 * r2; // 42
|
||||
r2 = r2 ^ dataset[r7 & MASK]; // 43
|
||||
r7 = r7 + r3 + select(0xe28c457cu, 0x610bd3c2u, ((sel >> 7u) & 1u) != 0u); // 44
|
||||
r7 = mulhi(r7, r6); // 45
|
||||
r3 = r3 ^ r4; // 46
|
||||
r3 = r3 ^ dataset[r7 & MASK]; // 47
|
||||
r7 = mulhi(r7, r2); // 48
|
||||
r6 = mulhi(r6, r3); // 49
|
||||
{ uint b_ = (r1 & MASK) & ~15u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint x_ = r2 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r2 = x_; } // 50
|
||||
{ uint b_ = (r3 & MASK) & ~15u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r6 = x_; } // 51
|
||||
r5 = r5 ^ r3; // 52
|
||||
r5 = r5 + r7 + select(0xd6457f6eu, 0xcca8fa7cu, ((sel >> 31u) & 1u) != 0u); // 53
|
||||
r7 = rotr_var(r7, r1); // 54
|
||||
r6 = r6 + r7 + select(0xf3e1301cu, 0x826cb755u, ((sel >> 12u) & 1u) != 0u); // 55
|
||||
{ uint b_ = (r0 & MASK) & ~15u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r3 = x_; } // 56
|
||||
r1 = rotr_var(r1, r5); // 57
|
||||
{ uint b_ = (r6 & MASK) & ~3u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint x_ = r2 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r2 = x_; } // 58
|
||||
r3 = r3 - r7; // 59
|
||||
r1 = r4 * r6 + r1; // 60
|
||||
r2 = r1 * r2 + r2; // 61
|
||||
r4 = r4 ^ r3; // 62
|
||||
r2 = r2 ^ dataset[r4 & MASK]; // 63
|
||||
}
|
||||
uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u);
|
||||
uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u);
|
||||
out[gid] = ((ulong)hi << 32) | (ulong)lo;
|
||||
}
|
||||
57
proto-cuda/packs-readwidth/mixA-5/vectors.h
Normal file
57
proto-cuda/packs-readwidth/mixA-5/vectors.h
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
// Generated by igneum-pow export (generator v2) for seed "igneum-readwidth/A/6". Do not edit by hand.
|
||||
// Expected outputs: igneum-pow (Rust) CPU interpreter, generator v2, memory-hard dataset
|
||||
#pragma once
|
||||
#ifdef __cplusplus
|
||||
#include <cstdint>
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
#define IGNEUM_VEC_WARPS 3
|
||||
static const uint32_t IGNEUM_VEC_BASE[IGNEUM_VEC_WARPS] = { 0u, 4096u, 1000000u };
|
||||
static const uint64_t IGNEUM_VEC_OUT[IGNEUM_VEC_WARPS][32] = {
|
||||
{ // base nonce 0
|
||||
0x93e8388cac40c811ull, 0xa7fc8484877d2d42ull, 0x0e4fade6c54c3828ull, 0xd51024c9edc222c6ull, 0xf69126345bc6a789ull, 0xe4bf38ace928f612ull, 0xa3915889cbe42924ull, 0x338fb75c6a087e3dull,
|
||||
0xf27481a4ff979f3bull, 0xefe50d7bc95581abull, 0x7d2fa9d720b02ecaull, 0xfca2c211f788acf2ull, 0x2e66cc8095f3cb16ull, 0xae75758d3dc34127ull, 0x9553b782a362e16eull, 0xcb22382b49172a28ull,
|
||||
0x5fa9a18442efb5d8ull, 0x8bdd7aceb04694f1ull, 0xd7b19cf5b3dd0d2eull, 0x2f704fb0b2342d83ull, 0x8c3747e33ccefd96ull, 0x67c00a117dfc2e3cull, 0x3d548ce336a6c72full, 0xfca49cfec0f68f8full,
|
||||
0x1c253507e5d1a81cull, 0xa17ebb784aa17028ull, 0x511b1f8191bbf57full, 0xabfd11f3a4eac2c8ull, 0x729a42cfe7386d86ull, 0xfa1d04c46ce4f2c2ull, 0xf108ab5b9481c6b0ull, 0xe9fe2f9e682f40d8ull
|
||||
},
|
||||
{ // base nonce 4096
|
||||
0xc5d7b8097741686bull, 0x7fae5d95c0939293ull, 0x9b115b4967fd0af2ull, 0xf347d09f0b570b6bull, 0xb611632e5e2cc724ull, 0x92a6046c22ce9826ull, 0x6a40216015aeabe7ull, 0x8c5b7bbf98ee8ad1ull,
|
||||
0x160da4c87f1ff350ull, 0xf898efb8f2ecbf70ull, 0x84ec67d175b97164ull, 0x5813809116708d53ull, 0xe5318deef160edcfull, 0x1d3a703990fe850eull, 0xf6a0b78ee2dc77adull, 0xfddb5e0da4c705d5ull,
|
||||
0x98af1bd6cbba216full, 0xd339b38e62f2f4a5ull, 0xa6ac444d1edabc78ull, 0xe37432779a991a79ull, 0x2e10f0ac4e7a00d6ull, 0xf948234a7b8a4b92ull, 0x44c7abbb3897dd06ull, 0x14c7287af3dcb661ull,
|
||||
0x9b6b3d1c5b2a53f8ull, 0x36f4b115baec85acull, 0x41192bfbaba0592full, 0x0a6a7e78a97065d0ull, 0x54a2f48437f43f94ull, 0x5c7b3a5411458527ull, 0x359ac92b685d331dull, 0x2746c6f53c998ac1ull
|
||||
},
|
||||
{ // base nonce 1000000
|
||||
0x299e126aefa2a456ull, 0xd7cb35bb207a4744ull, 0x28755e512456e322ull, 0x7e12f9a852ed67b7ull, 0x54ff55e7b8fdf7f7ull, 0xb36a09f8c0fefd19ull, 0xb466f445db516c51ull, 0xd129d222de67ce0dull,
|
||||
0xc8a4d0e8591982a8ull, 0xb7566ad957bb1e1dull, 0xa56457ebd28d83efull, 0xd981708266e400c0ull, 0x73c629bbcedab2d9ull, 0x0d5fb3aa79870efbull, 0xf225b95724a24e46ull, 0xdf8d23b7472004bfull,
|
||||
0x4ca04ddf25cd4aceull, 0x80864b3b0740f888ull, 0xc114ed0d7042660aull, 0x8a3c7c3bcb5575c3ull, 0xa46c25ba69798388ull, 0x33a8aeab66d63875ull, 0x5bea09d563955e97ull, 0x81e81e3c8ea6d163ull,
|
||||
0x09f4dca8200b8220ull, 0x0227171d66f5197dull, 0x9d5ae8c2fe24c1abull, 0x572b88825c78884dull, 0x33be787f0b6d52fcull, 0x88689ec5df299a7full, 0xfad078a36872646eull, 0x8d7439bc62c19870ull
|
||||
}
|
||||
};
|
||||
|
||||
// Dataset self-test: dataset[0..15] and dataset[IGNEUM_MASK] (268435455).
|
||||
static const uint32_t IGNEUM_DS_HEAD[16] = {
|
||||
0xffc3cd94u, 0x5920ccd8u, 0x392f44bbu, 0x5e57f67au, 0x2f2bc2a9u, 0x620b0e36u, 0xbdc09014u, 0x436654bfu,
|
||||
0x311e0b48u, 0x1abd93adu, 0x59cc7ce8u, 0xee5247b2u, 0x86171fe8u, 0x6d874751u, 0xc9f7728fu, 0x7c2a435du
|
||||
};
|
||||
static const uint32_t IGNEUM_DS_LAST_INDEX = 268435455u;
|
||||
static const uint32_t IGNEUM_DS_LAST = 0xa33ada72u;
|
||||
// 64 sampled dataset words (index, value) computed on the Mac.
|
||||
#define IGNEUM_DS_SAMPLES 64
|
||||
static const uint32_t IGNEUM_DS_SAMPLE_INDEX[IGNEUM_DS_SAMPLES] = {
|
||||
59471966u, 217795994u, 208353206u, 42483309u, 172547758u, 148076330u, 183853158u, 214389424u, 267488061u, 169781097u, 184093494u, 153880993u, 84977930u, 46426879u, 3093825u, 225364072u, 44593546u, 260713159u, 168250303u, 52384140u, 223401610u, 45554030u, 95410555u, 175039924u, 79171087u, 267580473u, 24168642u, 37981670u, 171551130u, 195559979u, 204611762u, 140997658u, 138925853u, 86637313u, 20736778u, 219665210u, 160430336u, 264654675u, 8013395u, 228945585u, 213884386u, 104419827u, 44185464u, 142737231u, 99284897u, 132475900u, 61861762u, 132056166u, 262388043u, 91878046u, 117353561u, 124768597u, 71352993u, 190698941u, 46055428u, 55281366u, 165145231u, 106810753u, 171985651u, 232085256u, 159510492u, 40072060u, 209107596u, 39023794u
|
||||
};
|
||||
static const uint32_t IGNEUM_DS_SAMPLE_VALUE[IGNEUM_DS_SAMPLES] = {
|
||||
0xe8b73d94u, 0x337028b5u, 0xafe148c9u, 0xab99f7aeu, 0x434ea619u, 0xd85cb880u, 0x54764c7fu, 0x82c7e420u, 0xedf4cb9eu, 0x9884c959u, 0x223ee793u, 0x3a9ccf69u, 0x81da4fd2u, 0xd6ce8cb9u, 0xe3922dcau, 0x3e7e6bdeu, 0x382a3acau, 0x567e7f7fu, 0x25a0f084u, 0xbfeef128u, 0xe338abfbu, 0x7c3b5280u, 0x909bc5f1u, 0xd8b74b9cu, 0x8e31a22eu, 0x26b5f1d8u, 0x79122c00u, 0xcafc3340u, 0xd5e02ea3u, 0x1aee1afdu, 0xdb090d9au, 0xb049f435u, 0x4954d8bau, 0x03797ba0u, 0x196eefbdu, 0xd153412au, 0xbe5d2c4bu, 0xdaa14f0eu, 0x8e61ed07u, 0x9e9a64c6u, 0x2e29ff36u, 0x392a8589u, 0xb56a5912u, 0xfa6e8b57u, 0xd1a737cbu, 0xb0fa841au, 0xbe1c341fu, 0xe25be0f1u, 0xe937f543u, 0xebab2248u, 0x8e1b607au, 0x202a2fedu, 0x95e2819cu, 0x9c9652d4u, 0x32fedef0u, 0xdecfff82u, 0xcb5d43e5u, 0xb735806au, 0x8905939cu, 0xfbf8472du, 0xada74e5du, 0x7ebdeeeau, 0x0119f2b3u, 0xa9a376b8u
|
||||
};
|
||||
// Cache self-test (memory-hard mode): cache[0..15], the last 16 words, and FNV-1a 64 over all 2^26 words.
|
||||
static const uint32_t IGNEUM_CACHE_HEAD[16] = {
|
||||
0x355a86d2u, 0x7957db1cu, 0xd21772afu, 0x6fc1e09bu, 0xd55ce61du, 0x6e6a278bu, 0xd3f543ceu, 0x223d8e82u,
|
||||
0x143ab337u, 0x2e9f05bdu, 0x2eb389bfu, 0x0c6e449eu, 0x5cfa4222u, 0xba6560feu, 0x8e3e1aa4u, 0xdbcc1d53u
|
||||
};
|
||||
static const uint32_t IGNEUM_CACHE_LAST[16] = {
|
||||
0x41190d91u, 0xbd277957u, 0x22ddbb49u, 0x6986f207u, 0xdf69a4d6u, 0x26401a3au, 0x818230fbu, 0xc417122du,
|
||||
0x3597b211u, 0xb553ce55u, 0xcf39cc0du, 0x3b7fc43au, 0x3fd43b00u, 0x67e1c80eu, 0xffa7ea7du, 0xca2960abu
|
||||
};
|
||||
static const uint64_t IGNEUM_CACHE_FNV64 = 0x48c4f5bf24166b2eull;
|
||||
36
proto-cuda/packs-readwidth/mixA-5/vectors.json
Normal file
36
proto-cuda/packs-readwidth/mixA-5/vectors.json
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
{
|
||||
"seed": "igneum-readwidth/A/6",
|
||||
"day": "2026-10-03",
|
||||
"dataset_mode": "memory-hard",
|
||||
"dataset_log2_words": 28,
|
||||
"mask": "0x0fffffff",
|
||||
"lanes": 32,
|
||||
"source": "igneum-pow (Rust) CPU interpreter, generator v2, memory-hard dataset",
|
||||
"warps": [
|
||||
{"base_nonce": 0, "expected": [
|
||||
"0x93e8388cac40c811", "0xa7fc8484877d2d42", "0x0e4fade6c54c3828", "0xd51024c9edc222c6", "0xf69126345bc6a789", "0xe4bf38ace928f612", "0xa3915889cbe42924", "0x338fb75c6a087e3d",
|
||||
"0xf27481a4ff979f3b", "0xefe50d7bc95581ab", "0x7d2fa9d720b02eca", "0xfca2c211f788acf2", "0x2e66cc8095f3cb16", "0xae75758d3dc34127", "0x9553b782a362e16e", "0xcb22382b49172a28",
|
||||
"0x5fa9a18442efb5d8", "0x8bdd7aceb04694f1", "0xd7b19cf5b3dd0d2e", "0x2f704fb0b2342d83", "0x8c3747e33ccefd96", "0x67c00a117dfc2e3c", "0x3d548ce336a6c72f", "0xfca49cfec0f68f8f",
|
||||
"0x1c253507e5d1a81c", "0xa17ebb784aa17028", "0x511b1f8191bbf57f", "0xabfd11f3a4eac2c8", "0x729a42cfe7386d86", "0xfa1d04c46ce4f2c2", "0xf108ab5b9481c6b0", "0xe9fe2f9e682f40d8"
|
||||
]},
|
||||
{"base_nonce": 4096, "expected": [
|
||||
"0xc5d7b8097741686b", "0x7fae5d95c0939293", "0x9b115b4967fd0af2", "0xf347d09f0b570b6b", "0xb611632e5e2cc724", "0x92a6046c22ce9826", "0x6a40216015aeabe7", "0x8c5b7bbf98ee8ad1",
|
||||
"0x160da4c87f1ff350", "0xf898efb8f2ecbf70", "0x84ec67d175b97164", "0x5813809116708d53", "0xe5318deef160edcf", "0x1d3a703990fe850e", "0xf6a0b78ee2dc77ad", "0xfddb5e0da4c705d5",
|
||||
"0x98af1bd6cbba216f", "0xd339b38e62f2f4a5", "0xa6ac444d1edabc78", "0xe37432779a991a79", "0x2e10f0ac4e7a00d6", "0xf948234a7b8a4b92", "0x44c7abbb3897dd06", "0x14c7287af3dcb661",
|
||||
"0x9b6b3d1c5b2a53f8", "0x36f4b115baec85ac", "0x41192bfbaba0592f", "0x0a6a7e78a97065d0", "0x54a2f48437f43f94", "0x5c7b3a5411458527", "0x359ac92b685d331d", "0x2746c6f53c998ac1"
|
||||
]},
|
||||
{"base_nonce": 1000000, "expected": [
|
||||
"0x299e126aefa2a456", "0xd7cb35bb207a4744", "0x28755e512456e322", "0x7e12f9a852ed67b7", "0x54ff55e7b8fdf7f7", "0xb36a09f8c0fefd19", "0xb466f445db516c51", "0xd129d222de67ce0d",
|
||||
"0xc8a4d0e8591982a8", "0xb7566ad957bb1e1d", "0xa56457ebd28d83ef", "0xd981708266e400c0", "0x73c629bbcedab2d9", "0x0d5fb3aa79870efb", "0xf225b95724a24e46", "0xdf8d23b7472004bf",
|
||||
"0x4ca04ddf25cd4ace", "0x80864b3b0740f888", "0xc114ed0d7042660a", "0x8a3c7c3bcb5575c3", "0xa46c25ba69798388", "0x33a8aeab66d63875", "0x5bea09d563955e97", "0x81e81e3c8ea6d163",
|
||||
"0x09f4dca8200b8220", "0x0227171d66f5197d", "0x9d5ae8c2fe24c1ab", "0x572b88825c78884d", "0x33be787f0b6d52fc", "0x88689ec5df299a7f", "0xfad078a36872646e", "0x8d7439bc62c19870"
|
||||
]}
|
||||
],
|
||||
"dataset_head": ["0xffc3cd94", "0x5920ccd8", "0x392f44bb", "0x5e57f67a", "0x2f2bc2a9", "0x620b0e36", "0xbdc09014", "0x436654bf", "0x311e0b48", "0x1abd93ad", "0x59cc7ce8", "0xee5247b2", "0x86171fe8", "0x6d874751", "0xc9f7728f", "0x7c2a435d"],
|
||||
"dataset_last_index": 268435455,
|
||||
"dataset_last": "0xa33ada72",
|
||||
"dataset_samples": [{"index": 59471966, "value": "0xe8b73d94"}, {"index": 217795994, "value": "0x337028b5"}, {"index": 208353206, "value": "0xafe148c9"}, {"index": 42483309, "value": "0xab99f7ae"}, {"index": 172547758, "value": "0x434ea619"}, {"index": 148076330, "value": "0xd85cb880"}, {"index": 183853158, "value": "0x54764c7f"}, {"index": 214389424, "value": "0x82c7e420"}, {"index": 267488061, "value": "0xedf4cb9e"}, {"index": 169781097, "value": "0x9884c959"}, {"index": 184093494, "value": "0x223ee793"}, {"index": 153880993, "value": "0x3a9ccf69"}, {"index": 84977930, "value": "0x81da4fd2"}, {"index": 46426879, "value": "0xd6ce8cb9"}, {"index": 3093825, "value": "0xe3922dca"}, {"index": 225364072, "value": "0x3e7e6bde"}, {"index": 44593546, "value": "0x382a3aca"}, {"index": 260713159, "value": "0x567e7f7f"}, {"index": 168250303, "value": "0x25a0f084"}, {"index": 52384140, "value": "0xbfeef128"}, {"index": 223401610, "value": "0xe338abfb"}, {"index": 45554030, "value": "0x7c3b5280"}, {"index": 95410555, "value": "0x909bc5f1"}, {"index": 175039924, "value": "0xd8b74b9c"}, {"index": 79171087, "value": "0x8e31a22e"}, {"index": 267580473, "value": "0x26b5f1d8"}, {"index": 24168642, "value": "0x79122c00"}, {"index": 37981670, "value": "0xcafc3340"}, {"index": 171551130, "value": "0xd5e02ea3"}, {"index": 195559979, "value": "0x1aee1afd"}, {"index": 204611762, "value": "0xdb090d9a"}, {"index": 140997658, "value": "0xb049f435"}, {"index": 138925853, "value": "0x4954d8ba"}, {"index": 86637313, "value": "0x03797ba0"}, {"index": 20736778, "value": "0x196eefbd"}, {"index": 219665210, "value": "0xd153412a"}, {"index": 160430336, "value": "0xbe5d2c4b"}, {"index": 264654675, "value": "0xdaa14f0e"}, {"index": 8013395, "value": "0x8e61ed07"}, {"index": 228945585, "value": "0x9e9a64c6"}, {"index": 213884386, "value": "0x2e29ff36"}, {"index": 104419827, "value": "0x392a8589"}, {"index": 44185464, "value": "0xb56a5912"}, {"index": 142737231, "value": "0xfa6e8b57"}, {"index": 99284897, "value": "0xd1a737cb"}, {"index": 132475900, "value": "0xb0fa841a"}, {"index": 61861762, "value": "0xbe1c341f"}, {"index": 132056166, "value": "0xe25be0f1"}, {"index": 262388043, "value": "0xe937f543"}, {"index": 91878046, "value": "0xebab2248"}, {"index": 117353561, "value": "0x8e1b607a"}, {"index": 124768597, "value": "0x202a2fed"}, {"index": 71352993, "value": "0x95e2819c"}, {"index": 190698941, "value": "0x9c9652d4"}, {"index": 46055428, "value": "0x32fedef0"}, {"index": 55281366, "value": "0xdecfff82"}, {"index": 165145231, "value": "0xcb5d43e5"}, {"index": 106810753, "value": "0xb735806a"}, {"index": 171985651, "value": "0x8905939c"}, {"index": 232085256, "value": "0xfbf8472d"}, {"index": 159510492, "value": "0xada74e5d"}, {"index": 40072060, "value": "0x7ebdeeea"}, {"index": 209107596, "value": "0x0119f2b3"}, {"index": 39023794, "value": "0xa9a376b8"}],
|
||||
"cache_head": ["0x355a86d2", "0x7957db1c", "0xd21772af", "0x6fc1e09b", "0xd55ce61d", "0x6e6a278b", "0xd3f543ce", "0x223d8e82", "0x143ab337", "0x2e9f05bd", "0x2eb389bf", "0x0c6e449e", "0x5cfa4222", "0xba6560fe", "0x8e3e1aa4", "0xdbcc1d53"],
|
||||
"cache_last_line": ["0x41190d91", "0xbd277957", "0x22ddbb49", "0x6986f207", "0xdf69a4d6", "0x26401a3a", "0x818230fb", "0xc417122d", "0x3597b211", "0xb553ce55", "0xcf39cc0d", "0x3b7fc43a", "0x3fd43b00", "0x67e1c80e", "0xffa7ea7d", "0xca2960ab"],
|
||||
"cache_fnv1a64": "0x48c4f5bf24166b2e"
|
||||
}
|
||||
278
proto-cuda/packs-readwidth/mixB-0/kernel.cl
Normal file
278
proto-cuda/packs-readwidth/mixB-0/kernel.cl
Normal file
|
|
@ -0,0 +1,278 @@
|
|||
// Generated by igneum-pow export (generator v2) for seed "igneum-readwidth/B/0". Do not edit by hand.
|
||||
// OpenCL C twin of the Metal kernel for the same seed (see proto-opencl/README.md, WAVEFRONT.md and program.metal).
|
||||
// Built from source at runtime by proto-opencl/host.c, which passes these defines:
|
||||
// IGNEUM_GROUP work-group size of igneum_hash, a multiple of 32 (default 32: one work-group = one 32-lane unit)
|
||||
// IGNEUM_EXCHANGE 0 = local-memory exchange with a barrier (any device, any wave width; the default)
|
||||
// 1 = sub_group_shuffle_xor (cl_khr_subgroup_shuffle), only with IGNEUM_GROUP 32 and a sub-group size of exactly 32
|
||||
// 2 = intel_sub_group_shuffle_xor (cl_intel_subgroups), same condition
|
||||
// The verification unit is always 32 lanes. A 64-wide hardware wave (AMD GCN/CDNA, RDNA in wave64) runs two units;
|
||||
// the exchange masks are 1, 2, 4, 8, 16, so every partner lane lies inside the lane's own aligned run of 32.
|
||||
#ifndef IGNEUM_GROUP
|
||||
#define IGNEUM_GROUP 32
|
||||
#endif
|
||||
#ifndef IGNEUM_EXCHANGE
|
||||
#define IGNEUM_EXCHANGE 0
|
||||
#endif
|
||||
#ifdef __OPENCL_VERSION__
|
||||
#define IGNEUM_KERNEL_HASH __kernel __attribute__((reqd_work_group_size(IGNEUM_GROUP, 1, 1)))
|
||||
#define IGNEUM_LOCAL_WORDS(name, n) __local uint name[n]
|
||||
#if IGNEUM_EXCHANGE == 1
|
||||
#ifdef cl_khr_subgroups
|
||||
#pragma OPENCL EXTENSION cl_khr_subgroups : enable
|
||||
#endif
|
||||
#ifdef cl_khr_subgroup_shuffle
|
||||
#pragma OPENCL EXTENSION cl_khr_subgroup_shuffle : enable
|
||||
#endif
|
||||
#elif IGNEUM_EXCHANGE == 2
|
||||
#pragma OPENCL EXTENSION cl_intel_subgroups : enable
|
||||
#endif
|
||||
#else
|
||||
// Not an OpenCL compiler: proto-opencl/emu compiles this file as C++ and supplies the built-ins and these two macros.
|
||||
#include "emu_opencl.h"
|
||||
#endif
|
||||
|
||||
#if IGNEUM_EXCHANGE == 1
|
||||
#define IGNEUM_SHFL_XOR(dst, a, m) dst = sub_group_shuffle_xor((a), (uint)(m))
|
||||
#define IGNEUM_BCAST0(dst, a) dst = sub_group_broadcast((a), 0u)
|
||||
#elif IGNEUM_EXCHANGE == 2
|
||||
#define IGNEUM_SHFL_XOR(dst, a, m) dst = intel_sub_group_shuffle_xor((a), (uint)(m))
|
||||
#define IGNEUM_BCAST0(dst, a) dst = sub_group_broadcast((a), 0u)
|
||||
#else
|
||||
// Local-memory exchange. Two buffers of IGNEUM_GROUP words alternate (xk counts exchanges), so one barrier per
|
||||
// exchange is enough: a lane can only overwrite buffer b at exchange k+2 after passing barrier k+1, and every lane
|
||||
// reaches barrier k+1 only after its read of buffer b at exchange k. The partner lid ^ m stays inside the lane's
|
||||
// aligned run of 32 because m < 32. Control flow is uniform, so every work-item reaches every barrier.
|
||||
#define IGNEUM_SHFL_XOR(dst, a, m) { xch[(xk & 1u) * IGNEUM_GROUP + lid] = (a); barrier(CLK_LOCAL_MEM_FENCE); dst = xch[(xk & 1u) * IGNEUM_GROUP + (lid ^ (uint)(m))]; xk += 1u; }
|
||||
#define IGNEUM_BCAST0(dst, a) { xch[(xk & 1u) * IGNEUM_GROUP + lid] = (a); barrier(CLK_LOCAL_MEM_FENCE); dst = xch[(xk & 1u) * IGNEUM_GROUP + (lid & ~31u)]; xk += 1u; }
|
||||
#endif
|
||||
|
||||
static inline uint splitmix32(uint x) {
|
||||
x ^= x >> 16; x *= 0x7feb352du;
|
||||
x ^= x >> 15; x *= 0x846ca68bu;
|
||||
x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
// n is a literal in 1..31 at every call site. OpenCL rotate() rotates left by n modulo 32.
|
||||
static inline uint rotl_imm(uint x, uint n) { return rotate(x, n); }
|
||||
// Right rotation by n modulo 32 as a left rotation by (32 - n) modulo 32; n == 0 gives x.
|
||||
static inline uint rotr_var(uint x, uint n) { return rotate(x, (0u - n) & 31u); }
|
||||
static inline uint ds_elem(uint i, uint d0, uint d1) {
|
||||
uint x = i ^ d0;
|
||||
x *= 0x9E3779B1u; x ^= x >> 15;
|
||||
x += d1;
|
||||
x *= 0x85EBCA77u; x ^= x >> 13;
|
||||
x *= 0xC2B2AE3Du; x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
|
||||
// Memory-hard dataset core (MEMHARD.md). Cache: 2^26 words in 2^16 segments of 64 chained ChaCha12 lines.
|
||||
// Item: 8 rounds of seed-parameterised mixer + one 64-byte cache read, then a final mixer. All parameters are literals.
|
||||
#define MH_CACHE_LINE_MASK 0x003fffffu
|
||||
#define MH_SEGMENT_LINES 64u
|
||||
#define MH_QR(a, b, c, d, r1, r2, r3, r4) { a += b; d ^= a; d = mh_rotl(d, r1); c += d; b ^= c; b = mh_rotl(b, r2); a += b; d ^= a; d = mh_rotl(d, r3); c += d; b ^= c; b = mh_rotl(b, r4); }
|
||||
static inline uint mh_rotl(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 at every call site
|
||||
|
||||
// y = ChaCha12 core(x) + x
|
||||
static inline void mh_chacha_block(const uint* x, uint* y) {
|
||||
for (uint i = 0u; i < 16u; ++i) y[i] = x[i];
|
||||
for (uint r = 0u; r < 6u; ++r) {
|
||||
MH_QR(y[0], y[4], y[8], y[12], 16u, 12u, 8u, 7u) MH_QR(y[1], y[5], y[9], y[13], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[2], y[6], y[10], y[14], 16u, 12u, 8u, 7u) MH_QR(y[3], y[7], y[11], y[15], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[0], y[5], y[10], y[15], 16u, 12u, 8u, 7u) MH_QR(y[1], y[6], y[11], y[12], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[2], y[7], y[8], y[13], 16u, 12u, 8u, 7u) MH_QR(y[3], y[4], y[9], y[14], 16u, 12u, 8u, 7u)
|
||||
}
|
||||
for (uint i = 0u; i < 16u; ++i) y[i] += x[i];
|
||||
}
|
||||
|
||||
// One cache segment: 64 chained lines written at cache[seg * 1024]. in_j = prev ^ (sigma || K || seg || j || tag), prev_0 = 0.
|
||||
static inline void mh_cache_segment(__global uint* cache, uint seg) {
|
||||
uint prev[16]; uint x[16]; uint y[16];
|
||||
for (uint i = 0u; i < 16u; ++i) prev[i] = 0u;
|
||||
for (uint j = 0u; j < MH_SEGMENT_LINES; ++j) {
|
||||
x[0] = 0x61707865u ^ prev[0]; x[1] = 0x3320646eu ^ prev[1]; x[2] = 0x79622d32u ^ prev[2]; x[3] = 0x6b206574u ^ prev[3];
|
||||
x[4] = 0x3067619fu ^ prev[4];
|
||||
x[5] = 0x3c269176u ^ prev[5];
|
||||
x[6] = 0x84a03b03u ^ prev[6];
|
||||
x[7] = 0xf8c63294u ^ prev[7];
|
||||
x[8] = 0xff977c5bu ^ prev[8];
|
||||
x[9] = 0xe60def3eu ^ prev[9];
|
||||
x[10] = 0x63630141u ^ prev[10];
|
||||
x[11] = 0xb8fbcb58u ^ prev[11];
|
||||
x[12] = seg ^ prev[12]; x[13] = j ^ prev[13]; x[14] = 0x49676e65u ^ prev[14]; x[15] = 0x756d4d48u ^ prev[15];
|
||||
mh_chacha_block(x, y);
|
||||
__global uint* line = cache + ((seg * MH_SEGMENT_LINES + j) * 16u);
|
||||
for (uint i = 0u; i < 16u; ++i) { line[i] = y[i]; prev[i] = y[i]; }
|
||||
}
|
||||
}
|
||||
|
||||
// M_r: per word (s ^ (RC + rk)) * MUL, then a column round and a diagonal round with the seed-drawn rotations.
|
||||
static inline void mh_mixer(uint* s, uint rk) {
|
||||
s[0] = (s[0] ^ (0xbab68293u + rk)) * 0x42146205u;
|
||||
s[1] = (s[1] ^ (0xcc162340u + rk)) * 0x52cbe0fbu;
|
||||
s[2] = (s[2] ^ (0x6ce151ccu + rk)) * 0x7ecf4a03u;
|
||||
s[3] = (s[3] ^ (0xe62b8997u + rk)) * 0x6728907fu;
|
||||
s[4] = (s[4] ^ (0xc9c80297u + rk)) * 0xd81d9751u;
|
||||
s[5] = (s[5] ^ (0xf74a1654u + rk)) * 0x132952c3u;
|
||||
s[6] = (s[6] ^ (0x3d704af5u + rk)) * 0xf60de277u;
|
||||
s[7] = (s[7] ^ (0x3cf522b7u + rk)) * 0x05358035u;
|
||||
s[8] = (s[8] ^ (0x2b9cac04u + rk)) * 0xbaf6499du;
|
||||
s[9] = (s[9] ^ (0xa880ac10u + rk)) * 0xe4db9667u;
|
||||
s[10] = (s[10] ^ (0x13e5dd1du + rk)) * 0x3e98f45du;
|
||||
s[11] = (s[11] ^ (0x6fc3e233u + rk)) * 0xd0004eddu;
|
||||
s[12] = (s[12] ^ (0x2d83eeacu + rk)) * 0x2691630du;
|
||||
s[13] = (s[13] ^ (0x9006e8bfu + rk)) * 0x9beb3bcfu;
|
||||
s[14] = (s[14] ^ (0x2c4b5362u + rk)) * 0xab310379u;
|
||||
s[15] = (s[15] ^ (0x31b49ee2u + rk)) * 0x99cfb423u;
|
||||
MH_QR(s[0], s[4], s[8], s[12], 20u, 20u, 19u, 4u) MH_QR(s[1], s[5], s[9], s[13], 20u, 20u, 19u, 4u)
|
||||
MH_QR(s[2], s[6], s[10], s[14], 20u, 20u, 19u, 4u) MH_QR(s[3], s[7], s[11], s[15], 20u, 20u, 19u, 4u)
|
||||
MH_QR(s[0], s[5], s[10], s[15], 26u, 3u, 3u, 27u) MH_QR(s[1], s[6], s[11], s[12], 26u, 3u, 3u, 27u)
|
||||
MH_QR(s[2], s[7], s[8], s[13], 26u, 3u, 3u, 27u) MH_QR(s[3], s[4], s[9], s[14], 26u, 3u, 3u, 27u)
|
||||
}
|
||||
|
||||
// Item t: 16 words. s = (K, t * MUL[i] + RC[i]); 8 rounds of mixer + cache line s[0] & mask; final mixer.
|
||||
static inline void mh_item(__global const uint* cache, uint t, uint* s) {
|
||||
s[0] = 0x3067619fu;
|
||||
s[1] = 0x3c269176u;
|
||||
s[2] = 0x84a03b03u;
|
||||
s[3] = 0xf8c63294u;
|
||||
s[4] = 0xff977c5bu;
|
||||
s[5] = 0xe60def3eu;
|
||||
s[6] = 0x63630141u;
|
||||
s[7] = 0xb8fbcb58u;
|
||||
s[8] = t * 0x42146205u + 0xbab68293u;
|
||||
s[9] = t * 0x52cbe0fbu + 0xcc162340u;
|
||||
s[10] = t * 0x7ecf4a03u + 0x6ce151ccu;
|
||||
s[11] = t * 0x6728907fu + 0xe62b8997u;
|
||||
s[12] = t * 0xd81d9751u + 0xc9c80297u;
|
||||
s[13] = t * 0x132952c3u + 0xf74a1654u;
|
||||
s[14] = t * 0xf60de277u + 0x3d704af5u;
|
||||
s[15] = t * 0x05358035u + 0x3cf522b7u;
|
||||
for (uint r = 0u; r < 8u; ++r) {
|
||||
mh_mixer(s, 0x9E3779B9u * (r + 1u));
|
||||
__global const uint* line = cache + ((s[0] & MH_CACHE_LINE_MASK) * 16u);
|
||||
for (uint i = 0u; i < 16u; ++i) s[i] ^= line[i];
|
||||
}
|
||||
mh_mixer(s, 0x9E3779B9u * 9u);
|
||||
}
|
||||
// dataset[w] without the dataset: derive item w >> 4 and take word w & 15.
|
||||
static inline uint mh_word(__global const uint* cache, uint w) { uint s[16]; mh_item(cache, w >> 4u, s); return s[w & 15u]; }
|
||||
|
||||
// Memory-hard dataset (MEMHARD.md). One work-item per cache segment; one work-item per 64-byte dataset item.
|
||||
// The same constants as memhard.h in this pack (one emitter, three dialects).
|
||||
__kernel void igneum_cache_fill(__global uint* cache, uint nSegments) {
|
||||
uint seg = (uint)get_global_id(0);
|
||||
if (seg < nSegments) mh_cache_segment(cache, seg);
|
||||
}
|
||||
__kernel void igneum_build(__global uint* ds, __global const uint* cache, uint nItems) {
|
||||
uint t = (uint)get_global_id(0);
|
||||
if (t < nItems) {
|
||||
uint s[16];
|
||||
mh_item(cache, t, s);
|
||||
__global uint* d = ds + ((ulong)t * 16u);
|
||||
for (uint i = 0u; i < 16u; ++i) d[i] = s[i];
|
||||
}
|
||||
}
|
||||
|
||||
// One hash per work-item. IGNEUM_GROUP is a multiple of 32; lane = lid & 31 and every exchange stays inside the
|
||||
// lane's own aligned run of 32 work-items, exactly like simd_shuffle_xor inside a 32-wide Metal SIMD group and
|
||||
// __shfl_xor_sync inside a CUDA warp. Control flow is uniform (no branches at all).
|
||||
IGNEUM_KERNEL_HASH void igneum_hash(__global const uint* ds, __global ulong* out, uint baseNonce, uint mask) {
|
||||
uint gid = (uint)get_global_id(0);
|
||||
uint lid = (uint)get_local_id(0);
|
||||
uint nonce = baseNonce + gid;
|
||||
uint r0, r1, r2, r3, r4, r5, r6, r7;
|
||||
#if IGNEUM_EXCHANGE == 0
|
||||
IGNEUM_LOCAL_WORDS(xch, 2 * IGNEUM_GROUP);
|
||||
uint xk = 0u;
|
||||
#else
|
||||
(void)lid;
|
||||
#endif
|
||||
{ uint x = nonce ^ 0x3673211cu; x += 0x9e3779b9u; x = splitmix32(x); r0 = x ^ 0xaae550b4u; } // SEEDW[0], 0x9e3779b9u * 1u, SEEDW[1]
|
||||
{ uint x = nonce ^ 0xaae550b4u; x += 0x3c6ef372u; x = splitmix32(x); r1 = x ^ 0x5a0ce2e0u; } // SEEDW[1], 0x9e3779b9u * 2u, SEEDW[2]
|
||||
{ uint x = nonce ^ 0x5a0ce2e0u; x += 0xdaa66d2bu; x = splitmix32(x); r2 = x ^ 0x1d2471cfu; } // SEEDW[2], 0x9e3779b9u * 3u, SEEDW[3]
|
||||
{ uint x = nonce ^ 0x1d2471cfu; x += 0x78dde6e4u; x = splitmix32(x); r3 = x ^ 0xba944366u; } // SEEDW[3], 0x9e3779b9u * 4u, SEEDW[4]
|
||||
{ uint x = nonce ^ 0xba944366u; x += 0x1715609du; x = splitmix32(x); r4 = x ^ 0xbdd4d1dbu; } // SEEDW[4], 0x9e3779b9u * 5u, SEEDW[5]
|
||||
{ uint x = nonce ^ 0xbdd4d1dbu; x += 0xb54cda56u; x = splitmix32(x); r5 = x ^ 0xcb1984a9u; } // SEEDW[5], 0x9e3779b9u * 6u, SEEDW[6]
|
||||
{ uint x = nonce ^ 0xcb1984a9u; x += 0x5384540fu; x = splitmix32(x); r6 = x ^ 0x081ce12au; } // SEEDW[6], 0x9e3779b9u * 7u, SEEDW[7]
|
||||
{ uint x = nonce ^ 0x081ce12au; x += 0xf1bbcdc8u; x = splitmix32(x); r7 = x ^ 0x3673211cu; } // SEEDW[7], 0x9e3779b9u * 8u, SEEDW[0]
|
||||
|
||||
for (uint it = 0u; it < 8u; ++it) {
|
||||
uint sel = r0;
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r2, 1u); r0 = r0 ^ t_; } // 0 shfl
|
||||
r2 = r2 * r0; // 1 mul
|
||||
r0 = r0 + r6 + ((((sel >> 20u) & 1u) != 0u) ? 0x03fa29f3u : 0x7fbf4ae6u); // 2 add
|
||||
r2 = r2 * r7; // 3 mul
|
||||
r6 = r6 ^ ds[r2 & mask]; // 4 load
|
||||
{ uint b_ = (r0 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r7 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r7 = x_; } // 5 load
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r4, 16u); r6 = r6 ^ t_; } // 6 shfl
|
||||
r3 = r3 ^ r5; // 7 xor
|
||||
r6 = r6 ^ ds[r7 & mask]; // 8 load
|
||||
r0 = r0 + r7 + ((((sel >> 25u) & 1u) != 0u) ? 0x308c81bfu : 0xd59b21b0u); // 9 add
|
||||
r5 = rotr_var(r5, r7); // 10 rotr
|
||||
{ uint b_ = (r6 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r3 = x_; } // 11 load
|
||||
r2 = r2 * r6; // 12 mul
|
||||
{ uint b_ = (r0 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r7 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r7 = x_; } // 13 load
|
||||
r2 = r5 * r2 + r2; // 14 mad
|
||||
r4 = r4 + r0 + ((((sel >> 24u) & 1u) != 0u) ? 0x67081e7eu : 0x902dc661u); // 15 add
|
||||
{ uint b_ = (r4 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r3 = x_; } // 16 load
|
||||
r3 = mul_hi(r3, r4); // 17 mulhi
|
||||
{ uint b_ = (r7 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r4 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r4 = x_; } // 18 load
|
||||
r2 = r2 + r1 + ((((sel >> 9u) & 1u) != 0u) ? 0xd1e74db0u : 0x3ee3182cu); // 19 add
|
||||
r7 = r7 ^ r6; // 20 xor
|
||||
r5 = r5 ^ r3; // 21 xor
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r2, 16u); r6 = r6 ^ t_; } // 22 shfl
|
||||
{ uint b_ = (r2 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r0 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r0 = x_; } // 23 load
|
||||
r2 = r2 + r5 + ((((sel >> 22u) & 1u) != 0u) ? 0x62ac9e52u : 0xd2d451c6u); // 24 add
|
||||
{ uint b_ = (r7 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r3 = x_; } // 25 load
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r1, 16u); r4 = r4 ^ t_; } // 26 shfl
|
||||
{ uint b_ = (r4 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r1 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r1 = x_; } // 27 load
|
||||
r1 = r1 + r5 + ((((sel >> 2u) & 1u) != 0u) ? 0x072cfabeu : 0x111ff813u); // 28 add
|
||||
r4 = r1 * r2 + r4; // 29 mad
|
||||
r2 = r2 * r0; // 30 mul
|
||||
r0 = r0 ^ r5; // 31 xor
|
||||
r1 = r1 ^ ds[r0 & mask]; // 32 load
|
||||
r2 = r2 - r3; // 33 sub
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r0, 2u); r2 = r2 ^ t_; } // 34 shfl
|
||||
r0 = r0 - r6; // 35 sub
|
||||
r4 = r4 * r7; // 36 mul
|
||||
r5 = r5 ^ r6; // 37 xor
|
||||
r0 = mul_hi(r0, r6); // 38 mulhi
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r7, 4u); r5 = r5 ^ t_; } // 39 shfl
|
||||
{ uint b_ = (r3 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r6 = x_; } // 40 load
|
||||
r2 = r2 ^ ds[r4 & mask]; // 41 load
|
||||
r5 = r5 ^ ds[r6 & mask]; // 42 load
|
||||
r1 = rotr_var(r1, r4); // 43 rotr
|
||||
r0 = r0 | r5; // 44 or
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r2, 2u); r0 = r0 ^ t_; } // 45 shfl
|
||||
r7 = r7 * r4; // 46 mul
|
||||
r3 = r3 ^ r4; // 47 xor
|
||||
r2 = mul_hi(r2, r6); // 48 mulhi
|
||||
r5 = r5 ^ r4; // 49 xor
|
||||
r1 = rotr_var(r1, r6); // 50 rotr
|
||||
r7 = r7 + r0 + ((((sel >> 22u) & 1u) != 0u) ? 0x0fe79cecu : 0x68d3a5c0u); // 51 add
|
||||
r5 = r5 + r4 + ((((sel >> 8u) & 1u) != 0u) ? 0x04309e6fu : 0xeb764d91u); // 52 add
|
||||
r7 = r7 ^ r0; // 53 xor
|
||||
r4 = r4 + r0 + ((((sel >> 6u) & 1u) != 0u) ? 0xba0b81c6u : 0x1390b188u); // 54 add
|
||||
r0 = r0 + r5 + ((((sel >> 15u) & 1u) != 0u) ? 0x5ec96dd8u : 0x4c21a6cdu); // 55 add
|
||||
r7 = r5 * r3 + r7; // 56 mad
|
||||
{ uint b_ = (r0 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r6 = x_; } // 57 load
|
||||
r5 = r5 + r1 + ((((sel >> 1u) & 1u) != 0u) ? 0x6c0ac4ddu : 0x68297b06u); // 58 add
|
||||
r6 = rotr_var(r6, r7); // 59 rotr
|
||||
{ uint b_ = (r4 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r7 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r7 = x_; } // 60 load
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r3, 4u); r6 = r6 ^ t_; } // 61 shfl
|
||||
r4 = rotl_imm(r4, 6u); // 62 rotl
|
||||
r1 = r2 * r1 + r1; // 63 mad
|
||||
}
|
||||
uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u);
|
||||
uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u);
|
||||
out[gid] = ((ulong)hi << 32) | (ulong)lo;
|
||||
}
|
||||
|
||||
#if IGNEUM_EXCHANGE != 0
|
||||
// Reports the sub-group size this device uses for a work-group of IGNEUM_GROUP items. host.c runs it only when the
|
||||
// per-kernel query (clGetKernelSubGroupInfoKHR on igneum_hash) is unavailable; that query is preferred because a
|
||||
// compiler may pick a different wave width per kernel (RDNA: wave32 or wave64). See WAVEFRONT.md.
|
||||
IGNEUM_KERNEL_HASH void igneum_probe_subgroup(__global uint* out) {
|
||||
if (get_local_id(0) == 0u) { out[0] = get_sub_group_size(); out[1] = get_num_sub_groups(); }
|
||||
}
|
||||
#endif
|
||||
164
proto-cuda/packs-readwidth/mixB-0/kernel.cu
Normal file
164
proto-cuda/packs-readwidth/mixB-0/kernel.cu
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
// Generated by igneum-pow export (generator v2) for seed "igneum-readwidth/B/0". Do not edit by hand.
|
||||
// Bit-exact twin of the Metal kernel for the same seed (see proto-cuda/CHECKLIST.md and program.metal).
|
||||
// Compiled ahead of time by nvcc together with proto-cuda/host.cu. No NVRTC.
|
||||
#include <cuda_runtime.h>
|
||||
#include <cstdint>
|
||||
#include "program.h"
|
||||
#include "memhard.h"
|
||||
|
||||
__device__ __forceinline__ uint32_t splitmix32(uint32_t x) {
|
||||
x ^= x >> 16; x *= 0x7feb352du;
|
||||
x ^= x >> 15; x *= 0x846ca68bu;
|
||||
x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
// n is a literal in 1..31 at every call site, so both shift amounts are in 1..31.
|
||||
__device__ __forceinline__ uint32_t rotl_imm(uint32_t x, uint32_t n) { return (x << n) | (x >> (32u - n)); }
|
||||
// n is masked to 0..31; the second shift amount is masked too, so n == 0 gives x.
|
||||
__device__ __forceinline__ uint32_t rotr_var(uint32_t x, uint32_t n) { n &= 31u; return (x >> n) | (x << ((32u - n) & 31u)); }
|
||||
__device__ __forceinline__ uint32_t ds_elem(uint32_t i, uint32_t d0, uint32_t d1) {
|
||||
uint32_t x = i ^ d0;
|
||||
x *= 0x9E3779B1u; x ^= x >> 15;
|
||||
x += d1;
|
||||
x *= 0x85EBCA77u; x ^= x >> 13;
|
||||
x *= 0xC2B2AE3Du; x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
|
||||
// Memory-hard dataset (MEMHARD.md). One thread per cache segment; one thread per 64-byte dataset item.
|
||||
// The core functions (mh_cache_segment, mh_item) are in memhard.h and are also compiled for the host.
|
||||
__global__ void igneum_cache_fill(uint32_t* cache, uint32_t nSegments) {
|
||||
uint32_t seg = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
if (seg < nSegments) mh_cache_segment(cache, seg);
|
||||
}
|
||||
__global__ void igneum_build(uint32_t* ds, const uint32_t* cache, uint32_t nItems) {
|
||||
uint32_t t = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
if (t < nItems) {
|
||||
uint32_t s[16];
|
||||
mh_item(cache, t, s);
|
||||
uint32_t* d = ds + (size_t)t * 16u;
|
||||
for (uint32_t i = 0u; i < 16u; ++i) d[i] = s[i];
|
||||
}
|
||||
}
|
||||
|
||||
// One hash per thread. blockDim.x is a multiple of 32; lane = threadIdx.x & 31 and every
|
||||
// __shfl_xor_sync stays inside the lane's own warp, exactly like simd_shuffle_xor inside a
|
||||
// 32-wide Metal SIMD group. Control flow is uniform, so the full 0xffffffff member mask is valid.
|
||||
__global__ void igneum_hash(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask) {
|
||||
uint32_t gid = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
uint32_t nonce = baseNonce + gid;
|
||||
uint32_t r0, r1, r2, r3, r4, r5, r6, r7;
|
||||
{ uint32_t x = nonce ^ 0x3673211cu; x += 0x9e3779b9u; x = splitmix32(x); r0 = x ^ 0xaae550b4u; } // SEEDW[0], 0x9e3779b9u * 1u, SEEDW[1]
|
||||
{ uint32_t x = nonce ^ 0xaae550b4u; x += 0x3c6ef372u; x = splitmix32(x); r1 = x ^ 0x5a0ce2e0u; } // SEEDW[1], 0x9e3779b9u * 2u, SEEDW[2]
|
||||
{ uint32_t x = nonce ^ 0x5a0ce2e0u; x += 0xdaa66d2bu; x = splitmix32(x); r2 = x ^ 0x1d2471cfu; } // SEEDW[2], 0x9e3779b9u * 3u, SEEDW[3]
|
||||
{ uint32_t x = nonce ^ 0x1d2471cfu; x += 0x78dde6e4u; x = splitmix32(x); r3 = x ^ 0xba944366u; } // SEEDW[3], 0x9e3779b9u * 4u, SEEDW[4]
|
||||
{ uint32_t x = nonce ^ 0xba944366u; x += 0x1715609du; x = splitmix32(x); r4 = x ^ 0xbdd4d1dbu; } // SEEDW[4], 0x9e3779b9u * 5u, SEEDW[5]
|
||||
{ uint32_t x = nonce ^ 0xbdd4d1dbu; x += 0xb54cda56u; x = splitmix32(x); r5 = x ^ 0xcb1984a9u; } // SEEDW[5], 0x9e3779b9u * 6u, SEEDW[6]
|
||||
{ uint32_t x = nonce ^ 0xcb1984a9u; x += 0x5384540fu; x = splitmix32(x); r6 = x ^ 0x081ce12au; } // SEEDW[6], 0x9e3779b9u * 7u, SEEDW[7]
|
||||
{ uint32_t x = nonce ^ 0x081ce12au; x += 0xf1bbcdc8u; x = splitmix32(x); r7 = x ^ 0x3673211cu; } // SEEDW[7], 0x9e3779b9u * 8u, SEEDW[0]
|
||||
|
||||
for (uint32_t it = 0u; it < 8u; ++it) {
|
||||
uint32_t sel = r0;
|
||||
r0 = r0 ^ __shfl_xor_sync(0xffffffffu, r2, 1); // 0 shfl
|
||||
r2 = r2 * r0; // 1 mul
|
||||
r0 = r0 + r6 + ((((sel >> 20u) & 1u) != 0u) ? 0x03fa29f3u : 0x7fbf4ae6u); // 2 add
|
||||
r2 = r2 * r7; // 3 mul
|
||||
r6 = r6 ^ ds[r2 & mask]; // 4 load
|
||||
{ uint32_t b_ = (r0 & mask) & ~3u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint32_t x_ = r7 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r7 = x_; } // 5 load
|
||||
r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r4, 16); // 6 shfl
|
||||
r3 = r3 ^ r5; // 7 xor
|
||||
r6 = r6 ^ ds[r7 & mask]; // 8 load
|
||||
r0 = r0 + r7 + ((((sel >> 25u) & 1u) != 0u) ? 0x308c81bfu : 0xd59b21b0u); // 9 add
|
||||
r5 = rotr_var(r5, r7); // 10 rotr
|
||||
{ uint32_t b_ = (r6 & mask) & ~3u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint32_t x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r3 = x_; } // 11 load
|
||||
r2 = r2 * r6; // 12 mul
|
||||
{ uint32_t b_ = (r0 & mask) & ~15u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint32_t x_ = r7 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r7 = x_; } // 13 load
|
||||
r2 = r5 * r2 + r2; // 14 mad
|
||||
r4 = r4 + r0 + ((((sel >> 24u) & 1u) != 0u) ? 0x67081e7eu : 0x902dc661u); // 15 add
|
||||
{ uint32_t b_ = (r4 & mask) & ~3u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint32_t x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r3 = x_; } // 16 load
|
||||
r3 = __umulhi(r3, r4); // 17 mulhi
|
||||
{ uint32_t b_ = (r7 & mask) & ~3u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint32_t x_ = r4 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r4 = x_; } // 18 load
|
||||
r2 = r2 + r1 + ((((sel >> 9u) & 1u) != 0u) ? 0xd1e74db0u : 0x3ee3182cu); // 19 add
|
||||
r7 = r7 ^ r6; // 20 xor
|
||||
r5 = r5 ^ r3; // 21 xor
|
||||
r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r2, 16); // 22 shfl
|
||||
{ uint32_t b_ = (r2 & mask) & ~3u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint32_t x_ = r0 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r0 = x_; } // 23 load
|
||||
r2 = r2 + r5 + ((((sel >> 22u) & 1u) != 0u) ? 0x62ac9e52u : 0xd2d451c6u); // 24 add
|
||||
{ uint32_t b_ = (r7 & mask) & ~3u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint32_t x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r3 = x_; } // 25 load
|
||||
r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r1, 16); // 26 shfl
|
||||
{ uint32_t b_ = (r4 & mask) & ~3u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint32_t x_ = r1 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r1 = x_; } // 27 load
|
||||
r1 = r1 + r5 + ((((sel >> 2u) & 1u) != 0u) ? 0x072cfabeu : 0x111ff813u); // 28 add
|
||||
r4 = r1 * r2 + r4; // 29 mad
|
||||
r2 = r2 * r0; // 30 mul
|
||||
r0 = r0 ^ r5; // 31 xor
|
||||
r1 = r1 ^ ds[r0 & mask]; // 32 load
|
||||
r2 = r2 - r3; // 33 sub
|
||||
r2 = r2 ^ __shfl_xor_sync(0xffffffffu, r0, 2); // 34 shfl
|
||||
r0 = r0 - r6; // 35 sub
|
||||
r4 = r4 * r7; // 36 mul
|
||||
r5 = r5 ^ r6; // 37 xor
|
||||
r0 = __umulhi(r0, r6); // 38 mulhi
|
||||
r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r7, 4); // 39 shfl
|
||||
{ uint32_t b_ = (r3 & mask) & ~3u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint32_t x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r6 = x_; } // 40 load
|
||||
r2 = r2 ^ ds[r4 & mask]; // 41 load
|
||||
r5 = r5 ^ ds[r6 & mask]; // 42 load
|
||||
r1 = rotr_var(r1, r4); // 43 rotr
|
||||
r0 = r0 | r5; // 44 or
|
||||
r0 = r0 ^ __shfl_xor_sync(0xffffffffu, r2, 2); // 45 shfl
|
||||
r7 = r7 * r4; // 46 mul
|
||||
r3 = r3 ^ r4; // 47 xor
|
||||
r2 = __umulhi(r2, r6); // 48 mulhi
|
||||
r5 = r5 ^ r4; // 49 xor
|
||||
r1 = rotr_var(r1, r6); // 50 rotr
|
||||
r7 = r7 + r0 + ((((sel >> 22u) & 1u) != 0u) ? 0x0fe79cecu : 0x68d3a5c0u); // 51 add
|
||||
r5 = r5 + r4 + ((((sel >> 8u) & 1u) != 0u) ? 0x04309e6fu : 0xeb764d91u); // 52 add
|
||||
r7 = r7 ^ r0; // 53 xor
|
||||
r4 = r4 + r0 + ((((sel >> 6u) & 1u) != 0u) ? 0xba0b81c6u : 0x1390b188u); // 54 add
|
||||
r0 = r0 + r5 + ((((sel >> 15u) & 1u) != 0u) ? 0x5ec96dd8u : 0x4c21a6cdu); // 55 add
|
||||
r7 = r5 * r3 + r7; // 56 mad
|
||||
{ uint32_t b_ = (r0 & mask) & ~15u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint32_t x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r6 = x_; } // 57 load
|
||||
r5 = r5 + r1 + ((((sel >> 1u) & 1u) != 0u) ? 0x6c0ac4ddu : 0x68297b06u); // 58 add
|
||||
r6 = rotr_var(r6, r7); // 59 rotr
|
||||
{ uint32_t b_ = (r4 & mask) & ~15u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint32_t x_ = r7 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r7 = x_; } // 60 load
|
||||
r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r3, 4); // 61 shfl
|
||||
r4 = rotl_imm(r4, 6u); // 62 rotl
|
||||
r1 = r2 * r1 + r1; // 63 mad
|
||||
}
|
||||
uint32_t lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u);
|
||||
uint32_t hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u);
|
||||
out[gid] = ((uint64_t)hi << 32) | (uint64_t)lo;
|
||||
}
|
||||
|
||||
// Host-side launch wrappers. Declared in program.h, called from host.cu.
|
||||
cudaError_t igneum_launch_cache_fill(uint32_t* cache, uint32_t nSegments) {
|
||||
if (nSegments == 0u) return cudaErrorInvalidValue;
|
||||
uint32_t block = 256u;
|
||||
uint32_t grid = (nSegments + block - 1u) / block;
|
||||
igneum_cache_fill<<<grid, block>>>(cache, nSegments);
|
||||
return cudaGetLastError();
|
||||
}
|
||||
|
||||
cudaError_t igneum_launch_build(uint32_t* ds, const uint32_t* cache, uint32_t nItems) {
|
||||
if (nItems == 0u) return cudaErrorInvalidValue;
|
||||
uint32_t block = 256u;
|
||||
uint32_t grid = (nItems + block - 1u) / block;
|
||||
igneum_build<<<grid, block>>>(ds, cache, nItems);
|
||||
return cudaGetLastError();
|
||||
}
|
||||
|
||||
cudaError_t igneum_launch_hash(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask,
|
||||
uint32_t nonces, uint32_t blockWarps) {
|
||||
if (blockWarps == 0u || blockWarps > 32u) return cudaErrorInvalidValue;
|
||||
uint32_t block = 32u * blockWarps;
|
||||
if (nonces == 0u || (nonces % block) != 0u) return cudaErrorInvalidValue;
|
||||
igneum_hash<<<nonces / block, block>>>(ds, out, baseNonce, mask);
|
||||
return cudaGetLastError();
|
||||
}
|
||||
|
||||
cudaError_t igneum_hash_info(int* numRegs, int* blocksPerSM, uint32_t blockWarps) {
|
||||
cudaFuncAttributes attr;
|
||||
cudaError_t e = cudaFuncGetAttributes(&attr, igneum_hash);
|
||||
if (e != cudaSuccess) return e;
|
||||
*numRegs = attr.numRegs;
|
||||
return cudaOccupancyMaxActiveBlocksPerMultiprocessor(blocksPerSM, igneum_hash, (int)(32u * blockWarps), 0);
|
||||
}
|
||||
372
proto-cuda/packs-readwidth/mixB-0/kernel_bound.cl
Normal file
372
proto-cuda/packs-readwidth/mixB-0/kernel_bound.cl
Normal file
|
|
@ -0,0 +1,372 @@
|
|||
// Generated by igneum-pow export (generator v2) for seed "igneum-readwidth/B/0". Do not edit by hand.
|
||||
// OpenCL C twin of the Metal kernel for the same seed (see proto-opencl/README.md, WAVEFRONT.md and program.metal).
|
||||
// Built from source at runtime by proto-opencl/host.c, which passes these defines:
|
||||
// IGNEUM_GROUP work-group size of igneum_hash, a multiple of 32 (default 32: one work-group = one 32-lane unit)
|
||||
// IGNEUM_EXCHANGE 0 = local-memory exchange with a barrier (any device, any wave width; the default)
|
||||
// 1 = sub_group_shuffle_xor (cl_khr_subgroup_shuffle), only with IGNEUM_GROUP 32 and a sub-group size of exactly 32
|
||||
// 2 = intel_sub_group_shuffle_xor (cl_intel_subgroups), same condition
|
||||
// The verification unit is always 32 lanes. A 64-wide hardware wave (AMD GCN/CDNA, RDNA in wave64) runs two units;
|
||||
// the exchange masks are 1, 2, 4, 8, 16, so every partner lane lies inside the lane's own aligned run of 32.
|
||||
#ifndef IGNEUM_GROUP
|
||||
#define IGNEUM_GROUP 32
|
||||
#endif
|
||||
#ifndef IGNEUM_EXCHANGE
|
||||
#define IGNEUM_EXCHANGE 0
|
||||
#endif
|
||||
#ifdef __OPENCL_VERSION__
|
||||
#define IGNEUM_KERNEL_HASH __kernel __attribute__((reqd_work_group_size(IGNEUM_GROUP, 1, 1)))
|
||||
#define IGNEUM_LOCAL_WORDS(name, n) __local uint name[n]
|
||||
#if IGNEUM_EXCHANGE == 1
|
||||
#ifdef cl_khr_subgroups
|
||||
#pragma OPENCL EXTENSION cl_khr_subgroups : enable
|
||||
#endif
|
||||
#ifdef cl_khr_subgroup_shuffle
|
||||
#pragma OPENCL EXTENSION cl_khr_subgroup_shuffle : enable
|
||||
#endif
|
||||
#elif IGNEUM_EXCHANGE == 2
|
||||
#pragma OPENCL EXTENSION cl_intel_subgroups : enable
|
||||
#endif
|
||||
#else
|
||||
// Not an OpenCL compiler: proto-opencl/emu compiles this file as C++ and supplies the built-ins and these two macros.
|
||||
#include "emu_opencl.h"
|
||||
#endif
|
||||
|
||||
#if IGNEUM_EXCHANGE == 1
|
||||
#define IGNEUM_SHFL_XOR(dst, a, m) dst = sub_group_shuffle_xor((a), (uint)(m))
|
||||
#define IGNEUM_BCAST0(dst, a) dst = sub_group_broadcast((a), 0u)
|
||||
#elif IGNEUM_EXCHANGE == 2
|
||||
#define IGNEUM_SHFL_XOR(dst, a, m) dst = intel_sub_group_shuffle_xor((a), (uint)(m))
|
||||
#define IGNEUM_BCAST0(dst, a) dst = sub_group_broadcast((a), 0u)
|
||||
#else
|
||||
// Local-memory exchange. Two buffers of IGNEUM_GROUP words alternate (xk counts exchanges), so one barrier per
|
||||
// exchange is enough: a lane can only overwrite buffer b at exchange k+2 after passing barrier k+1, and every lane
|
||||
// reaches barrier k+1 only after its read of buffer b at exchange k. The partner lid ^ m stays inside the lane's
|
||||
// aligned run of 32 because m < 32. Control flow is uniform, so every work-item reaches every barrier.
|
||||
#define IGNEUM_SHFL_XOR(dst, a, m) { xch[(xk & 1u) * IGNEUM_GROUP + lid] = (a); barrier(CLK_LOCAL_MEM_FENCE); dst = xch[(xk & 1u) * IGNEUM_GROUP + (lid ^ (uint)(m))]; xk += 1u; }
|
||||
#define IGNEUM_BCAST0(dst, a) { xch[(xk & 1u) * IGNEUM_GROUP + lid] = (a); barrier(CLK_LOCAL_MEM_FENCE); dst = xch[(xk & 1u) * IGNEUM_GROUP + (lid & ~31u)]; xk += 1u; }
|
||||
#endif
|
||||
|
||||
static inline uint splitmix32(uint x) {
|
||||
x ^= x >> 16; x *= 0x7feb352du;
|
||||
x ^= x >> 15; x *= 0x846ca68bu;
|
||||
x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
// n is a literal in 1..31 at every call site. OpenCL rotate() rotates left by n modulo 32.
|
||||
static inline uint rotl_imm(uint x, uint n) { return rotate(x, n); }
|
||||
// Right rotation by n modulo 32 as a left rotation by (32 - n) modulo 32; n == 0 gives x.
|
||||
static inline uint rotr_var(uint x, uint n) { return rotate(x, (0u - n) & 31u); }
|
||||
static inline uint ds_elem(uint i, uint d0, uint d1) {
|
||||
uint x = i ^ d0;
|
||||
x *= 0x9E3779B1u; x ^= x >> 15;
|
||||
x += d1;
|
||||
x *= 0x85EBCA77u; x ^= x >> 13;
|
||||
x *= 0xC2B2AE3Du; x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
|
||||
// Memory-hard dataset core (MEMHARD.md). Cache: 2^26 words in 2^16 segments of 64 chained ChaCha12 lines.
|
||||
// Item: 8 rounds of seed-parameterised mixer + one 64-byte cache read, then a final mixer. All parameters are literals.
|
||||
#define MH_CACHE_LINE_MASK 0x003fffffu
|
||||
#define MH_SEGMENT_LINES 64u
|
||||
#define MH_QR(a, b, c, d, r1, r2, r3, r4) { a += b; d ^= a; d = mh_rotl(d, r1); c += d; b ^= c; b = mh_rotl(b, r2); a += b; d ^= a; d = mh_rotl(d, r3); c += d; b ^= c; b = mh_rotl(b, r4); }
|
||||
static inline uint mh_rotl(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 at every call site
|
||||
|
||||
// y = ChaCha12 core(x) + x
|
||||
static inline void mh_chacha_block(const uint* x, uint* y) {
|
||||
for (uint i = 0u; i < 16u; ++i) y[i] = x[i];
|
||||
for (uint r = 0u; r < 6u; ++r) {
|
||||
MH_QR(y[0], y[4], y[8], y[12], 16u, 12u, 8u, 7u) MH_QR(y[1], y[5], y[9], y[13], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[2], y[6], y[10], y[14], 16u, 12u, 8u, 7u) MH_QR(y[3], y[7], y[11], y[15], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[0], y[5], y[10], y[15], 16u, 12u, 8u, 7u) MH_QR(y[1], y[6], y[11], y[12], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[2], y[7], y[8], y[13], 16u, 12u, 8u, 7u) MH_QR(y[3], y[4], y[9], y[14], 16u, 12u, 8u, 7u)
|
||||
}
|
||||
for (uint i = 0u; i < 16u; ++i) y[i] += x[i];
|
||||
}
|
||||
|
||||
// One cache segment: 64 chained lines written at cache[seg * 1024]. in_j = prev ^ (sigma || K || seg || j || tag), prev_0 = 0.
|
||||
static inline void mh_cache_segment(__global uint* cache, uint seg) {
|
||||
uint prev[16]; uint x[16]; uint y[16];
|
||||
for (uint i = 0u; i < 16u; ++i) prev[i] = 0u;
|
||||
for (uint j = 0u; j < MH_SEGMENT_LINES; ++j) {
|
||||
x[0] = 0x61707865u ^ prev[0]; x[1] = 0x3320646eu ^ prev[1]; x[2] = 0x79622d32u ^ prev[2]; x[3] = 0x6b206574u ^ prev[3];
|
||||
x[4] = 0x3067619fu ^ prev[4];
|
||||
x[5] = 0x3c269176u ^ prev[5];
|
||||
x[6] = 0x84a03b03u ^ prev[6];
|
||||
x[7] = 0xf8c63294u ^ prev[7];
|
||||
x[8] = 0xff977c5bu ^ prev[8];
|
||||
x[9] = 0xe60def3eu ^ prev[9];
|
||||
x[10] = 0x63630141u ^ prev[10];
|
||||
x[11] = 0xb8fbcb58u ^ prev[11];
|
||||
x[12] = seg ^ prev[12]; x[13] = j ^ prev[13]; x[14] = 0x49676e65u ^ prev[14]; x[15] = 0x756d4d48u ^ prev[15];
|
||||
mh_chacha_block(x, y);
|
||||
__global uint* line = cache + ((seg * MH_SEGMENT_LINES + j) * 16u);
|
||||
for (uint i = 0u; i < 16u; ++i) { line[i] = y[i]; prev[i] = y[i]; }
|
||||
}
|
||||
}
|
||||
|
||||
// M_r: per word (s ^ (RC + rk)) * MUL, then a column round and a diagonal round with the seed-drawn rotations.
|
||||
static inline void mh_mixer(uint* s, uint rk) {
|
||||
s[0] = (s[0] ^ (0xbab68293u + rk)) * 0x42146205u;
|
||||
s[1] = (s[1] ^ (0xcc162340u + rk)) * 0x52cbe0fbu;
|
||||
s[2] = (s[2] ^ (0x6ce151ccu + rk)) * 0x7ecf4a03u;
|
||||
s[3] = (s[3] ^ (0xe62b8997u + rk)) * 0x6728907fu;
|
||||
s[4] = (s[4] ^ (0xc9c80297u + rk)) * 0xd81d9751u;
|
||||
s[5] = (s[5] ^ (0xf74a1654u + rk)) * 0x132952c3u;
|
||||
s[6] = (s[6] ^ (0x3d704af5u + rk)) * 0xf60de277u;
|
||||
s[7] = (s[7] ^ (0x3cf522b7u + rk)) * 0x05358035u;
|
||||
s[8] = (s[8] ^ (0x2b9cac04u + rk)) * 0xbaf6499du;
|
||||
s[9] = (s[9] ^ (0xa880ac10u + rk)) * 0xe4db9667u;
|
||||
s[10] = (s[10] ^ (0x13e5dd1du + rk)) * 0x3e98f45du;
|
||||
s[11] = (s[11] ^ (0x6fc3e233u + rk)) * 0xd0004eddu;
|
||||
s[12] = (s[12] ^ (0x2d83eeacu + rk)) * 0x2691630du;
|
||||
s[13] = (s[13] ^ (0x9006e8bfu + rk)) * 0x9beb3bcfu;
|
||||
s[14] = (s[14] ^ (0x2c4b5362u + rk)) * 0xab310379u;
|
||||
s[15] = (s[15] ^ (0x31b49ee2u + rk)) * 0x99cfb423u;
|
||||
MH_QR(s[0], s[4], s[8], s[12], 20u, 20u, 19u, 4u) MH_QR(s[1], s[5], s[9], s[13], 20u, 20u, 19u, 4u)
|
||||
MH_QR(s[2], s[6], s[10], s[14], 20u, 20u, 19u, 4u) MH_QR(s[3], s[7], s[11], s[15], 20u, 20u, 19u, 4u)
|
||||
MH_QR(s[0], s[5], s[10], s[15], 26u, 3u, 3u, 27u) MH_QR(s[1], s[6], s[11], s[12], 26u, 3u, 3u, 27u)
|
||||
MH_QR(s[2], s[7], s[8], s[13], 26u, 3u, 3u, 27u) MH_QR(s[3], s[4], s[9], s[14], 26u, 3u, 3u, 27u)
|
||||
}
|
||||
|
||||
// Item t: 16 words. s = (K, t * MUL[i] + RC[i]); 8 rounds of mixer + cache line s[0] & mask; final mixer.
|
||||
static inline void mh_item(__global const uint* cache, uint t, uint* s) {
|
||||
s[0] = 0x3067619fu;
|
||||
s[1] = 0x3c269176u;
|
||||
s[2] = 0x84a03b03u;
|
||||
s[3] = 0xf8c63294u;
|
||||
s[4] = 0xff977c5bu;
|
||||
s[5] = 0xe60def3eu;
|
||||
s[6] = 0x63630141u;
|
||||
s[7] = 0xb8fbcb58u;
|
||||
s[8] = t * 0x42146205u + 0xbab68293u;
|
||||
s[9] = t * 0x52cbe0fbu + 0xcc162340u;
|
||||
s[10] = t * 0x7ecf4a03u + 0x6ce151ccu;
|
||||
s[11] = t * 0x6728907fu + 0xe62b8997u;
|
||||
s[12] = t * 0xd81d9751u + 0xc9c80297u;
|
||||
s[13] = t * 0x132952c3u + 0xf74a1654u;
|
||||
s[14] = t * 0xf60de277u + 0x3d704af5u;
|
||||
s[15] = t * 0x05358035u + 0x3cf522b7u;
|
||||
for (uint r = 0u; r < 8u; ++r) {
|
||||
mh_mixer(s, 0x9E3779B9u * (r + 1u));
|
||||
__global const uint* line = cache + ((s[0] & MH_CACHE_LINE_MASK) * 16u);
|
||||
for (uint i = 0u; i < 16u; ++i) s[i] ^= line[i];
|
||||
}
|
||||
mh_mixer(s, 0x9E3779B9u * 9u);
|
||||
}
|
||||
// dataset[w] without the dataset: derive item w >> 4 and take word w & 15.
|
||||
static inline uint mh_word(__global const uint* cache, uint w) { uint s[16]; mh_item(cache, w >> 4u, s); return s[w & 15u]; }
|
||||
|
||||
// Memory-hard dataset (MEMHARD.md). One work-item per cache segment; one work-item per 64-byte dataset item.
|
||||
// The same constants as memhard.h in this pack (one emitter, three dialects).
|
||||
__kernel void igneum_cache_fill(__global uint* cache, uint nSegments) {
|
||||
uint seg = (uint)get_global_id(0);
|
||||
if (seg < nSegments) mh_cache_segment(cache, seg);
|
||||
}
|
||||
__kernel void igneum_build(__global uint* ds, __global const uint* cache, uint nItems) {
|
||||
uint t = (uint)get_global_id(0);
|
||||
if (t < nItems) {
|
||||
uint s[16];
|
||||
mh_item(cache, t, s);
|
||||
__global uint* d = ds + ((ulong)t * 16u);
|
||||
for (uint i = 0u; i < 16u; ++i) d[i] = s[i];
|
||||
}
|
||||
}
|
||||
|
||||
// One hash per work-item. IGNEUM_GROUP is a multiple of 32; lane = lid & 31 and every exchange stays inside the
|
||||
// lane's own aligned run of 32 work-items, exactly like simd_shuffle_xor inside a 32-wide Metal SIMD group and
|
||||
// __shfl_xor_sync inside a CUDA warp. Control flow is uniform (no branches at all).
|
||||
IGNEUM_KERNEL_HASH void igneum_hash(__global const uint* ds, __global ulong* out, uint baseNonce, uint mask) {
|
||||
uint gid = (uint)get_global_id(0);
|
||||
uint lid = (uint)get_local_id(0);
|
||||
uint nonce = baseNonce + gid;
|
||||
uint r0, r1, r2, r3, r4, r5, r6, r7;
|
||||
#if IGNEUM_EXCHANGE == 0
|
||||
IGNEUM_LOCAL_WORDS(xch, 2 * IGNEUM_GROUP);
|
||||
uint xk = 0u;
|
||||
#else
|
||||
(void)lid;
|
||||
#endif
|
||||
{ uint x = nonce ^ 0x3673211cu; x += 0x9e3779b9u; x = splitmix32(x); r0 = x ^ 0xaae550b4u; } // SEEDW[0], 0x9e3779b9u * 1u, SEEDW[1]
|
||||
{ uint x = nonce ^ 0xaae550b4u; x += 0x3c6ef372u; x = splitmix32(x); r1 = x ^ 0x5a0ce2e0u; } // SEEDW[1], 0x9e3779b9u * 2u, SEEDW[2]
|
||||
{ uint x = nonce ^ 0x5a0ce2e0u; x += 0xdaa66d2bu; x = splitmix32(x); r2 = x ^ 0x1d2471cfu; } // SEEDW[2], 0x9e3779b9u * 3u, SEEDW[3]
|
||||
{ uint x = nonce ^ 0x1d2471cfu; x += 0x78dde6e4u; x = splitmix32(x); r3 = x ^ 0xba944366u; } // SEEDW[3], 0x9e3779b9u * 4u, SEEDW[4]
|
||||
{ uint x = nonce ^ 0xba944366u; x += 0x1715609du; x = splitmix32(x); r4 = x ^ 0xbdd4d1dbu; } // SEEDW[4], 0x9e3779b9u * 5u, SEEDW[5]
|
||||
{ uint x = nonce ^ 0xbdd4d1dbu; x += 0xb54cda56u; x = splitmix32(x); r5 = x ^ 0xcb1984a9u; } // SEEDW[5], 0x9e3779b9u * 6u, SEEDW[6]
|
||||
{ uint x = nonce ^ 0xcb1984a9u; x += 0x5384540fu; x = splitmix32(x); r6 = x ^ 0x081ce12au; } // SEEDW[6], 0x9e3779b9u * 7u, SEEDW[7]
|
||||
{ uint x = nonce ^ 0x081ce12au; x += 0xf1bbcdc8u; x = splitmix32(x); r7 = x ^ 0x3673211cu; } // SEEDW[7], 0x9e3779b9u * 8u, SEEDW[0]
|
||||
|
||||
for (uint it = 0u; it < 8u; ++it) {
|
||||
uint sel = r0;
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r2, 1u); r0 = r0 ^ t_; } // 0 shfl
|
||||
r2 = r2 * r0; // 1 mul
|
||||
r0 = r0 + r6 + ((((sel >> 20u) & 1u) != 0u) ? 0x03fa29f3u : 0x7fbf4ae6u); // 2 add
|
||||
r2 = r2 * r7; // 3 mul
|
||||
r6 = r6 ^ ds[r2 & mask]; // 4 load
|
||||
{ uint b_ = (r0 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r7 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r7 = x_; } // 5 load
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r4, 16u); r6 = r6 ^ t_; } // 6 shfl
|
||||
r3 = r3 ^ r5; // 7 xor
|
||||
r6 = r6 ^ ds[r7 & mask]; // 8 load
|
||||
r0 = r0 + r7 + ((((sel >> 25u) & 1u) != 0u) ? 0x308c81bfu : 0xd59b21b0u); // 9 add
|
||||
r5 = rotr_var(r5, r7); // 10 rotr
|
||||
{ uint b_ = (r6 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r3 = x_; } // 11 load
|
||||
r2 = r2 * r6; // 12 mul
|
||||
{ uint b_ = (r0 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r7 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r7 = x_; } // 13 load
|
||||
r2 = r5 * r2 + r2; // 14 mad
|
||||
r4 = r4 + r0 + ((((sel >> 24u) & 1u) != 0u) ? 0x67081e7eu : 0x902dc661u); // 15 add
|
||||
{ uint b_ = (r4 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r3 = x_; } // 16 load
|
||||
r3 = mul_hi(r3, r4); // 17 mulhi
|
||||
{ uint b_ = (r7 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r4 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r4 = x_; } // 18 load
|
||||
r2 = r2 + r1 + ((((sel >> 9u) & 1u) != 0u) ? 0xd1e74db0u : 0x3ee3182cu); // 19 add
|
||||
r7 = r7 ^ r6; // 20 xor
|
||||
r5 = r5 ^ r3; // 21 xor
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r2, 16u); r6 = r6 ^ t_; } // 22 shfl
|
||||
{ uint b_ = (r2 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r0 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r0 = x_; } // 23 load
|
||||
r2 = r2 + r5 + ((((sel >> 22u) & 1u) != 0u) ? 0x62ac9e52u : 0xd2d451c6u); // 24 add
|
||||
{ uint b_ = (r7 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r3 = x_; } // 25 load
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r1, 16u); r4 = r4 ^ t_; } // 26 shfl
|
||||
{ uint b_ = (r4 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r1 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r1 = x_; } // 27 load
|
||||
r1 = r1 + r5 + ((((sel >> 2u) & 1u) != 0u) ? 0x072cfabeu : 0x111ff813u); // 28 add
|
||||
r4 = r1 * r2 + r4; // 29 mad
|
||||
r2 = r2 * r0; // 30 mul
|
||||
r0 = r0 ^ r5; // 31 xor
|
||||
r1 = r1 ^ ds[r0 & mask]; // 32 load
|
||||
r2 = r2 - r3; // 33 sub
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r0, 2u); r2 = r2 ^ t_; } // 34 shfl
|
||||
r0 = r0 - r6; // 35 sub
|
||||
r4 = r4 * r7; // 36 mul
|
||||
r5 = r5 ^ r6; // 37 xor
|
||||
r0 = mul_hi(r0, r6); // 38 mulhi
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r7, 4u); r5 = r5 ^ t_; } // 39 shfl
|
||||
{ uint b_ = (r3 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r6 = x_; } // 40 load
|
||||
r2 = r2 ^ ds[r4 & mask]; // 41 load
|
||||
r5 = r5 ^ ds[r6 & mask]; // 42 load
|
||||
r1 = rotr_var(r1, r4); // 43 rotr
|
||||
r0 = r0 | r5; // 44 or
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r2, 2u); r0 = r0 ^ t_; } // 45 shfl
|
||||
r7 = r7 * r4; // 46 mul
|
||||
r3 = r3 ^ r4; // 47 xor
|
||||
r2 = mul_hi(r2, r6); // 48 mulhi
|
||||
r5 = r5 ^ r4; // 49 xor
|
||||
r1 = rotr_var(r1, r6); // 50 rotr
|
||||
r7 = r7 + r0 + ((((sel >> 22u) & 1u) != 0u) ? 0x0fe79cecu : 0x68d3a5c0u); // 51 add
|
||||
r5 = r5 + r4 + ((((sel >> 8u) & 1u) != 0u) ? 0x04309e6fu : 0xeb764d91u); // 52 add
|
||||
r7 = r7 ^ r0; // 53 xor
|
||||
r4 = r4 + r0 + ((((sel >> 6u) & 1u) != 0u) ? 0xba0b81c6u : 0x1390b188u); // 54 add
|
||||
r0 = r0 + r5 + ((((sel >> 15u) & 1u) != 0u) ? 0x5ec96dd8u : 0x4c21a6cdu); // 55 add
|
||||
r7 = r5 * r3 + r7; // 56 mad
|
||||
{ uint b_ = (r0 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r6 = x_; } // 57 load
|
||||
r5 = r5 + r1 + ((((sel >> 1u) & 1u) != 0u) ? 0x6c0ac4ddu : 0x68297b06u); // 58 add
|
||||
r6 = rotr_var(r6, r7); // 59 rotr
|
||||
{ uint b_ = (r4 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r7 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r7 = x_; } // 60 load
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r3, 4u); r6 = r6 ^ t_; } // 61 shfl
|
||||
r4 = rotl_imm(r4, 6u); // 62 rotl
|
||||
r1 = r2 * r1 + r1; // 63 mad
|
||||
}
|
||||
uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u);
|
||||
uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u);
|
||||
out[gid] = ((ulong)hi << 32) | (ulong)lo;
|
||||
}
|
||||
|
||||
#if IGNEUM_EXCHANGE != 0
|
||||
// Reports the sub-group size this device uses for a work-group of IGNEUM_GROUP items. host.c runs it only when the
|
||||
// per-kernel query (clGetKernelSubGroupInfoKHR on igneum_hash) is unavailable; that query is preferred because a
|
||||
// compiler may pick a different wave width per kernel (RDNA: wave32 or wave64). See WAVEFRONT.md.
|
||||
IGNEUM_KERNEL_HASH void igneum_probe_subgroup(__global uint* out) {
|
||||
if (get_local_id(0) == 0u) { out[0] = get_sub_group_size(); out[1] = get_num_sub_groups(); }
|
||||
}
|
||||
#endif
|
||||
|
||||
// Header-bound variant (bind.rs): the init words come from initw, not SEEDW. Same body as igneum_hash.
|
||||
IGNEUM_KERNEL_HASH void igneum_hash_bound(__global const uint* ds, __global ulong* out, uint baseNonce, uint mask, __global const uint* initw) {
|
||||
uint gid = (uint)get_global_id(0);
|
||||
uint lid = (uint)get_local_id(0);
|
||||
uint nonce = baseNonce + gid;
|
||||
uint r0, r1, r2, r3, r4, r5, r6, r7;
|
||||
uint iw0 = initw[0], iw1 = initw[1], iw2 = initw[2], iw3 = initw[3], iw4 = initw[4], iw5 = initw[5], iw6 = initw[6], iw7 = initw[7];
|
||||
#if IGNEUM_EXCHANGE == 0
|
||||
IGNEUM_LOCAL_WORDS(xch, 2 * IGNEUM_GROUP);
|
||||
uint xk = 0u;
|
||||
#else
|
||||
(void)lid;
|
||||
#endif
|
||||
{ uint x = nonce ^ iw0; x += 0x9e3779b9u * 1u; x = splitmix32(x); r0 = x ^ iw1; }
|
||||
{ uint x = nonce ^ iw1; x += 0x9e3779b9u * 2u; x = splitmix32(x); r1 = x ^ iw2; }
|
||||
{ uint x = nonce ^ iw2; x += 0x9e3779b9u * 3u; x = splitmix32(x); r2 = x ^ iw3; }
|
||||
{ uint x = nonce ^ iw3; x += 0x9e3779b9u * 4u; x = splitmix32(x); r3 = x ^ iw4; }
|
||||
{ uint x = nonce ^ iw4; x += 0x9e3779b9u * 5u; x = splitmix32(x); r4 = x ^ iw5; }
|
||||
{ uint x = nonce ^ iw5; x += 0x9e3779b9u * 6u; x = splitmix32(x); r5 = x ^ iw6; }
|
||||
{ uint x = nonce ^ iw6; x += 0x9e3779b9u * 7u; x = splitmix32(x); r6 = x ^ iw7; }
|
||||
{ uint x = nonce ^ iw7; x += 0x9e3779b9u * 8u; x = splitmix32(x); r7 = x ^ iw0; }
|
||||
|
||||
for (uint it = 0u; it < 8u; ++it) {
|
||||
uint sel = r0;
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r2, 1u); r0 = r0 ^ t_; } // 0 shfl
|
||||
r2 = r2 * r0; // 1 mul
|
||||
r0 = r0 + r6 + ((((sel >> 20u) & 1u) != 0u) ? 0x03fa29f3u : 0x7fbf4ae6u); // 2 add
|
||||
r2 = r2 * r7; // 3 mul
|
||||
r6 = r6 ^ ds[r2 & mask]; // 4 load
|
||||
{ uint b_ = (r0 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r7 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r7 = x_; } // 5 load
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r4, 16u); r6 = r6 ^ t_; } // 6 shfl
|
||||
r3 = r3 ^ r5; // 7 xor
|
||||
r6 = r6 ^ ds[r7 & mask]; // 8 load
|
||||
r0 = r0 + r7 + ((((sel >> 25u) & 1u) != 0u) ? 0x308c81bfu : 0xd59b21b0u); // 9 add
|
||||
r5 = rotr_var(r5, r7); // 10 rotr
|
||||
{ uint b_ = (r6 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r3 = x_; } // 11 load
|
||||
r2 = r2 * r6; // 12 mul
|
||||
{ uint b_ = (r0 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r7 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r7 = x_; } // 13 load
|
||||
r2 = r5 * r2 + r2; // 14 mad
|
||||
r4 = r4 + r0 + ((((sel >> 24u) & 1u) != 0u) ? 0x67081e7eu : 0x902dc661u); // 15 add
|
||||
{ uint b_ = (r4 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r3 = x_; } // 16 load
|
||||
r3 = mul_hi(r3, r4); // 17 mulhi
|
||||
{ uint b_ = (r7 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r4 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r4 = x_; } // 18 load
|
||||
r2 = r2 + r1 + ((((sel >> 9u) & 1u) != 0u) ? 0xd1e74db0u : 0x3ee3182cu); // 19 add
|
||||
r7 = r7 ^ r6; // 20 xor
|
||||
r5 = r5 ^ r3; // 21 xor
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r2, 16u); r6 = r6 ^ t_; } // 22 shfl
|
||||
{ uint b_ = (r2 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r0 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r0 = x_; } // 23 load
|
||||
r2 = r2 + r5 + ((((sel >> 22u) & 1u) != 0u) ? 0x62ac9e52u : 0xd2d451c6u); // 24 add
|
||||
{ uint b_ = (r7 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r3 = x_; } // 25 load
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r1, 16u); r4 = r4 ^ t_; } // 26 shfl
|
||||
{ uint b_ = (r4 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r1 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r1 = x_; } // 27 load
|
||||
r1 = r1 + r5 + ((((sel >> 2u) & 1u) != 0u) ? 0x072cfabeu : 0x111ff813u); // 28 add
|
||||
r4 = r1 * r2 + r4; // 29 mad
|
||||
r2 = r2 * r0; // 30 mul
|
||||
r0 = r0 ^ r5; // 31 xor
|
||||
r1 = r1 ^ ds[r0 & mask]; // 32 load
|
||||
r2 = r2 - r3; // 33 sub
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r0, 2u); r2 = r2 ^ t_; } // 34 shfl
|
||||
r0 = r0 - r6; // 35 sub
|
||||
r4 = r4 * r7; // 36 mul
|
||||
r5 = r5 ^ r6; // 37 xor
|
||||
r0 = mul_hi(r0, r6); // 38 mulhi
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r7, 4u); r5 = r5 ^ t_; } // 39 shfl
|
||||
{ uint b_ = (r3 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r6 = x_; } // 40 load
|
||||
r2 = r2 ^ ds[r4 & mask]; // 41 load
|
||||
r5 = r5 ^ ds[r6 & mask]; // 42 load
|
||||
r1 = rotr_var(r1, r4); // 43 rotr
|
||||
r0 = r0 | r5; // 44 or
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r2, 2u); r0 = r0 ^ t_; } // 45 shfl
|
||||
r7 = r7 * r4; // 46 mul
|
||||
r3 = r3 ^ r4; // 47 xor
|
||||
r2 = mul_hi(r2, r6); // 48 mulhi
|
||||
r5 = r5 ^ r4; // 49 xor
|
||||
r1 = rotr_var(r1, r6); // 50 rotr
|
||||
r7 = r7 + r0 + ((((sel >> 22u) & 1u) != 0u) ? 0x0fe79cecu : 0x68d3a5c0u); // 51 add
|
||||
r5 = r5 + r4 + ((((sel >> 8u) & 1u) != 0u) ? 0x04309e6fu : 0xeb764d91u); // 52 add
|
||||
r7 = r7 ^ r0; // 53 xor
|
||||
r4 = r4 + r0 + ((((sel >> 6u) & 1u) != 0u) ? 0xba0b81c6u : 0x1390b188u); // 54 add
|
||||
r0 = r0 + r5 + ((((sel >> 15u) & 1u) != 0u) ? 0x5ec96dd8u : 0x4c21a6cdu); // 55 add
|
||||
r7 = r5 * r3 + r7; // 56 mad
|
||||
{ uint b_ = (r0 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r6 = x_; } // 57 load
|
||||
r5 = r5 + r1 + ((((sel >> 1u) & 1u) != 0u) ? 0x6c0ac4ddu : 0x68297b06u); // 58 add
|
||||
r6 = rotr_var(r6, r7); // 59 rotr
|
||||
{ uint b_ = (r4 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r7 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r7 = x_; } // 60 load
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r3, 4u); r6 = r6 ^ t_; } // 61 shfl
|
||||
r4 = rotl_imm(r4, 6u); // 62 rotl
|
||||
r1 = r2 * r1 + r1; // 63 mad
|
||||
}
|
||||
uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u);
|
||||
uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u);
|
||||
out[gid] = ((ulong)hi << 32) | (ulong)lo;
|
||||
}
|
||||
123
proto-cuda/packs-readwidth/mixB-0/kernel_bound.cu
Normal file
123
proto-cuda/packs-readwidth/mixB-0/kernel_bound.cu
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
// Generated by igneum-pow export (generator v2) for seed "igneum-readwidth/B/0". Do not edit by hand.
|
||||
// Header-bound twin of igneum_hash in kernel.cu: the init words come from a kernel argument, not SEEDW.
|
||||
// Host declarations (also in program_bound.h if present):
|
||||
// struct IgneumInitWords { uint32_t w[8]; };
|
||||
// cudaError_t igneum_launch_hash_bound(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask,
|
||||
// IgneumInitWords iw, uint32_t nonces, uint32_t blockWarps);
|
||||
// cudaError_t igneum_hash_bound_info(int* numRegs, int* blocksPerSM, uint32_t blockWarps);
|
||||
#include <cuda_runtime.h>
|
||||
#include <cstdint>
|
||||
#include "program.h"
|
||||
|
||||
struct IgneumInitWords { uint32_t w[8]; };
|
||||
|
||||
__device__ __forceinline__ uint32_t splitmix32(uint32_t x) {
|
||||
x ^= x >> 16; x *= 0x7feb352du;
|
||||
x ^= x >> 15; x *= 0x846ca68bu;
|
||||
x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
__device__ __forceinline__ uint32_t rotl_imm(uint32_t x, uint32_t n) { return (x << n) | (x >> (32u - n)); }
|
||||
__device__ __forceinline__ uint32_t rotr_var(uint32_t x, uint32_t n) { n &= 31u; return (x >> n) | (x << ((32u - n) & 31u)); }
|
||||
|
||||
__global__ void igneum_hash_bound(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask, IgneumInitWords iw) {
|
||||
uint32_t gid = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
uint32_t nonce = baseNonce + gid;
|
||||
uint32_t r0, r1, r2, r3, r4, r5, r6, r7;
|
||||
{ uint32_t x = nonce ^ iw.w[0]; x += 0x9e3779b9u * 1u; x = splitmix32(x); r0 = x ^ iw.w[1]; }
|
||||
{ uint32_t x = nonce ^ iw.w[1]; x += 0x9e3779b9u * 2u; x = splitmix32(x); r1 = x ^ iw.w[2]; }
|
||||
{ uint32_t x = nonce ^ iw.w[2]; x += 0x9e3779b9u * 3u; x = splitmix32(x); r2 = x ^ iw.w[3]; }
|
||||
{ uint32_t x = nonce ^ iw.w[3]; x += 0x9e3779b9u * 4u; x = splitmix32(x); r3 = x ^ iw.w[4]; }
|
||||
{ uint32_t x = nonce ^ iw.w[4]; x += 0x9e3779b9u * 5u; x = splitmix32(x); r4 = x ^ iw.w[5]; }
|
||||
{ uint32_t x = nonce ^ iw.w[5]; x += 0x9e3779b9u * 6u; x = splitmix32(x); r5 = x ^ iw.w[6]; }
|
||||
{ uint32_t x = nonce ^ iw.w[6]; x += 0x9e3779b9u * 7u; x = splitmix32(x); r6 = x ^ iw.w[7]; }
|
||||
{ uint32_t x = nonce ^ iw.w[7]; x += 0x9e3779b9u * 8u; x = splitmix32(x); r7 = x ^ iw.w[0]; }
|
||||
|
||||
for (uint32_t it = 0u; it < 8u; ++it) {
|
||||
uint32_t sel = r0;
|
||||
r0 = r0 ^ __shfl_xor_sync(0xffffffffu, r2, 1); // 0 shfl
|
||||
r2 = r2 * r0; // 1 mul
|
||||
r0 = r0 + r6 + ((((sel >> 20u) & 1u) != 0u) ? 0x03fa29f3u : 0x7fbf4ae6u); // 2 add
|
||||
r2 = r2 * r7; // 3 mul
|
||||
r6 = r6 ^ ds[r2 & mask]; // 4 load
|
||||
{ uint32_t b_ = (r0 & mask) & ~3u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint32_t x_ = r7 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r7 = x_; } // 5 load
|
||||
r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r4, 16); // 6 shfl
|
||||
r3 = r3 ^ r5; // 7 xor
|
||||
r6 = r6 ^ ds[r7 & mask]; // 8 load
|
||||
r0 = r0 + r7 + ((((sel >> 25u) & 1u) != 0u) ? 0x308c81bfu : 0xd59b21b0u); // 9 add
|
||||
r5 = rotr_var(r5, r7); // 10 rotr
|
||||
{ uint32_t b_ = (r6 & mask) & ~3u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint32_t x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r3 = x_; } // 11 load
|
||||
r2 = r2 * r6; // 12 mul
|
||||
{ uint32_t b_ = (r0 & mask) & ~15u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint32_t x_ = r7 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r7 = x_; } // 13 load
|
||||
r2 = r5 * r2 + r2; // 14 mad
|
||||
r4 = r4 + r0 + ((((sel >> 24u) & 1u) != 0u) ? 0x67081e7eu : 0x902dc661u); // 15 add
|
||||
{ uint32_t b_ = (r4 & mask) & ~3u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint32_t x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r3 = x_; } // 16 load
|
||||
r3 = __umulhi(r3, r4); // 17 mulhi
|
||||
{ uint32_t b_ = (r7 & mask) & ~3u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint32_t x_ = r4 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r4 = x_; } // 18 load
|
||||
r2 = r2 + r1 + ((((sel >> 9u) & 1u) != 0u) ? 0xd1e74db0u : 0x3ee3182cu); // 19 add
|
||||
r7 = r7 ^ r6; // 20 xor
|
||||
r5 = r5 ^ r3; // 21 xor
|
||||
r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r2, 16); // 22 shfl
|
||||
{ uint32_t b_ = (r2 & mask) & ~3u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint32_t x_ = r0 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r0 = x_; } // 23 load
|
||||
r2 = r2 + r5 + ((((sel >> 22u) & 1u) != 0u) ? 0x62ac9e52u : 0xd2d451c6u); // 24 add
|
||||
{ uint32_t b_ = (r7 & mask) & ~3u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint32_t x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r3 = x_; } // 25 load
|
||||
r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r1, 16); // 26 shfl
|
||||
{ uint32_t b_ = (r4 & mask) & ~3u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint32_t x_ = r1 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r1 = x_; } // 27 load
|
||||
r1 = r1 + r5 + ((((sel >> 2u) & 1u) != 0u) ? 0x072cfabeu : 0x111ff813u); // 28 add
|
||||
r4 = r1 * r2 + r4; // 29 mad
|
||||
r2 = r2 * r0; // 30 mul
|
||||
r0 = r0 ^ r5; // 31 xor
|
||||
r1 = r1 ^ ds[r0 & mask]; // 32 load
|
||||
r2 = r2 - r3; // 33 sub
|
||||
r2 = r2 ^ __shfl_xor_sync(0xffffffffu, r0, 2); // 34 shfl
|
||||
r0 = r0 - r6; // 35 sub
|
||||
r4 = r4 * r7; // 36 mul
|
||||
r5 = r5 ^ r6; // 37 xor
|
||||
r0 = __umulhi(r0, r6); // 38 mulhi
|
||||
r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r7, 4); // 39 shfl
|
||||
{ uint32_t b_ = (r3 & mask) & ~3u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint32_t x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r6 = x_; } // 40 load
|
||||
r2 = r2 ^ ds[r4 & mask]; // 41 load
|
||||
r5 = r5 ^ ds[r6 & mask]; // 42 load
|
||||
r1 = rotr_var(r1, r4); // 43 rotr
|
||||
r0 = r0 | r5; // 44 or
|
||||
r0 = r0 ^ __shfl_xor_sync(0xffffffffu, r2, 2); // 45 shfl
|
||||
r7 = r7 * r4; // 46 mul
|
||||
r3 = r3 ^ r4; // 47 xor
|
||||
r2 = __umulhi(r2, r6); // 48 mulhi
|
||||
r5 = r5 ^ r4; // 49 xor
|
||||
r1 = rotr_var(r1, r6); // 50 rotr
|
||||
r7 = r7 + r0 + ((((sel >> 22u) & 1u) != 0u) ? 0x0fe79cecu : 0x68d3a5c0u); // 51 add
|
||||
r5 = r5 + r4 + ((((sel >> 8u) & 1u) != 0u) ? 0x04309e6fu : 0xeb764d91u); // 52 add
|
||||
r7 = r7 ^ r0; // 53 xor
|
||||
r4 = r4 + r0 + ((((sel >> 6u) & 1u) != 0u) ? 0xba0b81c6u : 0x1390b188u); // 54 add
|
||||
r0 = r0 + r5 + ((((sel >> 15u) & 1u) != 0u) ? 0x5ec96dd8u : 0x4c21a6cdu); // 55 add
|
||||
r7 = r5 * r3 + r7; // 56 mad
|
||||
{ uint32_t b_ = (r0 & mask) & ~15u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint32_t x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r6 = x_; } // 57 load
|
||||
r5 = r5 + r1 + ((((sel >> 1u) & 1u) != 0u) ? 0x6c0ac4ddu : 0x68297b06u); // 58 add
|
||||
r6 = rotr_var(r6, r7); // 59 rotr
|
||||
{ uint32_t b_ = (r4 & mask) & ~15u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint32_t x_ = r7 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r7 = x_; } // 60 load
|
||||
r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r3, 4); // 61 shfl
|
||||
r4 = rotl_imm(r4, 6u); // 62 rotl
|
||||
r1 = r2 * r1 + r1; // 63 mad
|
||||
}
|
||||
uint32_t lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u);
|
||||
uint32_t hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u);
|
||||
out[gid] = ((uint64_t)hi << 32) | (uint64_t)lo;
|
||||
}
|
||||
|
||||
cudaError_t igneum_launch_hash_bound(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask,
|
||||
IgneumInitWords iw, uint32_t nonces, uint32_t blockWarps) {
|
||||
if (blockWarps == 0u || blockWarps > 32u) return cudaErrorInvalidValue;
|
||||
uint32_t block = 32u * blockWarps;
|
||||
if (nonces == 0u || (nonces % block) != 0u) return cudaErrorInvalidValue;
|
||||
igneum_hash_bound<<<nonces / block, block>>>(ds, out, baseNonce, mask, iw);
|
||||
return cudaGetLastError();
|
||||
}
|
||||
|
||||
cudaError_t igneum_hash_bound_info(int* numRegs, int* blocksPerSM, uint32_t blockWarps) {
|
||||
cudaFuncAttributes attr;
|
||||
cudaError_t e = cudaFuncGetAttributes(&attr, igneum_hash_bound);
|
||||
if (e != cudaSuccess) return e;
|
||||
*numRegs = attr.numRegs;
|
||||
return cudaOccupancyMaxActiveBlocksPerMultiprocessor(blocksPerSM, igneum_hash_bound, (int)(32u * blockWarps), 0);
|
||||
}
|
||||
108
proto-cuda/packs-readwidth/mixB-0/memhard.h
Normal file
108
proto-cuda/packs-readwidth/mixB-0/memhard.h
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
// Generated by igneum-pow export (generator v2) for seed "igneum-readwidth/B/0". Do not edit by hand.
|
||||
// Memory-hard dataset core, the same text that the Mac's Metal kernels and CPU verifier were checked against.
|
||||
// Included by kernel.cu (device), host.cu (host reference) and proto-opencl/host.c (C99 host reference).
|
||||
// See proto-metal/MEMHARD.md for the construction. kernel.cl carries the same text in OpenCL C.
|
||||
#pragma once
|
||||
#ifdef __cplusplus
|
||||
#include <cstdint>
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
#if defined(__CUDACC__)
|
||||
#define IGNEUM_HD __host__ __device__ __forceinline__
|
||||
#elif defined(_MSC_VER) && !defined(__cplusplus)
|
||||
#define IGNEUM_HD static __inline
|
||||
#else
|
||||
#define IGNEUM_HD static inline
|
||||
#endif
|
||||
// Memory-hard dataset core (MEMHARD.md). Cache: 2^26 words in 2^16 segments of 64 chained ChaCha12 lines.
|
||||
// Item: 8 rounds of seed-parameterised mixer + one 64-byte cache read, then a final mixer. All parameters are literals.
|
||||
#define MH_CACHE_LINE_MASK 0x003fffffu
|
||||
#define MH_SEGMENT_LINES 64u
|
||||
#define MH_QR(a, b, c, d, r1, r2, r3, r4) { a += b; d ^= a; d = mh_rotl(d, r1); c += d; b ^= c; b = mh_rotl(b, r2); a += b; d ^= a; d = mh_rotl(d, r3); c += d; b ^= c; b = mh_rotl(b, r4); }
|
||||
IGNEUM_HD uint32_t mh_rotl(uint32_t x, uint32_t n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 at every call site
|
||||
|
||||
// y = ChaCha12 core(x) + x
|
||||
IGNEUM_HD void mh_chacha_block(const uint32_t* x, uint32_t* y) {
|
||||
for (uint32_t i = 0u; i < 16u; ++i) y[i] = x[i];
|
||||
for (uint32_t r = 0u; r < 6u; ++r) {
|
||||
MH_QR(y[0], y[4], y[8], y[12], 16u, 12u, 8u, 7u) MH_QR(y[1], y[5], y[9], y[13], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[2], y[6], y[10], y[14], 16u, 12u, 8u, 7u) MH_QR(y[3], y[7], y[11], y[15], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[0], y[5], y[10], y[15], 16u, 12u, 8u, 7u) MH_QR(y[1], y[6], y[11], y[12], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[2], y[7], y[8], y[13], 16u, 12u, 8u, 7u) MH_QR(y[3], y[4], y[9], y[14], 16u, 12u, 8u, 7u)
|
||||
}
|
||||
for (uint32_t i = 0u; i < 16u; ++i) y[i] += x[i];
|
||||
}
|
||||
|
||||
// One cache segment: 64 chained lines written at cache[seg * 1024]. in_j = prev ^ (sigma || K || seg || j || tag), prev_0 = 0.
|
||||
IGNEUM_HD void mh_cache_segment(uint32_t* cache, uint32_t seg) {
|
||||
uint32_t prev[16]; uint32_t x[16]; uint32_t y[16];
|
||||
for (uint32_t i = 0u; i < 16u; ++i) prev[i] = 0u;
|
||||
for (uint32_t j = 0u; j < MH_SEGMENT_LINES; ++j) {
|
||||
x[0] = 0x61707865u ^ prev[0]; x[1] = 0x3320646eu ^ prev[1]; x[2] = 0x79622d32u ^ prev[2]; x[3] = 0x6b206574u ^ prev[3];
|
||||
x[4] = 0x3067619fu ^ prev[4];
|
||||
x[5] = 0x3c269176u ^ prev[5];
|
||||
x[6] = 0x84a03b03u ^ prev[6];
|
||||
x[7] = 0xf8c63294u ^ prev[7];
|
||||
x[8] = 0xff977c5bu ^ prev[8];
|
||||
x[9] = 0xe60def3eu ^ prev[9];
|
||||
x[10] = 0x63630141u ^ prev[10];
|
||||
x[11] = 0xb8fbcb58u ^ prev[11];
|
||||
x[12] = seg ^ prev[12]; x[13] = j ^ prev[13]; x[14] = 0x49676e65u ^ prev[14]; x[15] = 0x756d4d48u ^ prev[15];
|
||||
mh_chacha_block(x, y);
|
||||
uint32_t* line = cache + ((seg * MH_SEGMENT_LINES + j) * 16u);
|
||||
for (uint32_t i = 0u; i < 16u; ++i) { line[i] = y[i]; prev[i] = y[i]; }
|
||||
}
|
||||
}
|
||||
|
||||
// M_r: per word (s ^ (RC + rk)) * MUL, then a column round and a diagonal round with the seed-drawn rotations.
|
||||
IGNEUM_HD void mh_mixer(uint32_t* s, uint32_t rk) {
|
||||
s[0] = (s[0] ^ (0xbab68293u + rk)) * 0x42146205u;
|
||||
s[1] = (s[1] ^ (0xcc162340u + rk)) * 0x52cbe0fbu;
|
||||
s[2] = (s[2] ^ (0x6ce151ccu + rk)) * 0x7ecf4a03u;
|
||||
s[3] = (s[3] ^ (0xe62b8997u + rk)) * 0x6728907fu;
|
||||
s[4] = (s[4] ^ (0xc9c80297u + rk)) * 0xd81d9751u;
|
||||
s[5] = (s[5] ^ (0xf74a1654u + rk)) * 0x132952c3u;
|
||||
s[6] = (s[6] ^ (0x3d704af5u + rk)) * 0xf60de277u;
|
||||
s[7] = (s[7] ^ (0x3cf522b7u + rk)) * 0x05358035u;
|
||||
s[8] = (s[8] ^ (0x2b9cac04u + rk)) * 0xbaf6499du;
|
||||
s[9] = (s[9] ^ (0xa880ac10u + rk)) * 0xe4db9667u;
|
||||
s[10] = (s[10] ^ (0x13e5dd1du + rk)) * 0x3e98f45du;
|
||||
s[11] = (s[11] ^ (0x6fc3e233u + rk)) * 0xd0004eddu;
|
||||
s[12] = (s[12] ^ (0x2d83eeacu + rk)) * 0x2691630du;
|
||||
s[13] = (s[13] ^ (0x9006e8bfu + rk)) * 0x9beb3bcfu;
|
||||
s[14] = (s[14] ^ (0x2c4b5362u + rk)) * 0xab310379u;
|
||||
s[15] = (s[15] ^ (0x31b49ee2u + rk)) * 0x99cfb423u;
|
||||
MH_QR(s[0], s[4], s[8], s[12], 20u, 20u, 19u, 4u) MH_QR(s[1], s[5], s[9], s[13], 20u, 20u, 19u, 4u)
|
||||
MH_QR(s[2], s[6], s[10], s[14], 20u, 20u, 19u, 4u) MH_QR(s[3], s[7], s[11], s[15], 20u, 20u, 19u, 4u)
|
||||
MH_QR(s[0], s[5], s[10], s[15], 26u, 3u, 3u, 27u) MH_QR(s[1], s[6], s[11], s[12], 26u, 3u, 3u, 27u)
|
||||
MH_QR(s[2], s[7], s[8], s[13], 26u, 3u, 3u, 27u) MH_QR(s[3], s[4], s[9], s[14], 26u, 3u, 3u, 27u)
|
||||
}
|
||||
|
||||
// Item t: 16 words. s = (K, t * MUL[i] + RC[i]); 8 rounds of mixer + cache line s[0] & mask; final mixer.
|
||||
IGNEUM_HD void mh_item(const uint32_t* cache, uint32_t t, uint32_t* s) {
|
||||
s[0] = 0x3067619fu;
|
||||
s[1] = 0x3c269176u;
|
||||
s[2] = 0x84a03b03u;
|
||||
s[3] = 0xf8c63294u;
|
||||
s[4] = 0xff977c5bu;
|
||||
s[5] = 0xe60def3eu;
|
||||
s[6] = 0x63630141u;
|
||||
s[7] = 0xb8fbcb58u;
|
||||
s[8] = t * 0x42146205u + 0xbab68293u;
|
||||
s[9] = t * 0x52cbe0fbu + 0xcc162340u;
|
||||
s[10] = t * 0x7ecf4a03u + 0x6ce151ccu;
|
||||
s[11] = t * 0x6728907fu + 0xe62b8997u;
|
||||
s[12] = t * 0xd81d9751u + 0xc9c80297u;
|
||||
s[13] = t * 0x132952c3u + 0xf74a1654u;
|
||||
s[14] = t * 0xf60de277u + 0x3d704af5u;
|
||||
s[15] = t * 0x05358035u + 0x3cf522b7u;
|
||||
for (uint32_t r = 0u; r < 8u; ++r) {
|
||||
mh_mixer(s, 0x9E3779B9u * (r + 1u));
|
||||
const uint32_t* line = cache + ((s[0] & MH_CACHE_LINE_MASK) * 16u);
|
||||
for (uint32_t i = 0u; i < 16u; ++i) s[i] ^= line[i];
|
||||
}
|
||||
mh_mixer(s, 0x9E3779B9u * 9u);
|
||||
}
|
||||
// dataset[w] without the dataset: derive item w >> 4 and take word w & 15.
|
||||
IGNEUM_HD uint32_t mh_word(const uint32_t* cache, uint32_t w) { uint32_t s[16]; mh_item(cache, w >> 4u, s); return s[w & 15u]; }
|
||||
106
proto-cuda/packs-readwidth/mixB-0/memhard.metal
Normal file
106
proto-cuda/packs-readwidth/mixB-0/memhard.metal
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
#include <metal_stdlib>
|
||||
using namespace metal;
|
||||
// Memory-hard dataset core (MEMHARD.md). Cache: 2^26 words in 2^16 segments of 64 chained ChaCha12 lines.
|
||||
// Item: 8 rounds of seed-parameterised mixer + one 64-byte cache read, then a final mixer. All parameters are literals.
|
||||
#define MH_CACHE_LINE_MASK 0x003fffffu
|
||||
#define MH_SEGMENT_LINES 64u
|
||||
#define MH_QR(a, b, c, d, r1, r2, r3, r4) { a += b; d ^= a; d = mh_rotl(d, r1); c += d; b ^= c; b = mh_rotl(b, r2); a += b; d ^= a; d = mh_rotl(d, r3); c += d; b ^= c; b = mh_rotl(b, r4); }
|
||||
inline uint mh_rotl(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 at every call site
|
||||
|
||||
// y = ChaCha12 core(x) + x
|
||||
inline void mh_chacha_block(const thread uint* x, thread uint* y) {
|
||||
for (uint i = 0u; i < 16u; ++i) y[i] = x[i];
|
||||
for (uint r = 0u; r < 6u; ++r) {
|
||||
MH_QR(y[0], y[4], y[8], y[12], 16u, 12u, 8u, 7u) MH_QR(y[1], y[5], y[9], y[13], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[2], y[6], y[10], y[14], 16u, 12u, 8u, 7u) MH_QR(y[3], y[7], y[11], y[15], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[0], y[5], y[10], y[15], 16u, 12u, 8u, 7u) MH_QR(y[1], y[6], y[11], y[12], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[2], y[7], y[8], y[13], 16u, 12u, 8u, 7u) MH_QR(y[3], y[4], y[9], y[14], 16u, 12u, 8u, 7u)
|
||||
}
|
||||
for (uint i = 0u; i < 16u; ++i) y[i] += x[i];
|
||||
}
|
||||
|
||||
// One cache segment: 64 chained lines written at cache[seg * 1024]. in_j = prev ^ (sigma || K || seg || j || tag), prev_0 = 0.
|
||||
inline void mh_cache_segment(device uint* cache, uint seg) {
|
||||
uint prev[16]; uint x[16]; uint y[16];
|
||||
for (uint i = 0u; i < 16u; ++i) prev[i] = 0u;
|
||||
for (uint j = 0u; j < MH_SEGMENT_LINES; ++j) {
|
||||
x[0] = 0x61707865u ^ prev[0]; x[1] = 0x3320646eu ^ prev[1]; x[2] = 0x79622d32u ^ prev[2]; x[3] = 0x6b206574u ^ prev[3];
|
||||
x[4] = 0x3067619fu ^ prev[4];
|
||||
x[5] = 0x3c269176u ^ prev[5];
|
||||
x[6] = 0x84a03b03u ^ prev[6];
|
||||
x[7] = 0xf8c63294u ^ prev[7];
|
||||
x[8] = 0xff977c5bu ^ prev[8];
|
||||
x[9] = 0xe60def3eu ^ prev[9];
|
||||
x[10] = 0x63630141u ^ prev[10];
|
||||
x[11] = 0xb8fbcb58u ^ prev[11];
|
||||
x[12] = seg ^ prev[12]; x[13] = j ^ prev[13]; x[14] = 0x49676e65u ^ prev[14]; x[15] = 0x756d4d48u ^ prev[15];
|
||||
mh_chacha_block(x, y);
|
||||
device uint* line = cache + ((seg * MH_SEGMENT_LINES + j) * 16u);
|
||||
for (uint i = 0u; i < 16u; ++i) { line[i] = y[i]; prev[i] = y[i]; }
|
||||
}
|
||||
}
|
||||
|
||||
// M_r: per word (s ^ (RC + rk)) * MUL, then a column round and a diagonal round with the seed-drawn rotations.
|
||||
inline void mh_mixer(thread uint* s, uint rk) {
|
||||
s[0] = (s[0] ^ (0xbab68293u + rk)) * 0x42146205u;
|
||||
s[1] = (s[1] ^ (0xcc162340u + rk)) * 0x52cbe0fbu;
|
||||
s[2] = (s[2] ^ (0x6ce151ccu + rk)) * 0x7ecf4a03u;
|
||||
s[3] = (s[3] ^ (0xe62b8997u + rk)) * 0x6728907fu;
|
||||
s[4] = (s[4] ^ (0xc9c80297u + rk)) * 0xd81d9751u;
|
||||
s[5] = (s[5] ^ (0xf74a1654u + rk)) * 0x132952c3u;
|
||||
s[6] = (s[6] ^ (0x3d704af5u + rk)) * 0xf60de277u;
|
||||
s[7] = (s[7] ^ (0x3cf522b7u + rk)) * 0x05358035u;
|
||||
s[8] = (s[8] ^ (0x2b9cac04u + rk)) * 0xbaf6499du;
|
||||
s[9] = (s[9] ^ (0xa880ac10u + rk)) * 0xe4db9667u;
|
||||
s[10] = (s[10] ^ (0x13e5dd1du + rk)) * 0x3e98f45du;
|
||||
s[11] = (s[11] ^ (0x6fc3e233u + rk)) * 0xd0004eddu;
|
||||
s[12] = (s[12] ^ (0x2d83eeacu + rk)) * 0x2691630du;
|
||||
s[13] = (s[13] ^ (0x9006e8bfu + rk)) * 0x9beb3bcfu;
|
||||
s[14] = (s[14] ^ (0x2c4b5362u + rk)) * 0xab310379u;
|
||||
s[15] = (s[15] ^ (0x31b49ee2u + rk)) * 0x99cfb423u;
|
||||
MH_QR(s[0], s[4], s[8], s[12], 20u, 20u, 19u, 4u) MH_QR(s[1], s[5], s[9], s[13], 20u, 20u, 19u, 4u)
|
||||
MH_QR(s[2], s[6], s[10], s[14], 20u, 20u, 19u, 4u) MH_QR(s[3], s[7], s[11], s[15], 20u, 20u, 19u, 4u)
|
||||
MH_QR(s[0], s[5], s[10], s[15], 26u, 3u, 3u, 27u) MH_QR(s[1], s[6], s[11], s[12], 26u, 3u, 3u, 27u)
|
||||
MH_QR(s[2], s[7], s[8], s[13], 26u, 3u, 3u, 27u) MH_QR(s[3], s[4], s[9], s[14], 26u, 3u, 3u, 27u)
|
||||
}
|
||||
|
||||
// Item t: 16 words. s = (K, t * MUL[i] + RC[i]); 8 rounds of mixer + cache line s[0] & mask; final mixer.
|
||||
inline void mh_item(device const uint* cache, uint t, thread uint* s) {
|
||||
s[0] = 0x3067619fu;
|
||||
s[1] = 0x3c269176u;
|
||||
s[2] = 0x84a03b03u;
|
||||
s[3] = 0xf8c63294u;
|
||||
s[4] = 0xff977c5bu;
|
||||
s[5] = 0xe60def3eu;
|
||||
s[6] = 0x63630141u;
|
||||
s[7] = 0xb8fbcb58u;
|
||||
s[8] = t * 0x42146205u + 0xbab68293u;
|
||||
s[9] = t * 0x52cbe0fbu + 0xcc162340u;
|
||||
s[10] = t * 0x7ecf4a03u + 0x6ce151ccu;
|
||||
s[11] = t * 0x6728907fu + 0xe62b8997u;
|
||||
s[12] = t * 0xd81d9751u + 0xc9c80297u;
|
||||
s[13] = t * 0x132952c3u + 0xf74a1654u;
|
||||
s[14] = t * 0xf60de277u + 0x3d704af5u;
|
||||
s[15] = t * 0x05358035u + 0x3cf522b7u;
|
||||
for (uint r = 0u; r < 8u; ++r) {
|
||||
mh_mixer(s, 0x9E3779B9u * (r + 1u));
|
||||
device const uint* line = cache + ((s[0] & MH_CACHE_LINE_MASK) * 16u);
|
||||
for (uint i = 0u; i < 16u; ++i) s[i] ^= line[i];
|
||||
}
|
||||
mh_mixer(s, 0x9E3779B9u * 9u);
|
||||
}
|
||||
// dataset[w] without the dataset: derive item w >> 4 and take word w & 15.
|
||||
inline uint mh_word(device const uint* cache, uint w) { uint s[16]; mh_item(cache, w >> 4u, s); return s[w & 15u]; }
|
||||
|
||||
// One thread per segment (2^16 threads).
|
||||
kernel void igneum_cache_fill(device uint* cache [[buffer(0)]], uint gid [[thread_position_in_grid]]) {
|
||||
mh_cache_segment(cache, gid);
|
||||
}
|
||||
// One thread per 64-byte item (dataset words / 16 threads).
|
||||
kernel void igneum_build(device const uint* cache [[buffer(0)]], device uint* dataset [[buffer(1)]],
|
||||
uint gid [[thread_position_in_grid]]) {
|
||||
uint s[16];
|
||||
mh_item(cache, gid, s);
|
||||
device uint* d = dataset + gid * 16u;
|
||||
for (uint i = 0u; i < 16u; ++i) d[i] = s[i];
|
||||
}
|
||||
60
proto-cuda/packs-readwidth/mixB-0/program.h
Normal file
60
proto-cuda/packs-readwidth/mixB-0/program.h
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
// Generated by igneum-pow export (generator v2) for seed "igneum-readwidth/B/0". Do not edit by hand.
|
||||
// Program metadata for host.cu plus the launch wrappers defined in kernel.cu.
|
||||
// Also included by proto-opencl/host.c (C99), which defines IGNEUM_NO_CUDA first and reads only the macros.
|
||||
#pragma once
|
||||
#ifdef __cplusplus
|
||||
#include <cstdint>
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
#ifndef IGNEUM_NO_CUDA
|
||||
#include <cuda_runtime.h>
|
||||
#endif
|
||||
|
||||
#define IGNEUM_SEED_STRING "igneum-readwidth/B/0"
|
||||
#define IGNEUM_SEED_BYTES_HEX "69676e65756d2d7265616477696474682f422f30"
|
||||
#define IGNEUM_GENERATOR 2
|
||||
#define IGNEUM_PROGRAM_ATTEMPT 0
|
||||
#define IGNEUM_PROGRAM_ID 0x5404700e8a2db8feull
|
||||
#define IGNEUM_DAY_STRING "2026-10-03"
|
||||
#define IGNEUM_DAY_BYTES_HEX "6461792f323032362d31302d3033"
|
||||
#define IGNEUM_DAY0 0x3067619fu
|
||||
#define IGNEUM_DAY1 0x3c269176u
|
||||
#define IGNEUM_DATASET_LOG2 28
|
||||
#define IGNEUM_MASK 0x0fffffffu
|
||||
#define IGNEUM_LANES 32
|
||||
#define IGNEUM_ITERATIONS 8
|
||||
#define IGNEUM_INSTR_COUNT 64
|
||||
#define IGNEUM_LOADS_PER_HASH 128
|
||||
#define IGNEUM_WIDE_LOADS_PER_HASH 0
|
||||
#define IGNEUM_OP_MIX "load=16 add=11 shfl=8 xor=8 mul=6 mad=4 rotr=4 mulhi=3 sub=2 or=1 rotl=1"
|
||||
// Read-width experiment (5 October 2026, docs/plans/read-width.md): NOT the lottery hash. A load of W words reads
|
||||
// the W-word-aligned address and folds every word into dst: x = dst ^ w[0]; x = (rotl(x, 11) * 0x9e3779b1) ^ w[j]; dst = x.
|
||||
#define IGNEUM_LOAD_CLASS "mix25-50-25"
|
||||
#define IGNEUM_LOAD_SLOTS 16
|
||||
#define IGNEUM_LOAD_MIX { 25, 50, 25 }
|
||||
#define IGNEUM_LOAD_WIDTH_COUNTS { 5, 8, 3 } // loads of 4, 16, 64 bytes per program
|
||||
#define IGNEUM_BYTES_PER_HASH 2720
|
||||
#define IGNEUM_FOLD_ROT 11
|
||||
#define IGNEUM_FOLD_MUL 0x9e3779b1u
|
||||
// 0 = closed-form dataset (ds_elem), 1 = memory-hard cache construction (MEMHARD.md, memhard.h)
|
||||
#define IGNEUM_DATASET_MODE 1
|
||||
|
||||
#define IGNEUM_SEEDW_INIT { 0x3673211cu, 0xaae550b4u, 0x5a0ce2e0u, 0x1d2471cfu, 0xba944366u, 0xbdd4d1dbu, 0xcb1984a9u, 0x081ce12au }
|
||||
#define IGNEUM_KEY_INIT { 0x3067619fu, 0x3c269176u, 0x84a03b03u, 0xf8c63294u, 0xff977c5bu, 0xe60def3eu, 0x63630141u, 0xb8fbcb58u }
|
||||
#define IGNEUM_CACHE_LOG2_WORDS 26
|
||||
#define IGNEUM_CACHE_SEGMENT_LOG2_LINES 6
|
||||
#define IGNEUM_CACHE_SEGMENTS 65536u
|
||||
#define IGNEUM_ITEM_ROUNDS 8
|
||||
#define IGNEUM_MIX_ROT_INIT { 20u, 20u, 19u, 4u, 26u, 3u, 3u, 27u }
|
||||
#define IGNEUM_MIX_MUL_INIT { 0x42146205u, 0x52cbe0fbu, 0x7ecf4a03u, 0x6728907fu, 0xd81d9751u, 0x132952c3u, 0xf60de277u, 0x05358035u, 0xbaf6499du, 0xe4db9667u, 0x3e98f45du, 0xd0004eddu, 0x2691630du, 0x9beb3bcfu, 0xab310379u, 0x99cfb423u }
|
||||
#define IGNEUM_MIX_RC_INIT { 0xbab68293u, 0xcc162340u, 0x6ce151ccu, 0xe62b8997u, 0xc9c80297u, 0xf74a1654u, 0x3d704af5u, 0x3cf522b7u, 0x2b9cac04u, 0xa880ac10u, 0x13e5dd1du, 0x6fc3e233u, 0x2d83eeacu, 0x9006e8bfu, 0x2c4b5362u, 0x31b49ee2u }
|
||||
|
||||
#ifndef IGNEUM_NO_CUDA
|
||||
// Defined in kernel.cu. All launch on the default stream and return cudaGetLastError().
|
||||
cudaError_t igneum_launch_cache_fill(uint32_t* cache, uint32_t nSegments);
|
||||
cudaError_t igneum_launch_build(uint32_t* ds, const uint32_t* cache, uint32_t nItems);
|
||||
cudaError_t igneum_launch_hash(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask,
|
||||
uint32_t nonces, uint32_t blockWarps);
|
||||
cudaError_t igneum_hash_info(int* numRegs, int* blocksPerSM, uint32_t blockWarps);
|
||||
#endif
|
||||
127
proto-cuda/packs-readwidth/mixB-0/program.json
Normal file
127
proto-cuda/packs-readwidth/mixB-0/program.json
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
{
|
||||
"format": "igneum-program-pack-3",
|
||||
"generator": 2,
|
||||
"attempt": 0,
|
||||
"program_id": "0x5404700e8a2db8fe",
|
||||
"program_id_derivation": "FNV-1a 64 over 'igneum-program/' || generator_le32 || seed_words as little-endian bytes || attempt_le32",
|
||||
"dataset_mode": "memory-hard",
|
||||
"seed": "igneum-readwidth/B/0",
|
||||
"seed_bytes": "69676e65756d2d7265616477696474682f422f30",
|
||||
"seed_words": ["0x3673211c", "0xaae550b4", "0x5a0ce2e0", "0x1d2471cf", "0xba944366", "0xbdd4d1db", "0xcb1984a9", "0x081ce12a"],
|
||||
"seed_derivation": "seed_words = FNV-1a 64 over seed_bytes (attempt 0) or seed_bytes || attempt_le32 (attempt k >= 1), basis ^ (salt * 0x9E3779B97F4A7C15) for salt 0..3, then h ^= h>>33; h *= 0xff51afd7ed558ccd; h ^= h>>33; words[2*salt] = low 32, words[2*salt+1] = high 32",
|
||||
"generator_rule": "version 2: exactly 16 load slots drawn first from instructions 1..63 (partial Fisher-Yates), the other 48 ops from the ten non-load weights (sum 75); a load's source is drawn from the registers other than dst written by an earlier instruction and not read by a load since; the candidate must pass the acceptance rule of spec 01 section 1.4.6 (static: no cyclically stale load source, every register has an injecting write; dynamic: 64 units on the seed-keyed closed-form dataset with no constant register bit, no lane-constant load site, under 164 saturated final values, every output bit within 136 of 1024, distinct addresses above 245760), else the next attempt of the seed is tried",
|
||||
"lanes": 32,
|
||||
"registers": 8,
|
||||
"iterations": 8,
|
||||
"instruction_count": 64,
|
||||
"loads_per_hash": 128,
|
||||
"load_class": "mix25-50-25",
|
||||
"load_slots": 16,
|
||||
"load_mix_percent_4_16_64": [25, 50, 25],
|
||||
"load_width_counts_4_16_64": [5, 8, 3],
|
||||
"bytes_per_hash": 2720,
|
||||
"wide_load": "read-width experiment (5 October 2026, docs/plans/read-width.md), NOT the lottery hash: a load of W words (width field, 4 or 16) reads dataset[b .. b + W) with b = (src & mask) & ~(W - 1) and folds every word into dst: x = dst ^ w[0]; for j in 1..W: x = (rotl(x, 11) * 0x9e3779b1) ^ w[j]; dst = x; width 1 is the plain load; the width is drawn per instruction from the class mix with one extra below(100) draw after the nine of version 2, and the program id is FNV-1a 64 over 'igneum-program-rw/' || generator_le32 || seed words || attempt_le32 || mix[3] || load_slots",
|
||||
"op_mix": {"load": 16, "add": 11, "shfl": 8, "xor": 8, "mul": 6, "mad": 4, "rotr": 4, "mulhi": 3, "sub": 2, "or": 1, "rotl": 1},
|
||||
"register_init": "for i in 0..7: x = nonce ^ seed_words[i]; x += 0x9e3779b9 * (i+1) (mod 2^32); x = splitmix32(x); r[i] = x ^ seed_words[(i+1) & 7]",
|
||||
"splitmix32": "x ^= x>>16; x *= 0x7feb352d; x ^= x>>15; x *= 0x846ca68b; x ^= x>>16",
|
||||
"iteration": "sel = r0 sampled once at the top of each iteration, then all instructions in order",
|
||||
"output": "lo = r0 ^ rotl(r1,7) ^ rotl(r2,14) ^ rotl(r3,21); hi = r4 ^ rotl(r5,9) ^ rotl(r6,18) ^ rotl(r7,27); out = (hi << 32) | lo",
|
||||
"op_semantics": {
|
||||
"add": "dst = dst + src + (bit `bit` of sel ? imm2 : imm)",
|
||||
"sub": "dst = dst - src",
|
||||
"mul": "dst = dst * src (low 32)",
|
||||
"mulhi": "dst = high 32 bits of dst * src",
|
||||
"xor": "dst = dst ^ src",
|
||||
"or": "dst = dst | src",
|
||||
"rotl": "dst = rotl(dst, rot), rot in 1..31",
|
||||
"rotr": "dst = rotr(dst, src & 31)",
|
||||
"mad": "dst = src * src2 + dst",
|
||||
"shfl": "dst = dst ^ (src of lane (lane ^ mask)), mask in {1,2,4,8,16}, within the 32-lane warp",
|
||||
"load": "dst = dst ^ dataset[src & dataset.mask]",
|
||||
"wload": "base = (src of lane 0 & dataset.mask) & ~31; dst = dst ^ dataset[base + lane] (warp-coalesced 128-byte load, lever b, only when --wide-frac > 0)"
|
||||
},
|
||||
"dataset": {
|
||||
"log2_words": 28,
|
||||
"bytes": 1073741824,
|
||||
"mask": "0x0fffffff",
|
||||
"day": "2026-10-03",
|
||||
"day_bytes": "6461792f323032362d31302d3033",
|
||||
"day_words_from": "seed_words_from_bytes(day_bytes)",
|
||||
"d0": "0x3067619f",
|
||||
"d1": "0x3c269176",
|
||||
"mode": "memory-hard",
|
||||
"spec": "proto-metal/MEMHARD.md",
|
||||
"key": ["0x3067619f", "0x3c269176", "0x84a03b03", "0xf8c63294", "0xff977c5b", "0xe60def3e", "0x63630141", "0xb8fbcb58"],
|
||||
"key_derivation": "the 8 words of seed_words_from_bytes(day_bytes); d0, d1 are key[0], key[1]",
|
||||
"cache": {"log2_words": 26, "bytes": 268435456, "line_words": 16, "segment_lines": 64, "segments": 65536, "block": "ChaCha12 core + feed-forward, rotations 16 12 8 7", "sigma": ["0x61707865", "0x3320646e", "0x79622d32", "0x6b206574"], "tag": ["0x49676e65", "0x756d4d48"], "chain": "in_j = prev_line ^ (sigma[0..3] || key[0..7] || seg || j || tag[0..1]); line_j = block(in_j); prev_0 = 0"},
|
||||
"mixer": {"draw": "SplitMix64 seeded with key[0] | key[1] << 32: rot[0..7] = 1 + next() % 31, mul[0..15] = low32(next()) | 1, rc[0..15] = low32(next())", "rot": [20, 20, 19, 4, 26, 3, 3, 27], "mul": ["0x42146205", "0x52cbe0fb", "0x7ecf4a03", "0x6728907f", "0xd81d9751", "0x132952c3", "0xf60de277", "0x05358035", "0xbaf6499d", "0xe4db9667", "0x3e98f45d", "0xd0004edd", "0x2691630d", "0x9beb3bcf", "0xab310379", "0x99cfb423"], "rc": ["0xbab68293", "0xcc162340", "0x6ce151cc", "0xe62b8997", "0xc9c80297", "0xf74a1654", "0x3d704af5", "0x3cf522b7", "0x2b9cac04", "0xa880ac10", "0x13e5dd1d", "0x6fc3e233", "0x2d83eeac", "0x9006e8bf", "0x2c4b5362", "0x31b49ee2"], "round": "for i in 0..15: s[i] = (s[i] ^ (rc[i] + (r+1) * 0x9E3779B9)) * mul[i]; then quarter rounds on columns (0,4,8,12) (1,5,9,13) (2,6,10,14) (3,7,11,15) with rot[0..3] and diagonals (0,5,10,15) (1,6,11,12) (2,7,8,13) (3,4,9,14) with rot[4..7]", "quarter_round": "a += b; d ^= a; d = rotl(d, r1); c += d; b ^= c; b = rotl(b, r2); a += b; d ^= a; d = rotl(d, r3); c += d; b ^= c; b = rotl(b, r4)"},
|
||||
"item": "s[0..7] = key; s[8+i] = t * mul[i] + rc[i] for i in 0..7; for r in 0..7: s = M_r(s); line = s[0] & 0x003fffff; s[i] ^= cache[line * 16 + i]; then s = M_8(s); item(t) = s",
|
||||
"word": "dataset[w] = item(w >> 4)[w & 15]"
|
||||
},
|
||||
"instructions": [
|
||||
{"i": 0, "op": "shfl", "dst": 0, "src": 2, "src2": 1, "imm": "0x4e24f8dc", "imm2": "0x287cd532", "rot": 25, "bit": 23, "mask": 1, "width": 1},
|
||||
{"i": 1, "op": "mul", "dst": 2, "src": 0, "src2": 2, "imm": "0x6268115c", "imm2": "0xfe52413e", "rot": 30, "bit": 14, "mask": 4, "width": 1},
|
||||
{"i": 2, "op": "add", "dst": 0, "src": 6, "src2": 3, "imm": "0x7fbf4ae6", "imm2": "0x03fa29f3", "rot": 30, "bit": 20, "mask": 4, "width": 1},
|
||||
{"i": 3, "op": "mul", "dst": 2, "src": 7, "src2": 5, "imm": "0xcd8625e1", "imm2": "0xd6540f7e", "rot": 15, "bit": 15, "mask": 4, "width": 1},
|
||||
{"i": 4, "op": "load", "dst": 6, "src": 2, "src2": 5, "imm": "0xfeb8e6c3", "imm2": "0x3a797ec1", "rot": 31, "bit": 17, "mask": 2, "width": 1},
|
||||
{"i": 5, "op": "load", "dst": 7, "src": 0, "src2": 4, "imm": "0x8f4f518d", "imm2": "0xa6ed0a9e", "rot": 2, "bit": 14, "mask": 1, "width": 4},
|
||||
{"i": 6, "op": "shfl", "dst": 6, "src": 4, "src2": 1, "imm": "0xddd60fee", "imm2": "0x9529e2c3", "rot": 21, "bit": 9, "mask": 16, "width": 1},
|
||||
{"i": 7, "op": "xor", "dst": 3, "src": 5, "src2": 3, "imm": "0x015e2388", "imm2": "0x1a59ccd7", "rot": 2, "bit": 12, "mask": 2, "width": 1},
|
||||
{"i": 8, "op": "load", "dst": 6, "src": 7, "src2": 5, "imm": "0x90060b55", "imm2": "0x2315bf19", "rot": 20, "bit": 1, "mask": 16, "width": 1},
|
||||
{"i": 9, "op": "add", "dst": 0, "src": 7, "src2": 7, "imm": "0xd59b21b0", "imm2": "0x308c81bf", "rot": 5, "bit": 25, "mask": 16, "width": 1},
|
||||
{"i": 10, "op": "rotr", "dst": 5, "src": 7, "src2": 0, "imm": "0x4d9af117", "imm2": "0x49369d76", "rot": 31, "bit": 21, "mask": 4, "width": 1},
|
||||
{"i": 11, "op": "load", "dst": 3, "src": 6, "src2": 2, "imm": "0x2ddeb7f6", "imm2": "0x855ff344", "rot": 25, "bit": 26, "mask": 1, "width": 4},
|
||||
{"i": 12, "op": "mul", "dst": 2, "src": 6, "src2": 6, "imm": "0x8b16ab7b", "imm2": "0x970dc008", "rot": 27, "bit": 10, "mask": 16, "width": 1},
|
||||
{"i": 13, "op": "load", "dst": 7, "src": 0, "src2": 7, "imm": "0xcfd7f002", "imm2": "0x1e1d817b", "rot": 1, "bit": 0, "mask": 2, "width": 16},
|
||||
{"i": 14, "op": "mad", "dst": 2, "src": 5, "src2": 2, "imm": "0xea959ce8", "imm2": "0x156549ed", "rot": 11, "bit": 2, "mask": 8, "width": 1},
|
||||
{"i": 15, "op": "add", "dst": 4, "src": 0, "src2": 7, "imm": "0x902dc661", "imm2": "0x67081e7e", "rot": 12, "bit": 24, "mask": 16, "width": 1},
|
||||
{"i": 16, "op": "load", "dst": 3, "src": 4, "src2": 4, "imm": "0x86963c37", "imm2": "0xcdea85b2", "rot": 8, "bit": 19, "mask": 8, "width": 4},
|
||||
{"i": 17, "op": "mulhi", "dst": 3, "src": 4, "src2": 5, "imm": "0x5c5720f0", "imm2": "0x551bd9d5", "rot": 20, "bit": 12, "mask": 1, "width": 1},
|
||||
{"i": 18, "op": "load", "dst": 4, "src": 7, "src2": 7, "imm": "0xa9fcc38a", "imm2": "0xca2468f8", "rot": 25, "bit": 31, "mask": 1, "width": 4},
|
||||
{"i": 19, "op": "add", "dst": 2, "src": 1, "src2": 7, "imm": "0x3ee3182c", "imm2": "0xd1e74db0", "rot": 6, "bit": 9, "mask": 16, "width": 1},
|
||||
{"i": 20, "op": "xor", "dst": 7, "src": 6, "src2": 0, "imm": "0x7e5446be", "imm2": "0x9e29589c", "rot": 30, "bit": 14, "mask": 4, "width": 1},
|
||||
{"i": 21, "op": "xor", "dst": 5, "src": 3, "src2": 1, "imm": "0x161aa453", "imm2": "0xf277d1f5", "rot": 22, "bit": 18, "mask": 4, "width": 1},
|
||||
{"i": 22, "op": "shfl", "dst": 6, "src": 2, "src2": 0, "imm": "0xde7d5591", "imm2": "0x6dce8eb2", "rot": 11, "bit": 15, "mask": 16, "width": 1},
|
||||
{"i": 23, "op": "load", "dst": 0, "src": 2, "src2": 1, "imm": "0xf1ab876f", "imm2": "0x976deeca", "rot": 15, "bit": 26, "mask": 8, "width": 4},
|
||||
{"i": 24, "op": "add", "dst": 2, "src": 5, "src2": 5, "imm": "0xd2d451c6", "imm2": "0x62ac9e52", "rot": 19, "bit": 22, "mask": 1, "width": 1},
|
||||
{"i": 25, "op": "load", "dst": 3, "src": 7, "src2": 0, "imm": "0xfed1b2fd", "imm2": "0x56ac9cfa", "rot": 1, "bit": 16, "mask": 4, "width": 4},
|
||||
{"i": 26, "op": "shfl", "dst": 4, "src": 1, "src2": 5, "imm": "0x41708a21", "imm2": "0x9c760382", "rot": 25, "bit": 30, "mask": 16, "width": 1},
|
||||
{"i": 27, "op": "load", "dst": 1, "src": 4, "src2": 6, "imm": "0xe3c92c63", "imm2": "0x6d61f62c", "rot": 13, "bit": 19, "mask": 1, "width": 4},
|
||||
{"i": 28, "op": "add", "dst": 1, "src": 5, "src2": 0, "imm": "0x111ff813", "imm2": "0x072cfabe", "rot": 16, "bit": 2, "mask": 1, "width": 1},
|
||||
{"i": 29, "op": "mad", "dst": 4, "src": 1, "src2": 2, "imm": "0xeae5ec79", "imm2": "0x537fa17e", "rot": 20, "bit": 10, "mask": 16, "width": 1},
|
||||
{"i": 30, "op": "mul", "dst": 2, "src": 0, "src2": 2, "imm": "0xf468725d", "imm2": "0xeb01a28a", "rot": 30, "bit": 11, "mask": 2, "width": 1},
|
||||
{"i": 31, "op": "xor", "dst": 0, "src": 5, "src2": 1, "imm": "0x4b6a048b", "imm2": "0xd15a1f0a", "rot": 26, "bit": 4, "mask": 4, "width": 1},
|
||||
{"i": 32, "op": "load", "dst": 1, "src": 0, "src2": 4, "imm": "0x80ec21f1", "imm2": "0x694ca047", "rot": 19, "bit": 26, "mask": 8, "width": 1},
|
||||
{"i": 33, "op": "sub", "dst": 2, "src": 3, "src2": 6, "imm": "0x11d13dc6", "imm2": "0x6c8931e8", "rot": 10, "bit": 13, "mask": 2, "width": 1},
|
||||
{"i": 34, "op": "shfl", "dst": 2, "src": 0, "src2": 2, "imm": "0x056d2ef8", "imm2": "0xa833af40", "rot": 22, "bit": 26, "mask": 2, "width": 1},
|
||||
{"i": 35, "op": "sub", "dst": 0, "src": 6, "src2": 6, "imm": "0x9e95fe74", "imm2": "0xbf36d23c", "rot": 1, "bit": 12, "mask": 2, "width": 1},
|
||||
{"i": 36, "op": "mul", "dst": 4, "src": 7, "src2": 5, "imm": "0x3d50d394", "imm2": "0x637cc722", "rot": 12, "bit": 4, "mask": 16, "width": 1},
|
||||
{"i": 37, "op": "xor", "dst": 5, "src": 6, "src2": 7, "imm": "0x3272395d", "imm2": "0x36dd11fb", "rot": 31, "bit": 4, "mask": 16, "width": 1},
|
||||
{"i": 38, "op": "mulhi", "dst": 0, "src": 6, "src2": 6, "imm": "0x67324b08", "imm2": "0xd825e2fa", "rot": 11, "bit": 21, "mask": 1, "width": 1},
|
||||
{"i": 39, "op": "shfl", "dst": 5, "src": 7, "src2": 6, "imm": "0x6aff9133", "imm2": "0x22d6b873", "rot": 17, "bit": 4, "mask": 4, "width": 1},
|
||||
{"i": 40, "op": "load", "dst": 6, "src": 3, "src2": 7, "imm": "0xac1e076f", "imm2": "0x0e0ff9a2", "rot": 21, "bit": 8, "mask": 2, "width": 4},
|
||||
{"i": 41, "op": "load", "dst": 2, "src": 4, "src2": 0, "imm": "0xd94d7e29", "imm2": "0xa18f1af4", "rot": 14, "bit": 4, "mask": 4, "width": 1},
|
||||
{"i": 42, "op": "load", "dst": 5, "src": 6, "src2": 4, "imm": "0xe02caafc", "imm2": "0xe37b52cf", "rot": 28, "bit": 24, "mask": 8, "width": 1},
|
||||
{"i": 43, "op": "rotr", "dst": 1, "src": 4, "src2": 5, "imm": "0xde64b2e0", "imm2": "0xeb2327ba", "rot": 19, "bit": 5, "mask": 1, "width": 1},
|
||||
{"i": 44, "op": "or", "dst": 0, "src": 5, "src2": 1, "imm": "0x23797ba8", "imm2": "0xdaa53dbe", "rot": 17, "bit": 0, "mask": 8, "width": 1},
|
||||
{"i": 45, "op": "shfl", "dst": 0, "src": 2, "src2": 5, "imm": "0x9bb8bc40", "imm2": "0x9a1d5dc9", "rot": 22, "bit": 4, "mask": 2, "width": 1},
|
||||
{"i": 46, "op": "mul", "dst": 7, "src": 4, "src2": 5, "imm": "0x238172b8", "imm2": "0x1a3008f9", "rot": 25, "bit": 20, "mask": 16, "width": 1},
|
||||
{"i": 47, "op": "xor", "dst": 3, "src": 4, "src2": 5, "imm": "0x934047d2", "imm2": "0xe984b304", "rot": 27, "bit": 2, "mask": 1, "width": 1},
|
||||
{"i": 48, "op": "mulhi", "dst": 2, "src": 6, "src2": 5, "imm": "0xf1c06c0c", "imm2": "0x0f679cae", "rot": 5, "bit": 31, "mask": 1, "width": 1},
|
||||
{"i": 49, "op": "xor", "dst": 5, "src": 4, "src2": 3, "imm": "0x4b9454cd", "imm2": "0x816b6e2d", "rot": 5, "bit": 22, "mask": 4, "width": 1},
|
||||
{"i": 50, "op": "rotr", "dst": 1, "src": 6, "src2": 3, "imm": "0xe234dec2", "imm2": "0xeddc8839", "rot": 6, "bit": 7, "mask": 1, "width": 1},
|
||||
{"i": 51, "op": "add", "dst": 7, "src": 0, "src2": 0, "imm": "0x68d3a5c0", "imm2": "0x0fe79cec", "rot": 5, "bit": 22, "mask": 2, "width": 1},
|
||||
{"i": 52, "op": "add", "dst": 5, "src": 4, "src2": 1, "imm": "0xeb764d91", "imm2": "0x04309e6f", "rot": 23, "bit": 8, "mask": 1, "width": 1},
|
||||
{"i": 53, "op": "xor", "dst": 7, "src": 0, "src2": 3, "imm": "0x6d420b6b", "imm2": "0xa4eb51ff", "rot": 27, "bit": 9, "mask": 1, "width": 1},
|
||||
{"i": 54, "op": "add", "dst": 4, "src": 0, "src2": 0, "imm": "0x1390b188", "imm2": "0xba0b81c6", "rot": 4, "bit": 6, "mask": 16, "width": 1},
|
||||
{"i": 55, "op": "add", "dst": 0, "src": 5, "src2": 0, "imm": "0x4c21a6cd", "imm2": "0x5ec96dd8", "rot": 18, "bit": 15, "mask": 2, "width": 1},
|
||||
{"i": 56, "op": "mad", "dst": 7, "src": 5, "src2": 3, "imm": "0xd0655c74", "imm2": "0x8dc4bd13", "rot": 24, "bit": 11, "mask": 1, "width": 1},
|
||||
{"i": 57, "op": "load", "dst": 6, "src": 0, "src2": 7, "imm": "0xe738815c", "imm2": "0xc546dbe7", "rot": 24, "bit": 29, "mask": 2, "width": 16},
|
||||
{"i": 58, "op": "add", "dst": 5, "src": 1, "src2": 6, "imm": "0x68297b06", "imm2": "0x6c0ac4dd", "rot": 19, "bit": 1, "mask": 8, "width": 1},
|
||||
{"i": 59, "op": "rotr", "dst": 6, "src": 7, "src2": 3, "imm": "0x83f974a4", "imm2": "0x13fcd20f", "rot": 3, "bit": 18, "mask": 2, "width": 1},
|
||||
{"i": 60, "op": "load", "dst": 7, "src": 4, "src2": 5, "imm": "0xbca249c5", "imm2": "0x2094b70b", "rot": 15, "bit": 24, "mask": 2, "width": 16},
|
||||
{"i": 61, "op": "shfl", "dst": 6, "src": 3, "src2": 0, "imm": "0xcd1113c9", "imm2": "0x475dbb4b", "rot": 11, "bit": 11, "mask": 4, "width": 1},
|
||||
{"i": 62, "op": "rotl", "dst": 4, "src": 5, "src2": 7, "imm": "0xdbc5d842", "imm2": "0xf8b7004c", "rot": 6, "bit": 25, "mask": 8, "width": 1},
|
||||
{"i": 63, "op": "mad", "dst": 1, "src": 2, "src2": 1, "imm": "0xd2538bab", "imm2": "0x6b862569", "rot": 9, "bit": 5, "mask": 1, "width": 1}
|
||||
]
|
||||
}
|
||||
109
proto-cuda/packs-readwidth/mixB-0/program.metal
Normal file
109
proto-cuda/packs-readwidth/mixB-0/program.metal
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
#include <metal_stdlib>
|
||||
using namespace metal;
|
||||
|
||||
#define MASK 0x0fffffffu
|
||||
constant uint SEEDW[8] = { 0x3673211cu, 0xaae550b4u, 0x5a0ce2e0u, 0x1d2471cfu, 0xba944366u, 0xbdd4d1dbu, 0xcb1984a9u, 0x081ce12au };
|
||||
|
||||
inline uint splitmix32(uint x) {
|
||||
x ^= x >> 16; x *= 0x7feb352du;
|
||||
x ^= x >> 15; x *= 0x846ca68bu;
|
||||
x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
inline uint rotl_imm(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31
|
||||
inline uint rotr_var(uint x, uint n) { n &= 31u; return (x >> n) | (x << ((32u - n) & 31u)); }
|
||||
inline uint ds_elem(uint i, uint d0, uint d1) {
|
||||
uint x = i ^ d0;
|
||||
x *= 0x9E3779B1u; x ^= x >> 15;
|
||||
x += d1;
|
||||
x *= 0x85EBCA77u; x ^= x >> 13;
|
||||
x *= 0xC2B2AE3Du; x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
|
||||
kernel void igneum_hash(device const uint* dataset [[buffer(0)]],
|
||||
device ulong* out [[buffer(1)]],
|
||||
constant uint& baseNonce [[buffer(2)]],
|
||||
uint gid [[thread_position_in_grid]]) {
|
||||
uint nonce = baseNonce + gid;
|
||||
uint r0, r1, r2, r3, r4, r5, r6, r7;
|
||||
{ uint x = nonce ^ SEEDW[0]; x += 0x9e3779b9u * 1u; x = splitmix32(x); r0 = x ^ SEEDW[1]; }
|
||||
{ uint x = nonce ^ SEEDW[1]; x += 0x9e3779b9u * 2u; x = splitmix32(x); r1 = x ^ SEEDW[2]; }
|
||||
{ uint x = nonce ^ SEEDW[2]; x += 0x9e3779b9u * 3u; x = splitmix32(x); r2 = x ^ SEEDW[3]; }
|
||||
{ uint x = nonce ^ SEEDW[3]; x += 0x9e3779b9u * 4u; x = splitmix32(x); r3 = x ^ SEEDW[4]; }
|
||||
{ uint x = nonce ^ SEEDW[4]; x += 0x9e3779b9u * 5u; x = splitmix32(x); r4 = x ^ SEEDW[5]; }
|
||||
{ uint x = nonce ^ SEEDW[5]; x += 0x9e3779b9u * 6u; x = splitmix32(x); r5 = x ^ SEEDW[6]; }
|
||||
{ uint x = nonce ^ SEEDW[6]; x += 0x9e3779b9u * 7u; x = splitmix32(x); r6 = x ^ SEEDW[7]; }
|
||||
{ uint x = nonce ^ SEEDW[7]; x += 0x9e3779b9u * 8u; x = splitmix32(x); r7 = x ^ SEEDW[0]; }
|
||||
|
||||
for (uint it = 0u; it < 8u; ++it) {
|
||||
uint sel = r0;
|
||||
r0 = r0 ^ simd_shuffle_xor(r2, (ushort)1); // 0
|
||||
r2 = r2 * r0; // 1
|
||||
r0 = r0 + r6 + select(0x7fbf4ae6u, 0x03fa29f3u, ((sel >> 20u) & 1u) != 0u); // 2
|
||||
r2 = r2 * r7; // 3
|
||||
r6 = r6 ^ dataset[r2 & MASK]; // 4
|
||||
{ uint b_ = (r0 & MASK) & ~3u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint x_ = r7 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r7 = x_; } // 5
|
||||
r6 = r6 ^ simd_shuffle_xor(r4, (ushort)16); // 6
|
||||
r3 = r3 ^ r5; // 7
|
||||
r6 = r6 ^ dataset[r7 & MASK]; // 8
|
||||
r0 = r0 + r7 + select(0xd59b21b0u, 0x308c81bfu, ((sel >> 25u) & 1u) != 0u); // 9
|
||||
r5 = rotr_var(r5, r7); // 10
|
||||
{ uint b_ = (r6 & MASK) & ~3u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r3 = x_; } // 11
|
||||
r2 = r2 * r6; // 12
|
||||
{ uint b_ = (r0 & MASK) & ~15u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint x_ = r7 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r7 = x_; } // 13
|
||||
r2 = r5 * r2 + r2; // 14
|
||||
r4 = r4 + r0 + select(0x902dc661u, 0x67081e7eu, ((sel >> 24u) & 1u) != 0u); // 15
|
||||
{ uint b_ = (r4 & MASK) & ~3u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r3 = x_; } // 16
|
||||
r3 = mulhi(r3, r4); // 17
|
||||
{ uint b_ = (r7 & MASK) & ~3u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint x_ = r4 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r4 = x_; } // 18
|
||||
r2 = r2 + r1 + select(0x3ee3182cu, 0xd1e74db0u, ((sel >> 9u) & 1u) != 0u); // 19
|
||||
r7 = r7 ^ r6; // 20
|
||||
r5 = r5 ^ r3; // 21
|
||||
r6 = r6 ^ simd_shuffle_xor(r2, (ushort)16); // 22
|
||||
{ uint b_ = (r2 & MASK) & ~3u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint x_ = r0 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r0 = x_; } // 23
|
||||
r2 = r2 + r5 + select(0xd2d451c6u, 0x62ac9e52u, ((sel >> 22u) & 1u) != 0u); // 24
|
||||
{ uint b_ = (r7 & MASK) & ~3u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r3 = x_; } // 25
|
||||
r4 = r4 ^ simd_shuffle_xor(r1, (ushort)16); // 26
|
||||
{ uint b_ = (r4 & MASK) & ~3u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint x_ = r1 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r1 = x_; } // 27
|
||||
r1 = r1 + r5 + select(0x111ff813u, 0x072cfabeu, ((sel >> 2u) & 1u) != 0u); // 28
|
||||
r4 = r1 * r2 + r4; // 29
|
||||
r2 = r2 * r0; // 30
|
||||
r0 = r0 ^ r5; // 31
|
||||
r1 = r1 ^ dataset[r0 & MASK]; // 32
|
||||
r2 = r2 - r3; // 33
|
||||
r2 = r2 ^ simd_shuffle_xor(r0, (ushort)2); // 34
|
||||
r0 = r0 - r6; // 35
|
||||
r4 = r4 * r7; // 36
|
||||
r5 = r5 ^ r6; // 37
|
||||
r0 = mulhi(r0, r6); // 38
|
||||
r5 = r5 ^ simd_shuffle_xor(r7, (ushort)4); // 39
|
||||
{ uint b_ = (r3 & MASK) & ~3u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r6 = x_; } // 40
|
||||
r2 = r2 ^ dataset[r4 & MASK]; // 41
|
||||
r5 = r5 ^ dataset[r6 & MASK]; // 42
|
||||
r1 = rotr_var(r1, r4); // 43
|
||||
r0 = r0 | r5; // 44
|
||||
r0 = r0 ^ simd_shuffle_xor(r2, (ushort)2); // 45
|
||||
r7 = r7 * r4; // 46
|
||||
r3 = r3 ^ r4; // 47
|
||||
r2 = mulhi(r2, r6); // 48
|
||||
r5 = r5 ^ r4; // 49
|
||||
r1 = rotr_var(r1, r6); // 50
|
||||
r7 = r7 + r0 + select(0x68d3a5c0u, 0x0fe79cecu, ((sel >> 22u) & 1u) != 0u); // 51
|
||||
r5 = r5 + r4 + select(0xeb764d91u, 0x04309e6fu, ((sel >> 8u) & 1u) != 0u); // 52
|
||||
r7 = r7 ^ r0; // 53
|
||||
r4 = r4 + r0 + select(0x1390b188u, 0xba0b81c6u, ((sel >> 6u) & 1u) != 0u); // 54
|
||||
r0 = r0 + r5 + select(0x4c21a6cdu, 0x5ec96dd8u, ((sel >> 15u) & 1u) != 0u); // 55
|
||||
r7 = r5 * r3 + r7; // 56
|
||||
{ uint b_ = (r0 & MASK) & ~15u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r6 = x_; } // 57
|
||||
r5 = r5 + r1 + select(0x68297b06u, 0x6c0ac4ddu, ((sel >> 1u) & 1u) != 0u); // 58
|
||||
r6 = rotr_var(r6, r7); // 59
|
||||
{ uint b_ = (r4 & MASK) & ~15u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint x_ = r7 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r7 = x_; } // 60
|
||||
r6 = r6 ^ simd_shuffle_xor(r3, (ushort)4); // 61
|
||||
r4 = rotl_imm(r4, 6u); // 62
|
||||
r1 = r2 * r1 + r1; // 63
|
||||
}
|
||||
uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u);
|
||||
uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u);
|
||||
out[gid] = ((ulong)hi << 32) | (ulong)lo;
|
||||
}
|
||||
111
proto-cuda/packs-readwidth/mixB-0/program_bound.metal
Normal file
111
proto-cuda/packs-readwidth/mixB-0/program_bound.metal
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
#include <metal_stdlib>
|
||||
using namespace metal;
|
||||
|
||||
#define MASK 0x0fffffffu
|
||||
constant uint SEEDW[8] = { 0x3673211cu, 0xaae550b4u, 0x5a0ce2e0u, 0x1d2471cfu, 0xba944366u, 0xbdd4d1dbu, 0xcb1984a9u, 0x081ce12au };
|
||||
|
||||
inline uint splitmix32(uint x) {
|
||||
x ^= x >> 16; x *= 0x7feb352du;
|
||||
x ^= x >> 15; x *= 0x846ca68bu;
|
||||
x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
inline uint rotl_imm(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31
|
||||
inline uint rotr_var(uint x, uint n) { n &= 31u; return (x >> n) | (x << ((32u - n) & 31u)); }
|
||||
inline uint ds_elem(uint i, uint d0, uint d1) {
|
||||
uint x = i ^ d0;
|
||||
x *= 0x9E3779B1u; x ^= x >> 15;
|
||||
x += d1;
|
||||
x *= 0x85EBCA77u; x ^= x >> 13;
|
||||
x *= 0xC2B2AE3Du; x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
|
||||
// Header-bound variant: the init words come from buffer 3 (bind.rs), not from SEEDW.
|
||||
kernel void igneum_hash_bound(device const uint* dataset [[buffer(0)]],
|
||||
device ulong* out [[buffer(1)]],
|
||||
constant uint& baseNonce [[buffer(2)]],
|
||||
constant uint* initw [[buffer(3)]],
|
||||
uint gid [[thread_position_in_grid]]) {
|
||||
uint nonce = baseNonce + gid;
|
||||
uint r0, r1, r2, r3, r4, r5, r6, r7;
|
||||
{ uint x = nonce ^ initw[0]; x += 0x9e3779b9u * 1u; x = splitmix32(x); r0 = x ^ initw[1]; }
|
||||
{ uint x = nonce ^ initw[1]; x += 0x9e3779b9u * 2u; x = splitmix32(x); r1 = x ^ initw[2]; }
|
||||
{ uint x = nonce ^ initw[2]; x += 0x9e3779b9u * 3u; x = splitmix32(x); r2 = x ^ initw[3]; }
|
||||
{ uint x = nonce ^ initw[3]; x += 0x9e3779b9u * 4u; x = splitmix32(x); r3 = x ^ initw[4]; }
|
||||
{ uint x = nonce ^ initw[4]; x += 0x9e3779b9u * 5u; x = splitmix32(x); r4 = x ^ initw[5]; }
|
||||
{ uint x = nonce ^ initw[5]; x += 0x9e3779b9u * 6u; x = splitmix32(x); r5 = x ^ initw[6]; }
|
||||
{ uint x = nonce ^ initw[6]; x += 0x9e3779b9u * 7u; x = splitmix32(x); r6 = x ^ initw[7]; }
|
||||
{ uint x = nonce ^ initw[7]; x += 0x9e3779b9u * 8u; x = splitmix32(x); r7 = x ^ initw[0]; }
|
||||
|
||||
for (uint it = 0u; it < 8u; ++it) {
|
||||
uint sel = r0;
|
||||
r0 = r0 ^ simd_shuffle_xor(r2, (ushort)1); // 0
|
||||
r2 = r2 * r0; // 1
|
||||
r0 = r0 + r6 + select(0x7fbf4ae6u, 0x03fa29f3u, ((sel >> 20u) & 1u) != 0u); // 2
|
||||
r2 = r2 * r7; // 3
|
||||
r6 = r6 ^ dataset[r2 & MASK]; // 4
|
||||
{ uint b_ = (r0 & MASK) & ~3u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint x_ = r7 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r7 = x_; } // 5
|
||||
r6 = r6 ^ simd_shuffle_xor(r4, (ushort)16); // 6
|
||||
r3 = r3 ^ r5; // 7
|
||||
r6 = r6 ^ dataset[r7 & MASK]; // 8
|
||||
r0 = r0 + r7 + select(0xd59b21b0u, 0x308c81bfu, ((sel >> 25u) & 1u) != 0u); // 9
|
||||
r5 = rotr_var(r5, r7); // 10
|
||||
{ uint b_ = (r6 & MASK) & ~3u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r3 = x_; } // 11
|
||||
r2 = r2 * r6; // 12
|
||||
{ uint b_ = (r0 & MASK) & ~15u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint x_ = r7 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r7 = x_; } // 13
|
||||
r2 = r5 * r2 + r2; // 14
|
||||
r4 = r4 + r0 + select(0x902dc661u, 0x67081e7eu, ((sel >> 24u) & 1u) != 0u); // 15
|
||||
{ uint b_ = (r4 & MASK) & ~3u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r3 = x_; } // 16
|
||||
r3 = mulhi(r3, r4); // 17
|
||||
{ uint b_ = (r7 & MASK) & ~3u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint x_ = r4 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r4 = x_; } // 18
|
||||
r2 = r2 + r1 + select(0x3ee3182cu, 0xd1e74db0u, ((sel >> 9u) & 1u) != 0u); // 19
|
||||
r7 = r7 ^ r6; // 20
|
||||
r5 = r5 ^ r3; // 21
|
||||
r6 = r6 ^ simd_shuffle_xor(r2, (ushort)16); // 22
|
||||
{ uint b_ = (r2 & MASK) & ~3u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint x_ = r0 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r0 = x_; } // 23
|
||||
r2 = r2 + r5 + select(0xd2d451c6u, 0x62ac9e52u, ((sel >> 22u) & 1u) != 0u); // 24
|
||||
{ uint b_ = (r7 & MASK) & ~3u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r3 = x_; } // 25
|
||||
r4 = r4 ^ simd_shuffle_xor(r1, (ushort)16); // 26
|
||||
{ uint b_ = (r4 & MASK) & ~3u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint x_ = r1 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r1 = x_; } // 27
|
||||
r1 = r1 + r5 + select(0x111ff813u, 0x072cfabeu, ((sel >> 2u) & 1u) != 0u); // 28
|
||||
r4 = r1 * r2 + r4; // 29
|
||||
r2 = r2 * r0; // 30
|
||||
r0 = r0 ^ r5; // 31
|
||||
r1 = r1 ^ dataset[r0 & MASK]; // 32
|
||||
r2 = r2 - r3; // 33
|
||||
r2 = r2 ^ simd_shuffle_xor(r0, (ushort)2); // 34
|
||||
r0 = r0 - r6; // 35
|
||||
r4 = r4 * r7; // 36
|
||||
r5 = r5 ^ r6; // 37
|
||||
r0 = mulhi(r0, r6); // 38
|
||||
r5 = r5 ^ simd_shuffle_xor(r7, (ushort)4); // 39
|
||||
{ uint b_ = (r3 & MASK) & ~3u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r6 = x_; } // 40
|
||||
r2 = r2 ^ dataset[r4 & MASK]; // 41
|
||||
r5 = r5 ^ dataset[r6 & MASK]; // 42
|
||||
r1 = rotr_var(r1, r4); // 43
|
||||
r0 = r0 | r5; // 44
|
||||
r0 = r0 ^ simd_shuffle_xor(r2, (ushort)2); // 45
|
||||
r7 = r7 * r4; // 46
|
||||
r3 = r3 ^ r4; // 47
|
||||
r2 = mulhi(r2, r6); // 48
|
||||
r5 = r5 ^ r4; // 49
|
||||
r1 = rotr_var(r1, r6); // 50
|
||||
r7 = r7 + r0 + select(0x68d3a5c0u, 0x0fe79cecu, ((sel >> 22u) & 1u) != 0u); // 51
|
||||
r5 = r5 + r4 + select(0xeb764d91u, 0x04309e6fu, ((sel >> 8u) & 1u) != 0u); // 52
|
||||
r7 = r7 ^ r0; // 53
|
||||
r4 = r4 + r0 + select(0x1390b188u, 0xba0b81c6u, ((sel >> 6u) & 1u) != 0u); // 54
|
||||
r0 = r0 + r5 + select(0x4c21a6cdu, 0x5ec96dd8u, ((sel >> 15u) & 1u) != 0u); // 55
|
||||
r7 = r5 * r3 + r7; // 56
|
||||
{ uint b_ = (r0 & MASK) & ~15u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint x_ = r6 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r6 = x_; } // 57
|
||||
r5 = r5 + r1 + select(0x68297b06u, 0x6c0ac4ddu, ((sel >> 1u) & 1u) != 0u); // 58
|
||||
r6 = rotr_var(r6, r7); // 59
|
||||
{ uint b_ = (r4 & MASK) & ~15u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint x_ = r7 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r7 = x_; } // 60
|
||||
r6 = r6 ^ simd_shuffle_xor(r3, (ushort)4); // 61
|
||||
r4 = rotl_imm(r4, 6u); // 62
|
||||
r1 = r2 * r1 + r1; // 63
|
||||
}
|
||||
uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u);
|
||||
uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u);
|
||||
out[gid] = ((ulong)hi << 32) | (ulong)lo;
|
||||
}
|
||||
57
proto-cuda/packs-readwidth/mixB-0/vectors.h
Normal file
57
proto-cuda/packs-readwidth/mixB-0/vectors.h
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
// Generated by igneum-pow export (generator v2) for seed "igneum-readwidth/B/0". Do not edit by hand.
|
||||
// Expected outputs: igneum-pow (Rust) CPU interpreter, generator v2, memory-hard dataset
|
||||
#pragma once
|
||||
#ifdef __cplusplus
|
||||
#include <cstdint>
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
#define IGNEUM_VEC_WARPS 3
|
||||
static const uint32_t IGNEUM_VEC_BASE[IGNEUM_VEC_WARPS] = { 0u, 4096u, 1000000u };
|
||||
static const uint64_t IGNEUM_VEC_OUT[IGNEUM_VEC_WARPS][32] = {
|
||||
{ // base nonce 0
|
||||
0x2b6c8e6b238224dbull, 0x94dca5778f870901ull, 0xb0c977094b3c1a7aull, 0xdc0f62ab6e8db552ull, 0x5581af7ea67bfd20ull, 0xaa10426d0e2aa72full, 0x60fd1bf45ef55751ull, 0x9ab74415a3de8b66ull,
|
||||
0x2cb6ee8ac9c0efc8ull, 0x2ae892465dff9094ull, 0x99c9c94b9d2874c7ull, 0xb12be63d01872ea3ull, 0x84024fac8312e908ull, 0xbb67e4878f174f0cull, 0x3b027e93ca233521ull, 0x8ba6cfeb9bfbbc0full,
|
||||
0x44c59d77e3247d78ull, 0xd4a765b48c283d2aull, 0xe53083a844015f24ull, 0xb0f7b8dad47d924bull, 0x185b4a0f6150375eull, 0x537ed78b8976846cull, 0xc9d4264a0fc2da7dull, 0x6c0ef3c92dd3e063ull,
|
||||
0x396461e1a90913e9ull, 0xc2ea0411a102f780ull, 0x0d8b3f485c471e7eull, 0xd8a5c0b7995246c7ull, 0x4507e1e49dbd3c35ull, 0x80145ecfc13419c0ull, 0x9c2f1f09b3ef4ed1ull, 0xd776b774670d63f1ull
|
||||
},
|
||||
{ // base nonce 4096
|
||||
0xe094ec92f00bd1fdull, 0x14d3ad7d06eba7bfull, 0xd4b4ee3a4e95e930ull, 0x5656fc12f488f952ull, 0x4db64fa3172356b8ull, 0x7669809a83c52addull, 0x240c4920d64dd3ebull, 0xfcc0c08f3cebe318ull,
|
||||
0xd48c95d54226a468ull, 0x383acc22e4367a07ull, 0x1b16e6976aa7160eull, 0xc1d0216840450b35ull, 0xcfc19bac8283d5e0ull, 0xaecef9011360b2c8ull, 0x6a1dbf38ce8f3476ull, 0x813ecd9804528e50ull,
|
||||
0x95273d12cbfda3e0ull, 0xb6abb5bc816f81d2ull, 0x3d734251c7eb5488ull, 0x162710fc525e1a35ull, 0xa8485c7fa11f1d69ull, 0xf81a8cdc4b928aa5ull, 0x1ad63b6197331e30ull, 0x04ce2b194f3fe8adull,
|
||||
0xc76ba96148e01225ull, 0x26e24635c3556e18ull, 0xeb8c92b751bc5c70ull, 0xb8886d57d441fe5dull, 0x3f8d68c1f1f1fe2dull, 0x7c441c21089fb44eull, 0x27e2950b292fec5aull, 0x581d48ac2f0dc82eull
|
||||
},
|
||||
{ // base nonce 1000000
|
||||
0xea40156c5e27f6a3ull, 0x1db25b47fd85ab8eull, 0xdf6bd10d80c1b46dull, 0x2e1da26fcbea64b0ull, 0xdd5e41310fcabbfbull, 0xdf9780cb1f87d4afull, 0x6028258e6529007full, 0x886fecbfe753c3d9ull,
|
||||
0x3c20a9a6f5bcb77eull, 0x605194089256f91cull, 0xd7546f5b5c79f188ull, 0xefc8ae5b45bd346bull, 0xd067b744f6659df8ull, 0x9c8fbb301da7e947ull, 0x238f22c8b511e7cbull, 0xa67a31f99be23902ull,
|
||||
0x5d9224b25e12fcffull, 0x0166de07227aaebbull, 0xfb50fea4c86552a7ull, 0xf7535d8fe65fe0d0ull, 0x161ab76c522de840ull, 0xaa3d2ddcd8e80d1aull, 0x9bdb9180dd7d39faull, 0xa4111c74b1d438c9ull,
|
||||
0x75ec298c4f067224ull, 0x9c923c3a46403618ull, 0x61ec429ff3c0283eull, 0x155cf3df9f82ff51ull, 0xd6f0279de6eec131ull, 0xc3ea627086d07a96ull, 0x1cb80fef0710e142ull, 0xfd4772b1cd071be4ull
|
||||
}
|
||||
};
|
||||
|
||||
// Dataset self-test: dataset[0..15] and dataset[IGNEUM_MASK] (268435455).
|
||||
static const uint32_t IGNEUM_DS_HEAD[16] = {
|
||||
0xffc3cd94u, 0x5920ccd8u, 0x392f44bbu, 0x5e57f67au, 0x2f2bc2a9u, 0x620b0e36u, 0xbdc09014u, 0x436654bfu,
|
||||
0x311e0b48u, 0x1abd93adu, 0x59cc7ce8u, 0xee5247b2u, 0x86171fe8u, 0x6d874751u, 0xc9f7728fu, 0x7c2a435du
|
||||
};
|
||||
static const uint32_t IGNEUM_DS_LAST_INDEX = 268435455u;
|
||||
static const uint32_t IGNEUM_DS_LAST = 0xa33ada72u;
|
||||
// 64 sampled dataset words (index, value) computed on the Mac.
|
||||
#define IGNEUM_DS_SAMPLES 64
|
||||
static const uint32_t IGNEUM_DS_SAMPLE_INDEX[IGNEUM_DS_SAMPLES] = {
|
||||
59471966u, 217795994u, 208353206u, 42483309u, 172547758u, 148076330u, 183853158u, 214389424u, 267488061u, 169781097u, 184093494u, 153880993u, 84977930u, 46426879u, 3093825u, 225364072u, 44593546u, 260713159u, 168250303u, 52384140u, 223401610u, 45554030u, 95410555u, 175039924u, 79171087u, 267580473u, 24168642u, 37981670u, 171551130u, 195559979u, 204611762u, 140997658u, 138925853u, 86637313u, 20736778u, 219665210u, 160430336u, 264654675u, 8013395u, 228945585u, 213884386u, 104419827u, 44185464u, 142737231u, 99284897u, 132475900u, 61861762u, 132056166u, 262388043u, 91878046u, 117353561u, 124768597u, 71352993u, 190698941u, 46055428u, 55281366u, 165145231u, 106810753u, 171985651u, 232085256u, 159510492u, 40072060u, 209107596u, 39023794u
|
||||
};
|
||||
static const uint32_t IGNEUM_DS_SAMPLE_VALUE[IGNEUM_DS_SAMPLES] = {
|
||||
0xe8b73d94u, 0x337028b5u, 0xafe148c9u, 0xab99f7aeu, 0x434ea619u, 0xd85cb880u, 0x54764c7fu, 0x82c7e420u, 0xedf4cb9eu, 0x9884c959u, 0x223ee793u, 0x3a9ccf69u, 0x81da4fd2u, 0xd6ce8cb9u, 0xe3922dcau, 0x3e7e6bdeu, 0x382a3acau, 0x567e7f7fu, 0x25a0f084u, 0xbfeef128u, 0xe338abfbu, 0x7c3b5280u, 0x909bc5f1u, 0xd8b74b9cu, 0x8e31a22eu, 0x26b5f1d8u, 0x79122c00u, 0xcafc3340u, 0xd5e02ea3u, 0x1aee1afdu, 0xdb090d9au, 0xb049f435u, 0x4954d8bau, 0x03797ba0u, 0x196eefbdu, 0xd153412au, 0xbe5d2c4bu, 0xdaa14f0eu, 0x8e61ed07u, 0x9e9a64c6u, 0x2e29ff36u, 0x392a8589u, 0xb56a5912u, 0xfa6e8b57u, 0xd1a737cbu, 0xb0fa841au, 0xbe1c341fu, 0xe25be0f1u, 0xe937f543u, 0xebab2248u, 0x8e1b607au, 0x202a2fedu, 0x95e2819cu, 0x9c9652d4u, 0x32fedef0u, 0xdecfff82u, 0xcb5d43e5u, 0xb735806au, 0x8905939cu, 0xfbf8472du, 0xada74e5du, 0x7ebdeeeau, 0x0119f2b3u, 0xa9a376b8u
|
||||
};
|
||||
// Cache self-test (memory-hard mode): cache[0..15], the last 16 words, and FNV-1a 64 over all 2^26 words.
|
||||
static const uint32_t IGNEUM_CACHE_HEAD[16] = {
|
||||
0x355a86d2u, 0x7957db1cu, 0xd21772afu, 0x6fc1e09bu, 0xd55ce61du, 0x6e6a278bu, 0xd3f543ceu, 0x223d8e82u,
|
||||
0x143ab337u, 0x2e9f05bdu, 0x2eb389bfu, 0x0c6e449eu, 0x5cfa4222u, 0xba6560feu, 0x8e3e1aa4u, 0xdbcc1d53u
|
||||
};
|
||||
static const uint32_t IGNEUM_CACHE_LAST[16] = {
|
||||
0x41190d91u, 0xbd277957u, 0x22ddbb49u, 0x6986f207u, 0xdf69a4d6u, 0x26401a3au, 0x818230fbu, 0xc417122du,
|
||||
0x3597b211u, 0xb553ce55u, 0xcf39cc0du, 0x3b7fc43au, 0x3fd43b00u, 0x67e1c80eu, 0xffa7ea7du, 0xca2960abu
|
||||
};
|
||||
static const uint64_t IGNEUM_CACHE_FNV64 = 0x48c4f5bf24166b2eull;
|
||||
36
proto-cuda/packs-readwidth/mixB-0/vectors.json
Normal file
36
proto-cuda/packs-readwidth/mixB-0/vectors.json
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
{
|
||||
"seed": "igneum-readwidth/B/0",
|
||||
"day": "2026-10-03",
|
||||
"dataset_mode": "memory-hard",
|
||||
"dataset_log2_words": 28,
|
||||
"mask": "0x0fffffff",
|
||||
"lanes": 32,
|
||||
"source": "igneum-pow (Rust) CPU interpreter, generator v2, memory-hard dataset",
|
||||
"warps": [
|
||||
{"base_nonce": 0, "expected": [
|
||||
"0x2b6c8e6b238224db", "0x94dca5778f870901", "0xb0c977094b3c1a7a", "0xdc0f62ab6e8db552", "0x5581af7ea67bfd20", "0xaa10426d0e2aa72f", "0x60fd1bf45ef55751", "0x9ab74415a3de8b66",
|
||||
"0x2cb6ee8ac9c0efc8", "0x2ae892465dff9094", "0x99c9c94b9d2874c7", "0xb12be63d01872ea3", "0x84024fac8312e908", "0xbb67e4878f174f0c", "0x3b027e93ca233521", "0x8ba6cfeb9bfbbc0f",
|
||||
"0x44c59d77e3247d78", "0xd4a765b48c283d2a", "0xe53083a844015f24", "0xb0f7b8dad47d924b", "0x185b4a0f6150375e", "0x537ed78b8976846c", "0xc9d4264a0fc2da7d", "0x6c0ef3c92dd3e063",
|
||||
"0x396461e1a90913e9", "0xc2ea0411a102f780", "0x0d8b3f485c471e7e", "0xd8a5c0b7995246c7", "0x4507e1e49dbd3c35", "0x80145ecfc13419c0", "0x9c2f1f09b3ef4ed1", "0xd776b774670d63f1"
|
||||
]},
|
||||
{"base_nonce": 4096, "expected": [
|
||||
"0xe094ec92f00bd1fd", "0x14d3ad7d06eba7bf", "0xd4b4ee3a4e95e930", "0x5656fc12f488f952", "0x4db64fa3172356b8", "0x7669809a83c52add", "0x240c4920d64dd3eb", "0xfcc0c08f3cebe318",
|
||||
"0xd48c95d54226a468", "0x383acc22e4367a07", "0x1b16e6976aa7160e", "0xc1d0216840450b35", "0xcfc19bac8283d5e0", "0xaecef9011360b2c8", "0x6a1dbf38ce8f3476", "0x813ecd9804528e50",
|
||||
"0x95273d12cbfda3e0", "0xb6abb5bc816f81d2", "0x3d734251c7eb5488", "0x162710fc525e1a35", "0xa8485c7fa11f1d69", "0xf81a8cdc4b928aa5", "0x1ad63b6197331e30", "0x04ce2b194f3fe8ad",
|
||||
"0xc76ba96148e01225", "0x26e24635c3556e18", "0xeb8c92b751bc5c70", "0xb8886d57d441fe5d", "0x3f8d68c1f1f1fe2d", "0x7c441c21089fb44e", "0x27e2950b292fec5a", "0x581d48ac2f0dc82e"
|
||||
]},
|
||||
{"base_nonce": 1000000, "expected": [
|
||||
"0xea40156c5e27f6a3", "0x1db25b47fd85ab8e", "0xdf6bd10d80c1b46d", "0x2e1da26fcbea64b0", "0xdd5e41310fcabbfb", "0xdf9780cb1f87d4af", "0x6028258e6529007f", "0x886fecbfe753c3d9",
|
||||
"0x3c20a9a6f5bcb77e", "0x605194089256f91c", "0xd7546f5b5c79f188", "0xefc8ae5b45bd346b", "0xd067b744f6659df8", "0x9c8fbb301da7e947", "0x238f22c8b511e7cb", "0xa67a31f99be23902",
|
||||
"0x5d9224b25e12fcff", "0x0166de07227aaebb", "0xfb50fea4c86552a7", "0xf7535d8fe65fe0d0", "0x161ab76c522de840", "0xaa3d2ddcd8e80d1a", "0x9bdb9180dd7d39fa", "0xa4111c74b1d438c9",
|
||||
"0x75ec298c4f067224", "0x9c923c3a46403618", "0x61ec429ff3c0283e", "0x155cf3df9f82ff51", "0xd6f0279de6eec131", "0xc3ea627086d07a96", "0x1cb80fef0710e142", "0xfd4772b1cd071be4"
|
||||
]}
|
||||
],
|
||||
"dataset_head": ["0xffc3cd94", "0x5920ccd8", "0x392f44bb", "0x5e57f67a", "0x2f2bc2a9", "0x620b0e36", "0xbdc09014", "0x436654bf", "0x311e0b48", "0x1abd93ad", "0x59cc7ce8", "0xee5247b2", "0x86171fe8", "0x6d874751", "0xc9f7728f", "0x7c2a435d"],
|
||||
"dataset_last_index": 268435455,
|
||||
"dataset_last": "0xa33ada72",
|
||||
"dataset_samples": [{"index": 59471966, "value": "0xe8b73d94"}, {"index": 217795994, "value": "0x337028b5"}, {"index": 208353206, "value": "0xafe148c9"}, {"index": 42483309, "value": "0xab99f7ae"}, {"index": 172547758, "value": "0x434ea619"}, {"index": 148076330, "value": "0xd85cb880"}, {"index": 183853158, "value": "0x54764c7f"}, {"index": 214389424, "value": "0x82c7e420"}, {"index": 267488061, "value": "0xedf4cb9e"}, {"index": 169781097, "value": "0x9884c959"}, {"index": 184093494, "value": "0x223ee793"}, {"index": 153880993, "value": "0x3a9ccf69"}, {"index": 84977930, "value": "0x81da4fd2"}, {"index": 46426879, "value": "0xd6ce8cb9"}, {"index": 3093825, "value": "0xe3922dca"}, {"index": 225364072, "value": "0x3e7e6bde"}, {"index": 44593546, "value": "0x382a3aca"}, {"index": 260713159, "value": "0x567e7f7f"}, {"index": 168250303, "value": "0x25a0f084"}, {"index": 52384140, "value": "0xbfeef128"}, {"index": 223401610, "value": "0xe338abfb"}, {"index": 45554030, "value": "0x7c3b5280"}, {"index": 95410555, "value": "0x909bc5f1"}, {"index": 175039924, "value": "0xd8b74b9c"}, {"index": 79171087, "value": "0x8e31a22e"}, {"index": 267580473, "value": "0x26b5f1d8"}, {"index": 24168642, "value": "0x79122c00"}, {"index": 37981670, "value": "0xcafc3340"}, {"index": 171551130, "value": "0xd5e02ea3"}, {"index": 195559979, "value": "0x1aee1afd"}, {"index": 204611762, "value": "0xdb090d9a"}, {"index": 140997658, "value": "0xb049f435"}, {"index": 138925853, "value": "0x4954d8ba"}, {"index": 86637313, "value": "0x03797ba0"}, {"index": 20736778, "value": "0x196eefbd"}, {"index": 219665210, "value": "0xd153412a"}, {"index": 160430336, "value": "0xbe5d2c4b"}, {"index": 264654675, "value": "0xdaa14f0e"}, {"index": 8013395, "value": "0x8e61ed07"}, {"index": 228945585, "value": "0x9e9a64c6"}, {"index": 213884386, "value": "0x2e29ff36"}, {"index": 104419827, "value": "0x392a8589"}, {"index": 44185464, "value": "0xb56a5912"}, {"index": 142737231, "value": "0xfa6e8b57"}, {"index": 99284897, "value": "0xd1a737cb"}, {"index": 132475900, "value": "0xb0fa841a"}, {"index": 61861762, "value": "0xbe1c341f"}, {"index": 132056166, "value": "0xe25be0f1"}, {"index": 262388043, "value": "0xe937f543"}, {"index": 91878046, "value": "0xebab2248"}, {"index": 117353561, "value": "0x8e1b607a"}, {"index": 124768597, "value": "0x202a2fed"}, {"index": 71352993, "value": "0x95e2819c"}, {"index": 190698941, "value": "0x9c9652d4"}, {"index": 46055428, "value": "0x32fedef0"}, {"index": 55281366, "value": "0xdecfff82"}, {"index": 165145231, "value": "0xcb5d43e5"}, {"index": 106810753, "value": "0xb735806a"}, {"index": 171985651, "value": "0x8905939c"}, {"index": 232085256, "value": "0xfbf8472d"}, {"index": 159510492, "value": "0xada74e5d"}, {"index": 40072060, "value": "0x7ebdeeea"}, {"index": 209107596, "value": "0x0119f2b3"}, {"index": 39023794, "value": "0xa9a376b8"}],
|
||||
"cache_head": ["0x355a86d2", "0x7957db1c", "0xd21772af", "0x6fc1e09b", "0xd55ce61d", "0x6e6a278b", "0xd3f543ce", "0x223d8e82", "0x143ab337", "0x2e9f05bd", "0x2eb389bf", "0x0c6e449e", "0x5cfa4222", "0xba6560fe", "0x8e3e1aa4", "0xdbcc1d53"],
|
||||
"cache_last_line": ["0x41190d91", "0xbd277957", "0x22ddbb49", "0x6986f207", "0xdf69a4d6", "0x26401a3a", "0x818230fb", "0xc417122d", "0x3597b211", "0xb553ce55", "0xcf39cc0d", "0x3b7fc43a", "0x3fd43b00", "0x67e1c80e", "0xffa7ea7d", "0xca2960ab"],
|
||||
"cache_fnv1a64": "0x48c4f5bf24166b2e"
|
||||
}
|
||||
278
proto-cuda/packs-readwidth/mixB-1/kernel.cl
Normal file
278
proto-cuda/packs-readwidth/mixB-1/kernel.cl
Normal file
|
|
@ -0,0 +1,278 @@
|
|||
// Generated by igneum-pow export (generator v2) for seed "igneum-readwidth/B/1". Do not edit by hand.
|
||||
// OpenCL C twin of the Metal kernel for the same seed (see proto-opencl/README.md, WAVEFRONT.md and program.metal).
|
||||
// Built from source at runtime by proto-opencl/host.c, which passes these defines:
|
||||
// IGNEUM_GROUP work-group size of igneum_hash, a multiple of 32 (default 32: one work-group = one 32-lane unit)
|
||||
// IGNEUM_EXCHANGE 0 = local-memory exchange with a barrier (any device, any wave width; the default)
|
||||
// 1 = sub_group_shuffle_xor (cl_khr_subgroup_shuffle), only with IGNEUM_GROUP 32 and a sub-group size of exactly 32
|
||||
// 2 = intel_sub_group_shuffle_xor (cl_intel_subgroups), same condition
|
||||
// The verification unit is always 32 lanes. A 64-wide hardware wave (AMD GCN/CDNA, RDNA in wave64) runs two units;
|
||||
// the exchange masks are 1, 2, 4, 8, 16, so every partner lane lies inside the lane's own aligned run of 32.
|
||||
#ifndef IGNEUM_GROUP
|
||||
#define IGNEUM_GROUP 32
|
||||
#endif
|
||||
#ifndef IGNEUM_EXCHANGE
|
||||
#define IGNEUM_EXCHANGE 0
|
||||
#endif
|
||||
#ifdef __OPENCL_VERSION__
|
||||
#define IGNEUM_KERNEL_HASH __kernel __attribute__((reqd_work_group_size(IGNEUM_GROUP, 1, 1)))
|
||||
#define IGNEUM_LOCAL_WORDS(name, n) __local uint name[n]
|
||||
#if IGNEUM_EXCHANGE == 1
|
||||
#ifdef cl_khr_subgroups
|
||||
#pragma OPENCL EXTENSION cl_khr_subgroups : enable
|
||||
#endif
|
||||
#ifdef cl_khr_subgroup_shuffle
|
||||
#pragma OPENCL EXTENSION cl_khr_subgroup_shuffle : enable
|
||||
#endif
|
||||
#elif IGNEUM_EXCHANGE == 2
|
||||
#pragma OPENCL EXTENSION cl_intel_subgroups : enable
|
||||
#endif
|
||||
#else
|
||||
// Not an OpenCL compiler: proto-opencl/emu compiles this file as C++ and supplies the built-ins and these two macros.
|
||||
#include "emu_opencl.h"
|
||||
#endif
|
||||
|
||||
#if IGNEUM_EXCHANGE == 1
|
||||
#define IGNEUM_SHFL_XOR(dst, a, m) dst = sub_group_shuffle_xor((a), (uint)(m))
|
||||
#define IGNEUM_BCAST0(dst, a) dst = sub_group_broadcast((a), 0u)
|
||||
#elif IGNEUM_EXCHANGE == 2
|
||||
#define IGNEUM_SHFL_XOR(dst, a, m) dst = intel_sub_group_shuffle_xor((a), (uint)(m))
|
||||
#define IGNEUM_BCAST0(dst, a) dst = sub_group_broadcast((a), 0u)
|
||||
#else
|
||||
// Local-memory exchange. Two buffers of IGNEUM_GROUP words alternate (xk counts exchanges), so one barrier per
|
||||
// exchange is enough: a lane can only overwrite buffer b at exchange k+2 after passing barrier k+1, and every lane
|
||||
// reaches barrier k+1 only after its read of buffer b at exchange k. The partner lid ^ m stays inside the lane's
|
||||
// aligned run of 32 because m < 32. Control flow is uniform, so every work-item reaches every barrier.
|
||||
#define IGNEUM_SHFL_XOR(dst, a, m) { xch[(xk & 1u) * IGNEUM_GROUP + lid] = (a); barrier(CLK_LOCAL_MEM_FENCE); dst = xch[(xk & 1u) * IGNEUM_GROUP + (lid ^ (uint)(m))]; xk += 1u; }
|
||||
#define IGNEUM_BCAST0(dst, a) { xch[(xk & 1u) * IGNEUM_GROUP + lid] = (a); barrier(CLK_LOCAL_MEM_FENCE); dst = xch[(xk & 1u) * IGNEUM_GROUP + (lid & ~31u)]; xk += 1u; }
|
||||
#endif
|
||||
|
||||
static inline uint splitmix32(uint x) {
|
||||
x ^= x >> 16; x *= 0x7feb352du;
|
||||
x ^= x >> 15; x *= 0x846ca68bu;
|
||||
x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
// n is a literal in 1..31 at every call site. OpenCL rotate() rotates left by n modulo 32.
|
||||
static inline uint rotl_imm(uint x, uint n) { return rotate(x, n); }
|
||||
// Right rotation by n modulo 32 as a left rotation by (32 - n) modulo 32; n == 0 gives x.
|
||||
static inline uint rotr_var(uint x, uint n) { return rotate(x, (0u - n) & 31u); }
|
||||
static inline uint ds_elem(uint i, uint d0, uint d1) {
|
||||
uint x = i ^ d0;
|
||||
x *= 0x9E3779B1u; x ^= x >> 15;
|
||||
x += d1;
|
||||
x *= 0x85EBCA77u; x ^= x >> 13;
|
||||
x *= 0xC2B2AE3Du; x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
|
||||
// Memory-hard dataset core (MEMHARD.md). Cache: 2^26 words in 2^16 segments of 64 chained ChaCha12 lines.
|
||||
// Item: 8 rounds of seed-parameterised mixer + one 64-byte cache read, then a final mixer. All parameters are literals.
|
||||
#define MH_CACHE_LINE_MASK 0x003fffffu
|
||||
#define MH_SEGMENT_LINES 64u
|
||||
#define MH_QR(a, b, c, d, r1, r2, r3, r4) { a += b; d ^= a; d = mh_rotl(d, r1); c += d; b ^= c; b = mh_rotl(b, r2); a += b; d ^= a; d = mh_rotl(d, r3); c += d; b ^= c; b = mh_rotl(b, r4); }
|
||||
static inline uint mh_rotl(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 at every call site
|
||||
|
||||
// y = ChaCha12 core(x) + x
|
||||
static inline void mh_chacha_block(const uint* x, uint* y) {
|
||||
for (uint i = 0u; i < 16u; ++i) y[i] = x[i];
|
||||
for (uint r = 0u; r < 6u; ++r) {
|
||||
MH_QR(y[0], y[4], y[8], y[12], 16u, 12u, 8u, 7u) MH_QR(y[1], y[5], y[9], y[13], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[2], y[6], y[10], y[14], 16u, 12u, 8u, 7u) MH_QR(y[3], y[7], y[11], y[15], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[0], y[5], y[10], y[15], 16u, 12u, 8u, 7u) MH_QR(y[1], y[6], y[11], y[12], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[2], y[7], y[8], y[13], 16u, 12u, 8u, 7u) MH_QR(y[3], y[4], y[9], y[14], 16u, 12u, 8u, 7u)
|
||||
}
|
||||
for (uint i = 0u; i < 16u; ++i) y[i] += x[i];
|
||||
}
|
||||
|
||||
// One cache segment: 64 chained lines written at cache[seg * 1024]. in_j = prev ^ (sigma || K || seg || j || tag), prev_0 = 0.
|
||||
static inline void mh_cache_segment(__global uint* cache, uint seg) {
|
||||
uint prev[16]; uint x[16]; uint y[16];
|
||||
for (uint i = 0u; i < 16u; ++i) prev[i] = 0u;
|
||||
for (uint j = 0u; j < MH_SEGMENT_LINES; ++j) {
|
||||
x[0] = 0x61707865u ^ prev[0]; x[1] = 0x3320646eu ^ prev[1]; x[2] = 0x79622d32u ^ prev[2]; x[3] = 0x6b206574u ^ prev[3];
|
||||
x[4] = 0x3067619fu ^ prev[4];
|
||||
x[5] = 0x3c269176u ^ prev[5];
|
||||
x[6] = 0x84a03b03u ^ prev[6];
|
||||
x[7] = 0xf8c63294u ^ prev[7];
|
||||
x[8] = 0xff977c5bu ^ prev[8];
|
||||
x[9] = 0xe60def3eu ^ prev[9];
|
||||
x[10] = 0x63630141u ^ prev[10];
|
||||
x[11] = 0xb8fbcb58u ^ prev[11];
|
||||
x[12] = seg ^ prev[12]; x[13] = j ^ prev[13]; x[14] = 0x49676e65u ^ prev[14]; x[15] = 0x756d4d48u ^ prev[15];
|
||||
mh_chacha_block(x, y);
|
||||
__global uint* line = cache + ((seg * MH_SEGMENT_LINES + j) * 16u);
|
||||
for (uint i = 0u; i < 16u; ++i) { line[i] = y[i]; prev[i] = y[i]; }
|
||||
}
|
||||
}
|
||||
|
||||
// M_r: per word (s ^ (RC + rk)) * MUL, then a column round and a diagonal round with the seed-drawn rotations.
|
||||
static inline void mh_mixer(uint* s, uint rk) {
|
||||
s[0] = (s[0] ^ (0xbab68293u + rk)) * 0x42146205u;
|
||||
s[1] = (s[1] ^ (0xcc162340u + rk)) * 0x52cbe0fbu;
|
||||
s[2] = (s[2] ^ (0x6ce151ccu + rk)) * 0x7ecf4a03u;
|
||||
s[3] = (s[3] ^ (0xe62b8997u + rk)) * 0x6728907fu;
|
||||
s[4] = (s[4] ^ (0xc9c80297u + rk)) * 0xd81d9751u;
|
||||
s[5] = (s[5] ^ (0xf74a1654u + rk)) * 0x132952c3u;
|
||||
s[6] = (s[6] ^ (0x3d704af5u + rk)) * 0xf60de277u;
|
||||
s[7] = (s[7] ^ (0x3cf522b7u + rk)) * 0x05358035u;
|
||||
s[8] = (s[8] ^ (0x2b9cac04u + rk)) * 0xbaf6499du;
|
||||
s[9] = (s[9] ^ (0xa880ac10u + rk)) * 0xe4db9667u;
|
||||
s[10] = (s[10] ^ (0x13e5dd1du + rk)) * 0x3e98f45du;
|
||||
s[11] = (s[11] ^ (0x6fc3e233u + rk)) * 0xd0004eddu;
|
||||
s[12] = (s[12] ^ (0x2d83eeacu + rk)) * 0x2691630du;
|
||||
s[13] = (s[13] ^ (0x9006e8bfu + rk)) * 0x9beb3bcfu;
|
||||
s[14] = (s[14] ^ (0x2c4b5362u + rk)) * 0xab310379u;
|
||||
s[15] = (s[15] ^ (0x31b49ee2u + rk)) * 0x99cfb423u;
|
||||
MH_QR(s[0], s[4], s[8], s[12], 20u, 20u, 19u, 4u) MH_QR(s[1], s[5], s[9], s[13], 20u, 20u, 19u, 4u)
|
||||
MH_QR(s[2], s[6], s[10], s[14], 20u, 20u, 19u, 4u) MH_QR(s[3], s[7], s[11], s[15], 20u, 20u, 19u, 4u)
|
||||
MH_QR(s[0], s[5], s[10], s[15], 26u, 3u, 3u, 27u) MH_QR(s[1], s[6], s[11], s[12], 26u, 3u, 3u, 27u)
|
||||
MH_QR(s[2], s[7], s[8], s[13], 26u, 3u, 3u, 27u) MH_QR(s[3], s[4], s[9], s[14], 26u, 3u, 3u, 27u)
|
||||
}
|
||||
|
||||
// Item t: 16 words. s = (K, t * MUL[i] + RC[i]); 8 rounds of mixer + cache line s[0] & mask; final mixer.
|
||||
static inline void mh_item(__global const uint* cache, uint t, uint* s) {
|
||||
s[0] = 0x3067619fu;
|
||||
s[1] = 0x3c269176u;
|
||||
s[2] = 0x84a03b03u;
|
||||
s[3] = 0xf8c63294u;
|
||||
s[4] = 0xff977c5bu;
|
||||
s[5] = 0xe60def3eu;
|
||||
s[6] = 0x63630141u;
|
||||
s[7] = 0xb8fbcb58u;
|
||||
s[8] = t * 0x42146205u + 0xbab68293u;
|
||||
s[9] = t * 0x52cbe0fbu + 0xcc162340u;
|
||||
s[10] = t * 0x7ecf4a03u + 0x6ce151ccu;
|
||||
s[11] = t * 0x6728907fu + 0xe62b8997u;
|
||||
s[12] = t * 0xd81d9751u + 0xc9c80297u;
|
||||
s[13] = t * 0x132952c3u + 0xf74a1654u;
|
||||
s[14] = t * 0xf60de277u + 0x3d704af5u;
|
||||
s[15] = t * 0x05358035u + 0x3cf522b7u;
|
||||
for (uint r = 0u; r < 8u; ++r) {
|
||||
mh_mixer(s, 0x9E3779B9u * (r + 1u));
|
||||
__global const uint* line = cache + ((s[0] & MH_CACHE_LINE_MASK) * 16u);
|
||||
for (uint i = 0u; i < 16u; ++i) s[i] ^= line[i];
|
||||
}
|
||||
mh_mixer(s, 0x9E3779B9u * 9u);
|
||||
}
|
||||
// dataset[w] without the dataset: derive item w >> 4 and take word w & 15.
|
||||
static inline uint mh_word(__global const uint* cache, uint w) { uint s[16]; mh_item(cache, w >> 4u, s); return s[w & 15u]; }
|
||||
|
||||
// Memory-hard dataset (MEMHARD.md). One work-item per cache segment; one work-item per 64-byte dataset item.
|
||||
// The same constants as memhard.h in this pack (one emitter, three dialects).
|
||||
__kernel void igneum_cache_fill(__global uint* cache, uint nSegments) {
|
||||
uint seg = (uint)get_global_id(0);
|
||||
if (seg < nSegments) mh_cache_segment(cache, seg);
|
||||
}
|
||||
__kernel void igneum_build(__global uint* ds, __global const uint* cache, uint nItems) {
|
||||
uint t = (uint)get_global_id(0);
|
||||
if (t < nItems) {
|
||||
uint s[16];
|
||||
mh_item(cache, t, s);
|
||||
__global uint* d = ds + ((ulong)t * 16u);
|
||||
for (uint i = 0u; i < 16u; ++i) d[i] = s[i];
|
||||
}
|
||||
}
|
||||
|
||||
// One hash per work-item. IGNEUM_GROUP is a multiple of 32; lane = lid & 31 and every exchange stays inside the
|
||||
// lane's own aligned run of 32 work-items, exactly like simd_shuffle_xor inside a 32-wide Metal SIMD group and
|
||||
// __shfl_xor_sync inside a CUDA warp. Control flow is uniform (no branches at all).
|
||||
IGNEUM_KERNEL_HASH void igneum_hash(__global const uint* ds, __global ulong* out, uint baseNonce, uint mask) {
|
||||
uint gid = (uint)get_global_id(0);
|
||||
uint lid = (uint)get_local_id(0);
|
||||
uint nonce = baseNonce + gid;
|
||||
uint r0, r1, r2, r3, r4, r5, r6, r7;
|
||||
#if IGNEUM_EXCHANGE == 0
|
||||
IGNEUM_LOCAL_WORDS(xch, 2 * IGNEUM_GROUP);
|
||||
uint xk = 0u;
|
||||
#else
|
||||
(void)lid;
|
||||
#endif
|
||||
{ uint x = nonce ^ 0x3e345412u; x += 0x9e3779b9u; x = splitmix32(x); r0 = x ^ 0xfc2b3a0eu; } // SEEDW[0], 0x9e3779b9u * 1u, SEEDW[1]
|
||||
{ uint x = nonce ^ 0xfc2b3a0eu; x += 0x3c6ef372u; x = splitmix32(x); r1 = x ^ 0x7740353du; } // SEEDW[1], 0x9e3779b9u * 2u, SEEDW[2]
|
||||
{ uint x = nonce ^ 0x7740353du; x += 0xdaa66d2bu; x = splitmix32(x); r2 = x ^ 0x2df159dbu; } // SEEDW[2], 0x9e3779b9u * 3u, SEEDW[3]
|
||||
{ uint x = nonce ^ 0x2df159dbu; x += 0x78dde6e4u; x = splitmix32(x); r3 = x ^ 0x50bc6eedu; } // SEEDW[3], 0x9e3779b9u * 4u, SEEDW[4]
|
||||
{ uint x = nonce ^ 0x50bc6eedu; x += 0x1715609du; x = splitmix32(x); r4 = x ^ 0x2e61acb2u; } // SEEDW[4], 0x9e3779b9u * 5u, SEEDW[5]
|
||||
{ uint x = nonce ^ 0x2e61acb2u; x += 0xb54cda56u; x = splitmix32(x); r5 = x ^ 0x3c800bffu; } // SEEDW[5], 0x9e3779b9u * 6u, SEEDW[6]
|
||||
{ uint x = nonce ^ 0x3c800bffu; x += 0x5384540fu; x = splitmix32(x); r6 = x ^ 0xbaecd8c1u; } // SEEDW[6], 0x9e3779b9u * 7u, SEEDW[7]
|
||||
{ uint x = nonce ^ 0xbaecd8c1u; x += 0xf1bbcdc8u; x = splitmix32(x); r7 = x ^ 0x3e345412u; } // SEEDW[7], 0x9e3779b9u * 8u, SEEDW[0]
|
||||
|
||||
for (uint it = 0u; it < 8u; ++it) {
|
||||
uint sel = r0;
|
||||
r5 = r4 * r0 + r5; // 0 mad
|
||||
r1 = rotl_imm(r1, 23u); // 1 rotl
|
||||
{ uint b_ = (r5 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r0 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r0 = x_; } // 2 load
|
||||
r5 = r4 * r2 + r5; // 3 mad
|
||||
r1 = r1 * r6; // 4 mul
|
||||
r1 = r1 + r0 + ((((sel >> 6u) & 1u) != 0u) ? 0x9dd9fb05u : 0x9db46598u); // 5 add
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r7, 16u); r1 = r1 ^ t_; } // 6 shfl
|
||||
r6 = r6 * r1; // 7 mul
|
||||
r1 = mul_hi(r1, r7); // 8 mulhi
|
||||
r2 = mul_hi(r2, r1); // 9 mulhi
|
||||
r0 = r0 + r4 + ((((sel >> 13u) & 1u) != 0u) ? 0xc15822b6u : 0xe45fccebu); // 10 add
|
||||
r5 = r1 * r2 + r5; // 11 mad
|
||||
r4 = r4 * r7; // 12 mul
|
||||
{ uint b_ = (r5 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r0 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r0 = x_; } // 13 load
|
||||
r3 = r3 ^ r4; // 14 xor
|
||||
r1 = r1 ^ r6; // 15 xor
|
||||
r5 = rotr_var(r5, r6); // 16 rotr
|
||||
r3 = rotr_var(r3, r7); // 17 rotr
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r4, 16u); r1 = r1 ^ t_; } // 18 shfl
|
||||
r5 = r5 ^ ds[r6 & mask]; // 19 load
|
||||
r6 = rotl_imm(r6, 30u); // 20 rotl
|
||||
{ uint b_ = (r2 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r5 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r5 = x_; } // 21 load
|
||||
r3 = r3 ^ r5; // 22 xor
|
||||
r5 = r5 + r7 + ((((sel >> 6u) & 1u) != 0u) ? 0x950603c6u : 0x1d4f8db7u); // 23 add
|
||||
{ uint b_ = (r4 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r3 = x_; } // 24 load
|
||||
{ uint b_ = (r1 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r0 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r0 = x_; } // 25 load
|
||||
r2 = r2 + r3 + ((((sel >> 31u) & 1u) != 0u) ? 0x0ae476a4u : 0x55db0d92u); // 26 add
|
||||
r5 = r5 ^ ds[r6 & mask]; // 27 load
|
||||
{ uint b_ = (r5 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r2 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r2 = x_; } // 28 load
|
||||
r1 = r1 ^ r6; // 29 xor
|
||||
r7 = mul_hi(r7, r4); // 30 mulhi
|
||||
r6 = rotr_var(r6, r3); // 31 rotr
|
||||
r0 = r0 ^ ds[r3 & mask]; // 32 load
|
||||
r5 = rotr_var(r5, r0); // 33 rotr
|
||||
r5 = rotl_imm(r5, 20u); // 34 rotl
|
||||
r0 = mul_hi(r0, r4); // 35 mulhi
|
||||
r6 = r6 + r7 + ((((sel >> 18u) & 1u) != 0u) ? 0xfe7a0454u : 0x5d6e3dc5u); // 36 add
|
||||
{ uint b_ = (r1 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r2 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r2 = x_; } // 37 load
|
||||
r2 = rotl_imm(r2, 19u); // 38 rotl
|
||||
r3 = r3 + r6 + ((((sel >> 20u) & 1u) != 0u) ? 0xc1d4ae24u : 0xe7e241bau); // 39 add
|
||||
{ uint b_ = (r7 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r4 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r4 = x_; } // 40 load
|
||||
r3 = r3 + r1 + ((((sel >> 21u) & 1u) != 0u) ? 0x8f9f8556u : 0xb45cdd60u); // 41 add
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r2, 4u); r5 = r5 ^ t_; } // 42 shfl
|
||||
r0 = r0 * r1; // 43 mul
|
||||
r0 = rotr_var(r0, r7); // 44 rotr
|
||||
r5 = r5 - r3; // 45 sub
|
||||
r2 = r7 * r7 + r2; // 46 mad
|
||||
r6 = r3 * r1 + r6; // 47 mad
|
||||
r0 = r0 * r7; // 48 mul
|
||||
r0 = r0 + r4 + ((((sel >> 1u) & 1u) != 0u) ? 0xb9083b6cu : 0x3fa0c5cdu); // 49 add
|
||||
r4 = r4 + r6 + ((((sel >> 13u) & 1u) != 0u) ? 0x9eecc778u : 0x2d6873e8u); // 50 add
|
||||
r2 = r2 - r7; // 51 sub
|
||||
r6 = rotl_imm(r6, 6u); // 52 rotl
|
||||
r3 = rotr_var(r3, r5); // 53 rotr
|
||||
{ uint b_ = (r2 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r3 = x_; } // 54 load
|
||||
{ uint b_ = (r5 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r7 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r7 = x_; } // 55 load
|
||||
r2 = r2 | r6; // 56 or
|
||||
r4 = r4 ^ ds[r0 & mask]; // 57 load
|
||||
r3 = r3 ^ r6; // 58 xor
|
||||
r0 = r0 ^ ds[r6 & mask]; // 59 load
|
||||
r2 = r2 + r4 + ((((sel >> 3u) & 1u) != 0u) ? 0x19c76fb3u : 0x5052a1c3u); // 60 add
|
||||
r7 = r7 ^ ds[r4 & mask]; // 61 load
|
||||
r6 = r6 | r1; // 62 or
|
||||
r5 = r5 + r1 + ((((sel >> 4u) & 1u) != 0u) ? 0x535fe3fau : 0x08c757c0u); // 63 add
|
||||
}
|
||||
uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u);
|
||||
uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u);
|
||||
out[gid] = ((ulong)hi << 32) | (ulong)lo;
|
||||
}
|
||||
|
||||
#if IGNEUM_EXCHANGE != 0
|
||||
// Reports the sub-group size this device uses for a work-group of IGNEUM_GROUP items. host.c runs it only when the
|
||||
// per-kernel query (clGetKernelSubGroupInfoKHR on igneum_hash) is unavailable; that query is preferred because a
|
||||
// compiler may pick a different wave width per kernel (RDNA: wave32 or wave64). See WAVEFRONT.md.
|
||||
IGNEUM_KERNEL_HASH void igneum_probe_subgroup(__global uint* out) {
|
||||
if (get_local_id(0) == 0u) { out[0] = get_sub_group_size(); out[1] = get_num_sub_groups(); }
|
||||
}
|
||||
#endif
|
||||
164
proto-cuda/packs-readwidth/mixB-1/kernel.cu
Normal file
164
proto-cuda/packs-readwidth/mixB-1/kernel.cu
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
// Generated by igneum-pow export (generator v2) for seed "igneum-readwidth/B/1". Do not edit by hand.
|
||||
// Bit-exact twin of the Metal kernel for the same seed (see proto-cuda/CHECKLIST.md and program.metal).
|
||||
// Compiled ahead of time by nvcc together with proto-cuda/host.cu. No NVRTC.
|
||||
#include <cuda_runtime.h>
|
||||
#include <cstdint>
|
||||
#include "program.h"
|
||||
#include "memhard.h"
|
||||
|
||||
__device__ __forceinline__ uint32_t splitmix32(uint32_t x) {
|
||||
x ^= x >> 16; x *= 0x7feb352du;
|
||||
x ^= x >> 15; x *= 0x846ca68bu;
|
||||
x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
// n is a literal in 1..31 at every call site, so both shift amounts are in 1..31.
|
||||
__device__ __forceinline__ uint32_t rotl_imm(uint32_t x, uint32_t n) { return (x << n) | (x >> (32u - n)); }
|
||||
// n is masked to 0..31; the second shift amount is masked too, so n == 0 gives x.
|
||||
__device__ __forceinline__ uint32_t rotr_var(uint32_t x, uint32_t n) { n &= 31u; return (x >> n) | (x << ((32u - n) & 31u)); }
|
||||
__device__ __forceinline__ uint32_t ds_elem(uint32_t i, uint32_t d0, uint32_t d1) {
|
||||
uint32_t x = i ^ d0;
|
||||
x *= 0x9E3779B1u; x ^= x >> 15;
|
||||
x += d1;
|
||||
x *= 0x85EBCA77u; x ^= x >> 13;
|
||||
x *= 0xC2B2AE3Du; x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
|
||||
// Memory-hard dataset (MEMHARD.md). One thread per cache segment; one thread per 64-byte dataset item.
|
||||
// The core functions (mh_cache_segment, mh_item) are in memhard.h and are also compiled for the host.
|
||||
__global__ void igneum_cache_fill(uint32_t* cache, uint32_t nSegments) {
|
||||
uint32_t seg = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
if (seg < nSegments) mh_cache_segment(cache, seg);
|
||||
}
|
||||
__global__ void igneum_build(uint32_t* ds, const uint32_t* cache, uint32_t nItems) {
|
||||
uint32_t t = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
if (t < nItems) {
|
||||
uint32_t s[16];
|
||||
mh_item(cache, t, s);
|
||||
uint32_t* d = ds + (size_t)t * 16u;
|
||||
for (uint32_t i = 0u; i < 16u; ++i) d[i] = s[i];
|
||||
}
|
||||
}
|
||||
|
||||
// One hash per thread. blockDim.x is a multiple of 32; lane = threadIdx.x & 31 and every
|
||||
// __shfl_xor_sync stays inside the lane's own warp, exactly like simd_shuffle_xor inside a
|
||||
// 32-wide Metal SIMD group. Control flow is uniform, so the full 0xffffffff member mask is valid.
|
||||
__global__ void igneum_hash(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask) {
|
||||
uint32_t gid = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
uint32_t nonce = baseNonce + gid;
|
||||
uint32_t r0, r1, r2, r3, r4, r5, r6, r7;
|
||||
{ uint32_t x = nonce ^ 0x3e345412u; x += 0x9e3779b9u; x = splitmix32(x); r0 = x ^ 0xfc2b3a0eu; } // SEEDW[0], 0x9e3779b9u * 1u, SEEDW[1]
|
||||
{ uint32_t x = nonce ^ 0xfc2b3a0eu; x += 0x3c6ef372u; x = splitmix32(x); r1 = x ^ 0x7740353du; } // SEEDW[1], 0x9e3779b9u * 2u, SEEDW[2]
|
||||
{ uint32_t x = nonce ^ 0x7740353du; x += 0xdaa66d2bu; x = splitmix32(x); r2 = x ^ 0x2df159dbu; } // SEEDW[2], 0x9e3779b9u * 3u, SEEDW[3]
|
||||
{ uint32_t x = nonce ^ 0x2df159dbu; x += 0x78dde6e4u; x = splitmix32(x); r3 = x ^ 0x50bc6eedu; } // SEEDW[3], 0x9e3779b9u * 4u, SEEDW[4]
|
||||
{ uint32_t x = nonce ^ 0x50bc6eedu; x += 0x1715609du; x = splitmix32(x); r4 = x ^ 0x2e61acb2u; } // SEEDW[4], 0x9e3779b9u * 5u, SEEDW[5]
|
||||
{ uint32_t x = nonce ^ 0x2e61acb2u; x += 0xb54cda56u; x = splitmix32(x); r5 = x ^ 0x3c800bffu; } // SEEDW[5], 0x9e3779b9u * 6u, SEEDW[6]
|
||||
{ uint32_t x = nonce ^ 0x3c800bffu; x += 0x5384540fu; x = splitmix32(x); r6 = x ^ 0xbaecd8c1u; } // SEEDW[6], 0x9e3779b9u * 7u, SEEDW[7]
|
||||
{ uint32_t x = nonce ^ 0xbaecd8c1u; x += 0xf1bbcdc8u; x = splitmix32(x); r7 = x ^ 0x3e345412u; } // SEEDW[7], 0x9e3779b9u * 8u, SEEDW[0]
|
||||
|
||||
for (uint32_t it = 0u; it < 8u; ++it) {
|
||||
uint32_t sel = r0;
|
||||
r5 = r4 * r0 + r5; // 0 mad
|
||||
r1 = rotl_imm(r1, 23u); // 1 rotl
|
||||
{ uint32_t b_ = (r5 & mask) & ~3u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint32_t x_ = r0 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r0 = x_; } // 2 load
|
||||
r5 = r4 * r2 + r5; // 3 mad
|
||||
r1 = r1 * r6; // 4 mul
|
||||
r1 = r1 + r0 + ((((sel >> 6u) & 1u) != 0u) ? 0x9dd9fb05u : 0x9db46598u); // 5 add
|
||||
r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r7, 16); // 6 shfl
|
||||
r6 = r6 * r1; // 7 mul
|
||||
r1 = __umulhi(r1, r7); // 8 mulhi
|
||||
r2 = __umulhi(r2, r1); // 9 mulhi
|
||||
r0 = r0 + r4 + ((((sel >> 13u) & 1u) != 0u) ? 0xc15822b6u : 0xe45fccebu); // 10 add
|
||||
r5 = r1 * r2 + r5; // 11 mad
|
||||
r4 = r4 * r7; // 12 mul
|
||||
{ uint32_t b_ = (r5 & mask) & ~15u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint32_t x_ = r0 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r0 = x_; } // 13 load
|
||||
r3 = r3 ^ r4; // 14 xor
|
||||
r1 = r1 ^ r6; // 15 xor
|
||||
r5 = rotr_var(r5, r6); // 16 rotr
|
||||
r3 = rotr_var(r3, r7); // 17 rotr
|
||||
r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r4, 16); // 18 shfl
|
||||
r5 = r5 ^ ds[r6 & mask]; // 19 load
|
||||
r6 = rotl_imm(r6, 30u); // 20 rotl
|
||||
{ uint32_t b_ = (r2 & mask) & ~3u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint32_t x_ = r5 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r5 = x_; } // 21 load
|
||||
r3 = r3 ^ r5; // 22 xor
|
||||
r5 = r5 + r7 + ((((sel >> 6u) & 1u) != 0u) ? 0x950603c6u : 0x1d4f8db7u); // 23 add
|
||||
{ uint32_t b_ = (r4 & mask) & ~3u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint32_t x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r3 = x_; } // 24 load
|
||||
{ uint32_t b_ = (r1 & mask) & ~15u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint32_t x_ = r0 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r0 = x_; } // 25 load
|
||||
r2 = r2 + r3 + ((((sel >> 31u) & 1u) != 0u) ? 0x0ae476a4u : 0x55db0d92u); // 26 add
|
||||
r5 = r5 ^ ds[r6 & mask]; // 27 load
|
||||
{ uint32_t b_ = (r5 & mask) & ~3u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint32_t x_ = r2 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r2 = x_; } // 28 load
|
||||
r1 = r1 ^ r6; // 29 xor
|
||||
r7 = __umulhi(r7, r4); // 30 mulhi
|
||||
r6 = rotr_var(r6, r3); // 31 rotr
|
||||
r0 = r0 ^ ds[r3 & mask]; // 32 load
|
||||
r5 = rotr_var(r5, r0); // 33 rotr
|
||||
r5 = rotl_imm(r5, 20u); // 34 rotl
|
||||
r0 = __umulhi(r0, r4); // 35 mulhi
|
||||
r6 = r6 + r7 + ((((sel >> 18u) & 1u) != 0u) ? 0xfe7a0454u : 0x5d6e3dc5u); // 36 add
|
||||
{ uint32_t b_ = (r1 & mask) & ~3u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint32_t x_ = r2 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r2 = x_; } // 37 load
|
||||
r2 = rotl_imm(r2, 19u); // 38 rotl
|
||||
r3 = r3 + r6 + ((((sel >> 20u) & 1u) != 0u) ? 0xc1d4ae24u : 0xe7e241bau); // 39 add
|
||||
{ uint32_t b_ = (r7 & mask) & ~3u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint32_t x_ = r4 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r4 = x_; } // 40 load
|
||||
r3 = r3 + r1 + ((((sel >> 21u) & 1u) != 0u) ? 0x8f9f8556u : 0xb45cdd60u); // 41 add
|
||||
r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r2, 4); // 42 shfl
|
||||
r0 = r0 * r1; // 43 mul
|
||||
r0 = rotr_var(r0, r7); // 44 rotr
|
||||
r5 = r5 - r3; // 45 sub
|
||||
r2 = r7 * r7 + r2; // 46 mad
|
||||
r6 = r3 * r1 + r6; // 47 mad
|
||||
r0 = r0 * r7; // 48 mul
|
||||
r0 = r0 + r4 + ((((sel >> 1u) & 1u) != 0u) ? 0xb9083b6cu : 0x3fa0c5cdu); // 49 add
|
||||
r4 = r4 + r6 + ((((sel >> 13u) & 1u) != 0u) ? 0x9eecc778u : 0x2d6873e8u); // 50 add
|
||||
r2 = r2 - r7; // 51 sub
|
||||
r6 = rotl_imm(r6, 6u); // 52 rotl
|
||||
r3 = rotr_var(r3, r5); // 53 rotr
|
||||
{ uint32_t b_ = (r2 & mask) & ~3u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint32_t x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r3 = x_; } // 54 load
|
||||
{ uint32_t b_ = (r5 & mask) & ~3u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint32_t x_ = r7 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r7 = x_; } // 55 load
|
||||
r2 = r2 | r6; // 56 or
|
||||
r4 = r4 ^ ds[r0 & mask]; // 57 load
|
||||
r3 = r3 ^ r6; // 58 xor
|
||||
r0 = r0 ^ ds[r6 & mask]; // 59 load
|
||||
r2 = r2 + r4 + ((((sel >> 3u) & 1u) != 0u) ? 0x19c76fb3u : 0x5052a1c3u); // 60 add
|
||||
r7 = r7 ^ ds[r4 & mask]; // 61 load
|
||||
r6 = r6 | r1; // 62 or
|
||||
r5 = r5 + r1 + ((((sel >> 4u) & 1u) != 0u) ? 0x535fe3fau : 0x08c757c0u); // 63 add
|
||||
}
|
||||
uint32_t lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u);
|
||||
uint32_t hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u);
|
||||
out[gid] = ((uint64_t)hi << 32) | (uint64_t)lo;
|
||||
}
|
||||
|
||||
// Host-side launch wrappers. Declared in program.h, called from host.cu.
|
||||
cudaError_t igneum_launch_cache_fill(uint32_t* cache, uint32_t nSegments) {
|
||||
if (nSegments == 0u) return cudaErrorInvalidValue;
|
||||
uint32_t block = 256u;
|
||||
uint32_t grid = (nSegments + block - 1u) / block;
|
||||
igneum_cache_fill<<<grid, block>>>(cache, nSegments);
|
||||
return cudaGetLastError();
|
||||
}
|
||||
|
||||
cudaError_t igneum_launch_build(uint32_t* ds, const uint32_t* cache, uint32_t nItems) {
|
||||
if (nItems == 0u) return cudaErrorInvalidValue;
|
||||
uint32_t block = 256u;
|
||||
uint32_t grid = (nItems + block - 1u) / block;
|
||||
igneum_build<<<grid, block>>>(ds, cache, nItems);
|
||||
return cudaGetLastError();
|
||||
}
|
||||
|
||||
cudaError_t igneum_launch_hash(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask,
|
||||
uint32_t nonces, uint32_t blockWarps) {
|
||||
if (blockWarps == 0u || blockWarps > 32u) return cudaErrorInvalidValue;
|
||||
uint32_t block = 32u * blockWarps;
|
||||
if (nonces == 0u || (nonces % block) != 0u) return cudaErrorInvalidValue;
|
||||
igneum_hash<<<nonces / block, block>>>(ds, out, baseNonce, mask);
|
||||
return cudaGetLastError();
|
||||
}
|
||||
|
||||
cudaError_t igneum_hash_info(int* numRegs, int* blocksPerSM, uint32_t blockWarps) {
|
||||
cudaFuncAttributes attr;
|
||||
cudaError_t e = cudaFuncGetAttributes(&attr, igneum_hash);
|
||||
if (e != cudaSuccess) return e;
|
||||
*numRegs = attr.numRegs;
|
||||
return cudaOccupancyMaxActiveBlocksPerMultiprocessor(blocksPerSM, igneum_hash, (int)(32u * blockWarps), 0);
|
||||
}
|
||||
372
proto-cuda/packs-readwidth/mixB-1/kernel_bound.cl
Normal file
372
proto-cuda/packs-readwidth/mixB-1/kernel_bound.cl
Normal file
|
|
@ -0,0 +1,372 @@
|
|||
// Generated by igneum-pow export (generator v2) for seed "igneum-readwidth/B/1". Do not edit by hand.
|
||||
// OpenCL C twin of the Metal kernel for the same seed (see proto-opencl/README.md, WAVEFRONT.md and program.metal).
|
||||
// Built from source at runtime by proto-opencl/host.c, which passes these defines:
|
||||
// IGNEUM_GROUP work-group size of igneum_hash, a multiple of 32 (default 32: one work-group = one 32-lane unit)
|
||||
// IGNEUM_EXCHANGE 0 = local-memory exchange with a barrier (any device, any wave width; the default)
|
||||
// 1 = sub_group_shuffle_xor (cl_khr_subgroup_shuffle), only with IGNEUM_GROUP 32 and a sub-group size of exactly 32
|
||||
// 2 = intel_sub_group_shuffle_xor (cl_intel_subgroups), same condition
|
||||
// The verification unit is always 32 lanes. A 64-wide hardware wave (AMD GCN/CDNA, RDNA in wave64) runs two units;
|
||||
// the exchange masks are 1, 2, 4, 8, 16, so every partner lane lies inside the lane's own aligned run of 32.
|
||||
#ifndef IGNEUM_GROUP
|
||||
#define IGNEUM_GROUP 32
|
||||
#endif
|
||||
#ifndef IGNEUM_EXCHANGE
|
||||
#define IGNEUM_EXCHANGE 0
|
||||
#endif
|
||||
#ifdef __OPENCL_VERSION__
|
||||
#define IGNEUM_KERNEL_HASH __kernel __attribute__((reqd_work_group_size(IGNEUM_GROUP, 1, 1)))
|
||||
#define IGNEUM_LOCAL_WORDS(name, n) __local uint name[n]
|
||||
#if IGNEUM_EXCHANGE == 1
|
||||
#ifdef cl_khr_subgroups
|
||||
#pragma OPENCL EXTENSION cl_khr_subgroups : enable
|
||||
#endif
|
||||
#ifdef cl_khr_subgroup_shuffle
|
||||
#pragma OPENCL EXTENSION cl_khr_subgroup_shuffle : enable
|
||||
#endif
|
||||
#elif IGNEUM_EXCHANGE == 2
|
||||
#pragma OPENCL EXTENSION cl_intel_subgroups : enable
|
||||
#endif
|
||||
#else
|
||||
// Not an OpenCL compiler: proto-opencl/emu compiles this file as C++ and supplies the built-ins and these two macros.
|
||||
#include "emu_opencl.h"
|
||||
#endif
|
||||
|
||||
#if IGNEUM_EXCHANGE == 1
|
||||
#define IGNEUM_SHFL_XOR(dst, a, m) dst = sub_group_shuffle_xor((a), (uint)(m))
|
||||
#define IGNEUM_BCAST0(dst, a) dst = sub_group_broadcast((a), 0u)
|
||||
#elif IGNEUM_EXCHANGE == 2
|
||||
#define IGNEUM_SHFL_XOR(dst, a, m) dst = intel_sub_group_shuffle_xor((a), (uint)(m))
|
||||
#define IGNEUM_BCAST0(dst, a) dst = sub_group_broadcast((a), 0u)
|
||||
#else
|
||||
// Local-memory exchange. Two buffers of IGNEUM_GROUP words alternate (xk counts exchanges), so one barrier per
|
||||
// exchange is enough: a lane can only overwrite buffer b at exchange k+2 after passing barrier k+1, and every lane
|
||||
// reaches barrier k+1 only after its read of buffer b at exchange k. The partner lid ^ m stays inside the lane's
|
||||
// aligned run of 32 because m < 32. Control flow is uniform, so every work-item reaches every barrier.
|
||||
#define IGNEUM_SHFL_XOR(dst, a, m) { xch[(xk & 1u) * IGNEUM_GROUP + lid] = (a); barrier(CLK_LOCAL_MEM_FENCE); dst = xch[(xk & 1u) * IGNEUM_GROUP + (lid ^ (uint)(m))]; xk += 1u; }
|
||||
#define IGNEUM_BCAST0(dst, a) { xch[(xk & 1u) * IGNEUM_GROUP + lid] = (a); barrier(CLK_LOCAL_MEM_FENCE); dst = xch[(xk & 1u) * IGNEUM_GROUP + (lid & ~31u)]; xk += 1u; }
|
||||
#endif
|
||||
|
||||
static inline uint splitmix32(uint x) {
|
||||
x ^= x >> 16; x *= 0x7feb352du;
|
||||
x ^= x >> 15; x *= 0x846ca68bu;
|
||||
x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
// n is a literal in 1..31 at every call site. OpenCL rotate() rotates left by n modulo 32.
|
||||
static inline uint rotl_imm(uint x, uint n) { return rotate(x, n); }
|
||||
// Right rotation by n modulo 32 as a left rotation by (32 - n) modulo 32; n == 0 gives x.
|
||||
static inline uint rotr_var(uint x, uint n) { return rotate(x, (0u - n) & 31u); }
|
||||
static inline uint ds_elem(uint i, uint d0, uint d1) {
|
||||
uint x = i ^ d0;
|
||||
x *= 0x9E3779B1u; x ^= x >> 15;
|
||||
x += d1;
|
||||
x *= 0x85EBCA77u; x ^= x >> 13;
|
||||
x *= 0xC2B2AE3Du; x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
|
||||
// Memory-hard dataset core (MEMHARD.md). Cache: 2^26 words in 2^16 segments of 64 chained ChaCha12 lines.
|
||||
// Item: 8 rounds of seed-parameterised mixer + one 64-byte cache read, then a final mixer. All parameters are literals.
|
||||
#define MH_CACHE_LINE_MASK 0x003fffffu
|
||||
#define MH_SEGMENT_LINES 64u
|
||||
#define MH_QR(a, b, c, d, r1, r2, r3, r4) { a += b; d ^= a; d = mh_rotl(d, r1); c += d; b ^= c; b = mh_rotl(b, r2); a += b; d ^= a; d = mh_rotl(d, r3); c += d; b ^= c; b = mh_rotl(b, r4); }
|
||||
static inline uint mh_rotl(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 at every call site
|
||||
|
||||
// y = ChaCha12 core(x) + x
|
||||
static inline void mh_chacha_block(const uint* x, uint* y) {
|
||||
for (uint i = 0u; i < 16u; ++i) y[i] = x[i];
|
||||
for (uint r = 0u; r < 6u; ++r) {
|
||||
MH_QR(y[0], y[4], y[8], y[12], 16u, 12u, 8u, 7u) MH_QR(y[1], y[5], y[9], y[13], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[2], y[6], y[10], y[14], 16u, 12u, 8u, 7u) MH_QR(y[3], y[7], y[11], y[15], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[0], y[5], y[10], y[15], 16u, 12u, 8u, 7u) MH_QR(y[1], y[6], y[11], y[12], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[2], y[7], y[8], y[13], 16u, 12u, 8u, 7u) MH_QR(y[3], y[4], y[9], y[14], 16u, 12u, 8u, 7u)
|
||||
}
|
||||
for (uint i = 0u; i < 16u; ++i) y[i] += x[i];
|
||||
}
|
||||
|
||||
// One cache segment: 64 chained lines written at cache[seg * 1024]. in_j = prev ^ (sigma || K || seg || j || tag), prev_0 = 0.
|
||||
static inline void mh_cache_segment(__global uint* cache, uint seg) {
|
||||
uint prev[16]; uint x[16]; uint y[16];
|
||||
for (uint i = 0u; i < 16u; ++i) prev[i] = 0u;
|
||||
for (uint j = 0u; j < MH_SEGMENT_LINES; ++j) {
|
||||
x[0] = 0x61707865u ^ prev[0]; x[1] = 0x3320646eu ^ prev[1]; x[2] = 0x79622d32u ^ prev[2]; x[3] = 0x6b206574u ^ prev[3];
|
||||
x[4] = 0x3067619fu ^ prev[4];
|
||||
x[5] = 0x3c269176u ^ prev[5];
|
||||
x[6] = 0x84a03b03u ^ prev[6];
|
||||
x[7] = 0xf8c63294u ^ prev[7];
|
||||
x[8] = 0xff977c5bu ^ prev[8];
|
||||
x[9] = 0xe60def3eu ^ prev[9];
|
||||
x[10] = 0x63630141u ^ prev[10];
|
||||
x[11] = 0xb8fbcb58u ^ prev[11];
|
||||
x[12] = seg ^ prev[12]; x[13] = j ^ prev[13]; x[14] = 0x49676e65u ^ prev[14]; x[15] = 0x756d4d48u ^ prev[15];
|
||||
mh_chacha_block(x, y);
|
||||
__global uint* line = cache + ((seg * MH_SEGMENT_LINES + j) * 16u);
|
||||
for (uint i = 0u; i < 16u; ++i) { line[i] = y[i]; prev[i] = y[i]; }
|
||||
}
|
||||
}
|
||||
|
||||
// M_r: per word (s ^ (RC + rk)) * MUL, then a column round and a diagonal round with the seed-drawn rotations.
|
||||
static inline void mh_mixer(uint* s, uint rk) {
|
||||
s[0] = (s[0] ^ (0xbab68293u + rk)) * 0x42146205u;
|
||||
s[1] = (s[1] ^ (0xcc162340u + rk)) * 0x52cbe0fbu;
|
||||
s[2] = (s[2] ^ (0x6ce151ccu + rk)) * 0x7ecf4a03u;
|
||||
s[3] = (s[3] ^ (0xe62b8997u + rk)) * 0x6728907fu;
|
||||
s[4] = (s[4] ^ (0xc9c80297u + rk)) * 0xd81d9751u;
|
||||
s[5] = (s[5] ^ (0xf74a1654u + rk)) * 0x132952c3u;
|
||||
s[6] = (s[6] ^ (0x3d704af5u + rk)) * 0xf60de277u;
|
||||
s[7] = (s[7] ^ (0x3cf522b7u + rk)) * 0x05358035u;
|
||||
s[8] = (s[8] ^ (0x2b9cac04u + rk)) * 0xbaf6499du;
|
||||
s[9] = (s[9] ^ (0xa880ac10u + rk)) * 0xe4db9667u;
|
||||
s[10] = (s[10] ^ (0x13e5dd1du + rk)) * 0x3e98f45du;
|
||||
s[11] = (s[11] ^ (0x6fc3e233u + rk)) * 0xd0004eddu;
|
||||
s[12] = (s[12] ^ (0x2d83eeacu + rk)) * 0x2691630du;
|
||||
s[13] = (s[13] ^ (0x9006e8bfu + rk)) * 0x9beb3bcfu;
|
||||
s[14] = (s[14] ^ (0x2c4b5362u + rk)) * 0xab310379u;
|
||||
s[15] = (s[15] ^ (0x31b49ee2u + rk)) * 0x99cfb423u;
|
||||
MH_QR(s[0], s[4], s[8], s[12], 20u, 20u, 19u, 4u) MH_QR(s[1], s[5], s[9], s[13], 20u, 20u, 19u, 4u)
|
||||
MH_QR(s[2], s[6], s[10], s[14], 20u, 20u, 19u, 4u) MH_QR(s[3], s[7], s[11], s[15], 20u, 20u, 19u, 4u)
|
||||
MH_QR(s[0], s[5], s[10], s[15], 26u, 3u, 3u, 27u) MH_QR(s[1], s[6], s[11], s[12], 26u, 3u, 3u, 27u)
|
||||
MH_QR(s[2], s[7], s[8], s[13], 26u, 3u, 3u, 27u) MH_QR(s[3], s[4], s[9], s[14], 26u, 3u, 3u, 27u)
|
||||
}
|
||||
|
||||
// Item t: 16 words. s = (K, t * MUL[i] + RC[i]); 8 rounds of mixer + cache line s[0] & mask; final mixer.
|
||||
static inline void mh_item(__global const uint* cache, uint t, uint* s) {
|
||||
s[0] = 0x3067619fu;
|
||||
s[1] = 0x3c269176u;
|
||||
s[2] = 0x84a03b03u;
|
||||
s[3] = 0xf8c63294u;
|
||||
s[4] = 0xff977c5bu;
|
||||
s[5] = 0xe60def3eu;
|
||||
s[6] = 0x63630141u;
|
||||
s[7] = 0xb8fbcb58u;
|
||||
s[8] = t * 0x42146205u + 0xbab68293u;
|
||||
s[9] = t * 0x52cbe0fbu + 0xcc162340u;
|
||||
s[10] = t * 0x7ecf4a03u + 0x6ce151ccu;
|
||||
s[11] = t * 0x6728907fu + 0xe62b8997u;
|
||||
s[12] = t * 0xd81d9751u + 0xc9c80297u;
|
||||
s[13] = t * 0x132952c3u + 0xf74a1654u;
|
||||
s[14] = t * 0xf60de277u + 0x3d704af5u;
|
||||
s[15] = t * 0x05358035u + 0x3cf522b7u;
|
||||
for (uint r = 0u; r < 8u; ++r) {
|
||||
mh_mixer(s, 0x9E3779B9u * (r + 1u));
|
||||
__global const uint* line = cache + ((s[0] & MH_CACHE_LINE_MASK) * 16u);
|
||||
for (uint i = 0u; i < 16u; ++i) s[i] ^= line[i];
|
||||
}
|
||||
mh_mixer(s, 0x9E3779B9u * 9u);
|
||||
}
|
||||
// dataset[w] without the dataset: derive item w >> 4 and take word w & 15.
|
||||
static inline uint mh_word(__global const uint* cache, uint w) { uint s[16]; mh_item(cache, w >> 4u, s); return s[w & 15u]; }
|
||||
|
||||
// Memory-hard dataset (MEMHARD.md). One work-item per cache segment; one work-item per 64-byte dataset item.
|
||||
// The same constants as memhard.h in this pack (one emitter, three dialects).
|
||||
__kernel void igneum_cache_fill(__global uint* cache, uint nSegments) {
|
||||
uint seg = (uint)get_global_id(0);
|
||||
if (seg < nSegments) mh_cache_segment(cache, seg);
|
||||
}
|
||||
__kernel void igneum_build(__global uint* ds, __global const uint* cache, uint nItems) {
|
||||
uint t = (uint)get_global_id(0);
|
||||
if (t < nItems) {
|
||||
uint s[16];
|
||||
mh_item(cache, t, s);
|
||||
__global uint* d = ds + ((ulong)t * 16u);
|
||||
for (uint i = 0u; i < 16u; ++i) d[i] = s[i];
|
||||
}
|
||||
}
|
||||
|
||||
// One hash per work-item. IGNEUM_GROUP is a multiple of 32; lane = lid & 31 and every exchange stays inside the
|
||||
// lane's own aligned run of 32 work-items, exactly like simd_shuffle_xor inside a 32-wide Metal SIMD group and
|
||||
// __shfl_xor_sync inside a CUDA warp. Control flow is uniform (no branches at all).
|
||||
IGNEUM_KERNEL_HASH void igneum_hash(__global const uint* ds, __global ulong* out, uint baseNonce, uint mask) {
|
||||
uint gid = (uint)get_global_id(0);
|
||||
uint lid = (uint)get_local_id(0);
|
||||
uint nonce = baseNonce + gid;
|
||||
uint r0, r1, r2, r3, r4, r5, r6, r7;
|
||||
#if IGNEUM_EXCHANGE == 0
|
||||
IGNEUM_LOCAL_WORDS(xch, 2 * IGNEUM_GROUP);
|
||||
uint xk = 0u;
|
||||
#else
|
||||
(void)lid;
|
||||
#endif
|
||||
{ uint x = nonce ^ 0x3e345412u; x += 0x9e3779b9u; x = splitmix32(x); r0 = x ^ 0xfc2b3a0eu; } // SEEDW[0], 0x9e3779b9u * 1u, SEEDW[1]
|
||||
{ uint x = nonce ^ 0xfc2b3a0eu; x += 0x3c6ef372u; x = splitmix32(x); r1 = x ^ 0x7740353du; } // SEEDW[1], 0x9e3779b9u * 2u, SEEDW[2]
|
||||
{ uint x = nonce ^ 0x7740353du; x += 0xdaa66d2bu; x = splitmix32(x); r2 = x ^ 0x2df159dbu; } // SEEDW[2], 0x9e3779b9u * 3u, SEEDW[3]
|
||||
{ uint x = nonce ^ 0x2df159dbu; x += 0x78dde6e4u; x = splitmix32(x); r3 = x ^ 0x50bc6eedu; } // SEEDW[3], 0x9e3779b9u * 4u, SEEDW[4]
|
||||
{ uint x = nonce ^ 0x50bc6eedu; x += 0x1715609du; x = splitmix32(x); r4 = x ^ 0x2e61acb2u; } // SEEDW[4], 0x9e3779b9u * 5u, SEEDW[5]
|
||||
{ uint x = nonce ^ 0x2e61acb2u; x += 0xb54cda56u; x = splitmix32(x); r5 = x ^ 0x3c800bffu; } // SEEDW[5], 0x9e3779b9u * 6u, SEEDW[6]
|
||||
{ uint x = nonce ^ 0x3c800bffu; x += 0x5384540fu; x = splitmix32(x); r6 = x ^ 0xbaecd8c1u; } // SEEDW[6], 0x9e3779b9u * 7u, SEEDW[7]
|
||||
{ uint x = nonce ^ 0xbaecd8c1u; x += 0xf1bbcdc8u; x = splitmix32(x); r7 = x ^ 0x3e345412u; } // SEEDW[7], 0x9e3779b9u * 8u, SEEDW[0]
|
||||
|
||||
for (uint it = 0u; it < 8u; ++it) {
|
||||
uint sel = r0;
|
||||
r5 = r4 * r0 + r5; // 0 mad
|
||||
r1 = rotl_imm(r1, 23u); // 1 rotl
|
||||
{ uint b_ = (r5 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r0 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r0 = x_; } // 2 load
|
||||
r5 = r4 * r2 + r5; // 3 mad
|
||||
r1 = r1 * r6; // 4 mul
|
||||
r1 = r1 + r0 + ((((sel >> 6u) & 1u) != 0u) ? 0x9dd9fb05u : 0x9db46598u); // 5 add
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r7, 16u); r1 = r1 ^ t_; } // 6 shfl
|
||||
r6 = r6 * r1; // 7 mul
|
||||
r1 = mul_hi(r1, r7); // 8 mulhi
|
||||
r2 = mul_hi(r2, r1); // 9 mulhi
|
||||
r0 = r0 + r4 + ((((sel >> 13u) & 1u) != 0u) ? 0xc15822b6u : 0xe45fccebu); // 10 add
|
||||
r5 = r1 * r2 + r5; // 11 mad
|
||||
r4 = r4 * r7; // 12 mul
|
||||
{ uint b_ = (r5 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r0 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r0 = x_; } // 13 load
|
||||
r3 = r3 ^ r4; // 14 xor
|
||||
r1 = r1 ^ r6; // 15 xor
|
||||
r5 = rotr_var(r5, r6); // 16 rotr
|
||||
r3 = rotr_var(r3, r7); // 17 rotr
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r4, 16u); r1 = r1 ^ t_; } // 18 shfl
|
||||
r5 = r5 ^ ds[r6 & mask]; // 19 load
|
||||
r6 = rotl_imm(r6, 30u); // 20 rotl
|
||||
{ uint b_ = (r2 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r5 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r5 = x_; } // 21 load
|
||||
r3 = r3 ^ r5; // 22 xor
|
||||
r5 = r5 + r7 + ((((sel >> 6u) & 1u) != 0u) ? 0x950603c6u : 0x1d4f8db7u); // 23 add
|
||||
{ uint b_ = (r4 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r3 = x_; } // 24 load
|
||||
{ uint b_ = (r1 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r0 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r0 = x_; } // 25 load
|
||||
r2 = r2 + r3 + ((((sel >> 31u) & 1u) != 0u) ? 0x0ae476a4u : 0x55db0d92u); // 26 add
|
||||
r5 = r5 ^ ds[r6 & mask]; // 27 load
|
||||
{ uint b_ = (r5 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r2 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r2 = x_; } // 28 load
|
||||
r1 = r1 ^ r6; // 29 xor
|
||||
r7 = mul_hi(r7, r4); // 30 mulhi
|
||||
r6 = rotr_var(r6, r3); // 31 rotr
|
||||
r0 = r0 ^ ds[r3 & mask]; // 32 load
|
||||
r5 = rotr_var(r5, r0); // 33 rotr
|
||||
r5 = rotl_imm(r5, 20u); // 34 rotl
|
||||
r0 = mul_hi(r0, r4); // 35 mulhi
|
||||
r6 = r6 + r7 + ((((sel >> 18u) & 1u) != 0u) ? 0xfe7a0454u : 0x5d6e3dc5u); // 36 add
|
||||
{ uint b_ = (r1 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r2 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r2 = x_; } // 37 load
|
||||
r2 = rotl_imm(r2, 19u); // 38 rotl
|
||||
r3 = r3 + r6 + ((((sel >> 20u) & 1u) != 0u) ? 0xc1d4ae24u : 0xe7e241bau); // 39 add
|
||||
{ uint b_ = (r7 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r4 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r4 = x_; } // 40 load
|
||||
r3 = r3 + r1 + ((((sel >> 21u) & 1u) != 0u) ? 0x8f9f8556u : 0xb45cdd60u); // 41 add
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r2, 4u); r5 = r5 ^ t_; } // 42 shfl
|
||||
r0 = r0 * r1; // 43 mul
|
||||
r0 = rotr_var(r0, r7); // 44 rotr
|
||||
r5 = r5 - r3; // 45 sub
|
||||
r2 = r7 * r7 + r2; // 46 mad
|
||||
r6 = r3 * r1 + r6; // 47 mad
|
||||
r0 = r0 * r7; // 48 mul
|
||||
r0 = r0 + r4 + ((((sel >> 1u) & 1u) != 0u) ? 0xb9083b6cu : 0x3fa0c5cdu); // 49 add
|
||||
r4 = r4 + r6 + ((((sel >> 13u) & 1u) != 0u) ? 0x9eecc778u : 0x2d6873e8u); // 50 add
|
||||
r2 = r2 - r7; // 51 sub
|
||||
r6 = rotl_imm(r6, 6u); // 52 rotl
|
||||
r3 = rotr_var(r3, r5); // 53 rotr
|
||||
{ uint b_ = (r2 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r3 = x_; } // 54 load
|
||||
{ uint b_ = (r5 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r7 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r7 = x_; } // 55 load
|
||||
r2 = r2 | r6; // 56 or
|
||||
r4 = r4 ^ ds[r0 & mask]; // 57 load
|
||||
r3 = r3 ^ r6; // 58 xor
|
||||
r0 = r0 ^ ds[r6 & mask]; // 59 load
|
||||
r2 = r2 + r4 + ((((sel >> 3u) & 1u) != 0u) ? 0x19c76fb3u : 0x5052a1c3u); // 60 add
|
||||
r7 = r7 ^ ds[r4 & mask]; // 61 load
|
||||
r6 = r6 | r1; // 62 or
|
||||
r5 = r5 + r1 + ((((sel >> 4u) & 1u) != 0u) ? 0x535fe3fau : 0x08c757c0u); // 63 add
|
||||
}
|
||||
uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u);
|
||||
uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u);
|
||||
out[gid] = ((ulong)hi << 32) | (ulong)lo;
|
||||
}
|
||||
|
||||
#if IGNEUM_EXCHANGE != 0
|
||||
// Reports the sub-group size this device uses for a work-group of IGNEUM_GROUP items. host.c runs it only when the
|
||||
// per-kernel query (clGetKernelSubGroupInfoKHR on igneum_hash) is unavailable; that query is preferred because a
|
||||
// compiler may pick a different wave width per kernel (RDNA: wave32 or wave64). See WAVEFRONT.md.
|
||||
IGNEUM_KERNEL_HASH void igneum_probe_subgroup(__global uint* out) {
|
||||
if (get_local_id(0) == 0u) { out[0] = get_sub_group_size(); out[1] = get_num_sub_groups(); }
|
||||
}
|
||||
#endif
|
||||
|
||||
// Header-bound variant (bind.rs): the init words come from initw, not SEEDW. Same body as igneum_hash.
|
||||
IGNEUM_KERNEL_HASH void igneum_hash_bound(__global const uint* ds, __global ulong* out, uint baseNonce, uint mask, __global const uint* initw) {
|
||||
uint gid = (uint)get_global_id(0);
|
||||
uint lid = (uint)get_local_id(0);
|
||||
uint nonce = baseNonce + gid;
|
||||
uint r0, r1, r2, r3, r4, r5, r6, r7;
|
||||
uint iw0 = initw[0], iw1 = initw[1], iw2 = initw[2], iw3 = initw[3], iw4 = initw[4], iw5 = initw[5], iw6 = initw[6], iw7 = initw[7];
|
||||
#if IGNEUM_EXCHANGE == 0
|
||||
IGNEUM_LOCAL_WORDS(xch, 2 * IGNEUM_GROUP);
|
||||
uint xk = 0u;
|
||||
#else
|
||||
(void)lid;
|
||||
#endif
|
||||
{ uint x = nonce ^ iw0; x += 0x9e3779b9u * 1u; x = splitmix32(x); r0 = x ^ iw1; }
|
||||
{ uint x = nonce ^ iw1; x += 0x9e3779b9u * 2u; x = splitmix32(x); r1 = x ^ iw2; }
|
||||
{ uint x = nonce ^ iw2; x += 0x9e3779b9u * 3u; x = splitmix32(x); r2 = x ^ iw3; }
|
||||
{ uint x = nonce ^ iw3; x += 0x9e3779b9u * 4u; x = splitmix32(x); r3 = x ^ iw4; }
|
||||
{ uint x = nonce ^ iw4; x += 0x9e3779b9u * 5u; x = splitmix32(x); r4 = x ^ iw5; }
|
||||
{ uint x = nonce ^ iw5; x += 0x9e3779b9u * 6u; x = splitmix32(x); r5 = x ^ iw6; }
|
||||
{ uint x = nonce ^ iw6; x += 0x9e3779b9u * 7u; x = splitmix32(x); r6 = x ^ iw7; }
|
||||
{ uint x = nonce ^ iw7; x += 0x9e3779b9u * 8u; x = splitmix32(x); r7 = x ^ iw0; }
|
||||
|
||||
for (uint it = 0u; it < 8u; ++it) {
|
||||
uint sel = r0;
|
||||
r5 = r4 * r0 + r5; // 0 mad
|
||||
r1 = rotl_imm(r1, 23u); // 1 rotl
|
||||
{ uint b_ = (r5 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r0 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r0 = x_; } // 2 load
|
||||
r5 = r4 * r2 + r5; // 3 mad
|
||||
r1 = r1 * r6; // 4 mul
|
||||
r1 = r1 + r0 + ((((sel >> 6u) & 1u) != 0u) ? 0x9dd9fb05u : 0x9db46598u); // 5 add
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r7, 16u); r1 = r1 ^ t_; } // 6 shfl
|
||||
r6 = r6 * r1; // 7 mul
|
||||
r1 = mul_hi(r1, r7); // 8 mulhi
|
||||
r2 = mul_hi(r2, r1); // 9 mulhi
|
||||
r0 = r0 + r4 + ((((sel >> 13u) & 1u) != 0u) ? 0xc15822b6u : 0xe45fccebu); // 10 add
|
||||
r5 = r1 * r2 + r5; // 11 mad
|
||||
r4 = r4 * r7; // 12 mul
|
||||
{ uint b_ = (r5 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r0 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r0 = x_; } // 13 load
|
||||
r3 = r3 ^ r4; // 14 xor
|
||||
r1 = r1 ^ r6; // 15 xor
|
||||
r5 = rotr_var(r5, r6); // 16 rotr
|
||||
r3 = rotr_var(r3, r7); // 17 rotr
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r4, 16u); r1 = r1 ^ t_; } // 18 shfl
|
||||
r5 = r5 ^ ds[r6 & mask]; // 19 load
|
||||
r6 = rotl_imm(r6, 30u); // 20 rotl
|
||||
{ uint b_ = (r2 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r5 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r5 = x_; } // 21 load
|
||||
r3 = r3 ^ r5; // 22 xor
|
||||
r5 = r5 + r7 + ((((sel >> 6u) & 1u) != 0u) ? 0x950603c6u : 0x1d4f8db7u); // 23 add
|
||||
{ uint b_ = (r4 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r3 = x_; } // 24 load
|
||||
{ uint b_ = (r1 & mask) & ~15u; uint4 v0_ = vload4(0u, ds + b_); uint4 v1_ = vload4(1u, ds + b_); uint4 v2_ = vload4(2u, ds + b_); uint4 v3_ = vload4(3u, ds + b_); uint x_ = r0 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r0 = x_; } // 25 load
|
||||
r2 = r2 + r3 + ((((sel >> 31u) & 1u) != 0u) ? 0x0ae476a4u : 0x55db0d92u); // 26 add
|
||||
r5 = r5 ^ ds[r6 & mask]; // 27 load
|
||||
{ uint b_ = (r5 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r2 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r2 = x_; } // 28 load
|
||||
r1 = r1 ^ r6; // 29 xor
|
||||
r7 = mul_hi(r7, r4); // 30 mulhi
|
||||
r6 = rotr_var(r6, r3); // 31 rotr
|
||||
r0 = r0 ^ ds[r3 & mask]; // 32 load
|
||||
r5 = rotr_var(r5, r0); // 33 rotr
|
||||
r5 = rotl_imm(r5, 20u); // 34 rotl
|
||||
r0 = mul_hi(r0, r4); // 35 mulhi
|
||||
r6 = r6 + r7 + ((((sel >> 18u) & 1u) != 0u) ? 0xfe7a0454u : 0x5d6e3dc5u); // 36 add
|
||||
{ uint b_ = (r1 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r2 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r2 = x_; } // 37 load
|
||||
r2 = rotl_imm(r2, 19u); // 38 rotl
|
||||
r3 = r3 + r6 + ((((sel >> 20u) & 1u) != 0u) ? 0xc1d4ae24u : 0xe7e241bau); // 39 add
|
||||
{ uint b_ = (r7 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r4 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r4 = x_; } // 40 load
|
||||
r3 = r3 + r1 + ((((sel >> 21u) & 1u) != 0u) ? 0x8f9f8556u : 0xb45cdd60u); // 41 add
|
||||
{ uint t_; IGNEUM_SHFL_XOR(t_, r2, 4u); r5 = r5 ^ t_; } // 42 shfl
|
||||
r0 = r0 * r1; // 43 mul
|
||||
r0 = rotr_var(r0, r7); // 44 rotr
|
||||
r5 = r5 - r3; // 45 sub
|
||||
r2 = r7 * r7 + r2; // 46 mad
|
||||
r6 = r3 * r1 + r6; // 47 mad
|
||||
r0 = r0 * r7; // 48 mul
|
||||
r0 = r0 + r4 + ((((sel >> 1u) & 1u) != 0u) ? 0xb9083b6cu : 0x3fa0c5cdu); // 49 add
|
||||
r4 = r4 + r6 + ((((sel >> 13u) & 1u) != 0u) ? 0x9eecc778u : 0x2d6873e8u); // 50 add
|
||||
r2 = r2 - r7; // 51 sub
|
||||
r6 = rotl_imm(r6, 6u); // 52 rotl
|
||||
r3 = rotr_var(r3, r5); // 53 rotr
|
||||
{ uint b_ = (r2 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r3 = x_; } // 54 load
|
||||
{ uint b_ = (r5 & mask) & ~3u; uint4 v0_ = vload4(0u, ds + b_); uint x_ = r7 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r7 = x_; } // 55 load
|
||||
r2 = r2 | r6; // 56 or
|
||||
r4 = r4 ^ ds[r0 & mask]; // 57 load
|
||||
r3 = r3 ^ r6; // 58 xor
|
||||
r0 = r0 ^ ds[r6 & mask]; // 59 load
|
||||
r2 = r2 + r4 + ((((sel >> 3u) & 1u) != 0u) ? 0x19c76fb3u : 0x5052a1c3u); // 60 add
|
||||
r7 = r7 ^ ds[r4 & mask]; // 61 load
|
||||
r6 = r6 | r1; // 62 or
|
||||
r5 = r5 + r1 + ((((sel >> 4u) & 1u) != 0u) ? 0x535fe3fau : 0x08c757c0u); // 63 add
|
||||
}
|
||||
uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u);
|
||||
uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u);
|
||||
out[gid] = ((ulong)hi << 32) | (ulong)lo;
|
||||
}
|
||||
123
proto-cuda/packs-readwidth/mixB-1/kernel_bound.cu
Normal file
123
proto-cuda/packs-readwidth/mixB-1/kernel_bound.cu
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
// Generated by igneum-pow export (generator v2) for seed "igneum-readwidth/B/1". Do not edit by hand.
|
||||
// Header-bound twin of igneum_hash in kernel.cu: the init words come from a kernel argument, not SEEDW.
|
||||
// Host declarations (also in program_bound.h if present):
|
||||
// struct IgneumInitWords { uint32_t w[8]; };
|
||||
// cudaError_t igneum_launch_hash_bound(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask,
|
||||
// IgneumInitWords iw, uint32_t nonces, uint32_t blockWarps);
|
||||
// cudaError_t igneum_hash_bound_info(int* numRegs, int* blocksPerSM, uint32_t blockWarps);
|
||||
#include <cuda_runtime.h>
|
||||
#include <cstdint>
|
||||
#include "program.h"
|
||||
|
||||
struct IgneumInitWords { uint32_t w[8]; };
|
||||
|
||||
__device__ __forceinline__ uint32_t splitmix32(uint32_t x) {
|
||||
x ^= x >> 16; x *= 0x7feb352du;
|
||||
x ^= x >> 15; x *= 0x846ca68bu;
|
||||
x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
__device__ __forceinline__ uint32_t rotl_imm(uint32_t x, uint32_t n) { return (x << n) | (x >> (32u - n)); }
|
||||
__device__ __forceinline__ uint32_t rotr_var(uint32_t x, uint32_t n) { n &= 31u; return (x >> n) | (x << ((32u - n) & 31u)); }
|
||||
|
||||
__global__ void igneum_hash_bound(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask, IgneumInitWords iw) {
|
||||
uint32_t gid = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
uint32_t nonce = baseNonce + gid;
|
||||
uint32_t r0, r1, r2, r3, r4, r5, r6, r7;
|
||||
{ uint32_t x = nonce ^ iw.w[0]; x += 0x9e3779b9u * 1u; x = splitmix32(x); r0 = x ^ iw.w[1]; }
|
||||
{ uint32_t x = nonce ^ iw.w[1]; x += 0x9e3779b9u * 2u; x = splitmix32(x); r1 = x ^ iw.w[2]; }
|
||||
{ uint32_t x = nonce ^ iw.w[2]; x += 0x9e3779b9u * 3u; x = splitmix32(x); r2 = x ^ iw.w[3]; }
|
||||
{ uint32_t x = nonce ^ iw.w[3]; x += 0x9e3779b9u * 4u; x = splitmix32(x); r3 = x ^ iw.w[4]; }
|
||||
{ uint32_t x = nonce ^ iw.w[4]; x += 0x9e3779b9u * 5u; x = splitmix32(x); r4 = x ^ iw.w[5]; }
|
||||
{ uint32_t x = nonce ^ iw.w[5]; x += 0x9e3779b9u * 6u; x = splitmix32(x); r5 = x ^ iw.w[6]; }
|
||||
{ uint32_t x = nonce ^ iw.w[6]; x += 0x9e3779b9u * 7u; x = splitmix32(x); r6 = x ^ iw.w[7]; }
|
||||
{ uint32_t x = nonce ^ iw.w[7]; x += 0x9e3779b9u * 8u; x = splitmix32(x); r7 = x ^ iw.w[0]; }
|
||||
|
||||
for (uint32_t it = 0u; it < 8u; ++it) {
|
||||
uint32_t sel = r0;
|
||||
r5 = r4 * r0 + r5; // 0 mad
|
||||
r1 = rotl_imm(r1, 23u); // 1 rotl
|
||||
{ uint32_t b_ = (r5 & mask) & ~3u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint32_t x_ = r0 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r0 = x_; } // 2 load
|
||||
r5 = r4 * r2 + r5; // 3 mad
|
||||
r1 = r1 * r6; // 4 mul
|
||||
r1 = r1 + r0 + ((((sel >> 6u) & 1u) != 0u) ? 0x9dd9fb05u : 0x9db46598u); // 5 add
|
||||
r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r7, 16); // 6 shfl
|
||||
r6 = r6 * r1; // 7 mul
|
||||
r1 = __umulhi(r1, r7); // 8 mulhi
|
||||
r2 = __umulhi(r2, r1); // 9 mulhi
|
||||
r0 = r0 + r4 + ((((sel >> 13u) & 1u) != 0u) ? 0xc15822b6u : 0xe45fccebu); // 10 add
|
||||
r5 = r1 * r2 + r5; // 11 mad
|
||||
r4 = r4 * r7; // 12 mul
|
||||
{ uint32_t b_ = (r5 & mask) & ~15u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint32_t x_ = r0 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r0 = x_; } // 13 load
|
||||
r3 = r3 ^ r4; // 14 xor
|
||||
r1 = r1 ^ r6; // 15 xor
|
||||
r5 = rotr_var(r5, r6); // 16 rotr
|
||||
r3 = rotr_var(r3, r7); // 17 rotr
|
||||
r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r4, 16); // 18 shfl
|
||||
r5 = r5 ^ ds[r6 & mask]; // 19 load
|
||||
r6 = rotl_imm(r6, 30u); // 20 rotl
|
||||
{ uint32_t b_ = (r2 & mask) & ~3u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint32_t x_ = r5 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r5 = x_; } // 21 load
|
||||
r3 = r3 ^ r5; // 22 xor
|
||||
r5 = r5 + r7 + ((((sel >> 6u) & 1u) != 0u) ? 0x950603c6u : 0x1d4f8db7u); // 23 add
|
||||
{ uint32_t b_ = (r4 & mask) & ~3u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint32_t x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r3 = x_; } // 24 load
|
||||
{ uint32_t b_ = (r1 & mask) & ~15u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint32_t x_ = r0 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r0 = x_; } // 25 load
|
||||
r2 = r2 + r3 + ((((sel >> 31u) & 1u) != 0u) ? 0x0ae476a4u : 0x55db0d92u); // 26 add
|
||||
r5 = r5 ^ ds[r6 & mask]; // 27 load
|
||||
{ uint32_t b_ = (r5 & mask) & ~3u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint32_t x_ = r2 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r2 = x_; } // 28 load
|
||||
r1 = r1 ^ r6; // 29 xor
|
||||
r7 = __umulhi(r7, r4); // 30 mulhi
|
||||
r6 = rotr_var(r6, r3); // 31 rotr
|
||||
r0 = r0 ^ ds[r3 & mask]; // 32 load
|
||||
r5 = rotr_var(r5, r0); // 33 rotr
|
||||
r5 = rotl_imm(r5, 20u); // 34 rotl
|
||||
r0 = __umulhi(r0, r4); // 35 mulhi
|
||||
r6 = r6 + r7 + ((((sel >> 18u) & 1u) != 0u) ? 0xfe7a0454u : 0x5d6e3dc5u); // 36 add
|
||||
{ uint32_t b_ = (r1 & mask) & ~3u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint32_t x_ = r2 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r2 = x_; } // 37 load
|
||||
r2 = rotl_imm(r2, 19u); // 38 rotl
|
||||
r3 = r3 + r6 + ((((sel >> 20u) & 1u) != 0u) ? 0xc1d4ae24u : 0xe7e241bau); // 39 add
|
||||
{ uint32_t b_ = (r7 & mask) & ~3u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint32_t x_ = r4 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r4 = x_; } // 40 load
|
||||
r3 = r3 + r1 + ((((sel >> 21u) & 1u) != 0u) ? 0x8f9f8556u : 0xb45cdd60u); // 41 add
|
||||
r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r2, 4); // 42 shfl
|
||||
r0 = r0 * r1; // 43 mul
|
||||
r0 = rotr_var(r0, r7); // 44 rotr
|
||||
r5 = r5 - r3; // 45 sub
|
||||
r2 = r7 * r7 + r2; // 46 mad
|
||||
r6 = r3 * r1 + r6; // 47 mad
|
||||
r0 = r0 * r7; // 48 mul
|
||||
r0 = r0 + r4 + ((((sel >> 1u) & 1u) != 0u) ? 0xb9083b6cu : 0x3fa0c5cdu); // 49 add
|
||||
r4 = r4 + r6 + ((((sel >> 13u) & 1u) != 0u) ? 0x9eecc778u : 0x2d6873e8u); // 50 add
|
||||
r2 = r2 - r7; // 51 sub
|
||||
r6 = rotl_imm(r6, 6u); // 52 rotl
|
||||
r3 = rotr_var(r3, r5); // 53 rotr
|
||||
{ uint32_t b_ = (r2 & mask) & ~3u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint32_t x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r3 = x_; } // 54 load
|
||||
{ uint32_t b_ = (r5 & mask) & ~3u; const uint4* l_ = (const uint4*)(ds + b_); uint4 v0_ = l_[0]; uint32_t x_ = r7 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r7 = x_; } // 55 load
|
||||
r2 = r2 | r6; // 56 or
|
||||
r4 = r4 ^ ds[r0 & mask]; // 57 load
|
||||
r3 = r3 ^ r6; // 58 xor
|
||||
r0 = r0 ^ ds[r6 & mask]; // 59 load
|
||||
r2 = r2 + r4 + ((((sel >> 3u) & 1u) != 0u) ? 0x19c76fb3u : 0x5052a1c3u); // 60 add
|
||||
r7 = r7 ^ ds[r4 & mask]; // 61 load
|
||||
r6 = r6 | r1; // 62 or
|
||||
r5 = r5 + r1 + ((((sel >> 4u) & 1u) != 0u) ? 0x535fe3fau : 0x08c757c0u); // 63 add
|
||||
}
|
||||
uint32_t lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u);
|
||||
uint32_t hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u);
|
||||
out[gid] = ((uint64_t)hi << 32) | (uint64_t)lo;
|
||||
}
|
||||
|
||||
cudaError_t igneum_launch_hash_bound(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask,
|
||||
IgneumInitWords iw, uint32_t nonces, uint32_t blockWarps) {
|
||||
if (blockWarps == 0u || blockWarps > 32u) return cudaErrorInvalidValue;
|
||||
uint32_t block = 32u * blockWarps;
|
||||
if (nonces == 0u || (nonces % block) != 0u) return cudaErrorInvalidValue;
|
||||
igneum_hash_bound<<<nonces / block, block>>>(ds, out, baseNonce, mask, iw);
|
||||
return cudaGetLastError();
|
||||
}
|
||||
|
||||
cudaError_t igneum_hash_bound_info(int* numRegs, int* blocksPerSM, uint32_t blockWarps) {
|
||||
cudaFuncAttributes attr;
|
||||
cudaError_t e = cudaFuncGetAttributes(&attr, igneum_hash_bound);
|
||||
if (e != cudaSuccess) return e;
|
||||
*numRegs = attr.numRegs;
|
||||
return cudaOccupancyMaxActiveBlocksPerMultiprocessor(blocksPerSM, igneum_hash_bound, (int)(32u * blockWarps), 0);
|
||||
}
|
||||
108
proto-cuda/packs-readwidth/mixB-1/memhard.h
Normal file
108
proto-cuda/packs-readwidth/mixB-1/memhard.h
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
// Generated by igneum-pow export (generator v2) for seed "igneum-readwidth/B/1". Do not edit by hand.
|
||||
// Memory-hard dataset core, the same text that the Mac's Metal kernels and CPU verifier were checked against.
|
||||
// Included by kernel.cu (device), host.cu (host reference) and proto-opencl/host.c (C99 host reference).
|
||||
// See proto-metal/MEMHARD.md for the construction. kernel.cl carries the same text in OpenCL C.
|
||||
#pragma once
|
||||
#ifdef __cplusplus
|
||||
#include <cstdint>
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
#if defined(__CUDACC__)
|
||||
#define IGNEUM_HD __host__ __device__ __forceinline__
|
||||
#elif defined(_MSC_VER) && !defined(__cplusplus)
|
||||
#define IGNEUM_HD static __inline
|
||||
#else
|
||||
#define IGNEUM_HD static inline
|
||||
#endif
|
||||
// Memory-hard dataset core (MEMHARD.md). Cache: 2^26 words in 2^16 segments of 64 chained ChaCha12 lines.
|
||||
// Item: 8 rounds of seed-parameterised mixer + one 64-byte cache read, then a final mixer. All parameters are literals.
|
||||
#define MH_CACHE_LINE_MASK 0x003fffffu
|
||||
#define MH_SEGMENT_LINES 64u
|
||||
#define MH_QR(a, b, c, d, r1, r2, r3, r4) { a += b; d ^= a; d = mh_rotl(d, r1); c += d; b ^= c; b = mh_rotl(b, r2); a += b; d ^= a; d = mh_rotl(d, r3); c += d; b ^= c; b = mh_rotl(b, r4); }
|
||||
IGNEUM_HD uint32_t mh_rotl(uint32_t x, uint32_t n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 at every call site
|
||||
|
||||
// y = ChaCha12 core(x) + x
|
||||
IGNEUM_HD void mh_chacha_block(const uint32_t* x, uint32_t* y) {
|
||||
for (uint32_t i = 0u; i < 16u; ++i) y[i] = x[i];
|
||||
for (uint32_t r = 0u; r < 6u; ++r) {
|
||||
MH_QR(y[0], y[4], y[8], y[12], 16u, 12u, 8u, 7u) MH_QR(y[1], y[5], y[9], y[13], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[2], y[6], y[10], y[14], 16u, 12u, 8u, 7u) MH_QR(y[3], y[7], y[11], y[15], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[0], y[5], y[10], y[15], 16u, 12u, 8u, 7u) MH_QR(y[1], y[6], y[11], y[12], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[2], y[7], y[8], y[13], 16u, 12u, 8u, 7u) MH_QR(y[3], y[4], y[9], y[14], 16u, 12u, 8u, 7u)
|
||||
}
|
||||
for (uint32_t i = 0u; i < 16u; ++i) y[i] += x[i];
|
||||
}
|
||||
|
||||
// One cache segment: 64 chained lines written at cache[seg * 1024]. in_j = prev ^ (sigma || K || seg || j || tag), prev_0 = 0.
|
||||
IGNEUM_HD void mh_cache_segment(uint32_t* cache, uint32_t seg) {
|
||||
uint32_t prev[16]; uint32_t x[16]; uint32_t y[16];
|
||||
for (uint32_t i = 0u; i < 16u; ++i) prev[i] = 0u;
|
||||
for (uint32_t j = 0u; j < MH_SEGMENT_LINES; ++j) {
|
||||
x[0] = 0x61707865u ^ prev[0]; x[1] = 0x3320646eu ^ prev[1]; x[2] = 0x79622d32u ^ prev[2]; x[3] = 0x6b206574u ^ prev[3];
|
||||
x[4] = 0x3067619fu ^ prev[4];
|
||||
x[5] = 0x3c269176u ^ prev[5];
|
||||
x[6] = 0x84a03b03u ^ prev[6];
|
||||
x[7] = 0xf8c63294u ^ prev[7];
|
||||
x[8] = 0xff977c5bu ^ prev[8];
|
||||
x[9] = 0xe60def3eu ^ prev[9];
|
||||
x[10] = 0x63630141u ^ prev[10];
|
||||
x[11] = 0xb8fbcb58u ^ prev[11];
|
||||
x[12] = seg ^ prev[12]; x[13] = j ^ prev[13]; x[14] = 0x49676e65u ^ prev[14]; x[15] = 0x756d4d48u ^ prev[15];
|
||||
mh_chacha_block(x, y);
|
||||
uint32_t* line = cache + ((seg * MH_SEGMENT_LINES + j) * 16u);
|
||||
for (uint32_t i = 0u; i < 16u; ++i) { line[i] = y[i]; prev[i] = y[i]; }
|
||||
}
|
||||
}
|
||||
|
||||
// M_r: per word (s ^ (RC + rk)) * MUL, then a column round and a diagonal round with the seed-drawn rotations.
|
||||
IGNEUM_HD void mh_mixer(uint32_t* s, uint32_t rk) {
|
||||
s[0] = (s[0] ^ (0xbab68293u + rk)) * 0x42146205u;
|
||||
s[1] = (s[1] ^ (0xcc162340u + rk)) * 0x52cbe0fbu;
|
||||
s[2] = (s[2] ^ (0x6ce151ccu + rk)) * 0x7ecf4a03u;
|
||||
s[3] = (s[3] ^ (0xe62b8997u + rk)) * 0x6728907fu;
|
||||
s[4] = (s[4] ^ (0xc9c80297u + rk)) * 0xd81d9751u;
|
||||
s[5] = (s[5] ^ (0xf74a1654u + rk)) * 0x132952c3u;
|
||||
s[6] = (s[6] ^ (0x3d704af5u + rk)) * 0xf60de277u;
|
||||
s[7] = (s[7] ^ (0x3cf522b7u + rk)) * 0x05358035u;
|
||||
s[8] = (s[8] ^ (0x2b9cac04u + rk)) * 0xbaf6499du;
|
||||
s[9] = (s[9] ^ (0xa880ac10u + rk)) * 0xe4db9667u;
|
||||
s[10] = (s[10] ^ (0x13e5dd1du + rk)) * 0x3e98f45du;
|
||||
s[11] = (s[11] ^ (0x6fc3e233u + rk)) * 0xd0004eddu;
|
||||
s[12] = (s[12] ^ (0x2d83eeacu + rk)) * 0x2691630du;
|
||||
s[13] = (s[13] ^ (0x9006e8bfu + rk)) * 0x9beb3bcfu;
|
||||
s[14] = (s[14] ^ (0x2c4b5362u + rk)) * 0xab310379u;
|
||||
s[15] = (s[15] ^ (0x31b49ee2u + rk)) * 0x99cfb423u;
|
||||
MH_QR(s[0], s[4], s[8], s[12], 20u, 20u, 19u, 4u) MH_QR(s[1], s[5], s[9], s[13], 20u, 20u, 19u, 4u)
|
||||
MH_QR(s[2], s[6], s[10], s[14], 20u, 20u, 19u, 4u) MH_QR(s[3], s[7], s[11], s[15], 20u, 20u, 19u, 4u)
|
||||
MH_QR(s[0], s[5], s[10], s[15], 26u, 3u, 3u, 27u) MH_QR(s[1], s[6], s[11], s[12], 26u, 3u, 3u, 27u)
|
||||
MH_QR(s[2], s[7], s[8], s[13], 26u, 3u, 3u, 27u) MH_QR(s[3], s[4], s[9], s[14], 26u, 3u, 3u, 27u)
|
||||
}
|
||||
|
||||
// Item t: 16 words. s = (K, t * MUL[i] + RC[i]); 8 rounds of mixer + cache line s[0] & mask; final mixer.
|
||||
IGNEUM_HD void mh_item(const uint32_t* cache, uint32_t t, uint32_t* s) {
|
||||
s[0] = 0x3067619fu;
|
||||
s[1] = 0x3c269176u;
|
||||
s[2] = 0x84a03b03u;
|
||||
s[3] = 0xf8c63294u;
|
||||
s[4] = 0xff977c5bu;
|
||||
s[5] = 0xe60def3eu;
|
||||
s[6] = 0x63630141u;
|
||||
s[7] = 0xb8fbcb58u;
|
||||
s[8] = t * 0x42146205u + 0xbab68293u;
|
||||
s[9] = t * 0x52cbe0fbu + 0xcc162340u;
|
||||
s[10] = t * 0x7ecf4a03u + 0x6ce151ccu;
|
||||
s[11] = t * 0x6728907fu + 0xe62b8997u;
|
||||
s[12] = t * 0xd81d9751u + 0xc9c80297u;
|
||||
s[13] = t * 0x132952c3u + 0xf74a1654u;
|
||||
s[14] = t * 0xf60de277u + 0x3d704af5u;
|
||||
s[15] = t * 0x05358035u + 0x3cf522b7u;
|
||||
for (uint32_t r = 0u; r < 8u; ++r) {
|
||||
mh_mixer(s, 0x9E3779B9u * (r + 1u));
|
||||
const uint32_t* line = cache + ((s[0] & MH_CACHE_LINE_MASK) * 16u);
|
||||
for (uint32_t i = 0u; i < 16u; ++i) s[i] ^= line[i];
|
||||
}
|
||||
mh_mixer(s, 0x9E3779B9u * 9u);
|
||||
}
|
||||
// dataset[w] without the dataset: derive item w >> 4 and take word w & 15.
|
||||
IGNEUM_HD uint32_t mh_word(const uint32_t* cache, uint32_t w) { uint32_t s[16]; mh_item(cache, w >> 4u, s); return s[w & 15u]; }
|
||||
106
proto-cuda/packs-readwidth/mixB-1/memhard.metal
Normal file
106
proto-cuda/packs-readwidth/mixB-1/memhard.metal
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
#include <metal_stdlib>
|
||||
using namespace metal;
|
||||
// Memory-hard dataset core (MEMHARD.md). Cache: 2^26 words in 2^16 segments of 64 chained ChaCha12 lines.
|
||||
// Item: 8 rounds of seed-parameterised mixer + one 64-byte cache read, then a final mixer. All parameters are literals.
|
||||
#define MH_CACHE_LINE_MASK 0x003fffffu
|
||||
#define MH_SEGMENT_LINES 64u
|
||||
#define MH_QR(a, b, c, d, r1, r2, r3, r4) { a += b; d ^= a; d = mh_rotl(d, r1); c += d; b ^= c; b = mh_rotl(b, r2); a += b; d ^= a; d = mh_rotl(d, r3); c += d; b ^= c; b = mh_rotl(b, r4); }
|
||||
inline uint mh_rotl(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 at every call site
|
||||
|
||||
// y = ChaCha12 core(x) + x
|
||||
inline void mh_chacha_block(const thread uint* x, thread uint* y) {
|
||||
for (uint i = 0u; i < 16u; ++i) y[i] = x[i];
|
||||
for (uint r = 0u; r < 6u; ++r) {
|
||||
MH_QR(y[0], y[4], y[8], y[12], 16u, 12u, 8u, 7u) MH_QR(y[1], y[5], y[9], y[13], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[2], y[6], y[10], y[14], 16u, 12u, 8u, 7u) MH_QR(y[3], y[7], y[11], y[15], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[0], y[5], y[10], y[15], 16u, 12u, 8u, 7u) MH_QR(y[1], y[6], y[11], y[12], 16u, 12u, 8u, 7u)
|
||||
MH_QR(y[2], y[7], y[8], y[13], 16u, 12u, 8u, 7u) MH_QR(y[3], y[4], y[9], y[14], 16u, 12u, 8u, 7u)
|
||||
}
|
||||
for (uint i = 0u; i < 16u; ++i) y[i] += x[i];
|
||||
}
|
||||
|
||||
// One cache segment: 64 chained lines written at cache[seg * 1024]. in_j = prev ^ (sigma || K || seg || j || tag), prev_0 = 0.
|
||||
inline void mh_cache_segment(device uint* cache, uint seg) {
|
||||
uint prev[16]; uint x[16]; uint y[16];
|
||||
for (uint i = 0u; i < 16u; ++i) prev[i] = 0u;
|
||||
for (uint j = 0u; j < MH_SEGMENT_LINES; ++j) {
|
||||
x[0] = 0x61707865u ^ prev[0]; x[1] = 0x3320646eu ^ prev[1]; x[2] = 0x79622d32u ^ prev[2]; x[3] = 0x6b206574u ^ prev[3];
|
||||
x[4] = 0x3067619fu ^ prev[4];
|
||||
x[5] = 0x3c269176u ^ prev[5];
|
||||
x[6] = 0x84a03b03u ^ prev[6];
|
||||
x[7] = 0xf8c63294u ^ prev[7];
|
||||
x[8] = 0xff977c5bu ^ prev[8];
|
||||
x[9] = 0xe60def3eu ^ prev[9];
|
||||
x[10] = 0x63630141u ^ prev[10];
|
||||
x[11] = 0xb8fbcb58u ^ prev[11];
|
||||
x[12] = seg ^ prev[12]; x[13] = j ^ prev[13]; x[14] = 0x49676e65u ^ prev[14]; x[15] = 0x756d4d48u ^ prev[15];
|
||||
mh_chacha_block(x, y);
|
||||
device uint* line = cache + ((seg * MH_SEGMENT_LINES + j) * 16u);
|
||||
for (uint i = 0u; i < 16u; ++i) { line[i] = y[i]; prev[i] = y[i]; }
|
||||
}
|
||||
}
|
||||
|
||||
// M_r: per word (s ^ (RC + rk)) * MUL, then a column round and a diagonal round with the seed-drawn rotations.
|
||||
inline void mh_mixer(thread uint* s, uint rk) {
|
||||
s[0] = (s[0] ^ (0xbab68293u + rk)) * 0x42146205u;
|
||||
s[1] = (s[1] ^ (0xcc162340u + rk)) * 0x52cbe0fbu;
|
||||
s[2] = (s[2] ^ (0x6ce151ccu + rk)) * 0x7ecf4a03u;
|
||||
s[3] = (s[3] ^ (0xe62b8997u + rk)) * 0x6728907fu;
|
||||
s[4] = (s[4] ^ (0xc9c80297u + rk)) * 0xd81d9751u;
|
||||
s[5] = (s[5] ^ (0xf74a1654u + rk)) * 0x132952c3u;
|
||||
s[6] = (s[6] ^ (0x3d704af5u + rk)) * 0xf60de277u;
|
||||
s[7] = (s[7] ^ (0x3cf522b7u + rk)) * 0x05358035u;
|
||||
s[8] = (s[8] ^ (0x2b9cac04u + rk)) * 0xbaf6499du;
|
||||
s[9] = (s[9] ^ (0xa880ac10u + rk)) * 0xe4db9667u;
|
||||
s[10] = (s[10] ^ (0x13e5dd1du + rk)) * 0x3e98f45du;
|
||||
s[11] = (s[11] ^ (0x6fc3e233u + rk)) * 0xd0004eddu;
|
||||
s[12] = (s[12] ^ (0x2d83eeacu + rk)) * 0x2691630du;
|
||||
s[13] = (s[13] ^ (0x9006e8bfu + rk)) * 0x9beb3bcfu;
|
||||
s[14] = (s[14] ^ (0x2c4b5362u + rk)) * 0xab310379u;
|
||||
s[15] = (s[15] ^ (0x31b49ee2u + rk)) * 0x99cfb423u;
|
||||
MH_QR(s[0], s[4], s[8], s[12], 20u, 20u, 19u, 4u) MH_QR(s[1], s[5], s[9], s[13], 20u, 20u, 19u, 4u)
|
||||
MH_QR(s[2], s[6], s[10], s[14], 20u, 20u, 19u, 4u) MH_QR(s[3], s[7], s[11], s[15], 20u, 20u, 19u, 4u)
|
||||
MH_QR(s[0], s[5], s[10], s[15], 26u, 3u, 3u, 27u) MH_QR(s[1], s[6], s[11], s[12], 26u, 3u, 3u, 27u)
|
||||
MH_QR(s[2], s[7], s[8], s[13], 26u, 3u, 3u, 27u) MH_QR(s[3], s[4], s[9], s[14], 26u, 3u, 3u, 27u)
|
||||
}
|
||||
|
||||
// Item t: 16 words. s = (K, t * MUL[i] + RC[i]); 8 rounds of mixer + cache line s[0] & mask; final mixer.
|
||||
inline void mh_item(device const uint* cache, uint t, thread uint* s) {
|
||||
s[0] = 0x3067619fu;
|
||||
s[1] = 0x3c269176u;
|
||||
s[2] = 0x84a03b03u;
|
||||
s[3] = 0xf8c63294u;
|
||||
s[4] = 0xff977c5bu;
|
||||
s[5] = 0xe60def3eu;
|
||||
s[6] = 0x63630141u;
|
||||
s[7] = 0xb8fbcb58u;
|
||||
s[8] = t * 0x42146205u + 0xbab68293u;
|
||||
s[9] = t * 0x52cbe0fbu + 0xcc162340u;
|
||||
s[10] = t * 0x7ecf4a03u + 0x6ce151ccu;
|
||||
s[11] = t * 0x6728907fu + 0xe62b8997u;
|
||||
s[12] = t * 0xd81d9751u + 0xc9c80297u;
|
||||
s[13] = t * 0x132952c3u + 0xf74a1654u;
|
||||
s[14] = t * 0xf60de277u + 0x3d704af5u;
|
||||
s[15] = t * 0x05358035u + 0x3cf522b7u;
|
||||
for (uint r = 0u; r < 8u; ++r) {
|
||||
mh_mixer(s, 0x9E3779B9u * (r + 1u));
|
||||
device const uint* line = cache + ((s[0] & MH_CACHE_LINE_MASK) * 16u);
|
||||
for (uint i = 0u; i < 16u; ++i) s[i] ^= line[i];
|
||||
}
|
||||
mh_mixer(s, 0x9E3779B9u * 9u);
|
||||
}
|
||||
// dataset[w] without the dataset: derive item w >> 4 and take word w & 15.
|
||||
inline uint mh_word(device const uint* cache, uint w) { uint s[16]; mh_item(cache, w >> 4u, s); return s[w & 15u]; }
|
||||
|
||||
// One thread per segment (2^16 threads).
|
||||
kernel void igneum_cache_fill(device uint* cache [[buffer(0)]], uint gid [[thread_position_in_grid]]) {
|
||||
mh_cache_segment(cache, gid);
|
||||
}
|
||||
// One thread per 64-byte item (dataset words / 16 threads).
|
||||
kernel void igneum_build(device const uint* cache [[buffer(0)]], device uint* dataset [[buffer(1)]],
|
||||
uint gid [[thread_position_in_grid]]) {
|
||||
uint s[16];
|
||||
mh_item(cache, gid, s);
|
||||
device uint* d = dataset + gid * 16u;
|
||||
for (uint i = 0u; i < 16u; ++i) d[i] = s[i];
|
||||
}
|
||||
60
proto-cuda/packs-readwidth/mixB-1/program.h
Normal file
60
proto-cuda/packs-readwidth/mixB-1/program.h
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
// Generated by igneum-pow export (generator v2) for seed "igneum-readwidth/B/1". Do not edit by hand.
|
||||
// Program metadata for host.cu plus the launch wrappers defined in kernel.cu.
|
||||
// Also included by proto-opencl/host.c (C99), which defines IGNEUM_NO_CUDA first and reads only the macros.
|
||||
#pragma once
|
||||
#ifdef __cplusplus
|
||||
#include <cstdint>
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
#ifndef IGNEUM_NO_CUDA
|
||||
#include <cuda_runtime.h>
|
||||
#endif
|
||||
|
||||
#define IGNEUM_SEED_STRING "igneum-readwidth/B/1"
|
||||
#define IGNEUM_SEED_BYTES_HEX "69676e65756d2d7265616477696474682f422f31"
|
||||
#define IGNEUM_GENERATOR 2
|
||||
#define IGNEUM_PROGRAM_ATTEMPT 0
|
||||
#define IGNEUM_PROGRAM_ID 0x695b119dcb76931bull
|
||||
#define IGNEUM_DAY_STRING "2026-10-03"
|
||||
#define IGNEUM_DAY_BYTES_HEX "6461792f323032362d31302d3033"
|
||||
#define IGNEUM_DAY0 0x3067619fu
|
||||
#define IGNEUM_DAY1 0x3c269176u
|
||||
#define IGNEUM_DATASET_LOG2 28
|
||||
#define IGNEUM_MASK 0x0fffffffu
|
||||
#define IGNEUM_LANES 32
|
||||
#define IGNEUM_ITERATIONS 8
|
||||
#define IGNEUM_INSTR_COUNT 64
|
||||
#define IGNEUM_LOADS_PER_HASH 128
|
||||
#define IGNEUM_WIDE_LOADS_PER_HASH 0
|
||||
#define IGNEUM_OP_MIX "load=16 add=11 rotr=6 mad=5 mul=5 rotl=5 xor=5 mulhi=4 shfl=3 or=2 sub=2"
|
||||
// Read-width experiment (5 October 2026, docs/plans/read-width.md): NOT the lottery hash. A load of W words reads
|
||||
// the W-word-aligned address and folds every word into dst: x = dst ^ w[0]; x = (rotl(x, 11) * 0x9e3779b1) ^ w[j]; dst = x.
|
||||
#define IGNEUM_LOAD_CLASS "mix25-50-25"
|
||||
#define IGNEUM_LOAD_SLOTS 16
|
||||
#define IGNEUM_LOAD_MIX { 25, 50, 25 }
|
||||
#define IGNEUM_LOAD_WIDTH_COUNTS { 6, 8, 2 } // loads of 4, 16, 64 bytes per program
|
||||
#define IGNEUM_BYTES_PER_HASH 2240
|
||||
#define IGNEUM_FOLD_ROT 11
|
||||
#define IGNEUM_FOLD_MUL 0x9e3779b1u
|
||||
// 0 = closed-form dataset (ds_elem), 1 = memory-hard cache construction (MEMHARD.md, memhard.h)
|
||||
#define IGNEUM_DATASET_MODE 1
|
||||
|
||||
#define IGNEUM_SEEDW_INIT { 0x3e345412u, 0xfc2b3a0eu, 0x7740353du, 0x2df159dbu, 0x50bc6eedu, 0x2e61acb2u, 0x3c800bffu, 0xbaecd8c1u }
|
||||
#define IGNEUM_KEY_INIT { 0x3067619fu, 0x3c269176u, 0x84a03b03u, 0xf8c63294u, 0xff977c5bu, 0xe60def3eu, 0x63630141u, 0xb8fbcb58u }
|
||||
#define IGNEUM_CACHE_LOG2_WORDS 26
|
||||
#define IGNEUM_CACHE_SEGMENT_LOG2_LINES 6
|
||||
#define IGNEUM_CACHE_SEGMENTS 65536u
|
||||
#define IGNEUM_ITEM_ROUNDS 8
|
||||
#define IGNEUM_MIX_ROT_INIT { 20u, 20u, 19u, 4u, 26u, 3u, 3u, 27u }
|
||||
#define IGNEUM_MIX_MUL_INIT { 0x42146205u, 0x52cbe0fbu, 0x7ecf4a03u, 0x6728907fu, 0xd81d9751u, 0x132952c3u, 0xf60de277u, 0x05358035u, 0xbaf6499du, 0xe4db9667u, 0x3e98f45du, 0xd0004eddu, 0x2691630du, 0x9beb3bcfu, 0xab310379u, 0x99cfb423u }
|
||||
#define IGNEUM_MIX_RC_INIT { 0xbab68293u, 0xcc162340u, 0x6ce151ccu, 0xe62b8997u, 0xc9c80297u, 0xf74a1654u, 0x3d704af5u, 0x3cf522b7u, 0x2b9cac04u, 0xa880ac10u, 0x13e5dd1du, 0x6fc3e233u, 0x2d83eeacu, 0x9006e8bfu, 0x2c4b5362u, 0x31b49ee2u }
|
||||
|
||||
#ifndef IGNEUM_NO_CUDA
|
||||
// Defined in kernel.cu. All launch on the default stream and return cudaGetLastError().
|
||||
cudaError_t igneum_launch_cache_fill(uint32_t* cache, uint32_t nSegments);
|
||||
cudaError_t igneum_launch_build(uint32_t* ds, const uint32_t* cache, uint32_t nItems);
|
||||
cudaError_t igneum_launch_hash(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask,
|
||||
uint32_t nonces, uint32_t blockWarps);
|
||||
cudaError_t igneum_hash_info(int* numRegs, int* blocksPerSM, uint32_t blockWarps);
|
||||
#endif
|
||||
127
proto-cuda/packs-readwidth/mixB-1/program.json
Normal file
127
proto-cuda/packs-readwidth/mixB-1/program.json
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
{
|
||||
"format": "igneum-program-pack-3",
|
||||
"generator": 2,
|
||||
"attempt": 0,
|
||||
"program_id": "0x695b119dcb76931b",
|
||||
"program_id_derivation": "FNV-1a 64 over 'igneum-program/' || generator_le32 || seed_words as little-endian bytes || attempt_le32",
|
||||
"dataset_mode": "memory-hard",
|
||||
"seed": "igneum-readwidth/B/1",
|
||||
"seed_bytes": "69676e65756d2d7265616477696474682f422f31",
|
||||
"seed_words": ["0x3e345412", "0xfc2b3a0e", "0x7740353d", "0x2df159db", "0x50bc6eed", "0x2e61acb2", "0x3c800bff", "0xbaecd8c1"],
|
||||
"seed_derivation": "seed_words = FNV-1a 64 over seed_bytes (attempt 0) or seed_bytes || attempt_le32 (attempt k >= 1), basis ^ (salt * 0x9E3779B97F4A7C15) for salt 0..3, then h ^= h>>33; h *= 0xff51afd7ed558ccd; h ^= h>>33; words[2*salt] = low 32, words[2*salt+1] = high 32",
|
||||
"generator_rule": "version 2: exactly 16 load slots drawn first from instructions 1..63 (partial Fisher-Yates), the other 48 ops from the ten non-load weights (sum 75); a load's source is drawn from the registers other than dst written by an earlier instruction and not read by a load since; the candidate must pass the acceptance rule of spec 01 section 1.4.6 (static: no cyclically stale load source, every register has an injecting write; dynamic: 64 units on the seed-keyed closed-form dataset with no constant register bit, no lane-constant load site, under 164 saturated final values, every output bit within 136 of 1024, distinct addresses above 245760), else the next attempt of the seed is tried",
|
||||
"lanes": 32,
|
||||
"registers": 8,
|
||||
"iterations": 8,
|
||||
"instruction_count": 64,
|
||||
"loads_per_hash": 128,
|
||||
"load_class": "mix25-50-25",
|
||||
"load_slots": 16,
|
||||
"load_mix_percent_4_16_64": [25, 50, 25],
|
||||
"load_width_counts_4_16_64": [6, 8, 2],
|
||||
"bytes_per_hash": 2240,
|
||||
"wide_load": "read-width experiment (5 October 2026, docs/plans/read-width.md), NOT the lottery hash: a load of W words (width field, 4 or 16) reads dataset[b .. b + W) with b = (src & mask) & ~(W - 1) and folds every word into dst: x = dst ^ w[0]; for j in 1..W: x = (rotl(x, 11) * 0x9e3779b1) ^ w[j]; dst = x; width 1 is the plain load; the width is drawn per instruction from the class mix with one extra below(100) draw after the nine of version 2, and the program id is FNV-1a 64 over 'igneum-program-rw/' || generator_le32 || seed words || attempt_le32 || mix[3] || load_slots",
|
||||
"op_mix": {"load": 16, "add": 11, "rotr": 6, "mad": 5, "mul": 5, "rotl": 5, "xor": 5, "mulhi": 4, "shfl": 3, "or": 2, "sub": 2},
|
||||
"register_init": "for i in 0..7: x = nonce ^ seed_words[i]; x += 0x9e3779b9 * (i+1) (mod 2^32); x = splitmix32(x); r[i] = x ^ seed_words[(i+1) & 7]",
|
||||
"splitmix32": "x ^= x>>16; x *= 0x7feb352d; x ^= x>>15; x *= 0x846ca68b; x ^= x>>16",
|
||||
"iteration": "sel = r0 sampled once at the top of each iteration, then all instructions in order",
|
||||
"output": "lo = r0 ^ rotl(r1,7) ^ rotl(r2,14) ^ rotl(r3,21); hi = r4 ^ rotl(r5,9) ^ rotl(r6,18) ^ rotl(r7,27); out = (hi << 32) | lo",
|
||||
"op_semantics": {
|
||||
"add": "dst = dst + src + (bit `bit` of sel ? imm2 : imm)",
|
||||
"sub": "dst = dst - src",
|
||||
"mul": "dst = dst * src (low 32)",
|
||||
"mulhi": "dst = high 32 bits of dst * src",
|
||||
"xor": "dst = dst ^ src",
|
||||
"or": "dst = dst | src",
|
||||
"rotl": "dst = rotl(dst, rot), rot in 1..31",
|
||||
"rotr": "dst = rotr(dst, src & 31)",
|
||||
"mad": "dst = src * src2 + dst",
|
||||
"shfl": "dst = dst ^ (src of lane (lane ^ mask)), mask in {1,2,4,8,16}, within the 32-lane warp",
|
||||
"load": "dst = dst ^ dataset[src & dataset.mask]",
|
||||
"wload": "base = (src of lane 0 & dataset.mask) & ~31; dst = dst ^ dataset[base + lane] (warp-coalesced 128-byte load, lever b, only when --wide-frac > 0)"
|
||||
},
|
||||
"dataset": {
|
||||
"log2_words": 28,
|
||||
"bytes": 1073741824,
|
||||
"mask": "0x0fffffff",
|
||||
"day": "2026-10-03",
|
||||
"day_bytes": "6461792f323032362d31302d3033",
|
||||
"day_words_from": "seed_words_from_bytes(day_bytes)",
|
||||
"d0": "0x3067619f",
|
||||
"d1": "0x3c269176",
|
||||
"mode": "memory-hard",
|
||||
"spec": "proto-metal/MEMHARD.md",
|
||||
"key": ["0x3067619f", "0x3c269176", "0x84a03b03", "0xf8c63294", "0xff977c5b", "0xe60def3e", "0x63630141", "0xb8fbcb58"],
|
||||
"key_derivation": "the 8 words of seed_words_from_bytes(day_bytes); d0, d1 are key[0], key[1]",
|
||||
"cache": {"log2_words": 26, "bytes": 268435456, "line_words": 16, "segment_lines": 64, "segments": 65536, "block": "ChaCha12 core + feed-forward, rotations 16 12 8 7", "sigma": ["0x61707865", "0x3320646e", "0x79622d32", "0x6b206574"], "tag": ["0x49676e65", "0x756d4d48"], "chain": "in_j = prev_line ^ (sigma[0..3] || key[0..7] || seg || j || tag[0..1]); line_j = block(in_j); prev_0 = 0"},
|
||||
"mixer": {"draw": "SplitMix64 seeded with key[0] | key[1] << 32: rot[0..7] = 1 + next() % 31, mul[0..15] = low32(next()) | 1, rc[0..15] = low32(next())", "rot": [20, 20, 19, 4, 26, 3, 3, 27], "mul": ["0x42146205", "0x52cbe0fb", "0x7ecf4a03", "0x6728907f", "0xd81d9751", "0x132952c3", "0xf60de277", "0x05358035", "0xbaf6499d", "0xe4db9667", "0x3e98f45d", "0xd0004edd", "0x2691630d", "0x9beb3bcf", "0xab310379", "0x99cfb423"], "rc": ["0xbab68293", "0xcc162340", "0x6ce151cc", "0xe62b8997", "0xc9c80297", "0xf74a1654", "0x3d704af5", "0x3cf522b7", "0x2b9cac04", "0xa880ac10", "0x13e5dd1d", "0x6fc3e233", "0x2d83eeac", "0x9006e8bf", "0x2c4b5362", "0x31b49ee2"], "round": "for i in 0..15: s[i] = (s[i] ^ (rc[i] + (r+1) * 0x9E3779B9)) * mul[i]; then quarter rounds on columns (0,4,8,12) (1,5,9,13) (2,6,10,14) (3,7,11,15) with rot[0..3] and diagonals (0,5,10,15) (1,6,11,12) (2,7,8,13) (3,4,9,14) with rot[4..7]", "quarter_round": "a += b; d ^= a; d = rotl(d, r1); c += d; b ^= c; b = rotl(b, r2); a += b; d ^= a; d = rotl(d, r3); c += d; b ^= c; b = rotl(b, r4)"},
|
||||
"item": "s[0..7] = key; s[8+i] = t * mul[i] + rc[i] for i in 0..7; for r in 0..7: s = M_r(s); line = s[0] & 0x003fffff; s[i] ^= cache[line * 16 + i]; then s = M_8(s); item(t) = s",
|
||||
"word": "dataset[w] = item(w >> 4)[w & 15]"
|
||||
},
|
||||
"instructions": [
|
||||
{"i": 0, "op": "mad", "dst": 5, "src": 4, "src2": 0, "imm": "0x392cc69d", "imm2": "0xdff38f87", "rot": 18, "bit": 19, "mask": 2, "width": 1},
|
||||
{"i": 1, "op": "rotl", "dst": 1, "src": 7, "src2": 0, "imm": "0xa731596a", "imm2": "0x4ce406f5", "rot": 23, "bit": 27, "mask": 4, "width": 1},
|
||||
{"i": 2, "op": "load", "dst": 0, "src": 5, "src2": 5, "imm": "0x4d78cee5", "imm2": "0x7a624dd7", "rot": 16, "bit": 24, "mask": 16, "width": 4},
|
||||
{"i": 3, "op": "mad", "dst": 5, "src": 4, "src2": 2, "imm": "0x80a8d418", "imm2": "0x3f405868", "rot": 21, "bit": 4, "mask": 8, "width": 1},
|
||||
{"i": 4, "op": "mul", "dst": 1, "src": 6, "src2": 4, "imm": "0xc4e8867c", "imm2": "0xd2ad8c44", "rot": 26, "bit": 21, "mask": 16, "width": 1},
|
||||
{"i": 5, "op": "add", "dst": 1, "src": 0, "src2": 6, "imm": "0x9db46598", "imm2": "0x9dd9fb05", "rot": 14, "bit": 6, "mask": 16, "width": 1},
|
||||
{"i": 6, "op": "shfl", "dst": 1, "src": 7, "src2": 5, "imm": "0xc9049c0f", "imm2": "0x007f6621", "rot": 24, "bit": 19, "mask": 16, "width": 1},
|
||||
{"i": 7, "op": "mul", "dst": 6, "src": 1, "src2": 7, "imm": "0x073fea86", "imm2": "0x1ed9dff1", "rot": 26, "bit": 24, "mask": 2, "width": 1},
|
||||
{"i": 8, "op": "mulhi", "dst": 1, "src": 7, "src2": 5, "imm": "0x3faa8f96", "imm2": "0x01445abc", "rot": 26, "bit": 3, "mask": 4, "width": 1},
|
||||
{"i": 9, "op": "mulhi", "dst": 2, "src": 1, "src2": 1, "imm": "0x97d622e9", "imm2": "0xfd732e57", "rot": 28, "bit": 29, "mask": 1, "width": 1},
|
||||
{"i": 10, "op": "add", "dst": 0, "src": 4, "src2": 4, "imm": "0xe45fcceb", "imm2": "0xc15822b6", "rot": 15, "bit": 13, "mask": 2, "width": 1},
|
||||
{"i": 11, "op": "mad", "dst": 5, "src": 1, "src2": 2, "imm": "0x6148c1cc", "imm2": "0xdaa7b1d3", "rot": 3, "bit": 25, "mask": 16, "width": 1},
|
||||
{"i": 12, "op": "mul", "dst": 4, "src": 7, "src2": 1, "imm": "0x7b0965e5", "imm2": "0x5086e5aa", "rot": 30, "bit": 28, "mask": 16, "width": 1},
|
||||
{"i": 13, "op": "load", "dst": 0, "src": 5, "src2": 4, "imm": "0x4c87a2ab", "imm2": "0x5db5ba1c", "rot": 22, "bit": 19, "mask": 16, "width": 16},
|
||||
{"i": 14, "op": "xor", "dst": 3, "src": 4, "src2": 6, "imm": "0xdc246d40", "imm2": "0xa5cfff4a", "rot": 6, "bit": 19, "mask": 16, "width": 1},
|
||||
{"i": 15, "op": "xor", "dst": 1, "src": 6, "src2": 6, "imm": "0x6d3e113d", "imm2": "0x69e25584", "rot": 12, "bit": 27, "mask": 2, "width": 1},
|
||||
{"i": 16, "op": "rotr", "dst": 5, "src": 6, "src2": 2, "imm": "0x45569439", "imm2": "0x14d0f916", "rot": 10, "bit": 5, "mask": 16, "width": 1},
|
||||
{"i": 17, "op": "rotr", "dst": 3, "src": 7, "src2": 1, "imm": "0x412cb31a", "imm2": "0xe0713d9c", "rot": 17, "bit": 0, "mask": 2, "width": 1},
|
||||
{"i": 18, "op": "shfl", "dst": 1, "src": 4, "src2": 3, "imm": "0x2419b99c", "imm2": "0x9ab3a71e", "rot": 17, "bit": 15, "mask": 16, "width": 1},
|
||||
{"i": 19, "op": "load", "dst": 5, "src": 6, "src2": 7, "imm": "0xa1f88336", "imm2": "0xca05a80c", "rot": 17, "bit": 22, "mask": 8, "width": 1},
|
||||
{"i": 20, "op": "rotl", "dst": 6, "src": 7, "src2": 4, "imm": "0x51de29c5", "imm2": "0xfe2d2af0", "rot": 30, "bit": 20, "mask": 1, "width": 1},
|
||||
{"i": 21, "op": "load", "dst": 5, "src": 2, "src2": 6, "imm": "0x5db413b6", "imm2": "0x3dad8864", "rot": 20, "bit": 23, "mask": 4, "width": 4},
|
||||
{"i": 22, "op": "xor", "dst": 3, "src": 5, "src2": 0, "imm": "0xdeadb225", "imm2": "0x7397a1f2", "rot": 5, "bit": 3, "mask": 2, "width": 1},
|
||||
{"i": 23, "op": "add", "dst": 5, "src": 7, "src2": 7, "imm": "0x1d4f8db7", "imm2": "0x950603c6", "rot": 19, "bit": 6, "mask": 1, "width": 1},
|
||||
{"i": 24, "op": "load", "dst": 3, "src": 4, "src2": 5, "imm": "0x148ee6e2", "imm2": "0xfc0cbfef", "rot": 1, "bit": 23, "mask": 16, "width": 4},
|
||||
{"i": 25, "op": "load", "dst": 0, "src": 1, "src2": 1, "imm": "0x114e77c3", "imm2": "0x8b1c13f1", "rot": 4, "bit": 0, "mask": 8, "width": 16},
|
||||
{"i": 26, "op": "add", "dst": 2, "src": 3, "src2": 3, "imm": "0x55db0d92", "imm2": "0x0ae476a4", "rot": 24, "bit": 31, "mask": 4, "width": 1},
|
||||
{"i": 27, "op": "load", "dst": 5, "src": 6, "src2": 5, "imm": "0xee300382", "imm2": "0x1609cf99", "rot": 8, "bit": 11, "mask": 16, "width": 1},
|
||||
{"i": 28, "op": "load", "dst": 2, "src": 5, "src2": 2, "imm": "0x96783a44", "imm2": "0x0f090418", "rot": 11, "bit": 24, "mask": 1, "width": 4},
|
||||
{"i": 29, "op": "xor", "dst": 1, "src": 6, "src2": 7, "imm": "0x6c8d15c2", "imm2": "0x2cde0f35", "rot": 18, "bit": 14, "mask": 4, "width": 1},
|
||||
{"i": 30, "op": "mulhi", "dst": 7, "src": 4, "src2": 1, "imm": "0xc68ea9de", "imm2": "0xc45d9dfa", "rot": 29, "bit": 14, "mask": 2, "width": 1},
|
||||
{"i": 31, "op": "rotr", "dst": 6, "src": 3, "src2": 5, "imm": "0x2b816dd1", "imm2": "0xdf13f697", "rot": 17, "bit": 12, "mask": 2, "width": 1},
|
||||
{"i": 32, "op": "load", "dst": 0, "src": 3, "src2": 3, "imm": "0x6711453d", "imm2": "0x78ae13e9", "rot": 2, "bit": 6, "mask": 4, "width": 1},
|
||||
{"i": 33, "op": "rotr", "dst": 5, "src": 0, "src2": 3, "imm": "0xe0068514", "imm2": "0xba437440", "rot": 14, "bit": 2, "mask": 2, "width": 1},
|
||||
{"i": 34, "op": "rotl", "dst": 5, "src": 3, "src2": 7, "imm": "0xdde8ab9a", "imm2": "0x9b3f4073", "rot": 20, "bit": 26, "mask": 1, "width": 1},
|
||||
{"i": 35, "op": "mulhi", "dst": 0, "src": 4, "src2": 2, "imm": "0x2b47ae8c", "imm2": "0x2617710c", "rot": 30, "bit": 29, "mask": 1, "width": 1},
|
||||
{"i": 36, "op": "add", "dst": 6, "src": 7, "src2": 0, "imm": "0x5d6e3dc5", "imm2": "0xfe7a0454", "rot": 22, "bit": 18, "mask": 8, "width": 1},
|
||||
{"i": 37, "op": "load", "dst": 2, "src": 1, "src2": 7, "imm": "0x21116475", "imm2": "0xbe53b7b8", "rot": 21, "bit": 2, "mask": 8, "width": 4},
|
||||
{"i": 38, "op": "rotl", "dst": 2, "src": 7, "src2": 2, "imm": "0xd76a18c4", "imm2": "0xb7ed0d92", "rot": 19, "bit": 10, "mask": 16, "width": 1},
|
||||
{"i": 39, "op": "add", "dst": 3, "src": 6, "src2": 3, "imm": "0xe7e241ba", "imm2": "0xc1d4ae24", "rot": 10, "bit": 20, "mask": 16, "width": 1},
|
||||
{"i": 40, "op": "load", "dst": 4, "src": 7, "src2": 0, "imm": "0xb1006316", "imm2": "0x617eb11a", "rot": 1, "bit": 27, "mask": 1, "width": 4},
|
||||
{"i": 41, "op": "add", "dst": 3, "src": 1, "src2": 3, "imm": "0xb45cdd60", "imm2": "0x8f9f8556", "rot": 5, "bit": 21, "mask": 16, "width": 1},
|
||||
{"i": 42, "op": "shfl", "dst": 5, "src": 2, "src2": 1, "imm": "0x8fc745c7", "imm2": "0x98256336", "rot": 16, "bit": 7, "mask": 4, "width": 1},
|
||||
{"i": 43, "op": "mul", "dst": 0, "src": 1, "src2": 3, "imm": "0xe8aea431", "imm2": "0xfeed34f6", "rot": 30, "bit": 2, "mask": 8, "width": 1},
|
||||
{"i": 44, "op": "rotr", "dst": 0, "src": 7, "src2": 4, "imm": "0x8f1da3ee", "imm2": "0xa9c20edf", "rot": 19, "bit": 17, "mask": 2, "width": 1},
|
||||
{"i": 45, "op": "sub", "dst": 5, "src": 3, "src2": 7, "imm": "0x9da4c5e7", "imm2": "0xbcd50b0c", "rot": 7, "bit": 18, "mask": 1, "width": 1},
|
||||
{"i": 46, "op": "mad", "dst": 2, "src": 7, "src2": 7, "imm": "0x837be930", "imm2": "0x9b62650b", "rot": 5, "bit": 23, "mask": 1, "width": 1},
|
||||
{"i": 47, "op": "mad", "dst": 6, "src": 3, "src2": 1, "imm": "0x825afaa4", "imm2": "0x0cf9f1f0", "rot": 17, "bit": 9, "mask": 2, "width": 1},
|
||||
{"i": 48, "op": "mul", "dst": 0, "src": 7, "src2": 2, "imm": "0x4424f910", "imm2": "0xbaeba671", "rot": 23, "bit": 6, "mask": 4, "width": 1},
|
||||
{"i": 49, "op": "add", "dst": 0, "src": 4, "src2": 7, "imm": "0x3fa0c5cd", "imm2": "0xb9083b6c", "rot": 28, "bit": 1, "mask": 2, "width": 1},
|
||||
{"i": 50, "op": "add", "dst": 4, "src": 6, "src2": 4, "imm": "0x2d6873e8", "imm2": "0x9eecc778", "rot": 29, "bit": 13, "mask": 16, "width": 1},
|
||||
{"i": 51, "op": "sub", "dst": 2, "src": 7, "src2": 2, "imm": "0xace9966d", "imm2": "0xe4213c89", "rot": 30, "bit": 18, "mask": 8, "width": 1},
|
||||
{"i": 52, "op": "rotl", "dst": 6, "src": 7, "src2": 0, "imm": "0x03bc6330", "imm2": "0x32d9aee6", "rot": 6, "bit": 19, "mask": 1, "width": 1},
|
||||
{"i": 53, "op": "rotr", "dst": 3, "src": 5, "src2": 1, "imm": "0xef7e5b3e", "imm2": "0xb2aea388", "rot": 27, "bit": 31, "mask": 2, "width": 1},
|
||||
{"i": 54, "op": "load", "dst": 3, "src": 2, "src2": 2, "imm": "0x711b4f5d", "imm2": "0xac8e6837", "rot": 1, "bit": 5, "mask": 1, "width": 4},
|
||||
{"i": 55, "op": "load", "dst": 7, "src": 5, "src2": 7, "imm": "0xb0f4faf4", "imm2": "0xb13fe736", "rot": 16, "bit": 2, "mask": 4, "width": 4},
|
||||
{"i": 56, "op": "or", "dst": 2, "src": 6, "src2": 5, "imm": "0x4f416150", "imm2": "0x2a9f59e3", "rot": 31, "bit": 6, "mask": 4, "width": 1},
|
||||
{"i": 57, "op": "load", "dst": 4, "src": 0, "src2": 0, "imm": "0x54ce0fba", "imm2": "0x48d98570", "rot": 11, "bit": 2, "mask": 4, "width": 1},
|
||||
{"i": 58, "op": "xor", "dst": 3, "src": 6, "src2": 6, "imm": "0xf34a7cca", "imm2": "0xf345c73d", "rot": 18, "bit": 18, "mask": 16, "width": 1},
|
||||
{"i": 59, "op": "load", "dst": 0, "src": 6, "src2": 6, "imm": "0x730474e9", "imm2": "0xb90ac73f", "rot": 25, "bit": 31, "mask": 4, "width": 1},
|
||||
{"i": 60, "op": "add", "dst": 2, "src": 4, "src2": 1, "imm": "0x5052a1c3", "imm2": "0x19c76fb3", "rot": 12, "bit": 3, "mask": 1, "width": 1},
|
||||
{"i": 61, "op": "load", "dst": 7, "src": 4, "src2": 0, "imm": "0xbecfc16b", "imm2": "0xd2837365", "rot": 21, "bit": 22, "mask": 8, "width": 1},
|
||||
{"i": 62, "op": "or", "dst": 6, "src": 1, "src2": 3, "imm": "0x7353a546", "imm2": "0xcc33abd9", "rot": 24, "bit": 5, "mask": 4, "width": 1},
|
||||
{"i": 63, "op": "add", "dst": 5, "src": 1, "src2": 1, "imm": "0x08c757c0", "imm2": "0x535fe3fa", "rot": 21, "bit": 4, "mask": 4, "width": 1}
|
||||
]
|
||||
}
|
||||
109
proto-cuda/packs-readwidth/mixB-1/program.metal
Normal file
109
proto-cuda/packs-readwidth/mixB-1/program.metal
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
#include <metal_stdlib>
|
||||
using namespace metal;
|
||||
|
||||
#define MASK 0x0fffffffu
|
||||
constant uint SEEDW[8] = { 0x3e345412u, 0xfc2b3a0eu, 0x7740353du, 0x2df159dbu, 0x50bc6eedu, 0x2e61acb2u, 0x3c800bffu, 0xbaecd8c1u };
|
||||
|
||||
inline uint splitmix32(uint x) {
|
||||
x ^= x >> 16; x *= 0x7feb352du;
|
||||
x ^= x >> 15; x *= 0x846ca68bu;
|
||||
x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
inline uint rotl_imm(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31
|
||||
inline uint rotr_var(uint x, uint n) { n &= 31u; return (x >> n) | (x << ((32u - n) & 31u)); }
|
||||
inline uint ds_elem(uint i, uint d0, uint d1) {
|
||||
uint x = i ^ d0;
|
||||
x *= 0x9E3779B1u; x ^= x >> 15;
|
||||
x += d1;
|
||||
x *= 0x85EBCA77u; x ^= x >> 13;
|
||||
x *= 0xC2B2AE3Du; x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
|
||||
kernel void igneum_hash(device const uint* dataset [[buffer(0)]],
|
||||
device ulong* out [[buffer(1)]],
|
||||
constant uint& baseNonce [[buffer(2)]],
|
||||
uint gid [[thread_position_in_grid]]) {
|
||||
uint nonce = baseNonce + gid;
|
||||
uint r0, r1, r2, r3, r4, r5, r6, r7;
|
||||
{ uint x = nonce ^ SEEDW[0]; x += 0x9e3779b9u * 1u; x = splitmix32(x); r0 = x ^ SEEDW[1]; }
|
||||
{ uint x = nonce ^ SEEDW[1]; x += 0x9e3779b9u * 2u; x = splitmix32(x); r1 = x ^ SEEDW[2]; }
|
||||
{ uint x = nonce ^ SEEDW[2]; x += 0x9e3779b9u * 3u; x = splitmix32(x); r2 = x ^ SEEDW[3]; }
|
||||
{ uint x = nonce ^ SEEDW[3]; x += 0x9e3779b9u * 4u; x = splitmix32(x); r3 = x ^ SEEDW[4]; }
|
||||
{ uint x = nonce ^ SEEDW[4]; x += 0x9e3779b9u * 5u; x = splitmix32(x); r4 = x ^ SEEDW[5]; }
|
||||
{ uint x = nonce ^ SEEDW[5]; x += 0x9e3779b9u * 6u; x = splitmix32(x); r5 = x ^ SEEDW[6]; }
|
||||
{ uint x = nonce ^ SEEDW[6]; x += 0x9e3779b9u * 7u; x = splitmix32(x); r6 = x ^ SEEDW[7]; }
|
||||
{ uint x = nonce ^ SEEDW[7]; x += 0x9e3779b9u * 8u; x = splitmix32(x); r7 = x ^ SEEDW[0]; }
|
||||
|
||||
for (uint it = 0u; it < 8u; ++it) {
|
||||
uint sel = r0;
|
||||
r5 = r4 * r0 + r5; // 0
|
||||
r1 = rotl_imm(r1, 23u); // 1
|
||||
{ uint b_ = (r5 & MASK) & ~3u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint x_ = r0 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r0 = x_; } // 2
|
||||
r5 = r4 * r2 + r5; // 3
|
||||
r1 = r1 * r6; // 4
|
||||
r1 = r1 + r0 + select(0x9db46598u, 0x9dd9fb05u, ((sel >> 6u) & 1u) != 0u); // 5
|
||||
r1 = r1 ^ simd_shuffle_xor(r7, (ushort)16); // 6
|
||||
r6 = r6 * r1; // 7
|
||||
r1 = mulhi(r1, r7); // 8
|
||||
r2 = mulhi(r2, r1); // 9
|
||||
r0 = r0 + r4 + select(0xe45fccebu, 0xc15822b6u, ((sel >> 13u) & 1u) != 0u); // 10
|
||||
r5 = r1 * r2 + r5; // 11
|
||||
r4 = r4 * r7; // 12
|
||||
{ uint b_ = (r5 & MASK) & ~15u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint x_ = r0 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r0 = x_; } // 13
|
||||
r3 = r3 ^ r4; // 14
|
||||
r1 = r1 ^ r6; // 15
|
||||
r5 = rotr_var(r5, r6); // 16
|
||||
r3 = rotr_var(r3, r7); // 17
|
||||
r1 = r1 ^ simd_shuffle_xor(r4, (ushort)16); // 18
|
||||
r5 = r5 ^ dataset[r6 & MASK]; // 19
|
||||
r6 = rotl_imm(r6, 30u); // 20
|
||||
{ uint b_ = (r2 & MASK) & ~3u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint x_ = r5 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r5 = x_; } // 21
|
||||
r3 = r3 ^ r5; // 22
|
||||
r5 = r5 + r7 + select(0x1d4f8db7u, 0x950603c6u, ((sel >> 6u) & 1u) != 0u); // 23
|
||||
{ uint b_ = (r4 & MASK) & ~3u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r3 = x_; } // 24
|
||||
{ uint b_ = (r1 & MASK) & ~15u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint4 v1_ = l_[1]; uint4 v2_ = l_[2]; uint4 v3_ = l_[3]; uint x_ = r0 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v1_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v2_.w; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v3_.w; r0 = x_; } // 25
|
||||
r2 = r2 + r3 + select(0x55db0d92u, 0x0ae476a4u, ((sel >> 31u) & 1u) != 0u); // 26
|
||||
r5 = r5 ^ dataset[r6 & MASK]; // 27
|
||||
{ uint b_ = (r5 & MASK) & ~3u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint x_ = r2 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r2 = x_; } // 28
|
||||
r1 = r1 ^ r6; // 29
|
||||
r7 = mulhi(r7, r4); // 30
|
||||
r6 = rotr_var(r6, r3); // 31
|
||||
r0 = r0 ^ dataset[r3 & MASK]; // 32
|
||||
r5 = rotr_var(r5, r0); // 33
|
||||
r5 = rotl_imm(r5, 20u); // 34
|
||||
r0 = mulhi(r0, r4); // 35
|
||||
r6 = r6 + r7 + select(0x5d6e3dc5u, 0xfe7a0454u, ((sel >> 18u) & 1u) != 0u); // 36
|
||||
{ uint b_ = (r1 & MASK) & ~3u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint x_ = r2 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r2 = x_; } // 37
|
||||
r2 = rotl_imm(r2, 19u); // 38
|
||||
r3 = r3 + r6 + select(0xe7e241bau, 0xc1d4ae24u, ((sel >> 20u) & 1u) != 0u); // 39
|
||||
{ uint b_ = (r7 & MASK) & ~3u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint x_ = r4 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r4 = x_; } // 40
|
||||
r3 = r3 + r1 + select(0xb45cdd60u, 0x8f9f8556u, ((sel >> 21u) & 1u) != 0u); // 41
|
||||
r5 = r5 ^ simd_shuffle_xor(r2, (ushort)4); // 42
|
||||
r0 = r0 * r1; // 43
|
||||
r0 = rotr_var(r0, r7); // 44
|
||||
r5 = r5 - r3; // 45
|
||||
r2 = r7 * r7 + r2; // 46
|
||||
r6 = r3 * r1 + r6; // 47
|
||||
r0 = r0 * r7; // 48
|
||||
r0 = r0 + r4 + select(0x3fa0c5cdu, 0xb9083b6cu, ((sel >> 1u) & 1u) != 0u); // 49
|
||||
r4 = r4 + r6 + select(0x2d6873e8u, 0x9eecc778u, ((sel >> 13u) & 1u) != 0u); // 50
|
||||
r2 = r2 - r7; // 51
|
||||
r6 = rotl_imm(r6, 6u); // 52
|
||||
r3 = rotr_var(r3, r5); // 53
|
||||
{ uint b_ = (r2 & MASK) & ~3u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint x_ = r3 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r3 = x_; } // 54
|
||||
{ uint b_ = (r5 & MASK) & ~3u; device const uint4* l_ = (device const uint4*)(dataset + b_); uint4 v0_ = l_[0]; uint x_ = r7 ^ v0_.x; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.y; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.z; x_ = (rotl_imm(x_, 11u) * 0x9e3779b1u) ^ v0_.w; r7 = x_; } // 55
|
||||
r2 = r2 | r6; // 56
|
||||
r4 = r4 ^ dataset[r0 & MASK]; // 57
|
||||
r3 = r3 ^ r6; // 58
|
||||
r0 = r0 ^ dataset[r6 & MASK]; // 59
|
||||
r2 = r2 + r4 + select(0x5052a1c3u, 0x19c76fb3u, ((sel >> 3u) & 1u) != 0u); // 60
|
||||
r7 = r7 ^ dataset[r4 & MASK]; // 61
|
||||
r6 = r6 | r1; // 62
|
||||
r5 = r5 + r1 + select(0x08c757c0u, 0x535fe3fau, ((sel >> 4u) & 1u) != 0u); // 63
|
||||
}
|
||||
uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u);
|
||||
uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u);
|
||||
out[gid] = ((ulong)hi << 32) | (ulong)lo;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue