From fe024ae0d46e7bd88bfeca06fb95e9a6c00da8a0 Mon Sep 17 00:00:00 2001 From: John Tromp Date: Wed, 26 Oct 2016 18:29:12 -0400 Subject: [PATCH] prepare blake2bip --- Makefile | 4 +- equi_dev_miner.cpp | 12 +++-- equi_dev_miner.h | 122 +++++++++++++++++++-------------------------- 3 files changed, 61 insertions(+), 77 deletions(-) diff --git a/Makefile b/Makefile index f996aa4..79b4233 100644 --- a/Makefile +++ b/Makefile @@ -26,10 +26,10 @@ hash1: equi.h dev_miner.h dev_miner.cpp blake2b/asm/zcblake2_avx2.o Makefile $(GPP) -DHASHONLY dev_miner.cpp blake/blake2b.cpp blake2b/asm/zcblake2_avx2.o -o hash1 equidev: equi.h equi_dev_miner.h equi_dev_miner.cpp Makefile - $(GPP) -DATOMIC equi_dev_miner.cpp blake/blake2b.cpp -o equidev + $(GPP) -DATOMIC equi_dev_miner.cpp blake/blake2b.cpp blake2-avx2/blake2bip.c -o equidev equidev1: equi.h equi_dev_miner.h equi_dev_miner.cpp Makefile - $(GPP) equi_dev_miner.cpp blake/blake2b.cpp -o equidev1 + $(GPP) equi_dev_miner.cpp blake/blake2b.cpp blake2-avx2/blake2bip.c -o equidev1 eqcuda: equi_miner.cu equi.h blake2b.cu Makefile nvcc -DXINTREE -DUNROLL -arch sm_35 equi_miner.cu blake/blake2b.cpp -o eqcuda diff --git a/equi_dev_miner.cpp b/equi_dev_miner.cpp index f6d494e..d75487f 100644 --- a/equi_dev_miner.cpp +++ b/equi_dev_miner.cpp @@ -49,8 +49,13 @@ int main(int argc, char **argv) { equi eq(nthreads); printf("Using %dMB of memory\n", 1 + eq.hta.alloced / 0x100000); u32 sumnsols = 0; + char headernonce[HEADERNONCELEN]; + u32 hdrlen = strlen(header); + memcpy(headernonce, header, hdrlen); + memset(headernonce+hdrlen, 0, sizeof(headernonce)-hdrlen); for (int r = 0; r < range; r++) { - eq.setnonce(header, strlen(header), nonce+r); + ((u32 *)headernonce)[32] = htole32(nonce+r); + eq.setheadernonce(headernonce, sizeof(headernonce)); for (int t = 0; t < nthreads; t++) { threads[t].id = t; threads[t].eq = &eq; @@ -65,13 +70,12 @@ int main(int argc, char **argv) { for (unsigned s = 0; s < eq.nsols; s++) { nsols++; if (showsol) { - printf("Solution"); + printf("\nSolution"); for (u32 i = 0; i < PROOFSIZE; i++) printf(" %jx", (uintmax_t)eq.sols[s][i]); - printf("\n"); } } - printf("%d solutions\n", nsols); + printf("\n%d solutions\n", nsols); sumnsols += nsols; } free(threads); diff --git a/equi_dev_miner.h b/equi_dev_miner.h index 994e492..bb7b5fe 100644 --- a/equi_dev_miner.h +++ b/equi_dev_miner.h @@ -1,6 +1,9 @@ // Equihash solver // Copyright (c) 2016 John Tromp +// This development version uses xenoncat's highly optimized +// 4-way parallel blake2b implementation + // Fix N, K, such that n = N/(k+1) is integer // Fix M = 2^{n+1} hashes each of length N bits, // H_0, ... , H_{M-1}, generated fom (n+1)-bit indices. @@ -23,9 +26,14 @@ #include #include +#include "blake2-avx2/blake2bip.h" + #if defined __builtin_bswap32 && defined __LITTLE_ENDIAN #undef htobe32 #define htobe32(x) __builtin_bswap32(x) +#elif defined __APPLE__ +#undef htobe32 +#define htobe32(x) OSSwapHostToBigInt32(x) #endif typedef uint16_t u16; @@ -56,6 +64,14 @@ typedef u32 au32; #endif #endif +#ifdef __AVX2__ +#define BLAKESINPARALLEL 4 +#elif defined __AVX__ +#define BLAKESINPARALLEL 2 +#else +#define BLAKESINPARALLEL 1 +#endif + // number of buckets static const u32 NBUCKETS = 1<bytes[prevbo] >> 4; #elif WN == 200 && RESTBITS == 8 return (slot->bytes[prevbo] & 0xf) << 4 | slot->bytes[prevbo+1] >> 4; -#elif WN == 200 && RESTBITS == 9 - return (slot->bytes[prevbo] & 0x1f) << 4 | slot->bytes[prevbo+1] >> 4; #elif WN == 144 && RESTBITS == 4 return slot->bytes[prevbo] & 0xf; #else @@ -426,8 +443,6 @@ struct equi { return slot->bytes[prevbo] & 0xf; #elif WN == 200 && RESTBITS == 8 return slot->bytes[prevbo]; -#elif WN == 200 && RESTBITS == 9 - return (slot->bytes[prevbo]&1) << 8 | slot->bytes[prevbo+1]; #elif WN == 144 && RESTBITS == 4 return slot->bytes[prevbo] & 0xf; #else @@ -502,40 +517,33 @@ struct equi { }; void digit0(const u32 id) { - uchar hash[HASHOUT]; - blake2b_state state; htlayout htl(this, 0); +#ifndef HASHONLY const u32 hashbytes = hashsize(0); - for (u32 block = id; block < NBLOCKS; block += nthreads) { - state = blake_ctx; - u32 leb = htole32(block); - blake2b_update(&state, (uchar *)&leb, sizeof(u32)); - blake2b_final(&state, hash, HASHOUT); - for (u32 i = 0; i> 4; -#elif BUCKBITS == 11 && RESTBITS == 9 - const u32 bucketid = ((u32)ph[0] << 3) | ph[1] >> 5; -#elif BUCKBITS == 20 && RESTBITS == 4 - const u32 bucketid = ((((u32)ph[0] << 8) | ph[1]) << 4) | ph[2] >> 4; -#elif BUCKBITS == 12 && RESTBITS == 4 - const u32 bucketid = ((u32)ph[0] << 4) | ph[1] >> 4; - const u32 xhash = ph[1] & 0xf; -#else -#error not implemented #endif - const u32 slot = getslot0(bucketid); - if (slot >= NSLOTS) { - bfull++; - continue; + uchar hashes[BLAKESINPARALLEL * 64]; + blake2b_state state = blake_ctx; + state->counter += state->buflen; + state->lastblock = 1; + memset(state->buf+state->buflen, 0, BLAKE2B_BLOCKBYTES-state->buflen); // Padding + for (u32 block = id; block < NBLOCKS; block += nthreads) { + blake2bip_final(&state, hashes, block); +#ifndef HASHONLY + for (u32 i = 0; i> 4; + const u32 slot = getslot0(bucketid); + if (slot >= NSLOTS) { + bfull++; + continue; + } + htunit *s = hta.heap0[bucketid][slot] + htl.nexthtunits; + memcpy(s->bytes-hashbytes, ph+WN/8-hashbytes, hashbytes); + s->tag = tree((block * BLAKESINPARALLEL + i) * HASHESPERBLAKE + j); } - htunit *s = hta.heap0[bucketid][slot] + htl.nexthtunits; - memcpy(s->bytes-hashbytes, ph+WN/8-hashbytes, hashbytes); - s->tag = tree(block * HASHESPERBLAKE + i); } +#endif } } @@ -564,9 +572,6 @@ struct equi { #if WN == 200 && BUCKBITS == 12 && RESTBITS == 8 xorbucketid = (((u32)(bytes0[htl.prevbo+1] ^ bytes1[htl.prevbo+1]) & 0xf) << 8) | (bytes0[htl.prevbo+2] ^ bytes1[htl.prevbo+2]); -#elif WN == 200 && BUCKBITS == 11 && RESTBITS == 9 - xorbucketid = (((u32)(bytes0[htl.prevbo+1] ^ bytes1[htl.prevbo+1]) & 0xf) << 7) - | (bytes0[htl.prevbo+2] ^ bytes1[htl.prevbo+2]) >> 1; #elif WN == 144 && BUCKBITS == 20 && RESTBITS == 4 xorbucketid = ((((u32)(bytes0[htl.prevbo+1] ^ bytes1[htl.prevbo+1]) << 8) | (bytes0[htl.prevbo+2] ^ bytes1[htl.prevbo+2])) << 4) @@ -616,9 +621,6 @@ struct equi { #if WN == 200 && BUCKBITS == 12 && RESTBITS == 8 xorbucketid = ((u32)(bytes0[htl.prevbo+1] ^ bytes1[htl.prevbo+1]) << 4) | (bytes0[htl.prevbo+2] ^ bytes1[htl.prevbo+2]) >> 4; -#elif WN == 200 && BUCKBITS == 11 && RESTBITS == 9 - xorbucketid = ((u32)(bytes0[htl.prevbo+2] ^ bytes1[htl.prevbo+2]) << 3) - | (bytes0[htl.prevbo+3] ^ bytes1[htl.prevbo+3]) >> 5; #elif WN == 144 && BUCKBITS == 20 && RESTBITS == 4 xorbucketid = ((((u32)(bytes0[htl.prevbo+1] ^ bytes1[htl.prevbo+1]) << 8) | (bytes0[htl.prevbo+2] ^ bytes1[htl.prevbo+2])) << 4) @@ -866,7 +868,7 @@ struct equi { u32 bsize = getnslots0(bucketid); for (u32 s1 = 0; s1 < bsize; s1++) { const htunit *slot1 = buck[s1]; - if (!cd.addslot(s1, (slot1->bytes[3] & 0xf) << 4 | slot1->bytes[3+1] >> 4)) { + if (!cd.addslot(s1, (slot1->bytes[3] & 0xf) << 4 | slot1->bytes[4] >> 4)) { xfull++; continue; } @@ -948,7 +950,7 @@ struct equi { } } } - // printf(" %d candidates ", nc); + printf(" %d candidates ", nc); } }; @@ -970,78 +972,56 @@ void *worker(void *vp) { thread_ctx *tp = (thread_ctx *)vp; equi *eq = tp->eq; - if (tp->id == 0) - printf("Digit 0"); - barrier(&eq->barry); + if (tp->id == 0) printf("Digit 0"); eq->digit0(tp->id); +#ifdef HASHONLY + pthread_exit(NULL); +#endif barrier(&eq->barry); if (tp->id == 0) eq->showbsizes(0); barrier(&eq->barry); #if WN == 200 && WK == 9 && RESTBITS == 8 - if (tp->id == 0) printf("Digit 1"); - barrier(&eq->barry); eq->digit1(tp->id); barrier(&eq->barry); if (tp->id == 0) eq->showbsizes(1); barrier(&eq->barry); - if (tp->id == 0) printf("Digit 2"); - barrier(&eq->barry); eq->digit2(tp->id); barrier(&eq->barry); if (tp->id == 0) eq->showbsizes(2); barrier(&eq->barry); - if (tp->id == 0) printf("Digit 3"); - barrier(&eq->barry); eq->digit3(tp->id); barrier(&eq->barry); if (tp->id == 0) eq->showbsizes(3); barrier(&eq->barry); - if (tp->id == 0) printf("Digit 4"); - barrier(&eq->barry); eq->digit4(tp->id); barrier(&eq->barry); if (tp->id == 0) eq->showbsizes(4); barrier(&eq->barry); - if (tp->id == 0) printf("Digit 5"); - barrier(&eq->barry); eq->digit5(tp->id); barrier(&eq->barry); if (tp->id == 0) eq->showbsizes(5); barrier(&eq->barry); - if (tp->id == 0) printf("Digit 6"); - barrier(&eq->barry); eq->digit6(tp->id); barrier(&eq->barry); if (tp->id == 0) eq->showbsizes(6); barrier(&eq->barry); - if (tp->id == 0) printf("Digit 7"); - barrier(&eq->barry); eq->digit7(tp->id); barrier(&eq->barry); if (tp->id == 0) eq->showbsizes(7); barrier(&eq->barry); - if (tp->id == 0) printf("Digit 8"); - barrier(&eq->barry); eq->digit8(tp->id); barrier(&eq->barry); if (tp->id == 0) eq->showbsizes(8); barrier(&eq->barry); #else for (u32 r = 1; r < WK; r++) { - if (tp->id == 0) - printf("Digit %d", r); - barrier(&eq->barry); r&1 ? eq->digitodd(r, tp->id) : eq->digiteven(r, tp->id); barrier(&eq->barry); if (tp->id == 0) eq->showbsizes(r); barrier(&eq->barry); } #endif - if (tp->id == 0) - printf("Digit %d\n", WK); - barrier(&eq->barry); eq->digitK(tp->id); - barrier(&eq->barry); pthread_exit(NULL); return 0; }