mirror of https://github.com/GOSTSec/ccminer
R4SAS
7 years ago
28 changed files with 5229 additions and 486 deletions
@ -0,0 +1,236 @@
@@ -0,0 +1,236 @@
|
||||
/* |
||||
* X12 algorithm |
||||
*/ |
||||
extern "C" { |
||||
#include "sph/sph_blake.h" |
||||
#include "sph/sph_bmw.h" |
||||
#include "sph/sph_luffa.h" |
||||
#include "sph/sph_cubehash.h" |
||||
#include "sph/sph_shavite.h" |
||||
#include "sph/sph_simd.h" |
||||
#include "sph/sph_echo.h" |
||||
#include "sph/sph_groestl.h" |
||||
#include "sph/sph_skein.h" |
||||
#include "sph/sph_jh.h" |
||||
#include "sph/sph_keccak.h" |
||||
#include "sph/sph_hamsi.h" |
||||
} |
||||
#include "miner.h" |
||||
|
||||
#include "cuda_helper.h" |
||||
#include "x11/cuda_x11.h" |
||||
|
||||
static uint32_t *d_hash[MAX_GPUS]; |
||||
|
||||
extern void x13_hamsi512_cpu_init(int thr_id, uint32_t threads); |
||||
extern void x13_hamsi512_cpu_hash_64(int thr_id, uint32_t threads, uint32_t startNounce, uint32_t *d_nonceVector, uint32_t *d_hash, int order); |
||||
|
||||
// X12 CPU Hash |
||||
extern "C" void x12hash(void *output, const void *input) |
||||
{ |
||||
sph_blake512_context ctx_blake; |
||||
sph_bmw512_context ctx_bmw; |
||||
sph_luffa512_context ctx_luffa; |
||||
sph_cubehash512_context ctx_cubehash; |
||||
sph_shavite512_context ctx_shavite; |
||||
sph_simd512_context ctx_simd; |
||||
sph_echo512_context ctx_echo; |
||||
sph_groestl512_context ctx_groestl; |
||||
sph_skein512_context ctx_skein; |
||||
sph_jh512_context ctx_jh; |
||||
sph_keccak512_context ctx_keccak; |
||||
sph_hamsi512_context ctx_hamsi; |
||||
|
||||
uint32_t hash[32]; |
||||
memset(hash, 0, sizeof hash); |
||||
|
||||
sph_blake512_init(&ctx_blake); |
||||
sph_blake512 (&ctx_blake, input, 80); |
||||
sph_blake512_close(&ctx_blake, (void*) hash); |
||||
|
||||
sph_bmw512_init(&ctx_bmw); |
||||
sph_bmw512(&ctx_bmw, (const void*) hash, 64); |
||||
sph_bmw512_close(&ctx_bmw, (void*) hash); |
||||
|
||||
sph_luffa512_init(&ctx_luffa); |
||||
sph_luffa512(&ctx_luffa, (const void*)hash, 64); |
||||
sph_luffa512_close(&ctx_luffa, (void*)hash); |
||||
|
||||
sph_cubehash512_init(&ctx_cubehash); |
||||
sph_cubehash512(&ctx_cubehash, (const void*)hash, 64); |
||||
sph_cubehash512_close(&ctx_cubehash, (void*)hash); |
||||
|
||||
sph_shavite512_init(&ctx_shavite); |
||||
sph_shavite512(&ctx_shavite, (const void*)hash, 64); |
||||
sph_shavite512_close(&ctx_shavite, (void*)hash); |
||||
|
||||
sph_simd512_init(&ctx_simd); |
||||
sph_simd512(&ctx_simd, (const void*)hash, 64); |
||||
sph_simd512_close(&ctx_simd, (void*)hash); |
||||
|
||||
sph_echo512_init(&ctx_echo); |
||||
sph_echo512(&ctx_echo, (const void*)hash, 64); |
||||
sph_echo512_close(&ctx_echo, (void*)hash); |
||||
|
||||
sph_groestl512_init(&ctx_groestl); |
||||
sph_groestl512(&ctx_groestl, (const void*) hash, 64); |
||||
sph_groestl512_close(&ctx_groestl, (void*) hash); |
||||
|
||||
sph_skein512_init(&ctx_skein); |
||||
sph_skein512(&ctx_skein, (const void*) hash, 64); |
||||
sph_skein512_close(&ctx_skein, (void*) hash); |
||||
|
||||
sph_jh512_init(&ctx_jh); |
||||
sph_jh512(&ctx_jh, (const void*) hash, 64); |
||||
sph_jh512_close(&ctx_jh, (void*) hash); |
||||
|
||||
sph_keccak512_init(&ctx_keccak); |
||||
sph_keccak512(&ctx_keccak, (const void*) hash, 64); |
||||
sph_keccak512_close(&ctx_keccak, (void*) hash); |
||||
|
||||
sph_hamsi512_init(&ctx_hamsi); |
||||
sph_hamsi512(&ctx_hamsi, (const void*) hash, 64); |
||||
sph_hamsi512_close(&ctx_hamsi, (void*) hash); |
||||
|
||||
memcpy(output, hash, 32); |
||||
} |
||||
|
||||
static bool init[MAX_GPUS] = { 0 }; |
||||
|
||||
extern "C" int scanhash_x12(int thr_id, struct work* work, uint32_t max_nonce, unsigned long *hashes_done) |
||||
{ |
||||
uint32_t *pdata = work->data; |
||||
uint32_t *ptarget = work->target; |
||||
const uint32_t first_nonce = pdata[19]; |
||||
int intensity = (device_sm[device_map[thr_id]] > 500 && !is_windows()) ? 20 : 19; |
||||
uint32_t throughput = cuda_default_throughput(thr_id, 1 << intensity); // 19=256*256*8; |
||||
//if (init[thr_id]) throughput = min(throughput, max_nonce - first_nonce); |
||||
|
||||
if (opt_benchmark) |
||||
((uint32_t*)ptarget)[7] = 0x000f; |
||||
|
||||
if (!init[thr_id]) |
||||
{ |
||||
cudaSetDevice(device_map[thr_id]); |
||||
if (opt_cudaschedule == -1 && gpu_threads == 1) { |
||||
cudaDeviceReset(); |
||||
// reduce cpu usage |
||||
cudaSetDeviceFlags(cudaDeviceScheduleBlockingSync); |
||||
CUDA_LOG_ERROR(); |
||||
} |
||||
gpulog(LOG_INFO, thr_id, "Intensity set to %g, %u cuda threads", throughput2intensity(throughput), throughput); |
||||
|
||||
quark_blake512_cpu_init(thr_id, throughput); |
||||
x11_luffaCubehash512_cpu_init(thr_id, throughput); |
||||
x11_shavite512_cpu_init(thr_id, throughput); |
||||
if (x11_simd512_cpu_init(thr_id, throughput) != 0) { |
||||
return 0; |
||||
} |
||||
x11_echo512_cpu_init(thr_id, throughput); |
||||
quark_groestl512_cpu_init(thr_id, throughput); |
||||
quark_skein512_cpu_init(thr_id, throughput); |
||||
quark_bmw512_cpu_init(thr_id, throughput); |
||||
quark_keccak512_cpu_init(thr_id, throughput); |
||||
quark_jh512_cpu_init(thr_id, throughput); |
||||
x13_hamsi512_cpu_init(thr_id, throughput); |
||||
|
||||
CUDA_CALL_OR_RET_X(cudaMalloc(&d_hash[thr_id], 16 * sizeof(uint32_t) * throughput), 0); |
||||
|
||||
cuda_check_cpu_init(thr_id, throughput); |
||||
|
||||
init[thr_id] = true; |
||||
} |
||||
|
||||
uint32_t endiandata[20]; |
||||
for (int k=0; k < 20; k++) |
||||
be32enc(&endiandata[k], pdata[k]); |
||||
|
||||
quark_blake512_cpu_setBlock_80(thr_id, endiandata); |
||||
cuda_check_cpu_setTarget(ptarget); |
||||
|
||||
do { |
||||
int order = 0; |
||||
|
||||
quark_blake512_cpu_hash_80(thr_id, throughput, pdata[19], d_hash[thr_id]); order++; |
||||
quark_bmw512_cpu_hash_64(thr_id, throughput, pdata[19], NULL, d_hash[thr_id], order++); |
||||
x11_luffaCubehash512_cpu_hash_64(thr_id, throughput, d_hash[thr_id], order++); |
||||
x11_shavite512_cpu_hash_64(thr_id, throughput, pdata[19], NULL, d_hash[thr_id], order++); |
||||
x11_simd512_cpu_hash_64(thr_id, throughput, pdata[19], NULL, d_hash[thr_id], order++); |
||||
x11_echo512_cpu_hash_64(thr_id, throughput, pdata[19], NULL, d_hash[thr_id], order++); |
||||
quark_groestl512_cpu_hash_64(thr_id, throughput, pdata[19], NULL, d_hash[thr_id], order++); |
||||
quark_skein512_cpu_hash_64(thr_id, throughput, pdata[19], NULL, d_hash[thr_id], order++); |
||||
quark_jh512_cpu_hash_64(thr_id, throughput, pdata[19], NULL, d_hash[thr_id], order++); |
||||
quark_keccak512_cpu_hash_64(thr_id, throughput, pdata[19], NULL, d_hash[thr_id], order++); |
||||
x13_hamsi512_cpu_hash_64(thr_id, throughput, pdata[19], NULL, d_hash[thr_id], order++); |
||||
|
||||
*hashes_done = pdata[19] - first_nonce + throughput; |
||||
|
||||
CUDA_LOG_ERROR(); |
||||
|
||||
work->nonces[0] = cuda_check_hash(thr_id, throughput, pdata[19], d_hash[thr_id]); |
||||
if (work->nonces[0] != UINT32_MAX) |
||||
{ |
||||
const uint32_t Htarg = ptarget[7]; |
||||
uint32_t _ALIGN(64) vhash[8]; |
||||
be32enc(&endiandata[19], work->nonces[0]); |
||||
x12hash(vhash, endiandata); |
||||
|
||||
if (vhash[7] <= ptarget[7] && fulltest(vhash, ptarget)) { |
||||
work->valid_nonces = 1; |
||||
work->nonces[1] = cuda_check_hash_suppl(thr_id, throughput, pdata[19], d_hash[thr_id], 1); |
||||
work_set_target_ratio(work, vhash); |
||||
if (work->nonces[1] != 0) { |
||||
be32enc(&endiandata[19], work->nonces[1]); |
||||
x12hash(vhash, endiandata); |
||||
bn_set_target_ratio(work, vhash, 1); |
||||
work->valid_nonces++; |
||||
pdata[19] = max(work->nonces[0], work->nonces[1]) + 1; |
||||
} else { |
||||
pdata[19] = work->nonces[0] + 1; // cursor |
||||
} |
||||
return work->valid_nonces; |
||||
} |
||||
else if (vhash[7] > Htarg) { |
||||
gpu_increment_reject(thr_id); |
||||
if (!opt_quiet) |
||||
gpulog(LOG_WARNING, thr_id, "result for %08x does not validate on CPU!", work->nonces[0]); |
||||
pdata[19] = work->nonces[0] + 1; |
||||
continue; |
||||
} |
||||
} |
||||
|
||||
if ((uint64_t)throughput + pdata[19] >= max_nonce) { |
||||
pdata[19] = max_nonce; |
||||
break; |
||||
} |
||||
pdata[19] += throughput; |
||||
|
||||
} while (!work_restart[thr_id].restart); |
||||
|
||||
*hashes_done = pdata[19] - first_nonce; |
||||
|
||||
CUDA_LOG_ERROR(); |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
// cleanup |
||||
extern "C" void free_x12(int thr_id) |
||||
{ |
||||
if (!init[thr_id]) |
||||
return; |
||||
|
||||
cudaThreadSynchronize(); |
||||
|
||||
cudaFree(d_hash[thr_id]); |
||||
|
||||
quark_blake512_cpu_free(thr_id); |
||||
quark_groestl512_cpu_free(thr_id); |
||||
x11_simd512_cpu_free(thr_id); |
||||
|
||||
cuda_check_cpu_free(thr_id); |
||||
CUDA_LOG_ERROR(); |
||||
|
||||
cudaDeviceSynchronize(); |
||||
init[thr_id] = false; |
||||
} |
@ -0,0 +1,80 @@
@@ -0,0 +1,80 @@
|
||||
#include "x11/cuda_x11.h" |
||||
|
||||
extern void x13_hamsi512_cpu_init(int thr_id, uint32_t threads); |
||||
extern void x13_hamsi512_cpu_hash_64(int thr_id, uint32_t threads, uint32_t startNonce, uint32_t *d_nonceVector, uint32_t *d_hash, int order); |
||||
|
||||
extern void x13_fugue512_cpu_init(int thr_id, uint32_t threads); |
||||
extern void x13_fugue512_cpu_hash_64(int thr_id, uint32_t threads, uint32_t startNonce, uint32_t *d_nonceVector, uint32_t *d_hash, int order); |
||||
extern void x13_fugue512_cpu_free(int thr_id); |
||||
|
||||
extern void x14_shabal512_cpu_init(int thr_id, uint32_t threads); |
||||
extern void x14_shabal512_cpu_hash_64(int thr_id, uint32_t threads, uint32_t startNonce, uint32_t *d_nonceVector, uint32_t *d_hash, int order); |
||||
|
||||
extern void x15_whirlpool_cpu_init(int thr_id, uint32_t threads, int flag); |
||||
extern void x15_whirlpool_cpu_hash_64(int thr_id, uint32_t threads, uint32_t startNonce, uint32_t *d_nonceVector, uint32_t *d_hash, int order); |
||||
extern void x15_whirlpool_cpu_free(int thr_id); |
||||
|
||||
extern void x17_sha512_cpu_init(int thr_id, uint32_t threads); |
||||
extern void x17_sha512_cpu_hash_64(int thr_id, uint32_t threads, uint32_t startNonce, uint32_t *d_hash); |
||||
|
||||
extern void x17_haval256_cpu_init(int thr_id, uint32_t threads); |
||||
extern void x17_haval256_cpu_hash_64(int thr_id, uint32_t threads, uint32_t startNonce, uint32_t *d_hash, const int outlen); |
||||
|
||||
void quark_blake512_cpu_hash_64(int thr_id, uint32_t threads, uint32_t startNonce, uint32_t *d_nonceVector, uint32_t *d_outputHash, int order); |
||||
|
||||
// ---- optimised but non compatible kernels
|
||||
|
||||
void x16_echo512_cpu_hash_64(int thr_id, uint32_t threads, uint32_t *d_hash); |
||||
|
||||
// ---- 80 bytes kernels
|
||||
|
||||
void quark_bmw512_cpu_setBlock_80(void *pdata); |
||||
void quark_bmw512_cpu_hash_80(int thr_id, uint32_t threads, uint32_t startNonce, uint32_t *d_hash, int order); |
||||
|
||||
void groestl512_setBlock_80(int thr_id, uint32_t *endiandata); |
||||
void groestl512_cuda_hash_80(const int thr_id, const uint32_t threads, const uint32_t startNonce, uint32_t *d_hash); |
||||
|
||||
void skein512_cpu_setBlock_80(void *pdata); |
||||
void skein512_cpu_hash_80(int thr_id, uint32_t threads, uint32_t startNonce, uint32_t *d_hash, int swap); |
||||
|
||||
void qubit_luffa512_cpu_init(int thr_id, uint32_t threads); |
||||
void qubit_luffa512_cpu_setBlock_80(void *pdata); |
||||
void qubit_luffa512_cpu_hash_80(int thr_id, uint32_t threads, uint32_t startNonce, uint32_t *d_hash, int order); |
||||
|
||||
void jh512_setBlock_80(int thr_id, uint32_t *endiandata); |
||||
void jh512_cuda_hash_80(const int thr_id, const uint32_t threads, const uint32_t startNonce, uint32_t *d_hash); |
||||
|
||||
void keccak512_setBlock_80(int thr_id, uint32_t *endiandata); |
||||
void keccak512_cuda_hash_80(const int thr_id, const uint32_t threads, const uint32_t startNonce, uint32_t *d_hash); |
||||
|
||||
void cubehash512_setBlock_80(int thr_id, uint32_t* endiandata); |
||||
void cubehash512_cuda_hash_80(const int thr_id, const uint32_t threads, const uint32_t startNonce, uint32_t *d_hash); |
||||
|
||||
void x11_shavite512_setBlock_80(void *pdata); |
||||
void x11_shavite512_cpu_hash_80(int thr_id, uint32_t threads, uint32_t startNonce, uint32_t *d_hash, int order); |
||||
|
||||
void x16_shabal512_setBlock_80(void *pdata); |
||||
void x16_shabal512_cuda_hash_80(int thr_id, const uint32_t threads, const uint32_t startNonce, uint32_t *d_hash); |
||||
|
||||
void x16_simd512_setBlock_80(void *pdata); |
||||
void x16_simd512_cuda_hash_80(int thr_id, const uint32_t threads, const uint32_t startNonce, uint32_t *d_hash); |
||||
|
||||
void x16_echo512_cuda_init(int thr_id, const uint32_t threads); |
||||
void x16_echo512_setBlock_80(void *pdata); |
||||
void x16_echo512_cuda_hash_80(int thr_id, const uint32_t threads, const uint32_t startNonce, uint32_t *d_hash); |
||||
|
||||
void x16_hamsi512_setBlock_80(void *pdata); |
||||
void x16_hamsi512_cuda_hash_80(int thr_id, const uint32_t threads, const uint32_t startNonce, uint32_t *d_hash); |
||||
|
||||
void x16_fugue512_cpu_init(int thr_id, uint32_t threads); |
||||
void x16_fugue512_cpu_free(int thr_id); |
||||
void x16_fugue512_setBlock_80(void *pdata); |
||||
void x16_fugue512_cuda_hash_80(int thr_id, const uint32_t threads, const uint32_t startNonce, uint32_t *d_hash); |
||||
|
||||
void x16_whirlpool512_init(int thr_id, uint32_t threads); |
||||
void x16_whirlpool512_setBlock_80(void* endiandata); |
||||
void x16_whirlpool512_hash_80(int thr_id, const uint32_t threads, const uint32_t startNonce, uint32_t *d_hash); |
||||
|
||||
void x16_sha512_setBlock_80(void *pdata); |
||||
void x16_sha512_cuda_hash_80(int thr_id, const uint32_t threads, const uint32_t startNonce, uint32_t *d_hash); |
||||
|
@ -0,0 +1,214 @@
@@ -0,0 +1,214 @@
|
||||
/** |
||||
* echo512-80 cuda kernel for X16R algorithm |
||||
* |
||||
* tpruvot 2018 - GPL code |
||||
*/ |
||||
|
||||
#include <stdio.h> |
||||
#include <memory.h> |
||||
|
||||
#include "cuda_helper.h" |
||||
|
||||
extern __device__ __device_builtin__ void __threadfence_block(void); |
||||
|
||||
#include "../x11/cuda_x11_aes.cuh" |
||||
|
||||
__device__ __forceinline__ void AES_2ROUND(const uint32_t* __restrict__ sharedMemory, |
||||
uint32_t &x0, uint32_t &x1, uint32_t &x2, uint32_t &x3, |
||||
uint32_t &k0) |
||||
{ |
||||
uint32_t y0, y1, y2, y3; |
||||
|
||||
aes_round(sharedMemory, |
||||
x0, x1, x2, x3, |
||||
k0, |
||||
y0, y1, y2, y3); |
||||
|
||||
aes_round(sharedMemory, |
||||
y0, y1, y2, y3, |
||||
x0, x1, x2, x3); |
||||
|
||||
k0++; |
||||
} |
||||
|
||||
__device__ |
||||
static void echo_round(uint32_t* const sharedMemory, uint32_t *W, uint32_t &k0) |
||||
{ |
||||
// Big Sub Words |
||||
#pragma unroll 16 |
||||
for (int idx = 0; idx < 16; idx++) { |
||||
AES_2ROUND(sharedMemory, W[(idx << 2) + 0], W[(idx << 2) + 1], W[(idx << 2) + 2], W[(idx << 2) + 3], k0); |
||||
} |
||||
|
||||
// Shift Rows |
||||
#pragma unroll 4 |
||||
for (int i = 0; i < 4; i++) |
||||
{ |
||||
uint32_t t[4]; |
||||
/// 1, 5, 9, 13 |
||||
t[0] = W[i + 4]; |
||||
t[1] = W[i + 8]; |
||||
t[2] = W[i + 24]; |
||||
t[3] = W[i + 60]; |
||||
|
||||
W[i + 4] = W[i + 20]; |
||||
W[i + 8] = W[i + 40]; |
||||
W[i + 24] = W[i + 56]; |
||||
W[i + 60] = W[i + 44]; |
||||
|
||||
W[i + 20] = W[i + 36]; |
||||
W[i + 40] = t[1]; |
||||
W[i + 56] = t[2]; |
||||
W[i + 44] = W[i + 28]; |
||||
|
||||
W[i + 28] = W[i + 12]; |
||||
W[i + 12] = t[3]; |
||||
W[i + 36] = W[i + 52]; |
||||
W[i + 52] = t[0]; |
||||
} |
||||
|
||||
// Mix Columns |
||||
#pragma unroll 4 |
||||
for (int i = 0; i < 4; i++) |
||||
{ |
||||
#pragma unroll 4 |
||||
for (int idx = 0; idx < 64; idx += 16) |
||||
{ |
||||
uint32_t a[4]; |
||||
a[0] = W[idx + i]; |
||||
a[1] = W[idx + i + 4]; |
||||
a[2] = W[idx + i + 8]; |
||||
a[3] = W[idx + i + 12]; |
||||
|
||||
uint32_t ab = a[0] ^ a[1]; |
||||
uint32_t bc = a[1] ^ a[2]; |
||||
uint32_t cd = a[2] ^ a[3]; |
||||
|
||||
uint32_t t, t2, t3; |
||||
t = (ab & 0x80808080); |
||||
t2 = (bc & 0x80808080); |
||||
t3 = (cd & 0x80808080); |
||||
|
||||
uint32_t abx = (t >> 7) * 27U ^ ((ab^t) << 1); |
||||
uint32_t bcx = (t2 >> 7) * 27U ^ ((bc^t2) << 1); |
||||
uint32_t cdx = (t3 >> 7) * 27U ^ ((cd^t3) << 1); |
||||
|
||||
W[idx + i] = bc ^ a[3] ^ abx; |
||||
W[idx + i + 4] = a[0] ^ cd ^ bcx; |
||||
W[idx + i + 8] = ab ^ a[3] ^ cdx; |
||||
W[idx + i + 12] = ab ^ a[2] ^ (abx ^ bcx ^ cdx); |
||||
} |
||||
} |
||||
} |
||||
|
||||
__device__ __forceinline__ |
||||
void cuda_echo_round_80(uint32_t *const __restrict__ sharedMemory, uint32_t *const __restrict__ data, const uint32_t nonce, uint32_t *hash) |
||||
{ |
||||
uint32_t h[29]; // <= 127 bytes input |
||||
|
||||
#pragma unroll 8 |
||||
for (int i = 0; i < 18; i += 2) |
||||
AS_UINT2(&h[i]) = AS_UINT2(&data[i]); |
||||
h[18] = data[18]; |
||||
h[19] = cuda_swab32(nonce); |
||||
h[20] = 0x80; |
||||
h[21] = h[22] = h[23] = h[24] = h[25] = h[26] = 0; |
||||
//((uint8_t*)h)[80] = 0x80; |
||||
//((uint8_t*)h)[128-17] = 0x02; |
||||
//((uint8_t*)h)[128-16] = 0x80; |
||||
//((uint8_t*)h)[128-15] = 0x02; |
||||
h[27] = 0x2000000; |
||||
h[28] = 0x280; |
||||
//h[29] = h[30] = h[31] = 0; |
||||
|
||||
uint32_t k0 = 640; // bitlen |
||||
uint32_t W[64]; |
||||
|
||||
#pragma unroll 8 |
||||
for (int i = 0; i < 32; i+=4) { |
||||
W[i] = 512; // L |
||||
W[i+1] = 0; // H |
||||
W[i+2] = 0; // X |
||||
W[i+3] = 0; |
||||
} |
||||
|
||||
uint32_t Z[16]; |
||||
#pragma unroll |
||||
for (int i = 0; i<16; i++) Z[i] = W[i]; |
||||
#pragma unroll |
||||
for (int i = 32; i<61; i++) W[i] = h[i - 32]; |
||||
#pragma unroll |
||||
for (int i = 61; i<64; i++) W[i] = 0; |
||||
|
||||
for (int i = 0; i < 10; i++) |
||||
echo_round(sharedMemory, W, k0); |
||||
|
||||
#pragma unroll 16 |
||||
for (int i = 0; i < 16; i++) { |
||||
Z[i] ^= h[i] ^ W[i] ^ W[i + 32]; |
||||
} |
||||
|
||||
#pragma unroll 8 |
||||
for (int i = 0; i < 16; i += 2) |
||||
AS_UINT2(&hash[i]) = AS_UINT2(&Z[i]); |
||||
} |
||||
|
||||
__device__ __forceinline__ |
||||
void echo_gpu_init(uint32_t *const __restrict__ sharedMemory) |
||||
{ |
||||
/* each thread startup will fill a uint32 */ |
||||
if (threadIdx.x < 128) { |
||||
sharedMemory[threadIdx.x] = d_AES0[threadIdx.x]; |
||||
sharedMemory[threadIdx.x + 256] = d_AES1[threadIdx.x]; |
||||
sharedMemory[threadIdx.x + 512] = d_AES2[threadIdx.x]; |
||||
sharedMemory[threadIdx.x + 768] = d_AES3[threadIdx.x]; |
||||
|
||||
sharedMemory[threadIdx.x + 64 * 2] = d_AES0[threadIdx.x + 64 * 2]; |
||||
sharedMemory[threadIdx.x + 64 * 2 + 256] = d_AES1[threadIdx.x + 64 * 2]; |
||||
sharedMemory[threadIdx.x + 64 * 2 + 512] = d_AES2[threadIdx.x + 64 * 2]; |
||||
sharedMemory[threadIdx.x + 64 * 2 + 768] = d_AES3[threadIdx.x + 64 * 2]; |
||||
} |
||||
} |
||||
|
||||
__host__ |
||||
void x16_echo512_cuda_init(int thr_id, const uint32_t threads) |
||||
{ |
||||
aes_cpu_init(thr_id); |
||||
} |
||||
|
||||
__constant__ static uint32_t c_PaddedMessage80[20]; |
||||
|
||||
__host__ |
||||
void x16_echo512_setBlock_80(void *endiandata) |
||||
{ |
||||
cudaMemcpyToSymbol(c_PaddedMessage80, endiandata, sizeof(c_PaddedMessage80), 0, cudaMemcpyHostToDevice); |
||||
} |
||||
|
||||
__global__ __launch_bounds__(128, 7) /* will force 72 registers */ |
||||
void x16_echo512_gpu_hash_80(uint32_t threads, uint32_t startNonce, uint64_t *g_hash) |
||||
{ |
||||
__shared__ uint32_t sharedMemory[1024]; |
||||
|
||||
echo_gpu_init(sharedMemory); |
||||
__threadfence_block(); |
||||
|
||||
const uint32_t thread = (blockDim.x * blockIdx.x + threadIdx.x); |
||||
if (thread < threads) |
||||
{ |
||||
uint64_t hashPosition = thread; |
||||
uint32_t *pHash = (uint32_t*)&g_hash[hashPosition<<3]; |
||||
|
||||
cuda_echo_round_80(sharedMemory, c_PaddedMessage80, startNonce + thread, pHash); |
||||
} |
||||
} |
||||
|
||||
__host__ |
||||
void x16_echo512_cuda_hash_80(int thr_id, const uint32_t threads, const uint32_t startNonce, uint32_t *d_hash) |
||||
{ |
||||
const uint32_t threadsperblock = 128; |
||||
|
||||
dim3 grid((threads + threadsperblock-1)/threadsperblock); |
||||
dim3 block(threadsperblock); |
||||
|
||||
x16_echo512_gpu_hash_80<<<grid, block>>>(threads, startNonce, (uint64_t*)d_hash); |
||||
} |
@ -0,0 +1,248 @@
@@ -0,0 +1,248 @@
|
||||
/** |
||||
* Echo512-64 kernel for maxwell, based on alexis work |
||||
*/ |
||||
|
||||
#include <cuda_helper.h> |
||||
#include <cuda_vector_uint2x4.h> |
||||
#include <cuda_vectors.h> |
||||
|
||||
#define INTENSIVE_GMF |
||||
#include "tribus/cuda_echo512_aes.cuh" |
||||
|
||||
#ifdef __INTELLISENSE__ |
||||
#define __byte_perm(x, y, b) x |
||||
#define atomicExch(p,y) (*p) = y |
||||
#endif |
||||
|
||||
__device__ |
||||
static void echo_round_alexis(const uint32_t sharedMemory[4][256], uint32_t *W, uint32_t &k0) |
||||
{ |
||||
// Big Sub Words |
||||
#pragma unroll 16 |
||||
for (int idx = 0; idx < 16; idx++) |
||||
AES_2ROUND(sharedMemory,W[(idx<<2) + 0], W[(idx<<2) + 1], W[(idx<<2) + 2], W[(idx<<2) + 3], k0); |
||||
|
||||
// Shift Rows |
||||
#pragma unroll 4 |
||||
for (int i = 0; i < 4; i++){ |
||||
uint32_t t[4]; |
||||
/// 1, 5, 9, 13 |
||||
t[0] = W[i+ 4]; |
||||
t[1] = W[i+ 8]; |
||||
t[2] = W[i+24]; |
||||
t[3] = W[i+60]; |
||||
W[i + 4] = W[i + 20]; |
||||
W[i + 8] = W[i + 40]; |
||||
W[i +24] = W[i + 56]; |
||||
W[i +60] = W[i + 44]; |
||||
|
||||
W[i +20] = W[i +36]; |
||||
W[i +40] = t[1]; |
||||
W[i +56] = t[2]; |
||||
W[i +44] = W[i +28]; |
||||
|
||||
W[i +28] = W[i +12]; |
||||
W[i +12] = t[3]; |
||||
W[i +36] = W[i +52]; |
||||
W[i +52] = t[0]; |
||||
} |
||||
// Mix Columns |
||||
#pragma unroll 4 |
||||
for (int i = 0; i < 4; i++){ // Schleife über je 2*uint32_t |
||||
#pragma unroll 4 |
||||
for (int idx = 0; idx < 64; idx += 16){ // Schleife über die elemnte |
||||
uint32_t a[4]; |
||||
a[0] = W[idx + i]; |
||||
a[1] = W[idx + i + 4]; |
||||
a[2] = W[idx + i + 8]; |
||||
a[3] = W[idx + i +12]; |
||||
|
||||
uint32_t ab = a[0] ^ a[1]; |
||||
uint32_t bc = a[1] ^ a[2]; |
||||
uint32_t cd = a[2] ^ a[3]; |
||||
|
||||
uint32_t t, t2, t3; |
||||
t = (ab & 0x80808080); |
||||
t2 = (bc & 0x80808080); |
||||
t3 = (cd & 0x80808080); |
||||
|
||||
uint32_t abx = (t >> 7) * 27U ^ ((ab^t) << 1); |
||||
uint32_t bcx = (t2 >> 7) * 27U ^ ((bc^t2) << 1); |
||||
uint32_t cdx = (t3 >> 7) * 27U ^ ((cd^t3) << 1); |
||||
|
||||
W[idx + i] = bc ^ a[3] ^ abx; |
||||
W[idx + i + 4] = a[0] ^ cd ^ bcx; |
||||
W[idx + i + 8] = ab ^ a[3] ^ cdx; |
||||
W[idx + i +12] = ab ^ a[2] ^ (abx ^ bcx ^ cdx); |
||||
} |
||||
} |
||||
} |
||||
|
||||
__global__ __launch_bounds__(128, 5) /* will force 80 registers */ |
||||
static void x16_echo512_gpu_hash_64(uint32_t threads, uint32_t *g_hash) |
||||
{ |
||||
__shared__ uint32_t sharedMemory[4][256]; |
||||
|
||||
aes_gpu_init128(sharedMemory); |
||||
|
||||
const uint32_t thread = (blockDim.x * blockIdx.x + threadIdx.x); |
||||
uint32_t k0; |
||||
uint32_t h[16]; |
||||
uint32_t hash[16]; |
||||
if (thread < threads) |
||||
{ |
||||
uint32_t *Hash = &g_hash[thread<<4]; |
||||
|
||||
*(uint2x4*)&h[ 0] = __ldg4((uint2x4*)&Hash[ 0]); |
||||
*(uint2x4*)&h[ 8] = __ldg4((uint2x4*)&Hash[ 8]); |
||||
|
||||
*(uint2x4*)&hash[ 0] = *(uint2x4*)&h[ 0]; |
||||
*(uint2x4*)&hash[ 8] = *(uint2x4*)&h[ 8]; |
||||
|
||||
__syncthreads(); |
||||
|
||||
const uint32_t P[48] = { |
||||
0xe7e9f5f5, 0xf5e7e9f5, 0xb3b36b23, 0xb3dbe7af, 0xa4213d7e, 0xf5e7e9f5, 0xb3b36b23, 0xb3dbe7af, |
||||
//8-12 |
||||
0x01425eb8, 0xf5e7e9f5, 0xb3b36b23, 0xb3dbe7af, 0x65978b09, 0xf5e7e9f5, 0xb3b36b23, 0xb3dbe7af, |
||||
//21-25 |
||||
0x2cb6b661, 0x6b23b3b3, 0xcf93a7cf, 0x9d9d3751, 0x9ac2dea3, 0xf5e7e9f5, 0xb3b36b23, 0xb3dbe7af, |
||||
//34-38 |
||||
0x579f9f33, 0xfbfbfbfb, 0xfbfbfbfb, 0xefefd3c7, 0xdbfde1dd, 0xf5e7e9f5, 0xb3b36b23, 0xb3dbe7af, |
||||
0x34514d9e, 0xf5e7e9f5, 0xb3b36b23, 0xb3dbe7af, 0xb134347e, 0xea6f7e7e, 0xbd7731bd, 0x8a8a1968, |
||||
0x14b8a457, 0xf5e7e9f5, 0xb3b36b23, 0xb3dbe7af, 0x265f4382, 0xf5e7e9f5, 0xb3b36b23, 0xb3dbe7af |
||||
//58-61 |
||||
}; |
||||
|
||||
k0 = 520; |
||||
|
||||
#pragma unroll 4 |
||||
for (uint32_t idx = 0; idx < 16; idx += 4) { |
||||
AES_2ROUND(sharedMemory, h[idx + 0], h[idx + 1], h[idx + 2], h[idx + 3], k0); |
||||
} |
||||
k0 += 4; |
||||
|
||||
uint32_t W[64]; |
||||
|
||||
#pragma unroll 4 |
||||
for (uint32_t i = 0; i < 4; i++) |
||||
{ |
||||
uint32_t a = P[i]; |
||||
uint32_t b = P[i + 4]; |
||||
uint32_t c = h[i + 8]; |
||||
uint32_t d = P[i + 8]; |
||||
|
||||
uint32_t ab = a ^ b; |
||||
uint32_t bc = b ^ c; |
||||
uint32_t cd = c ^ d; |
||||
|
||||
|
||||
uint32_t t = (ab & 0x80808080); |
||||
uint32_t t2 = (bc & 0x80808080); |
||||
uint32_t t3 = (cd & 0x80808080); |
||||
|
||||
uint32_t abx = (t >> 7) * 27U ^ ((ab^t) << 1); |
||||
uint32_t bcx = (t2 >> 7) * 27U ^ ((bc^t2) << 1); |
||||
uint32_t cdx = (t3 >> 7) * 27U ^ ((cd^t3) << 1); |
||||
|
||||
W[i] = abx ^ bc ^ d; |
||||
W[i + 4] = bcx ^ a ^ cd; |
||||
W[i + 8] = cdx ^ ab ^ d; |
||||
W[i +12] = abx ^ bcx ^ cdx ^ ab ^ c; |
||||
|
||||
a = P[i +12]; |
||||
b = h[i + 4]; |
||||
c = P[i +16]; |
||||
d = P[i +20]; |
||||
|
||||
ab = a ^ b; |
||||
bc = b ^ c; |
||||
cd = c ^ d; |
||||
|
||||
|
||||
t = (ab & 0x80808080); |
||||
t2 = (bc & 0x80808080); |
||||
t3 = (cd & 0x80808080); |
||||
|
||||
abx = (t >> 7) * 27U ^ ((ab^t) << 1); |
||||
bcx = (t2 >> 7) * 27U ^ ((bc^t2) << 1); |
||||
cdx = (t3 >> 7) * 27U ^ ((cd^t3) << 1); |
||||
|
||||
W[16 + i] = bc ^ d ^ abx; |
||||
W[16 + i + 4] = a ^ cd ^ bcx; |
||||
W[16 + i + 8] = d ^ ab ^ cdx; |
||||
W[16 + i + 12] = c ^ ab ^ abx ^ bcx ^ cdx; |
||||
|
||||
a = h[i]; |
||||
b = P[24 + i + 0]; |
||||
c = P[24 + i + 4]; |
||||
d = P[24 + i + 8]; |
||||
|
||||
ab = a ^ b; |
||||
bc = b ^ c; |
||||
cd = c ^ d; |
||||
|
||||
|
||||
t = (ab & 0x80808080); |
||||
t2 = (bc & 0x80808080); |
||||
t3 = (cd & 0x80808080); |
||||
|
||||
abx = (t >> 7) * 27U ^ ((ab^t) << 1); |
||||
bcx = (t2 >> 7) * 27U ^ ((bc^t2) << 1); |
||||
cdx = (t3 >> 7) * 27U ^ ((cd^t3) << 1); |
||||
|
||||
W[32 + i] = bc ^ d ^ abx; |
||||
W[32 + i + 4] = a ^ cd ^ bcx; |
||||
W[32 + i + 8] = d ^ ab ^ cdx; |
||||
W[32 + i + 12] = c ^ ab ^ abx ^ bcx ^ cdx; |
||||
|
||||
a = P[36 + i ]; |
||||
b = P[36 + i + 4]; |
||||
c = P[36 + i + 8]; |
||||
d = h[i + 12]; |
||||
|
||||
ab = a ^ b; |
||||
bc = b ^ c; |
||||
cd = c ^ d; |
||||
|
||||
t = (ab & 0x80808080); |
||||
t2 = (bc & 0x80808080); |
||||
t3 = (cd & 0x80808080); |
||||
|
||||
abx = (t >> 7) * 27U ^ ((ab^t) << 1); |
||||
bcx = (t2 >> 7) * 27U ^ ((bc^t2) << 1); |
||||
cdx = (t3 >> 7) * 27U ^ ((cd^t3) << 1); |
||||
|
||||
W[48 + i] = bc ^ d ^ abx; |
||||
W[48 + i + 4] = a ^ cd ^ bcx; |
||||
W[48 + i + 8] = d ^ ab ^ cdx; |
||||
W[48 + i + 12] = c ^ ab ^ abx ^ bcx ^ cdx; |
||||
|
||||
} |
||||
|
||||
for (int k = 1; k < 10; k++) |
||||
echo_round_alexis(sharedMemory,W,k0); |
||||
|
||||
#pragma unroll 4 |
||||
for (int i = 0; i < 16; i += 4) |
||||
{ |
||||
W[i] ^= W[32 + i] ^ 512; |
||||
W[i + 1] ^= W[32 + i + 1]; |
||||
W[i + 2] ^= W[32 + i + 2]; |
||||
W[i + 3] ^= W[32 + i + 3]; |
||||
} |
||||
*(uint2x4*)&Hash[ 0] = *(uint2x4*)&hash[ 0] ^ *(uint2x4*)&W[ 0]; |
||||
*(uint2x4*)&Hash[ 8] = *(uint2x4*)&hash[ 8] ^ *(uint2x4*)&W[ 8]; |
||||
} |
||||
} |
||||
|
||||
__host__ |
||||
void x16_echo512_cpu_hash_64(int thr_id, uint32_t threads, uint32_t *d_hash){ |
||||
|
||||
const uint32_t threadsperblock = 128; |
||||
|
||||
dim3 grid((threads + threadsperblock-1)/threadsperblock); |
||||
dim3 block(threadsperblock); |
||||
|
||||
x16_echo512_gpu_hash_64<<<grid, block>>>(threads, d_hash); |
||||
} |
@ -0,0 +1,467 @@
@@ -0,0 +1,467 @@
|
||||
|
||||
#include <stdio.h> |
||||
#include <cuda_helper.h> |
||||
|
||||
#define TPB 256 |
||||
|
||||
/* |
||||
* fugue512-80 x16r kernel implementation. |
||||
* |
||||
* ==========================(LICENSE BEGIN)============================ |
||||
* |
||||
* Copyright (c) 2018 tpruvot |
||||
* |
||||
* Permission is hereby granted, free of charge, to any person obtaining |
||||
* a copy of this software and associated documentation files (the |
||||
* "Software"), to deal in the Software without restriction, including |
||||
* without limitation the rights to use, copy, modify, merge, publish, |
||||
* distribute, sublicense, and/or sell copies of the Software, and to |
||||
* permit persons to whom the Software is furnished to do so, subject to |
||||
* the following conditions: |
||||
* |
||||
* The above copyright notice and this permission notice shall be |
||||
* included in all copies or substantial portions of the Software. |
||||
* |
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. |
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY |
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, |
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE |
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
||||
* |
||||
* ===========================(LICENSE END)============================= |
||||
*/ |
||||
|
||||
#ifdef __INTELLISENSE__ |
||||
#define __byte_perm(x, y, m) (x|y) |
||||
#define tex1Dfetch(t, n) (n) |
||||
#define __CUDACC__ |
||||
#include <cuda_texture_types.h> |
||||
#endif |
||||
|
||||
// store allocated textures device addresses |
||||
static unsigned int* d_textures[MAX_GPUS][1]; |
||||
|
||||
#define mixtab0(x) mixtabs[(x)] |
||||
#define mixtab1(x) mixtabs[(x)+256] |
||||
#define mixtab2(x) mixtabs[(x)+512] |
||||
#define mixtab3(x) mixtabs[(x)+768] |
||||
|
||||
static texture<unsigned int, 1, cudaReadModeElementType> mixTab0Tex; |
||||
|
||||
static const uint32_t mixtab0[] = { |
||||
0x63633297, 0x7c7c6feb, 0x77775ec7, 0x7b7b7af7, 0xf2f2e8e5, 0x6b6b0ab7, 0x6f6f16a7, 0xc5c56d39, |
||||
0x303090c0, 0x01010704, 0x67672e87, 0x2b2bd1ac, 0xfefeccd5, 0xd7d71371, 0xabab7c9a, 0x767659c3, |
||||
0xcaca4005, 0x8282a33e, 0xc9c94909, 0x7d7d68ef, 0xfafad0c5, 0x5959947f, 0x4747ce07, 0xf0f0e6ed, |
||||
0xadad6e82, 0xd4d41a7d, 0xa2a243be, 0xafaf608a, 0x9c9cf946, 0xa4a451a6, 0x727245d3, 0xc0c0762d, |
||||
0xb7b728ea, 0xfdfdc5d9, 0x9393d47a, 0x2626f298, 0x363682d8, 0x3f3fbdfc, 0xf7f7f3f1, 0xcccc521d, |
||||
0x34348cd0, 0xa5a556a2, 0xe5e58db9, 0xf1f1e1e9, 0x71714cdf, 0xd8d83e4d, 0x313197c4, 0x15156b54, |
||||
0x04041c10, 0xc7c76331, 0x2323e98c, 0xc3c37f21, 0x18184860, 0x9696cf6e, 0x05051b14, 0x9a9aeb5e, |
||||
0x0707151c, 0x12127e48, 0x8080ad36, 0xe2e298a5, 0xebeba781, 0x2727f59c, 0xb2b233fe, 0x757550cf, |
||||
0x09093f24, 0x8383a43a, 0x2c2cc4b0, 0x1a1a4668, 0x1b1b416c, 0x6e6e11a3, 0x5a5a9d73, 0xa0a04db6, |
||||
0x5252a553, 0x3b3ba1ec, 0xd6d61475, 0xb3b334fa, 0x2929dfa4, 0xe3e39fa1, 0x2f2fcdbc, 0x8484b126, |
||||
0x5353a257, 0xd1d10169, 0x00000000, 0xededb599, 0x2020e080, 0xfcfcc2dd, 0xb1b13af2, 0x5b5b9a77, |
||||
0x6a6a0db3, 0xcbcb4701, 0xbebe17ce, 0x3939afe4, 0x4a4aed33, 0x4c4cff2b, 0x5858937b, 0xcfcf5b11, |
||||
0xd0d0066d, 0xefefbb91, 0xaaaa7b9e, 0xfbfbd7c1, 0x4343d217, 0x4d4df82f, 0x333399cc, 0x8585b622, |
||||
0x4545c00f, 0xf9f9d9c9, 0x02020e08, 0x7f7f66e7, 0x5050ab5b, 0x3c3cb4f0, 0x9f9ff04a, 0xa8a87596, |
||||
0x5151ac5f, 0xa3a344ba, 0x4040db1b, 0x8f8f800a, 0x9292d37e, 0x9d9dfe42, 0x3838a8e0, 0xf5f5fdf9, |
||||
0xbcbc19c6, 0xb6b62fee, 0xdada3045, 0x2121e784, 0x10107040, 0xffffcbd1, 0xf3f3efe1, 0xd2d20865, |
||||
0xcdcd5519, 0x0c0c2430, 0x1313794c, 0xececb29d, 0x5f5f8667, 0x9797c86a, 0x4444c70b, 0x1717655c, |
||||
0xc4c46a3d, 0xa7a758aa, 0x7e7e61e3, 0x3d3db3f4, 0x6464278b, 0x5d5d886f, 0x19194f64, 0x737342d7, |
||||
0x60603b9b, 0x8181aa32, 0x4f4ff627, 0xdcdc225d, 0x2222ee88, 0x2a2ad6a8, 0x9090dd76, 0x88889516, |
||||
0x4646c903, 0xeeeebc95, 0xb8b805d6, 0x14146c50, 0xdede2c55, 0x5e5e8163, 0x0b0b312c, 0xdbdb3741, |
||||
0xe0e096ad, 0x32329ec8, 0x3a3aa6e8, 0x0a0a3628, 0x4949e43f, 0x06061218, 0x2424fc90, 0x5c5c8f6b, |
||||
0xc2c27825, 0xd3d30f61, 0xacac6986, 0x62623593, 0x9191da72, 0x9595c662, 0xe4e48abd, 0x797974ff, |
||||
0xe7e783b1, 0xc8c84e0d, 0x373785dc, 0x6d6d18af, 0x8d8d8e02, 0xd5d51d79, 0x4e4ef123, 0xa9a97292, |
||||
0x6c6c1fab, 0x5656b943, 0xf4f4fafd, 0xeaeaa085, 0x6565208f, 0x7a7a7df3, 0xaeae678e, 0x08083820, |
||||
0xbaba0bde, 0x787873fb, 0x2525fb94, 0x2e2ecab8, 0x1c1c5470, 0xa6a65fae, 0xb4b421e6, 0xc6c66435, |
||||
0xe8e8ae8d, 0xdddd2559, 0x747457cb, 0x1f1f5d7c, 0x4b4bea37, 0xbdbd1ec2, 0x8b8b9c1a, 0x8a8a9b1e, |
||||
0x70704bdb, 0x3e3ebaf8, 0xb5b526e2, 0x66662983, 0x4848e33b, 0x0303090c, 0xf6f6f4f5, 0x0e0e2a38, |
||||
0x61613c9f, 0x35358bd4, 0x5757be47, 0xb9b902d2, 0x8686bf2e, 0xc1c17129, 0x1d1d5374, 0x9e9ef74e, |
||||
0xe1e191a9, 0xf8f8decd, 0x9898e556, 0x11117744, 0x696904bf, 0xd9d93949, 0x8e8e870e, 0x9494c166, |
||||
0x9b9bec5a, 0x1e1e5a78, 0x8787b82a, 0xe9e9a989, 0xcece5c15, 0x5555b04f, 0x2828d8a0, 0xdfdf2b51, |
||||
0x8c8c8906, 0xa1a14ab2, 0x89899212, 0x0d0d2334, 0xbfbf10ca, 0xe6e684b5, 0x4242d513, 0x686803bb, |
||||
0x4141dc1f, 0x9999e252, 0x2d2dc3b4, 0x0f0f2d3c, 0xb0b03df6, 0x5454b74b, 0xbbbb0cda, 0x16166258 |
||||
}; |
||||
|
||||
#define TIX4(q, x00, x01, x04, x07, x08, x22, x24, x27, x30) { \ |
||||
x22 ^= x00; \ |
||||
x00 = (q); \ |
||||
x08 ^= x00; \ |
||||
x01 ^= x24; \ |
||||
x04 ^= x27; \ |
||||
x07 ^= x30; \ |
||||
} |
||||
|
||||
#define CMIX36(x00, x01, x02, x04, x05, x06, x18, x19, x20) { \ |
||||
x00 ^= x04; \ |
||||
x01 ^= x05; \ |
||||
x02 ^= x06; \ |
||||
x18 ^= x04; \ |
||||
x19 ^= x05; \ |
||||
x20 ^= x06; \ |
||||
} |
||||
|
||||
#define SMIX(x0, x1, x2, x3) { \ |
||||
uint32_t tmp; \ |
||||
uint32_t r0 = 0; \ |
||||
uint32_t r1 = 0; \ |
||||
uint32_t r2 = 0; \ |
||||
uint32_t r3 = 0; \ |
||||
uint32_t c0 = mixtab0(x0 >> 24); \ |
||||
tmp = mixtab1((x0 >> 16) & 0xFF); \ |
||||
c0 ^= tmp; \ |
||||
r1 ^= tmp; \ |
||||
tmp = mixtab2((x0 >> 8) & 0xFF); \ |
||||
c0 ^= tmp; \ |
||||
r2 ^= tmp; \ |
||||
tmp = mixtab3(x0 & 0xFF); \ |
||||
c0 ^= tmp; \ |
||||
r3 ^= tmp; \ |
||||
tmp = mixtab0(x1 >> 24); \ |
||||
uint32_t c1 = tmp; \ |
||||
r0 ^= tmp; \ |
||||
tmp = mixtab1((x1 >> 16) & 0xFF); \ |
||||
c1 ^= tmp; \ |
||||
tmp = mixtab2((x1 >> 8) & 0xFF); \ |
||||
c1 ^= tmp; \ |
||||
r2 ^= tmp; \ |
||||
tmp = mixtab3(x1 & 0xFF); \ |
||||
c1 ^= tmp; \ |
||||
r3 ^= tmp; \ |
||||
tmp = mixtab0(x2 >> 24); \ |
||||
uint32_t c2 = tmp; \ |
||||
r0 ^= tmp; \ |
||||
tmp = mixtab1((x2 >> 16) & 0xFF); \ |
||||
c2 ^= tmp; \ |
||||
r1 ^= tmp; \ |
||||
tmp = mixtab2((x2 >> 8) & 0xFF); \ |
||||
c2 ^= tmp; \ |
||||
tmp = mixtab3(x2 & 0xFF); \ |
||||
c2 ^= tmp; \ |
||||
r3 ^= tmp; \ |
||||
tmp = mixtab0(x3 >> 24); \ |
||||
uint32_t c3 = tmp; \ |
||||
r0 ^= tmp; \ |
||||
tmp = mixtab1((x3 >> 16) & 0xFF); \ |
||||
c3 ^= tmp; \ |
||||
r1 ^= tmp; \ |
||||
tmp = mixtab2((x3 >> 8) & 0xFF); \ |
||||
c3 ^= tmp; \ |
||||
r2 ^= tmp; \ |
||||
tmp = mixtab3(x3 & 0xFF); \ |
||||
c3 ^= tmp; \ |
||||
x0 = ((c0 ^ r0) & 0xFF000000) | ((c1 ^ r1) & 0x00FF0000) \ |
||||
| ((c2 ^ r2) & 0x0000FF00) | ((c3 ^ r3) & 0x000000FF); \ |
||||
x1 = ((c1 ^ (r0 << 8)) & 0xFF000000) | ((c2 ^ (r1 << 8)) & 0x00FF0000) \ |
||||
| ((c3 ^ (r2 << 8)) & 0x0000FF00) | ((c0 ^ (r3 >> 24)) & 0x000000FF); \ |
||||
x2 = ((c2 ^ (r0 << 16)) & 0xFF000000) | ((c3 ^ (r1 << 16)) & 0x00FF0000) \ |
||||
| ((c0 ^ (r2 >> 16)) & 0x0000FF00) | ((c1 ^ (r3 >> 16)) & 0x000000FF); \ |
||||
x3 = ((c3 ^ (r0 << 24)) & 0xFF000000) | ((c0 ^ (r1 >> 8)) & 0x00FF0000) \ |
||||
| ((c1 ^ (r2 >> 8)) & 0x0000FF00) | ((c2 ^ (r3 >> 8)) & 0x000000FF); \ |
||||
} |
||||
|
||||
#define SUB_ROR3 { \ |
||||
B33 = S33, B34 = S34, B35 = S35; \ |
||||
S35 = S32; S34 = S31; S33 = S30; S32 = S29; S31 = S28; S30 = S27; S29 = S26; S28 = S25; S27 = S24; \ |
||||
S26 = S23; S25 = S22; S24 = S21; S23 = S20; S22 = S19; S21 = S18; S20 = S17; S19 = S16; S18 = S15; \ |
||||
S17 = S14; S16 = S13; S15 = S12; S14 = S11; S13 = S10; S12 = S09; S11 = S08; S10 = S07; S09 = S06; \ |
||||
S08 = S05; S07 = S04; S06 = S03; S05 = S02; S04 = S01; S03 = S00; S02 = B35; S01 = B34; S00 = B33; \ |
||||
} |
||||
|
||||
#define SUB_ROR8 { \ |
||||
B28 = S28, B29 = S29, B30 = S30, B31 = S31, B32 = S32, B33 = S33, B34 = S34, B35 = S35; \ |
||||
S35 = S27; S34 = S26; S33 = S25; S32 = S24; S31 = S23; S30 = S22; S29 = S21; S28 = S20; S27 = S19; \ |
||||
S26 = S18; S25 = S17; S24 = S16; S23 = S15; S22 = S14; S21 = S13; S20 = S12; S19 = S11; S18 = S10; \ |
||||
S17 = S09; S16 = S08; S15 = S07; S14 = S06; S13 = S05; S12 = S04; S11 = S03; S10 = S02; S09 = S01; \ |
||||
S08 = S00; S07 = B35; S06 = B34; S05 = B33; S04 = B32; S03 = B31; S02 = B30; S01 = B29; S00 = B28; \ |
||||
} |
||||
|
||||
#define SUB_ROR9 { \ |
||||
B27 = S27, B28 = S28, B29 = S29, B30 = S30, B31 = S31, B32 = S32, B33 = S33, B34 = S34, B35 = S35; \ |
||||
S35 = S26; S34 = S25; S33 = S24; S32 = S23; S31 = S22; S30 = S21; S29 = S20; S28 = S19; S27 = S18; \ |
||||
S26 = S17; S25 = S16; S24 = S15; S23 = S14; S22 = S13; S21 = S12; S20 = S11; S19 = S10; S18 = S09; \ |
||||
S17 = S08; S16 = S07; S15 = S06; S14 = S05; S13 = S04; S12 = S03; S11 = S02; S10 = S01; S09 = S00; \ |
||||
S08 = B35; S07 = B34; S06 = B33; S05 = B32; S04 = B31; S03 = B30; S02 = B29; S01 = B28; S00 = B27; \ |
||||
} |
||||
|
||||
#define SUB_ROR9_3 { \ |
||||
SUB_ROR3; SUB_ROR3; SUB_ROR3; \ |
||||
} |
||||
|
||||
#define SUB_ROR12 { /* to fix */ \ |
||||
B24 = S00; B25 = S01; B26 = S02; B27 = S03; B28 = S04; B29 = S05; B30 = S06; B31 = S07; B32 = S08; B33 = S09; B34 = S10; B35 = S11; \ |
||||
S00 = S12; S01 = S13; S02 = S14; S03 = S15; S04 = S16; S05 = S17; S06 = S18; S07 = S19; S08 = S20; S09 = S21; S10 = S22; S11 = S23; \ |
||||
S12 = S24; S13 = S25; S14 = S26; S15 = S27; S16 = S28; S17 = S29; S18 = S30; S19 = S31; S20 = S32; S21 = S33; S22 = S34; S23 = S35; \ |
||||
S24 = B24; S25 = B25; S26 = B26; S27 = B27; S28 = B28; S29 = B29; S30 = B30; S31 = B31; S32 = B32; S33 = B33; S34 = B34; S35 = B35; \ |
||||
} |
||||
|
||||
#define FUGUE512_3(x, y, z) { \ |
||||
TIX4(x, S00, S01, S04, S07, S08, S22, S24, S27, S30); \ |
||||
CMIX36(S33, S34, S35, S01, S02, S03, S15, S16, S17); \ |
||||
SMIX(S33, S34, S35, S00); \ |
||||
CMIX36(S30, S31, S32, S34, S35, S00, S12, S13, S14); \ |
||||
SMIX(S30, S31, S32, S33); \ |
||||
CMIX36(S27, S28, S29, S31, S32, S33, S09, S10, S11); \ |
||||
SMIX(S27, S28, S29, S30); \ |
||||
CMIX36(S24, S25, S26, S28, S29, S30, S06, S07, S08); \ |
||||
SMIX(S24, S25, S26, S27); \ |
||||
\ |
||||
TIX4(y, S24, S25, S28, S31, S32, S10, S12, S15, S18); \ |
||||
CMIX36(S21, S22, S23, S25, S26, S27, S03, S04, S05); \ |
||||
SMIX(S21, S22, S23, S24); \ |
||||
CMIX36(S18, S19, S20, S22, S23, S24, S00, S01, S02); \ |
||||
SMIX(S18, S19, S20, S21); \ |
||||
CMIX36(S15, S16, S17, S19, S20, S21, S33, S34, S35); \ |
||||
SMIX(S15, S16, S17, S18); \ |
||||
CMIX36(S12, S13, S14, S16, S17, S18, S30, S31, S32); \ |
||||
SMIX(S12, S13, S14, S15); \ |
||||
\ |
||||
TIX4(z, S12, S13, S16, S19, S20, S34, S00, S03, S06); \ |
||||
CMIX36(S09, S10, S11, S13, S14, S15, S27, S28, S29); \ |
||||
SMIX(S09, S10, S11, S12); \ |
||||
CMIX36(S06, S07, S08, S10, S11, S12, S24, S25, S26); \ |
||||
SMIX(S06, S07, S08, S09); \ |
||||
CMIX36(S03, S04, S05, S07, S08, S09, S21, S22, S23); \ |
||||
SMIX(S03, S04, S05, S06); \ |
||||
CMIX36(S00, S01, S02, S04, S05, S06, S18, S19, S20); \ |
||||
SMIX(S00, S01, S02, S03); \ |
||||
} |
||||
|
||||
#define FUGUE512_F(w, x, y, z) { \ |
||||
TIX4(w, S00, S01, S04, S07, S08, S22, S24, S27, S30); \ |
||||
CMIX36(S33, S34, S35, S01, S02, S03, S15, S16, S17); \ |
||||
SMIX(S33, S34, S35, S00); \ |
||||
CMIX36(S30, S31, S32, S34, S35, S00, S12, S13, S14); \ |
||||
SMIX(S30, S31, S32, S33); \ |
||||
CMIX36(S27, S28, S29, S31, S32, S33, S09, S10, S11); \ |
||||
SMIX(S27, S28, S29, S30); \ |
||||
CMIX36(S24, S25, S26, S28, S29, S30, S06, S07, S08); \ |
||||
SMIX(S24, S25, S26, S27); \ |
||||
\ |
||||
TIX4(x, S24, S25, S28, S31, S32, S10, S12, S15, S18); \ |
||||
CMIX36(S21, S22, S23, S25, S26, S27, S03, S04, S05); \ |
||||
SMIX(S21, S22, S23, S24); \ |
||||
CMIX36(S18, S19, S20, S22, S23, S24, S00, S01, S02); \ |
||||
SMIX(S18, S19, S20, S21); \ |
||||
CMIX36(S15, S16, S17, S19, S20, S21, S33, S34, S35); \ |
||||
SMIX(S15, S16, S17, S18); \ |
||||
CMIX36(S12, S13, S14, S16, S17, S18, S30, S31, S32); \ |
||||
SMIX(S12, S13, S14, S15); \ |
||||
\ |
||||
TIX4(y, S12, S13, S16, S19, S20, S34, S00, S03, S06); \ |
||||
CMIX36(S09, S10, S11, S13, S14, S15, S27, S28, S29); \ |
||||
SMIX(S09, S10, S11, S12); \ |
||||
CMIX36(S06, S07, S08, S10, S11, S12, S24, S25, S26); \ |
||||
SMIX(S06, S07, S08, S09); \ |
||||
CMIX36(S03, S04, S05, S07, S08, S09, S21, S22, S23); \ |
||||
SMIX(S03, S04, S05, S06); \ |
||||
CMIX36(S00, S01, S02, S04, S05, S06, S18, S19, S20); \ |
||||
SMIX(S00, S01, S02, S03); \ |
||||
\ |
||||
TIX4(z, S00, S01, S04, S07, S08, S22, S24, S27, S30); \ |
||||
CMIX36(S33, S34, S35, S01, S02, S03, S15, S16, S17); \ |
||||
SMIX(S33, S34, S35, S00); \ |
||||
CMIX36(S30, S31, S32, S34, S35, S00, S12, S13, S14); \ |
||||
SMIX(S30, S31, S32, S33); \ |
||||
CMIX36(S27, S28, S29, S31, S32, S33, S09, S10, S11); \ |
||||
SMIX(S27, S28, S29, S30); \ |
||||
CMIX36(S24, S25, S26, S28, S29, S30, S06, S07, S08); \ |
||||
SMIX(S24, S25, S26, S27); \ |
||||
} |
||||
|
||||
#undef ROL8 |
||||
#ifdef __CUDA_ARCH__ |
||||
__device__ __forceinline__ |
||||
uint32_t ROL8(const uint32_t a) { |
||||
return __byte_perm(a, 0, 0x2103); |
||||
} |
||||
__device__ __forceinline__ |
||||
uint32_t ROR8(const uint32_t a) { |
||||
return __byte_perm(a, 0, 0x0321); |
||||
} |
||||
__device__ __forceinline__ |
||||
uint32_t ROL16(const uint32_t a) { |
||||
return __byte_perm(a, 0, 0x1032); |
||||
} |
||||
#else |
||||
#define ROL8(u) ROTL32(u, 8) |
||||
#define ROR8(u) ROTR32(u, 8) |
||||
#define ROL16(u) ROTL32(u,16) |
||||
#endif |
||||
|
||||
//#define AS_UINT4(addr) *((uint4*)(addr)) |
||||
|
||||
__constant__ static uint64_t c_PaddedMessage80[10]; |
||||
|
||||
__host__ |
||||
void x16_fugue512_setBlock_80(void *pdata) |
||||
{ |
||||
cudaMemcpyToSymbol(c_PaddedMessage80, pdata, sizeof(c_PaddedMessage80), 0, cudaMemcpyHostToDevice); |
||||
} |
||||
|
||||
/***************************************************/ |
||||
|
||||
__global__ |
||||
__launch_bounds__(TPB) |
||||
void x16_fugue512_gpu_hash_80(const uint32_t threads, const uint32_t startNonce, uint64_t *g_hash) |
||||
{ |
||||
__shared__ uint32_t mixtabs[1024]; |
||||
|
||||
// load shared mem (with 256 threads) |
||||
const uint32_t thr = threadIdx.x & 0xFF; |
||||
const uint32_t tmp = tex1Dfetch(mixTab0Tex, thr); |
||||
mixtabs[thr] = tmp; |
||||
mixtabs[thr+256] = ROR8(tmp); |
||||
mixtabs[thr+512] = ROL16(tmp); |
||||
mixtabs[thr+768] = ROL8(tmp); |
||||
#if TPB <= 256 |
||||
if (blockDim.x < 256) { |
||||
const uint32_t thr = (threadIdx.x + 0x80) & 0xFF; |
||||
const uint32_t tmp = tex1Dfetch(mixTab0Tex, thr); |
||||
mixtabs[thr] = tmp; |
||||
mixtabs[thr + 256] = ROR8(tmp); |
||||
mixtabs[thr + 512] = ROL16(tmp); |
||||
mixtabs[thr + 768] = ROL8(tmp); |
||||
} |
||||
#endif |
||||
|
||||
__syncthreads(); |
||||
|
||||
uint32_t thread = (blockDim.x * blockIdx.x + threadIdx.x); |
||||
if (thread < threads) |
||||
{ |
||||
uint32_t Data[20]; |
||||
|
||||
#pragma unroll |
||||
for(int i = 0; i < 10; i++) |
||||
AS_UINT2(&Data[i * 2]) = AS_UINT2(&c_PaddedMessage80[i]); |
||||
Data[19] = (startNonce + thread); |
||||
|
||||
uint32_t S00, S01, S02, S03, S04, S05, S06, S07, S08, S09, S10, S11; |
||||
uint32_t S12, S13, S14, S15, S16, S17, S18, S19, S20, S21, S22, S23; |
||||
uint32_t S24, S25, S26, S27, S28, S29, S30, S31, S32, S33, S34, S35; |
||||
//uint32_t B24, B25, B26, |
||||
uint32_t B27, B28, B29, B30, B31, B32, B33, B34, B35; |
||||
//const uint64_t bc = 640 bits to hash |
||||
//const uint32_t bclo = (uint32_t)(bc); |
||||
//const uint32_t bchi = (uint32_t)(bc >> 32); |
||||
|
||||
S00 = S01 = S02 = S03 = S04 = S05 = S06 = S07 = S08 = S09 = 0; |
||||
S10 = S11 = S12 = S13 = S14 = S15 = S16 = S17 = S18 = S19 = 0; |
||||
S20 = 0x8807a57e; S21 = 0xe616af75; S22 = 0xc5d3e4db; S23 = 0xac9ab027; |
||||
S24 = 0xd915f117; S25 = 0xb6eecc54; S26 = 0x06e8020b; S27 = 0x4a92efd1; |
||||
S28 = 0xaac6e2c9; S29 = 0xddb21398; S30 = 0xcae65838; S31 = 0x437f203f; |
||||
S32 = 0x25ea78e7; S33 = 0x951fddd6; S34 = 0xda6ed11d; S35 = 0xe13e3567; |
||||
|
||||
FUGUE512_3((Data[ 0]), (Data[ 1]), (Data[ 2])); |
||||
FUGUE512_3((Data[ 3]), (Data[ 4]), (Data[ 5])); |
||||
FUGUE512_3((Data[ 6]), (Data[ 7]), (Data[ 8])); |
||||
FUGUE512_3((Data[ 9]), (Data[10]), (Data[11])); |
||||
FUGUE512_3((Data[12]), (Data[13]), (Data[14])); |
||||
FUGUE512_3((Data[15]), (Data[16]), (Data[17])); |
||||
FUGUE512_F((Data[18]), (Data[19]), 0/*bchi*/, (80*8)/*bclo*/); |
||||
|
||||
// rotate right state by 3 dwords (S00 = S33, S03 = S00) |
||||
SUB_ROR3; |
||||
SUB_ROR9; |
||||
|
||||
#pragma unroll 32 |
||||
for (int i = 0; i < 32; i++) { |
||||
SUB_ROR3; |
||||
CMIX36(S00, S01, S02, S04, S05, S06, S18, S19, S20); |
||||
SMIX(S00, S01, S02, S03); |
||||
} |
||||
#pragma unroll 13 |
||||
for (int i = 0; i < 13; i++) { |
||||
S04 ^= S00; |
||||
S09 ^= S00; |
||||
S18 ^= S00; |
||||
S27 ^= S00; |
||||
SUB_ROR9; |
||||
SMIX(S00, S01, S02, S03); |
||||
S04 ^= S00; |
||||
S10 ^= S00; |
||||
S18 ^= S00; |
||||
S27 ^= S00; |
||||
SUB_ROR9; |
||||
SMIX(S00, S01, S02, S03); |
||||
S04 ^= S00; |
||||
S10 ^= S00; |
||||
S19 ^= S00; |
||||
S27 ^= S00; |
||||
SUB_ROR9; |
||||
SMIX(S00, S01, S02, S03); |
||||
S04 ^= S00; |
||||
S10 ^= S00; |
||||
S19 ^= S00; |
||||
S28 ^= S00; |
||||
SUB_ROR8; |
||||
SMIX(S00, S01, S02, S03); |
||||
} |
||||
S04 ^= S00; |
||||
S09 ^= S00; |
||||
S18 ^= S00; |
||||
S27 ^= S00; |
||||
|
||||
Data[ 0] = cuda_swab32(S01); |
||||
Data[ 1] = cuda_swab32(S02); |
||||
Data[ 2] = cuda_swab32(S03); |
||||
Data[ 3] = cuda_swab32(S04); |
||||
Data[ 4] = cuda_swab32(S09); |
||||
Data[ 5] = cuda_swab32(S10); |
||||
Data[ 6] = cuda_swab32(S11); |
||||
Data[ 7] = cuda_swab32(S12); |
||||
Data[ 8] = cuda_swab32(S18); |
||||
Data[ 9] = cuda_swab32(S19); |
||||
Data[10] = cuda_swab32(S20); |
||||
Data[11] = cuda_swab32(S21); |
||||
Data[12] = cuda_swab32(S27); |
||||
Data[13] = cuda_swab32(S28); |
||||
Data[14] = cuda_swab32(S29); |
||||
Data[15] = cuda_swab32(S30); |
||||
|
||||
const size_t hashPosition = thread; |
||||
uint64_t* pHash = &g_hash[hashPosition << 3]; |
||||
#pragma unroll 4 |
||||
for(int i = 0; i < 4; i++) |
||||
AS_UINT4(&pHash[i * 2]) = AS_UINT4(&Data[i * 4]); |
||||
} |
||||
} |
||||
|
||||
#define texDef(id, texname, texmem, texsource, texsize) { \ |
||||
unsigned int *texmem; \ |
||||
cudaMalloc(&texmem, texsize); \ |
||||
d_textures[thr_id][id] = texmem; \ |
||||
cudaMemcpy(texmem, texsource, texsize, cudaMemcpyHostToDevice); \ |
||||
texname.normalized = 0; \ |
||||
texname.filterMode = cudaFilterModePoint; \ |
||||
texname.addressMode[0] = cudaAddressModeClamp; \ |
||||
{ cudaChannelFormatDesc channelDesc = cudaCreateChannelDesc<unsigned int>(); \ |
||||
cudaBindTexture(NULL, &texname, texmem, &channelDesc, texsize ); \ |
||||
} \ |
||||
} |
||||
|
||||
__host__ |
||||
void x16_fugue512_cpu_init(int thr_id, uint32_t threads) |
||||
{ |
||||
texDef(0, mixTab0Tex, mixTab0m, mixtab0, sizeof(uint32_t)*256); |
||||
} |
||||
|
||||
__host__ |
||||
void x16_fugue512_cpu_free(int thr_id) |
||||
{ |
||||
cudaFree(d_textures[thr_id][0]); |
||||
} |
||||
|
||||
__host__ |
||||
void x16_fugue512_cuda_hash_80(int thr_id, const uint32_t threads, const uint32_t startNonce, uint32_t *d_hash) |
||||
{ |
||||
const uint32_t threadsperblock = TPB; |
||||
|
||||
dim3 grid((threads + threadsperblock-1)/threadsperblock); |
||||
dim3 block(threadsperblock); |
||||
|
||||
x16_fugue512_gpu_hash_80 <<<grid, block>>> (threads, startNonce, (uint64_t*)d_hash); |
||||
} |
@ -0,0 +1,350 @@
@@ -0,0 +1,350 @@
|
||||
/* |
||||
* Shabal-512 for X16R |
||||
* tpruvot 2018, based on alexis x14 and xevan kernlx code |
||||
*/ |
||||
|
||||
#include <cuda_helper.h> |
||||
#include <cuda_vectors.h> |
||||
#include <cuda_vector_uint2x4.h> |
||||
|
||||
typedef uint32_t sph_u32; |
||||
|
||||
#define C32(x) (x) |
||||
#define T32(x) (x) |
||||
|
||||
#define INPUT_BLOCK_ADD do { \ |
||||
B0 = T32(B0 + M0); \ |
||||
B1 = T32(B1 + M1); \ |
||||
B2 = T32(B2 + M2); \ |
||||
B3 = T32(B3 + M3); \ |
||||
B4 = T32(B4 + M4); \ |
||||
B5 = T32(B5 + M5); \ |
||||
B6 = T32(B6 + M6); \ |
||||
B7 = T32(B7 + M7); \ |
||||
B8 = T32(B8 + M8); \ |
||||
B9 = T32(B9 + M9); \ |
||||
BA = T32(BA + MA); \ |
||||
BB = T32(BB + MB); \ |
||||
BC = T32(BC + MC); \ |
||||
BD = T32(BD + MD); \ |
||||
BE = T32(BE + ME); \ |
||||
BF = T32(BF + MF); \ |
||||
} while (0) |
||||
|
||||
#define INPUT_BLOCK_SUB do { \ |
||||
C0 = T32(C0 - M0); \ |
||||
C1 = T32(C1 - M1); \ |
||||
C2 = T32(C2 - M2); \ |
||||
C3 = T32(C3 - M3); \ |
||||
C4 = T32(C4 - M4); \ |
||||
C5 = T32(C5 - M5); \ |
||||
C6 = T32(C6 - M6); \ |
||||
C7 = T32(C7 - M7); \ |
||||
C8 = T32(C8 - M8); \ |
||||
C9 = T32(C9 - M9); \ |
||||
CA = T32(CA - MA); \ |
||||
CB = T32(CB - MB); \ |
||||
CC = T32(CC - MC); \ |
||||
CD = T32(CD - MD); \ |
||||
CE = T32(CE - ME); \ |
||||
CF = T32(CF - MF); \ |
||||
} while (0) |
||||
|
||||
#define XOR_W do { \ |
||||
A00 ^= Wlow; \ |
||||
A01 ^= Whigh; \ |
||||
} while (0) |
||||
|
||||
#define SWAP(v1, v2) do { \ |
||||
sph_u32 tmp = (v1); \ |
||||
(v1) = (v2); \ |
||||
(v2) = tmp; \ |
||||
} while (0) |
||||
|
||||
#define SWAP_BC do { \ |
||||
SWAP(B0, C0); \ |
||||
SWAP(B1, C1); \ |
||||
SWAP(B2, C2); \ |
||||
SWAP(B3, C3); \ |
||||
SWAP(B4, C4); \ |
||||
SWAP(B5, C5); \ |
||||
SWAP(B6, C6); \ |
||||
SWAP(B7, C7); \ |
||||
SWAP(B8, C8); \ |
||||
SWAP(B9, C9); \ |
||||
SWAP(BA, CA); \ |
||||
SWAP(BB, CB); \ |
||||
SWAP(BC, CC); \ |
||||
SWAP(BD, CD); \ |
||||
SWAP(BE, CE); \ |
||||
SWAP(BF, CF); \ |
||||
} while (0) |
||||
|
||||
#define PERM_ELT(xa0, xa1, xb0, xb1, xb2, xb3, xc, xm) do { \ |
||||
xa0 = T32((xa0 \ |
||||
^ (((xa1 << 15) | (xa1 >> 17)) * 5U) \ |
||||
^ xc) * 3U) \ |
||||
^ xb1 ^ (xb2 & ~xb3) ^ xm; \ |
||||
xb0 = T32(~(((xb0 << 1) | (xb0 >> 31)) ^ xa0)); \ |
||||
} while (0) |
||||
|
||||
#define PERM_STEP_0 do { \ |
||||
PERM_ELT(A00, A0B, B0, BD, B9, B6, C8, M0); \ |
||||
PERM_ELT(A01, A00, B1, BE, BA, B7, C7, M1); \ |
||||
PERM_ELT(A02, A01, B2, BF, BB, B8, C6, M2); \ |
||||
PERM_ELT(A03, A02, B3, B0, BC, B9, C5, M3); \ |
||||
PERM_ELT(A04, A03, B4, B1, BD, BA, C4, M4); \ |
||||
PERM_ELT(A05, A04, B5, B2, BE, BB, C3, M5); \ |
||||
PERM_ELT(A06, A05, B6, B3, BF, BC, C2, M6); \ |
||||
PERM_ELT(A07, A06, B7, B4, B0, BD, C1, M7); \ |
||||
PERM_ELT(A08, A07, B8, B5, B1, BE, C0, M8); \ |
||||
PERM_ELT(A09, A08, B9, B6, B2, BF, CF, M9); \ |
||||
PERM_ELT(A0A, A09, BA, B7, B3, B0, CE, MA); \ |
||||
PERM_ELT(A0B, A0A, BB, B8, B4, B1, CD, MB); \ |
||||
PERM_ELT(A00, A0B, BC, B9, B5, B2, CC, MC); \ |
||||
PERM_ELT(A01, A00, BD, BA, B6, B3, CB, MD); \ |
||||
PERM_ELT(A02, A01, BE, BB, B7, B4, CA, ME); \ |
||||
PERM_ELT(A03, A02, BF, BC, B8, B5, C9, MF); \ |
||||
} while (0) |
||||
|
||||
#define PERM_STEP_1 do { \ |
||||
PERM_ELT(A04, A03, B0, BD, B9, B6, C8, M0); \ |
||||
PERM_ELT(A05, A04, B1, BE, BA, B7, C7, M1); \ |
||||
PERM_ELT(A06, A05, B2, BF, BB, B8, C6, M2); \ |
||||
PERM_ELT(A07, A06, B3, B0, BC, B9, C5, M3); \ |
||||
PERM_ELT(A08, A07, B4, B1, BD, BA, C4, M4); \ |
||||
PERM_ELT(A09, A08, B5, B2, BE, BB, C3, M5); \ |
||||
PERM_ELT(A0A, A09, B6, B3, BF, BC, C2, M6); \ |
||||
PERM_ELT(A0B, A0A, B7, B4, B0, BD, C1, M7); \ |
||||
PERM_ELT(A00, A0B, B8, B5, B1, BE, C0, M8); \ |
||||
PERM_ELT(A01, A00, B9, B6, B2, BF, CF, M9); \ |
||||
PERM_ELT(A02, A01, BA, B7, B3, B0, CE, MA); \ |
||||
PERM_ELT(A03, A02, BB, B8, B4, B1, CD, MB); \ |
||||
PERM_ELT(A04, A03, BC, B9, B5, B2, CC, MC); \ |
||||
PERM_ELT(A05, A04, BD, BA, B6, B3, CB, MD); \ |
||||
PERM_ELT(A06, A05, BE, BB, B7, B4, CA, ME); \ |
||||
PERM_ELT(A07, A06, BF, BC, B8, B5, C9, MF); \ |
||||
} while (0) |
||||
|
||||
#define PERM_STEP_2 do { \ |
||||
PERM_ELT(A08, A07, B0, BD, B9, B6, C8, M0); \ |
||||
PERM_ELT(A09, A08, B1, BE, BA, B7, C7, M1); \ |
||||
PERM_ELT(A0A, A09, B2, BF, BB, B8, C6, M2); \ |
||||
PERM_ELT(A0B, A0A, B3, B0, BC, B9, C5, M3); \ |
||||
PERM_ELT(A00, A0B, B4, B1, BD, BA, C4, M4); \ |
||||
PERM_ELT(A01, A00, B5, B2, BE, BB, C3, M5); \ |
||||
PERM_ELT(A02, A01, B6, B3, BF, BC, C2, M6); \ |
||||
PERM_ELT(A03, A02, B7, B4, B0, BD, C1, M7); \ |
||||
PERM_ELT(A04, A03, B8, B5, B1, BE, C0, M8); \ |
||||
PERM_ELT(A05, A04, B9, B6, B2, BF, CF, M9); \ |
||||
PERM_ELT(A06, A05, BA, B7, B3, B0, CE, MA); \ |
||||
PERM_ELT(A07, A06, BB, B8, B4, B1, CD, MB); \ |
||||
PERM_ELT(A08, A07, BC, B9, B5, B2, CC, MC); \ |
||||
PERM_ELT(A09, A08, BD, BA, B6, B3, CB, MD); \ |
||||
PERM_ELT(A0A, A09, BE, BB, B7, B4, CA, ME); \ |
||||
PERM_ELT(A0B, A0A, BF, BC, B8, B5, C9, MF); \ |
||||
} while (0) |
||||
|
||||
#define APPLY_P do { \ |
||||
B0 = T32(B0 << 17) | (B0 >> 15); \ |
||||
B1 = T32(B1 << 17) | (B1 >> 15); \ |
||||
B2 = T32(B2 << 17) | (B2 >> 15); \ |
||||
B3 = T32(B3 << 17) | (B3 >> 15); \ |
||||
B4 = T32(B4 << 17) | (B4 >> 15); \ |
||||
B5 = T32(B5 << 17) | (B5 >> 15); \ |
||||
B6 = T32(B6 << 17) | (B6 >> 15); \ |
||||
B7 = T32(B7 << 17) | (B7 >> 15); \ |
||||
B8 = T32(B8 << 17) | (B8 >> 15); \ |
||||
B9 = T32(B9 << 17) | (B9 >> 15); \ |
||||
BA = T32(BA << 17) | (BA >> 15); \ |
||||
BB = T32(BB << 17) | (BB >> 15); \ |
||||
BC = T32(BC << 17) | (BC >> 15); \ |
||||
BD = T32(BD << 17) | (BD >> 15); \ |
||||
BE = T32(BE << 17) | (BE >> 15); \ |
||||
BF = T32(BF << 17) | (BF >> 15); \ |
||||
PERM_STEP_0; \ |
||||
PERM_STEP_1; \ |
||||
PERM_STEP_2; \ |
||||
A0B = T32(A0B + C6); \ |
||||
A0A = T32(A0A + C5); \ |
||||
A09 = T32(A09 + C4); \ |
||||
A08 = T32(A08 + C3); \ |
||||
A07 = T32(A07 + C2); \ |
||||
A06 = T32(A06 + C1); \ |
||||
A05 = T32(A05 + C0); \ |
||||
A04 = T32(A04 + CF); \ |
||||
A03 = T32(A03 + CE); \ |
||||
A02 = T32(A02 + CD); \ |
||||
A01 = T32(A01 + CC); \ |
||||
A00 = T32(A00 + CB); \ |
||||
A0B = T32(A0B + CA); \ |
||||
A0A = T32(A0A + C9); \ |
||||
A09 = T32(A09 + C8); \ |
||||
A08 = T32(A08 + C7); \ |
||||
A07 = T32(A07 + C6); \ |
||||
A06 = T32(A06 + C5); \ |
||||
A05 = T32(A05 + C4); \ |
||||
A04 = T32(A04 + C3); \ |
||||
A03 = T32(A03 + C2); \ |
||||
A02 = T32(A02 + C1); \ |
||||
A01 = T32(A01 + C0); \ |
||||
A00 = T32(A00 + CF); \ |
||||
A0B = T32(A0B + CE); \ |
||||
A0A = T32(A0A + CD); \ |
||||
A09 = T32(A09 + CC); \ |
||||
A08 = T32(A08 + CB); \ |
||||
A07 = T32(A07 + CA); \ |
||||
A06 = T32(A06 + C9); \ |
||||
A05 = T32(A05 + C8); \ |
||||
A04 = T32(A04 + C7); \ |
||||
A03 = T32(A03 + C6); \ |
||||
A02 = T32(A02 + C5); \ |
||||
A01 = T32(A01 + C4); \ |
||||
A00 = T32(A00 + C3); \ |
||||
} while (0) |
||||
|
||||
#define INCR_W do { \ |
||||
if ((Wlow = T32(Wlow + 1)) == 0) \ |
||||
Whigh = T32(Whigh + 1); \ |
||||
} while (0) |
||||
|
||||
__constant__ static const sph_u32 A_init_512[] = { |
||||
C32(0x20728DFD), C32(0x46C0BD53), C32(0xE782B699), C32(0x55304632), |
||||
C32(0x71B4EF90), C32(0x0EA9E82C), C32(0xDBB930F1), C32(0xFAD06B8B), |
||||
C32(0xBE0CAE40), C32(0x8BD14410), C32(0x76D2ADAC), C32(0x28ACAB7F) |
||||
}; |
||||
|
||||
__constant__ static const sph_u32 B_init_512[] = { |
||||
C32(0xC1099CB7), C32(0x07B385F3), C32(0xE7442C26), C32(0xCC8AD640), |
||||
C32(0xEB6F56C7), C32(0x1EA81AA9), C32(0x73B9D314), C32(0x1DE85D08), |
||||
C32(0x48910A5A), C32(0x893B22DB), C32(0xC5A0DF44), C32(0xBBC4324E), |
||||
C32(0x72D2F240), C32(0x75941D99), C32(0x6D8BDE82), C32(0xA1A7502B) |
||||
}; |
||||
|
||||
__constant__ static const sph_u32 C_init_512[] = { |
||||
C32(0xD9BF68D1), C32(0x58BAD750), C32(0x56028CB2), C32(0x8134F359), |
||||
C32(0xB5D469D8), C32(0x941A8CC2), C32(0x418B2A6E), C32(0x04052780), |
||||
C32(0x7F07D787), C32(0x5194358F), C32(0x3C60D665), C32(0xBE97D79A), |
||||
C32(0x950C3434), C32(0xAED9A06D), C32(0x2537DC8D), C32(0x7CDB5969) |
||||
}; |
||||
|
||||
__constant__ static uint32_t c_PaddedMessage80[20]; |
||||
|
||||
__host__ |
||||
void x16_shabal512_setBlock_80(void *pdata) |
||||
{ |
||||
cudaMemcpyToSymbol(c_PaddedMessage80, pdata, sizeof(c_PaddedMessage80), 0, cudaMemcpyHostToDevice); |
||||
} |
||||
|
||||
#define TPB_SHABAL 256 |
||||
|
||||
__global__ __launch_bounds__(TPB_SHABAL, 2) |
||||
void x16_shabal512_gpu_hash_80(uint32_t threads, const uint32_t startNonce, uint32_t *g_hash) |
||||
{ |
||||
const uint32_t thread = (blockDim.x * blockIdx.x + threadIdx.x); |
||||
|
||||
uint32_t B[] = { |
||||
0xC1099CB7, 0x07B385F3, 0xE7442C26, 0xCC8AD640, 0xEB6F56C7, 0x1EA81AA9, 0x73B9D314, 0x1DE85D08, |
||||
0x48910A5A, 0x893B22DB, 0xC5A0DF44, 0xBBC4324E, 0x72D2F240, 0x75941D99, 0x6D8BDE82, 0xA1A7502B |
||||
}; |
||||
uint32_t M[16]; |
||||
|
||||
if (thread < threads) |
||||
{ |
||||
// todo: try __ldc |
||||
*(uint2x4*)&M[0] = *(uint2x4*)&c_PaddedMessage80[0]; |
||||
*(uint2x4*)&M[8] = *(uint2x4*)&c_PaddedMessage80[8]; |
||||
|
||||
sph_u32 A00 = A_init_512[0], A01 = A_init_512[1], A02 = A_init_512[ 2], A03 = A_init_512[ 3]; |
||||
sph_u32 A04 = A_init_512[4], A05 = A_init_512[5], A06 = A_init_512[ 6], A07 = A_init_512[ 7]; |
||||
sph_u32 A08 = A_init_512[8], A09 = A_init_512[9], A0A = A_init_512[10], A0B = A_init_512[11]; |
||||
|
||||
sph_u32 B0 = B_init_512[ 0], B1 = B_init_512[ 1], B2 = B_init_512[ 2], B3 = B_init_512 [3]; |
||||
sph_u32 B4 = B_init_512[ 4], B5 = B_init_512[ 5], B6 = B_init_512[ 6], B7 = B_init_512[ 7]; |
||||
sph_u32 B8 = B_init_512[ 8], B9 = B_init_512[ 9], BA = B_init_512[10], BB = B_init_512[11]; |
||||
sph_u32 BC = B_init_512[12], BD = B_init_512[13], BE = B_init_512[14], BF = B_init_512[15]; |
||||
|
||||
sph_u32 C0 = C_init_512[ 0], C1 = C_init_512[ 1], C2 = C_init_512[ 2], C3 = C_init_512[ 3]; |
||||
sph_u32 C4 = C_init_512[ 4], C5 = C_init_512[ 5], C6 = C_init_512[ 6], C7 = C_init_512[ 7]; |
||||
sph_u32 C8 = C_init_512[ 8], C9 = C_init_512[ 9], CA = C_init_512[10], CB = C_init_512[11]; |
||||
sph_u32 CC = C_init_512[12], CD = C_init_512[13], CE = C_init_512[14], CF = C_init_512[15]; |
||||
|
||||
sph_u32 M0, M1, M2, M3, M4, M5, M6, M7, M8, M9, MA, MB, MC, MD, ME, MF; |
||||
sph_u32 Wlow = 1, Whigh = 0; |
||||
|
||||
M0 = M[ 0]; |
||||
M1 = M[ 1]; |
||||
M2 = M[ 2]; |
||||
M3 = M[ 3]; |
||||
M4 = M[ 4]; |
||||
M5 = M[ 5]; |
||||
M6 = M[ 6]; |
||||
M7 = M[ 7]; |
||||
M8 = M[ 8]; |
||||
M9 = M[ 9]; |
||||
MA = M[10]; |
||||
MB = M[11]; |
||||
MC = M[12]; |
||||
MD = M[13]; |
||||
ME = M[14]; |
||||
MF = M[15]; |
||||
|
||||
INPUT_BLOCK_ADD; |
||||
XOR_W; |
||||
APPLY_P; |
||||
INPUT_BLOCK_SUB; |
||||
SWAP_BC; |
||||
INCR_W; |
||||
|
||||
M0 = c_PaddedMessage80[16]; |
||||
M1 = c_PaddedMessage80[17]; |
||||
M2 = c_PaddedMessage80[18]; |
||||
M3 = cuda_swab32(startNonce + thread); |
||||
M4 = 0x80; |
||||
M5 = M6 = M7 = M8 = M9 = MA = MB = MC = MD = ME = MF = 0; |
||||
|
||||
INPUT_BLOCK_ADD; |
||||
XOR_W; |
||||
APPLY_P; |
||||
|
||||
for (unsigned i = 0; i < 3; i++) { |
||||
SWAP_BC; |
||||
XOR_W; |
||||
APPLY_P; |
||||
} |
||||
|
||||
B[ 0] = B0; |
||||
B[ 1] = B1; |
||||
B[ 2] = B2; |
||||
B[ 3] = B3; |
||||
B[ 4] = B4; |
||||
B[ 5] = B5; |
||||
B[ 6] = B6; |
||||
B[ 7] = B7; |
||||
B[ 8] = B8; |
||||
B[ 9] = B9; |
||||
B[10] = BA; |
||||
B[11] = BB; |
||||
B[12] = BC; |
||||
B[13] = BD; |
||||
B[14] = BE; |
||||
B[15] = BF; |
||||
|
||||
// output |
||||
uint64_t hashPosition = thread; |
||||
uint32_t *Hash = &g_hash[hashPosition << 4]; |
||||
*(uint2x4*)&Hash[0] = *(uint2x4*)&B[0]; |
||||
*(uint2x4*)&Hash[8] = *(uint2x4*)&B[8]; |
||||
} |
||||
} |
||||
|
||||
__host__ |
||||
void x16_shabal512_cuda_hash_80(int thr_id, const uint32_t threads, const uint32_t startNonce, uint32_t *d_hash) |
||||
{ |
||||
const uint32_t threadsperblock = TPB_SHABAL; |
||||
|
||||
dim3 grid((threads + threadsperblock - 1) / threadsperblock); |
||||
dim3 block(threadsperblock); |
||||
|
||||
x16_shabal512_gpu_hash_80 <<<grid, block >>>(threads, startNonce, d_hash); |
||||
} |
@ -0,0 +1,622 @@
@@ -0,0 +1,622 @@
|
||||
/** |
||||
* X16R algorithm (X16 with Randomized chain order) |
||||
* |
||||
* tpruvot 2018 - GPL code |
||||
*/ |
||||
|
||||
#include <stdio.h> |
||||
#include <memory.h> |
||||
#include <unistd.h> |
||||
|
||||
extern "C" { |
||||
#include "sph/sph_blake.h" |
||||
#include "sph/sph_bmw.h" |
||||
#include "sph/sph_groestl.h" |
||||
#include "sph/sph_skein.h" |
||||
#include "sph/sph_jh.h" |
||||
#include "sph/sph_keccak.h" |
||||
|
||||
#include "sph/sph_luffa.h" |
||||
#include "sph/sph_cubehash.h" |
||||
#include "sph/sph_shavite.h" |
||||
#include "sph/sph_simd.h" |
||||
#include "sph/sph_echo.h" |
||||
|
||||
#include "sph/sph_hamsi.h" |
||||
#include "sph/sph_fugue.h" |
||||
#include "sph/sph_shabal.h" |
||||
#include "sph/sph_whirlpool.h" |
||||
#include "sph/sph_sha2.h" |
||||
} |
||||
|
||||
#include "miner.h" |
||||
#include "cuda_helper.h" |
||||
#include "cuda_x16.h" |
||||
|
||||
static uint32_t *d_hash[MAX_GPUS]; |
||||
|
||||
enum Algo { |
||||
BLAKE = 0, |
||||
BMW, |
||||
GROESTL, |
||||
JH, |
||||
KECCAK, |
||||
SKEIN, |
||||
LUFFA, |
||||
CUBEHASH, |
||||
SHAVITE, |
||||
SIMD, |
||||
ECHO, |
||||
HAMSI, |
||||
FUGUE, |
||||
SHABAL, |
||||
WHIRLPOOL, |
||||
SHA512, |
||||
HASH_FUNC_COUNT |
||||
}; |
||||
|
||||
static const char* algo_strings[] = { |
||||
"blake", |
||||
"bmw512", |
||||
"groestl", |
||||
"jh512", |
||||
"keccak", |
||||
"skein", |
||||
"luffa", |
||||
"cube", |
||||
"shavite", |
||||
"simd", |
||||
"echo", |
||||
"hamsi", |
||||
"fugue", |
||||
"shabal", |
||||
"whirlpool", |
||||
"sha512", |
||||
NULL |
||||
}; |
||||
|
||||
static __thread uint32_t s_ntime = UINT32_MAX; |
||||
static __thread char hashOrder[HASH_FUNC_COUNT + 1] = { 0 }; |
||||
|
||||
static void getAlgoString(const uint32_t* prevblock, char *output) |
||||
{ |
||||
char *sptr = output; |
||||
uint8_t* data = (uint8_t*)prevblock; |
||||
|
||||
for (uint8_t j = 0; j < HASH_FUNC_COUNT; j++) { |
||||
uint8_t b = (15 - j) >> 1; // 16 ascii hex chars, reversed |
||||
uint8_t algoDigit = (j & 1) ? data[b] & 0xF : data[b] >> 4; |
||||
if (algoDigit >= 10) |
||||
sprintf(sptr, "%c", 'A' + (algoDigit - 10)); |
||||
else |
||||
sprintf(sptr, "%u", (uint32_t) algoDigit); |
||||
sptr++; |
||||
} |
||||
*sptr = '\0'; |
||||
} |
||||
|
||||
// X16R CPU Hash (Validation) |
||||
extern "C" void x16r_hash(void *output, const void *input) |
||||
{ |
||||
unsigned char _ALIGN(64) hash[128]; |
||||
|
||||
sph_blake512_context ctx_blake; |
||||
sph_bmw512_context ctx_bmw; |
||||
sph_groestl512_context ctx_groestl; |
||||
sph_jh512_context ctx_jh; |
||||
sph_keccak512_context ctx_keccak; |
||||
sph_skein512_context ctx_skein; |
||||
sph_luffa512_context ctx_luffa; |
||||
sph_cubehash512_context ctx_cubehash; |
||||
sph_shavite512_context ctx_shavite; |
||||
sph_simd512_context ctx_simd; |
||||
sph_echo512_context ctx_echo; |
||||
sph_hamsi512_context ctx_hamsi; |
||||
sph_fugue512_context ctx_fugue; |
||||
sph_shabal512_context ctx_shabal; |
||||
sph_whirlpool_context ctx_whirlpool; |
||||
sph_sha512_context ctx_sha512; |
||||
|
||||
void *in = (void*) input; |
||||
int size = 80; |
||||
|
||||
uint32_t *in32 = (uint32_t*) input; |
||||
getAlgoString(&in32[1], hashOrder); |
||||
|
||||
for (int i = 0; i < 16; i++) |
||||
{ |
||||
const char elem = hashOrder[i]; |
||||
const uint8_t algo = elem >= 'A' ? elem - 'A' + 10 : elem - '0'; |
||||
|
||||
switch (algo) { |
||||
case BLAKE: |
||||
sph_blake512_init(&ctx_blake); |
||||
sph_blake512(&ctx_blake, in, size); |
||||
sph_blake512_close(&ctx_blake, hash); |
||||
break; |
||||
case BMW: |
||||
sph_bmw512_init(&ctx_bmw); |
||||
sph_bmw512(&ctx_bmw, in, size); |
||||
sph_bmw512_close(&ctx_bmw, hash); |
||||
break; |
||||
case GROESTL: |
||||
sph_groestl512_init(&ctx_groestl); |
||||
sph_groestl512(&ctx_groestl, in, size); |
||||
sph_groestl512_close(&ctx_groestl, hash); |
||||
break; |
||||
case SKEIN: |
||||
sph_skein512_init(&ctx_skein); |
||||
sph_skein512(&ctx_skein, in, size); |
||||
sph_skein512_close(&ctx_skein, hash); |
||||
break; |
||||
case JH: |
||||
sph_jh512_init(&ctx_jh); |
||||
sph_jh512(&ctx_jh, in, size); |
||||
sph_jh512_close(&ctx_jh, hash); |
||||
break; |
||||
case KECCAK: |
||||
sph_keccak512_init(&ctx_keccak); |
||||
sph_keccak512(&ctx_keccak, in, size); |
||||
sph_keccak512_close(&ctx_keccak, hash); |
||||
break; |
||||
case LUFFA: |
||||
sph_luffa512_init(&ctx_luffa); |
||||
sph_luffa512(&ctx_luffa, in, size); |
||||
sph_luffa512_close(&ctx_luffa, hash); |
||||
break; |
||||
case CUBEHASH: |
||||
sph_cubehash512_init(&ctx_cubehash); |
||||
sph_cubehash512(&ctx_cubehash, in, size); |
||||
sph_cubehash512_close(&ctx_cubehash, hash); |
||||
break; |
||||
case SHAVITE: |
||||
sph_shavite512_init(&ctx_shavite); |
||||
sph_shavite512(&ctx_shavite, in, size); |
||||
sph_shavite512_close(&ctx_shavite, hash); |
||||
break; |
||||
case SIMD: |
||||
sph_simd512_init(&ctx_simd); |
||||
sph_simd512(&ctx_simd, in, size); |
||||
sph_simd512_close(&ctx_simd, hash); |
||||
break; |
||||
case ECHO: |
||||
sph_echo512_init(&ctx_echo); |
||||
sph_echo512(&ctx_echo, in, size); |
||||
sph_echo512_close(&ctx_echo, hash); |
||||
break; |
||||
case HAMSI: |
||||
sph_hamsi512_init(&ctx_hamsi); |
||||
sph_hamsi512(&ctx_hamsi, in, size); |
||||
sph_hamsi512_close(&ctx_hamsi, hash); |
||||
break; |
||||
case FUGUE: |
||||
sph_fugue512_init(&ctx_fugue); |
||||
sph_fugue512(&ctx_fugue, in, size); |
||||
sph_fugue512_close(&ctx_fugue, hash); |
||||
break; |
||||
case SHABAL: |
||||
sph_shabal512_init(&ctx_shabal); |
||||
sph_shabal512(&ctx_shabal, in, size); |
||||
sph_shabal512_close(&ctx_shabal, hash); |
||||
break; |
||||
case WHIRLPOOL: |
||||
sph_whirlpool_init(&ctx_whirlpool); |
||||
sph_whirlpool(&ctx_whirlpool, in, size); |
||||
sph_whirlpool_close(&ctx_whirlpool, hash); |
||||
break; |
||||
case SHA512: |
||||
sph_sha512_init(&ctx_sha512); |
||||
sph_sha512(&ctx_sha512,(const void*) in, size); |
||||
sph_sha512_close(&ctx_sha512,(void*) hash); |
||||
break; |
||||
} |
||||
in = (void*) hash; |
||||
size = 64; |
||||
} |
||||
memcpy(output, hash, 32); |
||||
} |
||||
|
||||
void whirlpool_midstate(void *state, const void *input) |
||||
{ |
||||
sph_whirlpool_context ctx; |
||||
|
||||
sph_whirlpool_init(&ctx); |
||||
sph_whirlpool(&ctx, input, 64); |
||||
|
||||
memcpy(state, ctx.state, 64); |
||||
} |
||||
|
||||
static bool init[MAX_GPUS] = { 0 }; |
||||
static bool use_compat_kernels[MAX_GPUS] = { 0 }; |
||||
|
||||
//#define _DEBUG |
||||
#define _DEBUG_PREFIX "x16r-" |
||||
#include "cuda_debug.cuh" |
||||
|
||||
//static int algo80_tests[HASH_FUNC_COUNT] = { 0 }; |
||||
//static int algo64_tests[HASH_FUNC_COUNT] = { 0 }; |
||||
static int algo80_fails[HASH_FUNC_COUNT] = { 0 }; |
||||
|
||||
extern "C" int scanhash_x16r(int thr_id, struct work* work, uint32_t max_nonce, unsigned long *hashes_done) |
||||
{ |
||||
uint32_t *pdata = work->data; |
||||
uint32_t *ptarget = work->target; |
||||
const uint32_t first_nonce = pdata[19]; |
||||
const int dev_id = device_map[thr_id]; |
||||
int intensity = (device_sm[dev_id] > 500 && !is_windows()) ? 20 : 19; |
||||
if (strstr(device_name[dev_id], "GTX 1080")) intensity = 20; |
||||
uint32_t throughput = cuda_default_throughput(thr_id, 1U << intensity); |
||||
//if (init[thr_id]) throughput = min(throughput, max_nonce - first_nonce); |
||||
|
||||
if (!init[thr_id]) |
||||
{ |
||||
cudaSetDevice(device_map[thr_id]); |
||||
if (opt_cudaschedule == -1 && gpu_threads == 1) { |
||||
cudaDeviceReset(); |
||||
// reduce cpu usage |
||||
cudaSetDeviceFlags(cudaDeviceScheduleBlockingSync); |
||||
} |
||||
gpulog(LOG_INFO, thr_id, "Intensity set to %g, %u cuda threads", throughput2intensity(throughput), throughput); |
||||
|
||||
cuda_get_arch(thr_id); |
||||
use_compat_kernels[thr_id] = (cuda_arch[dev_id] < 500); |
||||
if (use_compat_kernels[thr_id]) |
||||
x11_echo512_cpu_init(thr_id, throughput); |
||||
|
||||
quark_blake512_cpu_init(thr_id, throughput); |
||||
quark_bmw512_cpu_init(thr_id, throughput); |
||||
quark_groestl512_cpu_init(thr_id, throughput); |
||||
quark_skein512_cpu_init(thr_id, throughput); |
||||
quark_jh512_cpu_init(thr_id, throughput); |
||||
quark_keccak512_cpu_init(thr_id, throughput); |
||||
qubit_luffa512_cpu_init(thr_id, throughput); |
||||
x11_luffa512_cpu_init(thr_id, throughput); // 64 |
||||
x11_shavite512_cpu_init(thr_id, throughput); |
||||
x11_simd512_cpu_init(thr_id, throughput); // 64 |
||||
x16_echo512_cuda_init(thr_id, throughput); |
||||
x13_hamsi512_cpu_init(thr_id, throughput); |
||||
x13_fugue512_cpu_init(thr_id, throughput); |
||||
x16_fugue512_cpu_init(thr_id, throughput); |
||||
x14_shabal512_cpu_init(thr_id, throughput); |
||||
x15_whirlpool_cpu_init(thr_id, throughput, 0); |
||||
x16_whirlpool512_init(thr_id, throughput); |
||||
x17_sha512_cpu_init(thr_id, throughput); |
||||
|
||||
CUDA_CALL_OR_RET_X(cudaMalloc(&d_hash[thr_id], (size_t) 64 * throughput), 0); |
||||
|
||||
cuda_check_cpu_init(thr_id, throughput); |
||||
|
||||
init[thr_id] = true; |
||||
} |
||||
|
||||
if (opt_benchmark) { |
||||
((uint32_t*)ptarget)[7] = 0x003f; |
||||
//((uint8_t*)pdata)[8] = 0x90; // hashOrder[0] = '9'; for simd 80 + blake512 64 |
||||
((uint8_t*)pdata)[8] = 0xAA; // hashOrder[0] = 'A'; for echo 80 + 64 |
||||
//((uint8_t*)pdata)[8] = 0xB0; // hashOrder[0] = 'B'; for hamsi 80 + blake512 64 |
||||
//((uint8_t*)pdata)[8] = 0xC0; // hashOrder[0] = 'C'; for fugue 80 + blake512 64 |
||||
//((uint8_t*)pdata)[8] = 0xE0; // hashOrder[0] = 'E'; for whirlpool 80 + blake512 64 |
||||
} |
||||
uint32_t _ALIGN(64) endiandata[20]; |
||||
|
||||
for (int k=0; k < 19; k++) |
||||
be32enc(&endiandata[k], pdata[k]); |
||||
|
||||
uint32_t ntime = swab32(pdata[17]); |
||||
if (s_ntime != ntime) { |
||||
getAlgoString(&endiandata[1], hashOrder); |
||||
s_ntime = ntime; |
||||
if (opt_debug && !thr_id) applog(LOG_DEBUG, "hash order %s (%08x)", hashOrder, ntime); |
||||
} |
||||
|
||||
cuda_check_cpu_setTarget(ptarget); |
||||
|
||||
char elem = hashOrder[0]; |
||||
const uint8_t algo80 = elem >= 'A' ? elem - 'A' + 10 : elem - '0'; |
||||
|
||||
switch (algo80) { |
||||
case BLAKE: |
||||
quark_blake512_cpu_setBlock_80(thr_id, endiandata); |
||||
break; |
||||
case BMW: |
||||
quark_bmw512_cpu_setBlock_80(endiandata); |
||||
break; |
||||
case GROESTL: |
||||
groestl512_setBlock_80(thr_id, endiandata); |
||||
break; |
||||
case JH: |
||||
jh512_setBlock_80(thr_id, endiandata); |
||||
break; |
||||
case KECCAK: |
||||
keccak512_setBlock_80(thr_id, endiandata); |
||||
break; |
||||
case SKEIN: |
||||
skein512_cpu_setBlock_80((void*)endiandata); |
||||
break; |
||||
case LUFFA: |
||||
qubit_luffa512_cpu_setBlock_80((void*)endiandata); |
||||
break; |
||||
case CUBEHASH: |
||||
cubehash512_setBlock_80(thr_id, endiandata); |
||||
break; |
||||
case SHAVITE: |
||||
x11_shavite512_setBlock_80((void*)endiandata); |
||||
break; |
||||
case SIMD: |
||||
x16_simd512_setBlock_80((void*)endiandata); |
||||
break; |
||||
case ECHO: |
||||
x16_echo512_setBlock_80((void*)endiandata); |
||||
break; |
||||
case HAMSI: |
||||
x16_hamsi512_setBlock_80((void*)endiandata); |
||||
break; |
||||
case FUGUE: |
||||
x16_fugue512_setBlock_80((void*)pdata); |
||||
break; |
||||
case SHABAL: |
||||
x16_shabal512_setBlock_80((void*)endiandata); |
||||
break; |
||||
case WHIRLPOOL: |
||||
x16_whirlpool512_setBlock_80((void*)endiandata); |
||||
break; |
||||
case SHA512: |
||||
x16_sha512_setBlock_80(endiandata); |
||||
break; |
||||
default: { |
||||
return -1; |
||||
} |
||||
} |
||||
|
||||
int warn = 0; |
||||
|
||||
do { |
||||
int order = 0; |
||||
|
||||
// Hash with CUDA |
||||
|
||||
switch (algo80) { |
||||
case BLAKE: |
||||
quark_blake512_cpu_hash_80(thr_id, throughput, pdata[19], d_hash[thr_id]); order++; |
||||
TRACE("blake80:"); |
||||
break; |
||||
case BMW: |
||||
quark_bmw512_cpu_hash_80(thr_id, throughput, pdata[19], d_hash[thr_id], order++); |
||||
TRACE("bmw80 :"); |
||||
break; |
||||
case GROESTL: |
||||
groestl512_cuda_hash_80(thr_id, throughput, pdata[19], d_hash[thr_id]); order++; |
||||
TRACE("grstl80:"); |
||||
break; |
||||
case JH: |
||||
jh512_cuda_hash_80(thr_id, throughput, pdata[19], d_hash[thr_id]); order++; |
||||
TRACE("jh51280:"); |
||||
break; |
||||
case KECCAK: |
||||
keccak512_cuda_hash_80(thr_id, throughput, pdata[19], d_hash[thr_id]); order++; |
||||
TRACE("kecck80:"); |
||||
break; |
||||
case SKEIN: |
||||
skein512_cpu_hash_80(thr_id, throughput, pdata[19], d_hash[thr_id], 1); order++; |
||||
TRACE("skein80:"); |
||||
break; |
||||
case LUFFA: |
||||
qubit_luffa512_cpu_hash_80(thr_id, throughput, pdata[19], d_hash[thr_id], order++); |
||||
TRACE("luffa80:"); |
||||
break; |
||||
case CUBEHASH: |
||||
cubehash512_cuda_hash_80(thr_id, throughput, pdata[19], d_hash[thr_id]); order++; |
||||
TRACE("cube 80:"); |
||||
break; |
||||
case SHAVITE: |
||||
x11_shavite512_cpu_hash_80(thr_id, throughput, pdata[19], d_hash[thr_id], order++); |
||||
TRACE("shavite:"); |
||||
break; |
||||
case SIMD: |
||||
x16_simd512_cuda_hash_80(thr_id, throughput, pdata[19], d_hash[thr_id]); order++; |
||||
TRACE("simd512:"); |
||||
break; |
||||
case ECHO: |
||||
x16_echo512_cuda_hash_80(thr_id, throughput, pdata[19], d_hash[thr_id]); order++; |
||||
TRACE("echo :"); |
||||
break; |
||||
case HAMSI: |
||||
x16_hamsi512_cuda_hash_80(thr_id, throughput, pdata[19], d_hash[thr_id]); order++; |
||||
TRACE("hamsi :"); |
||||
break; |
||||
case FUGUE: |
||||
x16_fugue512_cuda_hash_80(thr_id, throughput, pdata[19], d_hash[thr_id]); order++; |
||||
TRACE("fugue :"); |
||||
break; |
||||
case SHABAL: |
||||
x16_shabal512_cuda_hash_80(thr_id, throughput, pdata[19], d_hash[thr_id]); order++; |
||||
TRACE("shabal :"); |
||||
break; |
||||
case WHIRLPOOL: |
||||
x16_whirlpool512_hash_80(thr_id, throughput, pdata[19], d_hash[thr_id]); order++; |
||||
TRACE("whirl :"); |
||||
break; |
||||
case SHA512: |
||||
x16_sha512_cuda_hash_80(thr_id, throughput, pdata[19], d_hash[thr_id]); order++; |
||||
TRACE("sha512 :"); |
||||
break; |
||||
} |
||||
|
||||
for (int i = 1; i < 16; i++) |
||||
{ |
||||
const char elem = hashOrder[i]; |
||||
const uint8_t algo64 = elem >= 'A' ? elem - 'A' + 10 : elem - '0'; |
||||
|
||||
switch (algo64) { |
||||
case BLAKE: |
||||
quark_blake512_cpu_hash_64(thr_id, throughput, pdata[19], NULL, d_hash[thr_id], order++); |
||||
TRACE("blake :"); |
||||
break; |
||||
case BMW: |
||||
quark_bmw512_cpu_hash_64(thr_id, throughput, pdata[19], NULL, d_hash[thr_id], order++); |
||||
TRACE("bmw :"); |
||||
break; |
||||
case GROESTL: |
||||
quark_groestl512_cpu_hash_64(thr_id, throughput, pdata[19], NULL, d_hash[thr_id], order++); |
||||
TRACE("groestl:"); |
||||
break; |
||||
case JH: |
||||
quark_jh512_cpu_hash_64(thr_id, throughput, pdata[19], NULL, d_hash[thr_id], order++); |
||||
TRACE("jh512 :"); |
||||
break; |
||||
case KECCAK: |
||||
quark_keccak512_cpu_hash_64(thr_id, throughput, pdata[19], NULL, d_hash[thr_id], order++); |
||||
TRACE("keccak :"); |
||||
break; |
||||
case SKEIN: |
||||
quark_skein512_cpu_hash_64(thr_id, throughput, pdata[19], NULL, d_hash[thr_id], order++); |
||||
TRACE("skein :"); |
||||
break; |
||||
case LUFFA: |
||||
x11_luffa512_cpu_hash_64(thr_id, throughput, pdata[19], NULL, d_hash[thr_id], order++); |
||||
TRACE("luffa :"); |
||||
break; |
||||
case CUBEHASH: |
||||
x11_cubehash512_cpu_hash_64(thr_id, throughput, pdata[19], NULL, d_hash[thr_id], order++); |
||||
TRACE("cube :"); |
||||
break; |
||||
case SHAVITE: |
||||
x11_shavite512_cpu_hash_64(thr_id, throughput, pdata[19], NULL, d_hash[thr_id], order++); |
||||
TRACE("shavite:"); |
||||
break; |
||||
case SIMD: |
||||
x11_simd512_cpu_hash_64(thr_id, throughput, pdata[19], NULL, d_hash[thr_id], order++); |
||||
TRACE("simd :"); |
||||
break; |
||||
case ECHO: |
||||
if (use_compat_kernels[thr_id]) |
||||
x11_echo512_cpu_hash_64(thr_id, throughput, pdata[19], NULL, d_hash[thr_id], order++); |
||||
else |
||||
x16_echo512_cpu_hash_64(thr_id, throughput, d_hash[thr_id]); order++; |
||||
TRACE("echo :"); |
||||
break; |
||||
case HAMSI: |
||||
x13_hamsi512_cpu_hash_64(thr_id, throughput, pdata[19], NULL, d_hash[thr_id], order++); |
||||
TRACE("hamsi :"); |
||||
break; |
||||
case FUGUE: |
||||
x13_fugue512_cpu_hash_64(thr_id, throughput, pdata[19], NULL, d_hash[thr_id], order++); |
||||
TRACE("fugue :"); |
||||
break; |
||||
case SHABAL: |
||||
x14_shabal512_cpu_hash_64(thr_id, throughput, pdata[19], NULL, d_hash[thr_id], order++); |
||||
TRACE("shabal :"); |
||||
break; |
||||
case WHIRLPOOL: |
||||
x15_whirlpool_cpu_hash_64(thr_id, throughput, pdata[19], NULL, d_hash[thr_id], order++); |
||||
TRACE("shabal :"); |
||||
break; |
||||
case SHA512: |
||||
x17_sha512_cpu_hash_64(thr_id, throughput, pdata[19], d_hash[thr_id]); order++; |
||||
TRACE("sha512 :"); |
||||
break; |
||||
} |
||||
} |
||||
|
||||
*hashes_done = pdata[19] - first_nonce + throughput; |
||||
|
||||
work->nonces[0] = cuda_check_hash(thr_id, throughput, pdata[19], d_hash[thr_id]); |
||||
#ifdef _DEBUG |
||||
uint32_t _ALIGN(64) dhash[8]; |
||||
be32enc(&endiandata[19], pdata[19]); |
||||
x16r_hash(dhash, endiandata); |
||||
applog_hash(dhash); |
||||
return -1; |
||||
#endif |
||||
if (work->nonces[0] != UINT32_MAX) |
||||
{ |
||||
const uint32_t Htarg = ptarget[7]; |
||||
uint32_t _ALIGN(64) vhash[8]; |
||||
be32enc(&endiandata[19], work->nonces[0]); |
||||
x16r_hash(vhash, endiandata); |
||||
|
||||
if (vhash[7] <= Htarg && fulltest(vhash, ptarget)) { |
||||
work->valid_nonces = 1; |
||||
work->nonces[1] = cuda_check_hash_suppl(thr_id, throughput, pdata[19], d_hash[thr_id], 1); |
||||
work_set_target_ratio(work, vhash); |
||||
if (work->nonces[1] != 0) { |
||||
be32enc(&endiandata[19], work->nonces[1]); |
||||
x16r_hash(vhash, endiandata); |
||||
bn_set_target_ratio(work, vhash, 1); |
||||
work->valid_nonces++; |
||||
pdata[19] = max(work->nonces[0], work->nonces[1]) + 1; |
||||
} else { |
||||
pdata[19] = work->nonces[0] + 1; // cursor |
||||
} |
||||
#if 0 |
||||
gpulog(LOG_INFO, thr_id, "hash found with %s 80!", algo_strings[algo80]); |
||||
|
||||
algo80_tests[algo80] += work->valid_nonces; |
||||
char oks64[128] = { 0 }; |
||||
char oks80[128] = { 0 }; |
||||
char fails[128] = { 0 }; |
||||
for (int a = 0; a < HASH_FUNC_COUNT; a++) { |
||||
const char elem = hashOrder[a]; |
||||
const uint8_t algo64 = elem >= 'A' ? elem - 'A' + 10 : elem - '0'; |
||||
if (a > 0) algo64_tests[algo64] += work->valid_nonces; |
||||
sprintf(&oks64[strlen(oks64)], "|%X:%2d", a, algo64_tests[a] < 100 ? algo64_tests[a] : 99); |
||||
sprintf(&oks80[strlen(oks80)], "|%X:%2d", a, algo80_tests[a] < 100 ? algo80_tests[a] : 99); |
||||
sprintf(&fails[strlen(fails)], "|%X:%2d", a, algo80_fails[a] < 100 ? algo80_fails[a] : 99); |
||||
} |
||||
applog(LOG_INFO, "K64: %s", oks64); |
||||
applog(LOG_INFO, "K80: %s", oks80); |
||||
applog(LOG_ERR, "F80: %s", fails); |
||||
#endif |
||||
return work->valid_nonces; |
||||
} |
||||
else if (vhash[7] > Htarg) { |
||||
// x11+ coins could do some random error, but not on retry |
||||
gpu_increment_reject(thr_id); |
||||
algo80_fails[algo80]++; |
||||
if (!warn) { |
||||
warn++; |
||||
pdata[19] = work->nonces[0] + 1; |
||||
continue; |
||||
} else { |
||||
if (!opt_quiet) gpulog(LOG_WARNING, thr_id, "result for %08x does not validate on CPU! %s %s", |
||||
work->nonces[0], algo_strings[algo80], hashOrder); |
||||
warn = 0; |
||||
} |
||||
} |
||||
} |
||||
|
||||
if ((uint64_t)throughput + pdata[19] >= max_nonce) { |
||||
pdata[19] = max_nonce; |
||||
break; |
||||
} |
||||
|
||||
pdata[19] += throughput; |
||||
|
||||
} while (pdata[19] < max_nonce && !work_restart[thr_id].restart); |
||||
|
||||
*hashes_done = pdata[19] - first_nonce; |
||||
return 0; |
||||
} |
||||
|
||||
// cleanup |
||||
extern "C" void free_x16r(int thr_id) |
||||
{ |
||||
if (!init[thr_id]) |
||||
return; |
||||
|
||||
cudaThreadSynchronize(); |
||||
|
||||
cudaFree(d_hash[thr_id]); |
||||
|
||||
quark_blake512_cpu_free(thr_id); |
||||
quark_groestl512_cpu_free(thr_id); |
||||
x11_simd512_cpu_free(thr_id); |
||||
x13_fugue512_cpu_free(thr_id); |
||||
x16_fugue512_cpu_free(thr_id); // to merge with x13_fugue512 ? |
||||
x15_whirlpool_cpu_free(thr_id); |
||||
|
||||
cuda_check_cpu_free(thr_id); |
||||
|
||||
cudaDeviceSynchronize(); |
||||
init[thr_id] = false; |
||||
} |
@ -0,0 +1,601 @@
@@ -0,0 +1,601 @@
|
||||
/** |
||||
* X16S algorithm (X16 with Shuffled chain order) |
||||
* |
||||
* tpruvot 2018 - GPL code |
||||
*/ |
||||
|
||||
#include <stdio.h> |
||||
#include <memory.h> |
||||
#include <unistd.h> |
||||
|
||||
extern "C" { |
||||
#include "sph/sph_blake.h" |
||||
#include "sph/sph_bmw.h" |
||||
#include "sph/sph_groestl.h" |
||||
#include "sph/sph_skein.h" |
||||
#include "sph/sph_jh.h" |
||||
#include "sph/sph_keccak.h" |
||||
|
||||
#include "sph/sph_luffa.h" |
||||
#include "sph/sph_cubehash.h" |
||||
#include "sph/sph_shavite.h" |
||||
#include "sph/sph_simd.h" |
||||
#include "sph/sph_echo.h" |
||||
|
||||
#include "sph/sph_hamsi.h" |
||||
#include "sph/sph_fugue.h" |
||||
#include "sph/sph_shabal.h" |
||||
#include "sph/sph_whirlpool.h" |
||||
#include "sph/sph_sha2.h" |
||||
} |
||||
|
||||
#include "miner.h" |
||||
#include "cuda_helper.h" |
||||
#include "cuda_x16.h" |
||||
|
||||
static uint32_t *d_hash[MAX_GPUS]; |
||||
|
||||
enum Algo { |
||||
BLAKE = 0, |
||||
BMW, |
||||
GROESTL, |
||||
JH, |
||||
KECCAK, |
||||
SKEIN, |
||||
LUFFA, |
||||
CUBEHASH, |
||||
SHAVITE, |
||||
SIMD, |
||||
ECHO, |
||||
HAMSI, |
||||
FUGUE, |
||||
SHABAL, |
||||
WHIRLPOOL, |
||||
SHA512, |
||||
HASH_FUNC_COUNT |
||||
}; |
||||
|
||||
static const char* algo_strings[] = { |
||||
"blake", |
||||
"bmw512", |
||||
"groestl", |
||||
"jh512", |
||||
"keccak", |
||||
"skein", |
||||
"luffa", |
||||
"cube", |
||||
"shavite", |
||||
"simd", |
||||
"echo", |
||||
"hamsi", |
||||
"fugue", |
||||
"shabal", |
||||
"whirlpool", |
||||
"sha512", |
||||
NULL |
||||
}; |
||||
|
||||
static __thread uint32_t s_ntime = UINT32_MAX; |
||||
static __thread char hashOrder[HASH_FUNC_COUNT + 1] = { 0 }; |
||||
|
||||
static void getAlgoString(const uint32_t* prevblock, char *output) |
||||
{ |
||||
uint8_t* data = (uint8_t*)prevblock; |
||||
|
||||
strcpy(output, "0123456789ABCDEF"); |
||||
|
||||
for (uint8_t i = 0; i < HASH_FUNC_COUNT; i++) { |
||||
uint8_t b = (15 - i) >> 1; // 16 ascii hex chars, reversed |
||||
uint8_t algoDigit = (i & 1) ? data[b] & 0xF : data[b] >> 4; |
||||
int offset = (int) algoDigit; |
||||
char oldVal = output[offset]; |
||||
for(int j=offset; j-->0;) |
||||
output[j+1] = output[j]; |
||||
output[0] = oldVal; |
||||
} |
||||
} |
||||
|
||||
// X16S CPU Hash (Validation) |
||||
extern "C" void x16s_hash(void *output, const void *input) |
||||
{ |
||||
unsigned char _ALIGN(64) hash[128]; |
||||
|
||||
sph_blake512_context ctx_blake; |
||||
sph_bmw512_context ctx_bmw; |
||||
sph_groestl512_context ctx_groestl; |
||||
sph_jh512_context ctx_jh; |
||||
sph_keccak512_context ctx_keccak; |
||||
sph_skein512_context ctx_skein; |
||||
sph_luffa512_context ctx_luffa; |
||||
sph_cubehash512_context ctx_cubehash; |
||||
sph_shavite512_context ctx_shavite; |
||||
sph_simd512_context ctx_simd; |
||||
sph_echo512_context ctx_echo; |
||||
sph_hamsi512_context ctx_hamsi; |
||||
sph_fugue512_context ctx_fugue; |
||||
sph_shabal512_context ctx_shabal; |
||||
sph_whirlpool_context ctx_whirlpool; |
||||
sph_sha512_context ctx_sha512; |
||||
|
||||
void *in = (void*) input; |
||||
int size = 80; |
||||
|
||||
uint32_t *in32 = (uint32_t*) input; |
||||
getAlgoString(&in32[1], hashOrder); |
||||
|
||||
for (int i = 0; i < 16; i++) |
||||
{ |
||||
const char elem = hashOrder[i]; |
||||
const uint8_t algo = elem >= 'A' ? elem - 'A' + 10 : elem - '0'; |
||||
|
||||
switch (algo) { |
||||
case BLAKE: |
||||
sph_blake512_init(&ctx_blake); |
||||
sph_blake512(&ctx_blake, in, size); |
||||
sph_blake512_close(&ctx_blake, hash); |
||||
break; |
||||
case BMW: |
||||
sph_bmw512_init(&ctx_bmw); |
||||
sph_bmw512(&ctx_bmw, in, size); |
||||
sph_bmw512_close(&ctx_bmw, hash); |
||||
break; |
||||
case GROESTL: |
||||
sph_groestl512_init(&ctx_groestl); |
||||
sph_groestl512(&ctx_groestl, in, size); |
||||
sph_groestl512_close(&ctx_groestl, hash); |
||||
break; |
||||
case SKEIN: |
||||
sph_skein512_init(&ctx_skein); |
||||
sph_skein512(&ctx_skein, in, size); |
||||
sph_skein512_close(&ctx_skein, hash); |
||||
break; |
||||
case JH: |
||||
sph_jh512_init(&ctx_jh); |
||||
sph_jh512(&ctx_jh, in, size); |
||||
sph_jh512_close(&ctx_jh, hash); |
||||
break; |
||||
case KECCAK: |
||||
sph_keccak512_init(&ctx_keccak); |
||||
sph_keccak512(&ctx_keccak, in, size); |
||||
sph_keccak512_close(&ctx_keccak, hash); |
||||
break; |
||||
case LUFFA: |
||||
sph_luffa512_init(&ctx_luffa); |
||||
sph_luffa512(&ctx_luffa, in, size); |
||||
sph_luffa512_close(&ctx_luffa, hash); |
||||
break; |
||||
case CUBEHASH: |
||||
sph_cubehash512_init(&ctx_cubehash); |
||||
sph_cubehash512(&ctx_cubehash, in, size); |
||||
sph_cubehash512_close(&ctx_cubehash, hash); |
||||
break; |
||||
case SHAVITE: |
||||
sph_shavite512_init(&ctx_shavite); |
||||
sph_shavite512(&ctx_shavite, in, size); |
||||
sph_shavite512_close(&ctx_shavite, hash); |
||||
break; |
||||
case SIMD: |
||||
sph_simd512_init(&ctx_simd); |
||||
sph_simd512(&ctx_simd, in, size); |
||||
sph_simd512_close(&ctx_simd, hash); |
||||
break; |
||||
case ECHO: |
||||
sph_echo512_init(&ctx_echo); |
||||
sph_echo512(&ctx_echo, in, size); |
||||
sph_echo512_close(&ctx_echo, hash); |
||||
break; |
||||
case HAMSI: |
||||
sph_hamsi512_init(&ctx_hamsi); |
||||
sph_hamsi512(&ctx_hamsi, in, size); |
||||
sph_hamsi512_close(&ctx_hamsi, hash); |
||||
break; |
||||
case FUGUE: |
||||
sph_fugue512_init(&ctx_fugue); |
||||
sph_fugue512(&ctx_fugue, in, size); |
||||
sph_fugue512_close(&ctx_fugue, hash); |
||||
break; |
||||
case SHABAL: |
||||
sph_shabal512_init(&ctx_shabal); |
||||
sph_shabal512(&ctx_shabal, in, size); |
||||
sph_shabal512_close(&ctx_shabal, hash); |
||||
break; |
||||
case WHIRLPOOL: |
||||
sph_whirlpool_init(&ctx_whirlpool); |
||||
sph_whirlpool(&ctx_whirlpool, in, size); |
||||
sph_whirlpool_close(&ctx_whirlpool, hash); |
||||
break; |
||||
case SHA512: |
||||
sph_sha512_init(&ctx_sha512); |
||||
sph_sha512(&ctx_sha512,(const void*) in, size); |
||||
sph_sha512_close(&ctx_sha512,(void*) hash); |
||||
break; |
||||
} |
||||
in = (void*) hash; |
||||
size = 64; |
||||
} |
||||
memcpy(output, hash, 32); |
||||
} |
||||
|
||||
#if 0 /* in x16r */ |
||||
void whirlpool_midstate(void *state, const void *input) |
||||
{ |
||||
sph_whirlpool_context ctx; |
||||
|
||||
sph_whirlpool_init(&ctx); |
||||
sph_whirlpool(&ctx, input, 64); |
||||
|
||||
memcpy(state, ctx.state, 64); |
||||
} |
||||
#endif |
||||
|
||||
static bool init[MAX_GPUS] = { 0 }; |
||||
static bool use_compat_kernels[MAX_GPUS] = { 0 }; |
||||
|
||||
//#define _DEBUG |
||||
#define _DEBUG_PREFIX "x16s-" |
||||
#include "cuda_debug.cuh" |
||||
|
||||
extern "C" int scanhash_x16s(int thr_id, struct work* work, uint32_t max_nonce, unsigned long *hashes_done) |
||||
{ |
||||
uint32_t *pdata = work->data; |
||||
uint32_t *ptarget = work->target; |
||||
const uint32_t first_nonce = pdata[19]; |
||||
const int dev_id = device_map[thr_id]; |
||||
int intensity = (device_sm[dev_id] > 500 && !is_windows()) ? 20 : 19; |
||||
if (strstr(device_name[dev_id], "GTX 1080")) intensity = 20; |
||||
uint32_t throughput = cuda_default_throughput(thr_id, 1U << intensity); |
||||
//if (init[thr_id]) throughput = min(throughput, max_nonce - first_nonce); |
||||
|
||||
if (!init[thr_id]) |
||||
{ |
||||
cudaSetDevice(device_map[thr_id]); |
||||
if (opt_cudaschedule == -1 && gpu_threads == 1) { |
||||
cudaDeviceReset(); |
||||
// reduce cpu usage |
||||
cudaSetDeviceFlags(cudaDeviceScheduleBlockingSync); |
||||
} |
||||
gpulog(LOG_INFO, thr_id, "Intensity set to %g, %u cuda threads", throughput2intensity(throughput), throughput); |
||||
|
||||
cuda_get_arch(thr_id); |
||||
use_compat_kernels[thr_id] = (cuda_arch[dev_id] < 500); |
||||
if (use_compat_kernels[thr_id]) |
||||
x11_echo512_cpu_init(thr_id, throughput); |
||||
|
||||
quark_blake512_cpu_init(thr_id, throughput); |
||||
quark_bmw512_cpu_init(thr_id, throughput); |
||||
quark_groestl512_cpu_init(thr_id, throughput); |
||||
quark_skein512_cpu_init(thr_id, throughput); |
||||
quark_jh512_cpu_init(thr_id, throughput); |
||||
quark_keccak512_cpu_init(thr_id, throughput); |
||||
qubit_luffa512_cpu_init(thr_id, throughput); |
||||
x11_luffa512_cpu_init(thr_id, throughput); // 64 |
||||
x11_shavite512_cpu_init(thr_id, throughput); |
||||
x11_simd512_cpu_init(thr_id, throughput); // 64 |
||||
x16_echo512_cuda_init(thr_id, throughput); |
||||
x13_hamsi512_cpu_init(thr_id, throughput); |
||||
x13_fugue512_cpu_init(thr_id, throughput); |
||||
x16_fugue512_cpu_init(thr_id, throughput); |
||||
x14_shabal512_cpu_init(thr_id, throughput); |
||||
x15_whirlpool_cpu_init(thr_id, throughput, 0); |
||||
x16_whirlpool512_init(thr_id, throughput); |
||||
x17_sha512_cpu_init(thr_id, throughput); |
||||
|
||||
CUDA_CALL_OR_RET_X(cudaMalloc(&d_hash[thr_id], (size_t) 64 * throughput), 0); |
||||
|
||||
cuda_check_cpu_init(thr_id, throughput); |
||||
|
||||
init[thr_id] = true; |
||||
} |
||||
|
||||
if (opt_benchmark) { |
||||
((uint32_t*)ptarget)[7] = 0x003f; |
||||
//((uint8_t*)pdata)[8] = 0x90; // hashOrder[0] = '9'; for simd 80 + blake512 64 |
||||
//((uint8_t*)pdata)[8] = 0x0A; // hashOrder[0] = 'A'; for echo 64 |
||||
//((uint8_t*)pdata)[8] = 0xB0; // hashOrder[0] = 'B'; for hamsi 80 + blake512 64 |
||||
//((uint8_t*)pdata)[8] = 0xC0; // hashOrder[0] = 'C'; for fugue 80 + blake512 64 |
||||
//((uint8_t*)pdata)[8] = 0xE0; // hashOrder[0] = 'E'; for whirlpool 80 + blake512 64 |
||||
} |
||||
uint32_t _ALIGN(64) endiandata[20]; |
||||
|
||||
for (int k=0; k < 19; k++) |
||||
be32enc(&endiandata[k], pdata[k]); |
||||
|
||||
uint32_t ntime = swab32(pdata[17]); |
||||
if (s_ntime != ntime) { |
||||
getAlgoString(&endiandata[1], hashOrder); |
||||
s_ntime = ntime; |
||||
if (opt_debug && !thr_id) applog(LOG_DEBUG, "hash order %s (%08x)", hashOrder, ntime); |
||||
} |
||||
|
||||
cuda_check_cpu_setTarget(ptarget); |
||||
|
||||
char elem = hashOrder[0]; |
||||
const uint8_t algo80 = elem >= 'A' ? elem - 'A' + 10 : elem - '0'; |
||||
|
||||
switch (algo80) { |
||||
case BLAKE: |
||||
quark_blake512_cpu_setBlock_80(thr_id, endiandata); |
||||
break; |
||||
case BMW: |
||||
quark_bmw512_cpu_setBlock_80(endiandata); |
||||
break; |
||||
case GROESTL: |
||||
groestl512_setBlock_80(thr_id, endiandata); |
||||
break; |
||||
case JH: |
||||
jh512_setBlock_80(thr_id, endiandata); |
||||
break; |
||||
case KECCAK: |
||||
keccak512_setBlock_80(thr_id, endiandata); |
||||
break; |
||||
case SKEIN: |
||||
skein512_cpu_setBlock_80((void*)endiandata); |
||||
break; |
||||
case LUFFA: |
||||
qubit_luffa512_cpu_setBlock_80((void*)endiandata); |
||||
break; |
||||
case CUBEHASH: |
||||
cubehash512_setBlock_80(thr_id, endiandata); |
||||
break; |
||||
case SHAVITE: |
||||
x11_shavite512_setBlock_80((void*)endiandata); |
||||
break; |
||||
case SIMD: |
||||
x16_simd512_setBlock_80((void*)endiandata); |
||||
break; |
||||
case ECHO: |
||||
x16_echo512_setBlock_80((void*)endiandata); |
||||
break; |
||||
case HAMSI: |
||||
x16_hamsi512_setBlock_80((void*)endiandata); |
||||
break; |
||||
case FUGUE: |
||||
x16_fugue512_setBlock_80((void*)pdata); |
||||
break; |
||||
case SHABAL: |
||||
x16_shabal512_setBlock_80((void*)endiandata); |
||||
break; |
||||
case WHIRLPOOL: |
||||
x16_whirlpool512_setBlock_80((void*)endiandata); |
||||
break; |
||||
case SHA512: |
||||
x16_sha512_setBlock_80(endiandata); |
||||
break; |
||||
default: { |
||||
return -1; |
||||
} |
||||
} |
||||
|
||||
int warn = 0; |
||||
|
||||
do { |
||||
int order = 0; |
||||
|
||||
// Hash with CUDA |
||||
|
||||
switch (algo80) { |
||||
case BLAKE: |
||||
quark_blake512_cpu_hash_80(thr_id, throughput, pdata[19], d_hash[thr_id]); order++; |
||||
TRACE("blake80:"); |
||||
break; |
||||
case BMW: |
||||
quark_bmw512_cpu_hash_80(thr_id, throughput, pdata[19], d_hash[thr_id], order++); |
||||
TRACE("bmw80 :"); |
||||
break; |
||||
case GROESTL: |
||||
groestl512_cuda_hash_80(thr_id, throughput, pdata[19], d_hash[thr_id]); order++; |
||||
TRACE("grstl80:"); |
||||
break; |
||||
case JH: |
||||
jh512_cuda_hash_80(thr_id, throughput, pdata[19], d_hash[thr_id]); order++; |
||||
TRACE("jh51280:"); |
||||
break; |
||||
case KECCAK: |
||||
keccak512_cuda_hash_80(thr_id, throughput, pdata[19], d_hash[thr_id]); order++; |
||||
TRACE("kecck80:"); |
||||
break; |
||||
case SKEIN: |
||||
skein512_cpu_hash_80(thr_id, throughput, pdata[19], d_hash[thr_id], 1); order++; |
||||
TRACE("skein80:"); |
||||
break; |
||||
case LUFFA: |
||||
qubit_luffa512_cpu_hash_80(thr_id, throughput, pdata[19], d_hash[thr_id], order++); |
||||
TRACE("luffa80:"); |
||||
break; |
||||
case CUBEHASH: |
||||
cubehash512_cuda_hash_80(thr_id, throughput, pdata[19], d_hash[thr_id]); order++; |
||||
TRACE("cube 80:"); |
||||
break; |
||||
case SHAVITE: |
||||
x11_shavite512_cpu_hash_80(thr_id, throughput, pdata[19], d_hash[thr_id], order++); |
||||
TRACE("shavite:"); |
||||
break; |
||||
case SIMD: |
||||
x16_simd512_cuda_hash_80(thr_id, throughput, pdata[19], d_hash[thr_id]); order++; |
||||
TRACE("simd512:"); |
||||
break; |
||||
case ECHO: |
||||
x16_echo512_cuda_hash_80(thr_id, throughput, pdata[19], d_hash[thr_id]); order++; |
||||
TRACE("echo :"); |
||||
break; |
||||
case HAMSI: |
||||
x16_hamsi512_cuda_hash_80(thr_id, throughput, pdata[19], d_hash[thr_id]); order++; |
||||
TRACE("hamsi :"); |
||||
break; |
||||
case FUGUE: |
||||
x16_fugue512_cuda_hash_80(thr_id, throughput, pdata[19], d_hash[thr_id]); order++; |
||||
TRACE("fugue :"); |
||||
break; |
||||
case SHABAL: |
||||
x16_shabal512_cuda_hash_80(thr_id, throughput, pdata[19], d_hash[thr_id]); order++; |
||||
TRACE("shabal :"); |
||||
break; |
||||
case WHIRLPOOL: |
||||
x16_whirlpool512_hash_80(thr_id, throughput, pdata[19], d_hash[thr_id]); order++; |
||||
TRACE("whirl :"); |
||||
break; |
||||
case SHA512: |
||||
x16_sha512_cuda_hash_80(thr_id, throughput, pdata[19], d_hash[thr_id]); order++; |
||||
TRACE("sha512 :"); |
||||
break; |
||||
} |
||||
|
||||
for (int i = 1; i < 16; i++) |
||||
{ |
||||
const char elem = hashOrder[i]; |
||||
const uint8_t algo64 = elem >= 'A' ? elem - 'A' + 10 : elem - '0'; |
||||
|
||||
switch (algo64) { |
||||
case BLAKE: |
||||
quark_blake512_cpu_hash_64(thr_id, throughput, pdata[19], NULL, d_hash[thr_id], order++); |
||||
TRACE("blake :"); |
||||
break; |
||||
case BMW: |
||||
quark_bmw512_cpu_hash_64(thr_id, throughput, pdata[19], NULL, d_hash[thr_id], order++); |
||||
TRACE("bmw :"); |
||||
break; |
||||
case GROESTL: |
||||
quark_groestl512_cpu_hash_64(thr_id, throughput, pdata[19], NULL, d_hash[thr_id], order++); |
||||
TRACE("groestl:"); |
||||
break; |
||||
case JH: |
||||
quark_jh512_cpu_hash_64(thr_id, throughput, pdata[19], NULL, d_hash[thr_id], order++); |
||||
TRACE("jh512 :"); |
||||
break; |
||||
case KECCAK: |
||||
quark_keccak512_cpu_hash_64(thr_id, throughput, pdata[19], NULL, d_hash[thr_id], order++); |
||||
TRACE("keccak :"); |
||||
break; |
||||
case SKEIN: |
||||
quark_skein512_cpu_hash_64(thr_id, throughput, pdata[19], NULL, d_hash[thr_id], order++); |
||||
TRACE("skein :"); |
||||
break; |
||||
case LUFFA: |
||||
x11_luffa512_cpu_hash_64(thr_id, throughput, pdata[19], NULL, d_hash[thr_id], order++); |
||||
TRACE("luffa :"); |
||||
break; |
||||
case CUBEHASH: |
||||
x11_cubehash512_cpu_hash_64(thr_id, throughput, pdata[19], NULL, d_hash[thr_id], order++); |
||||
TRACE("cube :"); |
||||
break; |
||||
case SHAVITE: |
||||
x11_shavite512_cpu_hash_64(thr_id, throughput, pdata[19], NULL, d_hash[thr_id], order++); |
||||
TRACE("shavite:"); |
||||
break; |
||||
case SIMD: |
||||
x11_simd512_cpu_hash_64(thr_id, throughput, pdata[19], NULL, d_hash[thr_id], order++); |
||||
TRACE("simd :"); |
||||
break; |
||||
case ECHO: |
||||
if (use_compat_kernels[thr_id]) |
||||
x11_echo512_cpu_hash_64(thr_id, throughput, pdata[19], NULL, d_hash[thr_id], order++); |
||||
else |
||||
x16_echo512_cpu_hash_64(thr_id, throughput, d_hash[thr_id]); order++; |
||||
TRACE("echo :"); |
||||
break; |
||||
case HAMSI: |
||||
x13_hamsi512_cpu_hash_64(thr_id, throughput, pdata[19], NULL, d_hash[thr_id], order++); |
||||
TRACE("hamsi :"); |
||||
break; |
||||
case FUGUE: |
||||
x13_fugue512_cpu_hash_64(thr_id, throughput, pdata[19], NULL, d_hash[thr_id], order++); |
||||
TRACE("fugue :"); |
||||
break; |
||||
case SHABAL: |
||||
x14_shabal512_cpu_hash_64(thr_id, throughput, pdata[19], NULL, d_hash[thr_id], order++); |
||||
TRACE("shabal :"); |
||||
break; |
||||
case WHIRLPOOL: |
||||
x15_whirlpool_cpu_hash_64(thr_id, throughput, pdata[19], NULL, d_hash[thr_id], order++); |
||||
TRACE("shabal :"); |
||||
break; |
||||
case SHA512: |
||||
x17_sha512_cpu_hash_64(thr_id, throughput, pdata[19], d_hash[thr_id]); order++; |
||||
TRACE("sha512 :"); |
||||
break; |
||||
} |
||||
} |
||||
|
||||
*hashes_done = pdata[19] - first_nonce + throughput; |
||||
|
||||
work->nonces[0] = cuda_check_hash(thr_id, throughput, pdata[19], d_hash[thr_id]); |
||||
#ifdef _DEBUG |
||||
uint32_t _ALIGN(64) dhash[8]; |
||||
be32enc(&endiandata[19], pdata[19]); |
||||
x16s_hash(dhash, endiandata); |
||||
applog_hash(dhash); |
||||
return -1; |
||||
#endif |
||||
if (work->nonces[0] != UINT32_MAX) |
||||
{ |
||||
const uint32_t Htarg = ptarget[7]; |
||||
uint32_t _ALIGN(64) vhash[8]; |
||||
be32enc(&endiandata[19], work->nonces[0]); |
||||
x16s_hash(vhash, endiandata); |
||||
|
||||
if (vhash[7] <= Htarg && fulltest(vhash, ptarget)) { |
||||
work->valid_nonces = 1; |
||||
work->nonces[1] = cuda_check_hash_suppl(thr_id, throughput, pdata[19], d_hash[thr_id], 1); |
||||
work_set_target_ratio(work, vhash); |
||||
if (work->nonces[1] != 0) { |
||||
be32enc(&endiandata[19], work->nonces[1]); |
||||
x16s_hash(vhash, endiandata); |
||||
bn_set_target_ratio(work, vhash, 1); |
||||
work->valid_nonces++; |
||||
pdata[19] = max(work->nonces[0], work->nonces[1]) + 1; |
||||
} else { |
||||
pdata[19] = work->nonces[0] + 1; // cursor |
||||
} |
||||
//gpulog(LOG_INFO, thr_id, "hash found with %s 80 (%s)!", algo_strings[algo80], hashOrder); |
||||
return work->valid_nonces; |
||||
} |
||||
else if (vhash[7] > Htarg) { |
||||
// x11+ coins could do some random error, but not on retry |
||||
gpu_increment_reject(thr_id); |
||||
if (!warn) { |
||||
warn++; |
||||
pdata[19] = work->nonces[0] + 1; |
||||
continue; |
||||
} else { |
||||
if (!opt_quiet) gpulog(LOG_WARNING, thr_id, "result for %08x does not validate on CPU! %s %s", |
||||
work->nonces[0], algo_strings[algo80], hashOrder); |
||||
warn = 0; |
||||
} |
||||
} |
||||
} |
||||
|
||||
if ((uint64_t)throughput + pdata[19] >= max_nonce) { |
||||
pdata[19] = max_nonce; |
||||
break; |
||||
} |
||||
|
||||
pdata[19] += throughput; |
||||
|
||||
} while (pdata[19] < max_nonce && !work_restart[thr_id].restart); |
||||
|
||||
*hashes_done = pdata[19] - first_nonce; |
||||
return 0; |
||||
} |
||||
|
||||
// cleanup |
||||
extern "C" void free_x16s(int thr_id) |
||||
{ |
||||
if (!init[thr_id]) |
||||
return; |
||||
|
||||
cudaThreadSynchronize(); |
||||
|
||||
cudaFree(d_hash[thr_id]); |
||||
|
||||
quark_blake512_cpu_free(thr_id); |
||||
quark_groestl512_cpu_free(thr_id); |
||||
x11_simd512_cpu_free(thr_id); |
||||
x13_fugue512_cpu_free(thr_id); |
||||
x16_fugue512_cpu_free(thr_id); // to merge with x13_fugue512 ? |
||||
x15_whirlpool_cpu_free(thr_id); |
||||
|
||||
cuda_check_cpu_free(thr_id); |
||||
|
||||
cudaDeviceSynchronize(); |
||||
init[thr_id] = false; |
||||
} |
Loading…
Reference in new issue