start blake2bp work on dev_miner
This commit is contained in:
parent
80b6c72ab4
commit
2d3cd5f945
561
dev_miner.h
561
dev_miner.h
|
@ -18,12 +18,16 @@
|
|||
// the i*n 0s, each bucket having 4 * 2^RESTBITS slots,
|
||||
// twice the number of subtrees expected to land there.
|
||||
|
||||
#include "equi.h"
|
||||
#include "dev.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <assert.h>
|
||||
|
||||
#if defined __builtin_bswap32 && defined __LITTLE_ENDIAN
|
||||
#undef htobe32
|
||||
#define htobe32(x) __builtin_bswap32(x)
|
||||
#endif
|
||||
|
||||
typedef uint16_t u16;
|
||||
typedef uint64_t u64;
|
||||
|
||||
|
@ -54,6 +58,8 @@ typedef u32 au32;
|
|||
|
||||
// number of buckets
|
||||
static const u32 NBUCKETS = 1<<BUCKBITS;
|
||||
// bucket mask
|
||||
static const u32 BUCKMASK = NBUCKETS-1;
|
||||
// 2_log of number of slots per bucket
|
||||
static const u32 SLOTBITS = RESTBITS+1+1;
|
||||
static const u32 SLOTRANGE = 1<<SLOTBITS;
|
||||
|
@ -66,7 +72,7 @@ static const u32 XFULL = 16;
|
|||
static const u32 SLOTMASK = SLOTRANGE-1;
|
||||
// number of possible values of xhash (rest of n) bits
|
||||
static const u32 NRESTS = 1<<RESTBITS;
|
||||
// number of blocks of hashes extracted from single 512 bit blake2b output
|
||||
// number of blocks of hashes extracted from single blake2bp call
|
||||
static const u32 NBLOCKS = (NHASHES+HASHESPERBLAKE-1)/HASHESPERBLAKE;
|
||||
// nothing larger found in 100000 runs
|
||||
static const u32 MAXSOLS = 8;
|
||||
|
@ -127,50 +133,21 @@ union htunit {
|
|||
#define HASHWORDS0 WORDS(WN - DIGITBITS + RESTBITS)
|
||||
#define HASHWORDS1 WORDS(WN - 2*DIGITBITS + RESTBITS)
|
||||
|
||||
u32 min(const u32 a, const u32 b) {
|
||||
return a < b ? a : b;
|
||||
}
|
||||
|
||||
// A slot is up to HASHWORDS0 hash units followed by a tag
|
||||
typedef htunit slot0[HASHWORDS0+1];
|
||||
typedef htunit slot1[HASHWORDS1+1];
|
||||
// a bucket is NSLOTS treenodes
|
||||
struct bucket0 {
|
||||
au32 nslots;
|
||||
slot0 slots[NSLOTS];
|
||||
u32 getnslots() {
|
||||
const u32 n = min(nslots, NSLOTS);
|
||||
nslots = 0;
|
||||
return n;
|
||||
}
|
||||
u32 getslot() {
|
||||
#ifdef ATOMIC
|
||||
return std::atomic_fetch_add_explicit(&nslots, 1U, std::memory_order_relaxed);
|
||||
#else
|
||||
return nslots++;
|
||||
#endif
|
||||
}
|
||||
};
|
||||
struct bucket1 {
|
||||
au32 nslots;
|
||||
slot1 slots[NSLOTS];
|
||||
u32 getnslots() {
|
||||
const u32 n = min(nslots, NSLOTS);
|
||||
nslots = 0;
|
||||
return n;
|
||||
}
|
||||
u32 getslot() {
|
||||
#ifdef ATOMIC
|
||||
return std::atomic_fetch_add_explicit(&nslots, 1U, std::memory_order_relaxed);
|
||||
#else
|
||||
return nslots++;
|
||||
#endif
|
||||
}
|
||||
};
|
||||
typedef slot0 bucket0[NSLOTS];
|
||||
typedef slot1 bucket1[NSLOTS];
|
||||
// the N-bit hash consists of K+1 n-bit "digits"
|
||||
// each of which corresponds to a layer of NBUCKETS buckets
|
||||
typedef bucket0 digit0[NBUCKETS];
|
||||
typedef bucket1 digit1[NBUCKETS];
|
||||
typedef au32 bsizes[NBUCKETS];
|
||||
|
||||
u32 min(const u32 a, const u32 b) {
|
||||
return a < b ? a : b;
|
||||
}
|
||||
|
||||
// size (in bytes) of hash in round 0 <= r < WK
|
||||
u32 hashsize(const u32 r) {
|
||||
|
@ -219,80 +196,121 @@ struct htalloc {
|
|||
};
|
||||
|
||||
struct equi {
|
||||
blake2b_state blake_ctx;
|
||||
blake2bp_state blake_ctx;
|
||||
htalloc hta;
|
||||
bsizes *nslots;
|
||||
proof *sols;
|
||||
au32 nsols;
|
||||
u32 nthreads;
|
||||
u32 xfull;
|
||||
u32 hfull;
|
||||
u32 bfull;
|
||||
u32 hfull;
|
||||
pthread_barrier_t barry;
|
||||
equi(const u32 n_threads) {
|
||||
assert(sizeof(htunit) == 4);
|
||||
assert(WK&1); // assumed in candidate() calling indices1()
|
||||
nthreads = n_threads;
|
||||
const int err = pthread_barrier_init(&barry, NULL, nthreads);
|
||||
assert(!err);
|
||||
hta.alloctrees();
|
||||
nslots = (bsizes *)hta.alloc(2 * NBUCKETS, sizeof(au32));
|
||||
sols = (proof *)hta.alloc(MAXSOLS, sizeof(proof));
|
||||
}
|
||||
~equi() {
|
||||
hta.dealloctrees();
|
||||
free(nslots);
|
||||
free(sols);
|
||||
}
|
||||
void setnonce(const char *header, const u32 headerlen, const u32 nonce) {
|
||||
setheader(&blake_ctx, header, headerlen, nonce);
|
||||
for (u32 i = 0; i < NBUCKETS; i++)
|
||||
hta.heap0[i].nslots = 0;
|
||||
nsols = 0;
|
||||
memset(nslots, 0, NBUCKETS * sizeof(au32)); // only nslots[0] needs zeroing
|
||||
nsols = xfull = bfull = hfull = 0;
|
||||
}
|
||||
void orderindices(u32 *indices, u32 size) {
|
||||
if (indices[0] > indices[size]) {
|
||||
for (u32 i=0; i < size; i++) {
|
||||
const u32 tmp = indices[i];
|
||||
indices[i] = indices[size+i];
|
||||
indices[size+i] = tmp;
|
||||
u32 getslot0(const u32 bucketi) {
|
||||
#ifdef ATOMIC
|
||||
return std::atomic_fetch_add_explicit(&nslots[0][bucketi], 1U, std::memory_order_relaxed);
|
||||
#else
|
||||
return nslots[0][bucketi]++;
|
||||
#endif
|
||||
}
|
||||
u32 getslot1(const u32 bucketi) {
|
||||
#ifdef ATOMIC
|
||||
return std::atomic_fetch_add_explicit(&nslots[1][bucketi], 1U, std::memory_order_relaxed);
|
||||
#else
|
||||
return nslots[1][bucketi]++;
|
||||
#endif
|
||||
}
|
||||
u32 getnslots0(const u32 bid) {
|
||||
au32 &nslot = nslots[0][bid];
|
||||
const u32 n = min(nslot, NSLOTS);
|
||||
nslot = 0;
|
||||
return n;
|
||||
}
|
||||
u32 getnslots1(const u32 bid) {
|
||||
au32 &nslot = nslots[1][bid];
|
||||
const u32 n = min(nslot, NSLOTS);
|
||||
nslot = 0;
|
||||
return n;
|
||||
}
|
||||
// if merged != 0, mergesort indices and return true if dupe found
|
||||
// if merged == 0, order indices as in Wagner condition
|
||||
bool orderindices(u32 *indices, u32 size, u32 *merged) {
|
||||
if (merged) {
|
||||
u32 i = 0, j = 0, k;
|
||||
for (k = 0; i<size && j<size; k++) {
|
||||
if (indices[i] == indices[size+j]) return true;
|
||||
merged[k] = indices[i] < indices[size+j] ? indices[i++] : indices[size+j++];
|
||||
}
|
||||
memcpy(merged+k, indices+i, (size-i) * sizeof(u32));
|
||||
memcpy(indices, merged, (size+j) * sizeof(u32));
|
||||
return false;
|
||||
} else {
|
||||
if (indices[0] > indices[size]) {
|
||||
for (u32 i=0; i < size; i++) {
|
||||
const u32 tmp = indices[i];
|
||||
indices[i] = indices[size+i];
|
||||
indices[size+i] = tmp;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
void listindices0(u32 r, const tree t, u32 *indices) {
|
||||
// return true if dupe found
|
||||
bool listindices0(u32 r, const tree t, u32 *indices, u32 *merged) {
|
||||
if (r == 0) {
|
||||
*indices = t.getindex(); // TRY INTEGRATE PROBDUPE TEST HERE
|
||||
return;
|
||||
*indices = t.getindex();
|
||||
return false;
|
||||
}
|
||||
const slot1 *buck = hta.heap1[t.bucketid()].slots;
|
||||
const slot1 *buck = hta.heap1[t.bucketid()];
|
||||
const u32 size = 1 << --r;
|
||||
u32 *indices1 = indices + size;
|
||||
u32 tagi = hashwords(hashsize(r));
|
||||
listindices1(r, buck[t.slotid0()][tagi].tag, indices);
|
||||
listindices1(r, buck[t.slotid1()][tagi].tag, indices1);
|
||||
orderindices(indices, size);
|
||||
return listindices1(r, buck[t.slotid0()][tagi].tag, indices, merged)
|
||||
|| listindices1(r, buck[t.slotid1()][tagi].tag, indices1, merged)
|
||||
|| orderindices(indices, size, merged);
|
||||
}
|
||||
void listindices1(u32 r, const tree t, u32 *indices) {
|
||||
const slot0 *buck = hta.heap0[t.bucketid()].slots;
|
||||
bool listindices1(u32 r, const tree t, u32 *indices, u32 *merged) {
|
||||
const slot0 *buck = hta.heap0[t.bucketid()];
|
||||
const u32 size = 1 << --r;
|
||||
u32 *indices1 = indices + size;
|
||||
u32 tagi = hashwords(hashsize(r));
|
||||
listindices0(r, buck[t.slotid0()][tagi].tag, indices);
|
||||
listindices0(r, buck[t.slotid1()][tagi].tag, indices1);
|
||||
orderindices(indices, size);
|
||||
return listindices0(r, buck[t.slotid0()][tagi].tag, indices, merged)
|
||||
|| listindices0(r, buck[t.slotid1()][tagi].tag, indices1, merged)
|
||||
|| orderindices(indices, size, merged);
|
||||
}
|
||||
void candidate(const tree t) {
|
||||
proof prf;
|
||||
listindices1(WK, t, prf); // assume WK odd
|
||||
qsort(prf, PROOFSIZE, sizeof(u32), &compu32);
|
||||
for (u32 i=1; i<PROOFSIZE; i++)
|
||||
if (prf[i] <= prf[i-1])
|
||||
return;
|
||||
proof prf, merged;
|
||||
if (listindices1(WK, t, prf, merged)) return;
|
||||
#ifdef ATOMIC
|
||||
u32 soli = std::atomic_fetch_add_explicit(&nsols, 1U, std::memory_order_relaxed);
|
||||
#else
|
||||
u32 soli = nsols++;
|
||||
#endif
|
||||
if (soli < MAXSOLS)
|
||||
listindices1(WK, t, sols[soli]); // assume WK odd
|
||||
if (soli < MAXSOLS) listindices1(WK, t, sols[soli], 0);
|
||||
}
|
||||
void showbsizes(u32 r) {
|
||||
printf(" x%d b%d h%d\n", xfull, bfull, hfull);
|
||||
xfull = bfull = hfull = 0;
|
||||
#if defined(HIST) || defined(SPARK) || defined(LOGSPARK)
|
||||
u32 binsizes[65];
|
||||
memset(binsizes, 0, 65 * sizeof(u32));
|
||||
|
@ -431,14 +449,15 @@ struct equi {
|
|||
|
||||
void digit0(const u32 id) {
|
||||
uchar hash[HASHOUT];
|
||||
blake2b_state state;
|
||||
blake2bp_state state;
|
||||
htlayout htl(this, 0);
|
||||
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);
|
||||
// blake2bp_update(&state, (uchar *)&leb, sizeof(u32));
|
||||
// blake2bp_final(&state, hash, HASHOUT);
|
||||
blake2bp(hash, (uchar *)&leb, sizeof(u32));
|
||||
for (u32 i = 0; i<HASHESPERBLAKE; i++) {
|
||||
const uchar *ph = hash + i * WN/8;
|
||||
#if BUCKBITS == 16 && RESTBITS == 4
|
||||
|
@ -455,13 +474,12 @@ struct equi {
|
|||
#else
|
||||
#error not implemented
|
||||
#endif
|
||||
bucket0 *buck = htl.hta.heap0 + bucketid;
|
||||
const u32 slot = buck->getslot();
|
||||
const u32 slot = getslot0(bucketid);
|
||||
if (slot >= NSLOTS) {
|
||||
bfull++;
|
||||
continue;
|
||||
}
|
||||
htunit *s = buck->slots[slot] + htl.nexthtunits;
|
||||
htunit *s = hta.heap0[bucketid][slot] + htl.nexthtunits;
|
||||
memcpy(s->bytes-hashbytes, ph+WN/8-hashbytes, hashbytes);
|
||||
s->tag = tree(block * HASHESPERBLAKE + i);
|
||||
}
|
||||
|
@ -473,17 +491,17 @@ struct equi {
|
|||
collisiondata cd;
|
||||
for (u32 bucketid=id; bucketid < NBUCKETS; bucketid += nthreads) {
|
||||
cd.clear();
|
||||
bucket0 *buck = htl.hta.heap0 + bucketid;
|
||||
u32 bsize = buck->getnslots();
|
||||
slot0 *buck = htl.hta.heap0[bucketid];
|
||||
u32 bsize = getnslots0(bucketid);
|
||||
for (u32 s1 = 0; s1 < bsize; s1++) {
|
||||
const htunit *slot1 = buck->slots[s1];
|
||||
const htunit *slot1 = buck[s1];
|
||||
if (!cd.addslot(s1, htl.getxhash0(slot1))) {
|
||||
xfull++;
|
||||
continue;
|
||||
}
|
||||
for (; cd.nextcollision(); ) {
|
||||
const u32 s0 = cd.slot();
|
||||
const htunit *slot0 = buck->slots[s0];
|
||||
const htunit *slot0 = buck[s0];
|
||||
if (htl.equal(slot0, slot1)) {
|
||||
hfull++;
|
||||
continue;
|
||||
|
@ -506,13 +524,12 @@ struct equi {
|
|||
#else
|
||||
#error not implemented
|
||||
#endif
|
||||
bucket1 *xorbuck = htl.hta.heap1 + xorbucketid;
|
||||
const u32 xorslot = xorbuck->getslot();
|
||||
const u32 xorslot = getslot1(xorbucketid);
|
||||
if (xorslot >= NSLOTS) {
|
||||
bfull++;
|
||||
continue;
|
||||
}
|
||||
htunit *xs = xorbuck->slots[xorslot];
|
||||
htunit *xs = htl.hta.heap1[xorbucketid][xorslot];
|
||||
for (u32 i=htl.dunits; i < htl.prevhtunits; i++)
|
||||
xs++->word = slot0[i].word ^ slot1[i].word;
|
||||
xs->tag = tree(bucketid, s0, s1);
|
||||
|
@ -526,17 +543,17 @@ struct equi {
|
|||
collisiondata cd;
|
||||
for (u32 bucketid=id; bucketid < NBUCKETS; bucketid += nthreads) {
|
||||
cd.clear();
|
||||
bucket1 *buck = htl.hta.heap1 + bucketid; // OPTIMIZE BY UPDATING PREVIOUS
|
||||
u32 bsize = buck->getnslots();
|
||||
slot1 *buck = htl.hta.heap1[bucketid];
|
||||
u32 bsize = getnslots1(bucketid);
|
||||
for (u32 s1 = 0; s1 < bsize; s1++) {
|
||||
const htunit *slot1 = buck->slots[s1]; // OPTIMIZE BY UPDATING PREVIOUS
|
||||
const htunit *slot1 = buck[s1];
|
||||
if (!cd.addslot(s1, htl.getxhash1(slot1))) {
|
||||
xfull++;
|
||||
continue;
|
||||
}
|
||||
for (; cd.nextcollision(); ) {
|
||||
const u32 s0 = cd.slot();
|
||||
const htunit *slot0 = buck->slots[s0];
|
||||
const htunit *slot0 = buck[s0];
|
||||
if (htl.equal(slot0, slot1)) {
|
||||
hfull++;
|
||||
continue;
|
||||
|
@ -559,13 +576,12 @@ struct equi {
|
|||
#else
|
||||
#error not implemented
|
||||
#endif
|
||||
bucket0 *xorbuck = htl.hta.heap0 + xorbucketid;
|
||||
const u32 xorslot = xorbuck->getslot();
|
||||
const u32 xorslot = getslot0(xorbucketid);
|
||||
if (xorslot >= NSLOTS) {
|
||||
bfull++;
|
||||
continue;
|
||||
}
|
||||
htunit *xs = xorbuck->slots[xorslot];
|
||||
htunit *xs = htl.hta.heap0[xorbucketid][xorslot];
|
||||
for (u32 i=htl.dunits; i < htl.prevhtunits; i++)
|
||||
xs++->word = slot0[i].word ^ slot1[i].word;
|
||||
xs->tag = tree(bucketid, s0, s1);
|
||||
|
@ -574,26 +590,312 @@ struct equi {
|
|||
}
|
||||
}
|
||||
|
||||
void digit1(const u32 id) {
|
||||
htalloc heaps = hta;
|
||||
collisiondata cd;
|
||||
for (u32 bucketid=id; bucketid < NBUCKETS; bucketid += nthreads) {
|
||||
cd.clear();
|
||||
slot0 *buck = heaps.heap0[bucketid];
|
||||
u32 bsize = getnslots0(bucketid);
|
||||
for (u32 s1 = 0; s1 < bsize; s1++) {
|
||||
const htunit *slot1 = buck[s1];
|
||||
if (!cd.addslot(s1, htobe32(slot1->word) >> 20 & 0xff)) {
|
||||
xfull++;
|
||||
continue;
|
||||
}
|
||||
for (; cd.nextcollision(); ) {
|
||||
const u32 s0 = cd.slot();
|
||||
const htunit *slot0 = buck[s0];
|
||||
if (slot0[5].word == slot1[5].word) {
|
||||
hfull++;
|
||||
continue;
|
||||
}
|
||||
u32 xorbucketid = htobe32(slot0->word ^ slot1->word) >> 8 & BUCKMASK;
|
||||
const u32 xorslot = getslot1(xorbucketid);
|
||||
if (xorslot >= NSLOTS) {
|
||||
bfull++;
|
||||
continue;
|
||||
}
|
||||
u64 *x = (u64 *)heaps.heap1[xorbucketid][xorslot];
|
||||
u64 *x0 = (u64 *)slot0, *x1 = (u64 *)slot1;
|
||||
*x++ = x0[0] ^ x1[0];
|
||||
*x++ = x0[1] ^ x1[1];
|
||||
*x++ = x0[2] ^ x1[2];
|
||||
((htunit *)x)->tag = tree(bucketid, s0, s1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
void digit2(const u32 id) {
|
||||
htalloc heaps = hta;
|
||||
collisiondata cd;
|
||||
for (u32 bucketid=id; bucketid < NBUCKETS; bucketid += nthreads) {
|
||||
cd.clear();
|
||||
slot1 *buck = heaps.heap1[bucketid];
|
||||
u32 bsize = getnslots1(bucketid);
|
||||
for (u32 s1 = 0; s1 < bsize; s1++) {
|
||||
const htunit *slot1 = buck[s1];
|
||||
if (!cd.addslot(s1, slot1->bytes[3])) {
|
||||
xfull++;
|
||||
continue;
|
||||
}
|
||||
for (; cd.nextcollision(); ) {
|
||||
const u32 s0 = cd.slot();
|
||||
const htunit *slot0 = buck[s0];
|
||||
if (slot0[5].word == slot1[5].word) {
|
||||
hfull++;
|
||||
continue;
|
||||
}
|
||||
u32 xorbucketid = htobe32(slot0[1].word ^ slot1[1].word) >> 20;
|
||||
const u32 xorslot = getslot0(xorbucketid);
|
||||
if (xorslot >= NSLOTS) {
|
||||
bfull++;
|
||||
continue;
|
||||
}
|
||||
htunit *xs = heaps.heap0[xorbucketid][xorslot];
|
||||
xs++->word = slot0[1].word ^ slot1[1].word;
|
||||
u64 *x = (u64 *)xs, *x0 = (u64 *)slot0, *x1 = (u64 *)slot1;
|
||||
*x++ = x0[1] ^ x1[1];
|
||||
*x++ = x0[2] ^ x1[2];
|
||||
((htunit *)x)->tag = tree(bucketid, s0, s1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
void digit3(const u32 id) {
|
||||
htalloc heaps = hta;
|
||||
collisiondata cd;
|
||||
for (u32 bucketid=id; bucketid < NBUCKETS; bucketid += nthreads) {
|
||||
cd.clear();
|
||||
slot0 *buck = heaps.heap0[bucketid];
|
||||
u32 bsize = getnslots0(bucketid);
|
||||
for (u32 s1 = 0; s1 < bsize; s1++) {
|
||||
const htunit *slot1 = buck[s1];
|
||||
if (!cd.addslot(s1, htobe32(slot1->word) >> 12 & 0xff)) {
|
||||
xfull++;
|
||||
continue;
|
||||
}
|
||||
for (; cd.nextcollision(); ) {
|
||||
const u32 s0 = cd.slot();
|
||||
const htunit *slot0 = buck[s0];
|
||||
if (slot0[4].word == slot1[4].word) {
|
||||
hfull++;
|
||||
continue;
|
||||
}
|
||||
u32 xorbucketid = htobe32(slot0[0].word ^ slot1[0].word) & BUCKMASK;
|
||||
const u32 xorslot = getslot1(xorbucketid);
|
||||
if (xorslot >= NSLOTS) {
|
||||
bfull++;
|
||||
continue;
|
||||
}
|
||||
u64 *x = (u64 *)heaps.heap1[xorbucketid][xorslot];
|
||||
u64 *x0 = (u64 *)(slot0+1), *x1 = (u64 *)(slot1+1);
|
||||
*x++ = x0[0] ^ x1[0];
|
||||
*x++ = x0[1] ^ x1[1];
|
||||
((htunit *)x)->tag = tree(bucketid, s0, s1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
void digit4(const u32 id) {
|
||||
htalloc heaps = hta;
|
||||
collisiondata cd;
|
||||
for (u32 bucketid=id; bucketid < NBUCKETS; bucketid += nthreads) {
|
||||
cd.clear();
|
||||
slot1 *buck = heaps.heap1[bucketid];
|
||||
u32 bsize = getnslots1(bucketid);
|
||||
for (u32 s1 = 0; s1 < bsize; s1++) {
|
||||
const htunit *slot1 = buck[s1];
|
||||
if (!cd.addslot(s1, slot1->bytes[0])) {
|
||||
xfull++;
|
||||
continue;
|
||||
}
|
||||
for (; cd.nextcollision(); ) {
|
||||
const u32 s0 = cd.slot();
|
||||
const htunit *slot0 = buck[s0];
|
||||
if (slot0[3].word == slot1[3].word) {
|
||||
hfull++;
|
||||
continue;
|
||||
}
|
||||
u32 xorbucketid = htobe32(slot0[0].word ^ slot1[0].word) >> 12 & BUCKMASK;
|
||||
const u32 xorslot = getslot0(xorbucketid);
|
||||
if (xorslot >= NSLOTS) {
|
||||
bfull++;
|
||||
continue;
|
||||
}
|
||||
u64 *x = (u64 *)heaps.heap0[xorbucketid][xorslot];
|
||||
u64 *x0 = (u64 *)slot0, *x1 = (u64 *)slot1;
|
||||
*x++ = x0[0] ^ x1[0];
|
||||
*x++ = x0[1] ^ x1[1];
|
||||
((htunit *)x)->tag = tree(bucketid, s0, s1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
void digit5(const u32 id) {
|
||||
htalloc heaps = hta;
|
||||
collisiondata cd;
|
||||
for (u32 bucketid=id; bucketid < NBUCKETS; bucketid += nthreads) {
|
||||
cd.clear();
|
||||
slot0 *buck = heaps.heap0[bucketid];
|
||||
u32 bsize = getnslots0(bucketid);
|
||||
for (u32 s1 = 0; s1 < bsize; s1++) {
|
||||
const htunit *slot1 = buck[s1];
|
||||
if (!cd.addslot(s1, htobe32(slot1->word) >> 4 & 0xff)) {
|
||||
xfull++;
|
||||
continue;
|
||||
}
|
||||
for (; cd.nextcollision(); ) {
|
||||
const u32 s0 = cd.slot();
|
||||
const htunit *slot0 = buck[s0];
|
||||
if (slot0[3].word == slot1[3].word) {
|
||||
hfull++;
|
||||
continue;
|
||||
}
|
||||
u32 xor1 = slot0[1].word ^ slot1[1].word;
|
||||
u32 xorbucketid = (((u32)(slot0->bytes[3] ^ slot1->bytes[3]) & 0xf)
|
||||
<< 8) | (xor1 & 0xff);
|
||||
const u32 xorslot = getslot1(xorbucketid);
|
||||
if (xorslot >= NSLOTS) {
|
||||
bfull++;
|
||||
continue;
|
||||
}
|
||||
htunit *xs = heaps.heap1[xorbucketid][xorslot];
|
||||
xs++->word = xor1;
|
||||
u64 *x = (u64 *)xs, *x0 = (u64 *)slot0, *x1 = (u64 *)slot1;
|
||||
*x++ = x0[1] ^ x1[1];
|
||||
((htunit *)x)->tag = tree(bucketid, s0, s1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
void digit6(const u32 id) {
|
||||
htalloc heaps = hta;
|
||||
collisiondata cd;
|
||||
for (u32 bucketid=id; bucketid < NBUCKETS; bucketid += nthreads) {
|
||||
cd.clear();
|
||||
slot1 *buck = heaps.heap1[bucketid];
|
||||
u32 bsize = getnslots1(bucketid);
|
||||
for (u32 s1 = 0; s1 < bsize; s1++) {
|
||||
const htunit *slot1 = buck[s1];
|
||||
if (!cd.addslot(s1, slot1->bytes[1])) {
|
||||
xfull++;
|
||||
continue;
|
||||
}
|
||||
for (; cd.nextcollision(); ) {
|
||||
const u32 s0 = cd.slot();
|
||||
const htunit *slot0 = buck[s0];
|
||||
if (slot0[2].word == slot1[2].word) {
|
||||
hfull++;
|
||||
continue;
|
||||
}
|
||||
u32 xorbucketid = htobe32(slot0[0].word ^ slot1[0].word) >> 4 & BUCKMASK;
|
||||
const u32 xorslot = getslot0(xorbucketid);
|
||||
if (xorslot >= NSLOTS) {
|
||||
bfull++;
|
||||
continue;
|
||||
}
|
||||
htunit *xs = heaps.heap0[xorbucketid][xorslot];
|
||||
xs++->word = slot0[0].word ^ slot1[0].word;
|
||||
u64 *x = (u64 *)xs, *x0 = (u64 *)(slot0+1), *x1 = (u64 *)(slot1+1);
|
||||
*x++ = x0[0] ^ x1[0];
|
||||
((htunit *)x)->tag = tree(bucketid, s0, s1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
void digit7(const u32 id) {
|
||||
htalloc heaps = hta;
|
||||
collisiondata cd;
|
||||
for (u32 bucketid=id; bucketid < NBUCKETS; bucketid += nthreads) {
|
||||
cd.clear();
|
||||
slot0 *buck = heaps.heap0[bucketid];
|
||||
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)) {
|
||||
xfull++;
|
||||
continue;
|
||||
}
|
||||
for (; cd.nextcollision(); ) {
|
||||
const u32 s0 = cd.slot();
|
||||
const htunit *slot0 = buck[s0];
|
||||
if (slot0[2].word == slot1[2].word) {
|
||||
hfull++;
|
||||
continue;
|
||||
}
|
||||
u32 xorbucketid = htobe32(slot0[1].word ^ slot1[1].word) >> 16 & BUCKMASK;
|
||||
const u32 xorslot = getslot1(xorbucketid);
|
||||
if (xorslot >= NSLOTS) {
|
||||
bfull++;
|
||||
continue;
|
||||
}
|
||||
u64 *x = (u64 *)heaps.heap1[xorbucketid][xorslot];
|
||||
u64 *x0 = (u64 *)(slot0+1), *x1 = (u64 *)(slot1+1);
|
||||
*x++ = x0[0] ^ x1[0];
|
||||
((htunit *)x)->tag = tree(bucketid, s0, s1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
void digit8(const u32 id) {
|
||||
htalloc heaps = hta;
|
||||
collisiondata cd;
|
||||
for (u32 bucketid=id; bucketid < NBUCKETS; bucketid += nthreads) {
|
||||
cd.clear();
|
||||
slot1 *buck = heaps.heap1[bucketid];
|
||||
u32 bsize = getnslots1(bucketid);
|
||||
for (u32 s1 = 0; s1 < bsize; s1++) {
|
||||
const htunit *slot1 = buck[s1];
|
||||
if (!cd.addslot(s1, slot1->bytes[2])) {
|
||||
xfull++;
|
||||
continue;
|
||||
}
|
||||
for (; cd.nextcollision(); ) {
|
||||
const u32 s0 = cd.slot();
|
||||
const htunit *slot0 = buck[s0];
|
||||
u32 xor1 = slot0[1].word ^ slot1[1].word;
|
||||
if (!xor1) {
|
||||
hfull++;
|
||||
continue;
|
||||
}
|
||||
u32 xorbucketid = ((u32)(slot0->bytes[3] ^ slot1->bytes[3]) << 4)
|
||||
| (xor1 >> 4 & 0xf);
|
||||
const u32 xorslot = getslot0(xorbucketid);
|
||||
if (xorslot >= NSLOTS) {
|
||||
bfull++;
|
||||
continue;
|
||||
}
|
||||
htunit *xs = heaps.heap0[xorbucketid][xorslot];
|
||||
xs++->word = xor1;
|
||||
xs->tag = tree(bucketid, s0, s1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void digitK(const u32 id) {
|
||||
collisiondata cd;
|
||||
htlayout htl(this, WK);
|
||||
u32 nc = 0;
|
||||
u32 nc = 0;
|
||||
for (u32 bucketid = id; bucketid < NBUCKETS; bucketid += nthreads) {
|
||||
cd.clear();
|
||||
bucket0 *buck = htl.hta.heap0 + bucketid;
|
||||
u32 bsize = buck->getnslots();
|
||||
slot0 *buck = htl.hta.heap0[bucketid];
|
||||
u32 bsize = getnslots0(bucketid);
|
||||
for (u32 s1 = 0; s1 < bsize; s1++) {
|
||||
const htunit *slot1 = buck->slots[s1];
|
||||
const htunit *slot1 = buck[s1];
|
||||
if (!cd.addslot(s1, htl.getxhash0(slot1))) // assume WK odd
|
||||
continue;
|
||||
for (; cd.nextcollision(); ) {
|
||||
const u32 s0 = cd.slot();
|
||||
if (htl.equal(buck->slots[s0], slot1))
|
||||
nc++, candidate(tree(bucketid, s0, s1));
|
||||
if (htl.equal(buck[s0], slot1)) { // EASY OPTIMIZE
|
||||
candidate(tree(bucketid, s0, s1));
|
||||
nc++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
printf(" %d candidates ", nc);
|
||||
// printf(" %d candidates ", nc);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -616,30 +918,75 @@ void *worker(void *vp) {
|
|||
equi *eq = tp->eq;
|
||||
|
||||
if (tp->id == 0)
|
||||
printf("Digit 0\n");
|
||||
printf("Digit 0");
|
||||
barrier(&eq->barry);
|
||||
eq->digit0(tp->id);
|
||||
barrier(&eq->barry);
|
||||
if (tp->id == 0) {
|
||||
eq->xfull = eq->bfull = eq->hfull = 0;
|
||||
eq->showbsizes(0);
|
||||
}
|
||||
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) {
|
||||
printf(" x%d b%d h%d\n", eq->xfull, eq->bfull, eq->hfull);
|
||||
eq->xfull = eq->bfull = eq->hfull = 0;
|
||||
eq->showbsizes(r);
|
||||
}
|
||||
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);
|
||||
|
|
Loading…
Reference in New Issue