This commit is contained in:
Jay D Dee
2020-01-23 00:11:08 -05:00
parent 1a7a573675
commit 103e6ad36c
12 changed files with 329 additions and 285 deletions

View File

@@ -33,3 +33,6 @@ Jay D Dee
xcouiz@gmail.com
Cryply
Colin Percival
Alexander Peslyak

View File

@@ -65,6 +65,13 @@ If not what makes it happen or not happen?
Change Log
----------
v3.11.6
Fixed CPU temperature regression from v3.11.5.
More improvements to share log. More compact, highlight incremented counter,
block height when solved, job id when stale.
v3.11.5
Fixed AVX512 detection that could cause compilation errors on CPUs

View File

@@ -320,18 +320,19 @@ bool init_allium_8way_ctx()
return true;
}
void allium_8way_hash( void *state, const void *input )
void allium_8way_hash( void *hash, const void *input )
{
uint32_t vhashA[8*8] __attribute__ ((aligned (64)));
uint32_t vhashB[8*8] __attribute__ ((aligned (64)));
uint32_t hash0[8] __attribute__ ((aligned (32)));
uint32_t hash1[8] __attribute__ ((aligned (32)));
uint32_t hash2[8] __attribute__ ((aligned (32)));
uint32_t hash3[8] __attribute__ ((aligned (32)));
uint32_t hash4[8] __attribute__ ((aligned (64)));
uint32_t hash5[8] __attribute__ ((aligned (32)));
uint32_t hash6[8] __attribute__ ((aligned (32)));
uint32_t hash7[8] __attribute__ ((aligned (32)));
uint64_t vhashA[4*8] __attribute__ ((aligned (64)));
uint64_t vhashB[4*8] __attribute__ ((aligned (64)));
// uint64_t hash[4*8] __attribute__ ((aligned (64)));
uint64_t *hash0 = (uint64_t*)hash;
uint64_t *hash1 = (uint64_t*)hash+ 4;
uint64_t *hash2 = (uint64_t*)hash+ 8;
uint64_t *hash3 = (uint64_t*)hash+12;
uint64_t *hash4 = (uint64_t*)hash+16;
uint64_t *hash5 = (uint64_t*)hash+20;
uint64_t *hash6 = (uint64_t*)hash+24;
uint64_t *hash7 = (uint64_t*)hash+28;
allium_8way_ctx_holder ctx __attribute__ ((aligned (64)));
memcpy( &ctx, &allium_8way_ctx, sizeof(allium_8way_ctx) );
@@ -398,69 +399,74 @@ void allium_8way_hash( void *state, const void *input )
dintrlv_4x64( hash0, hash1, hash2, hash3, vhashA, 256 );
dintrlv_4x64( hash4, hash5, hash6, hash7, vhashB, 256 );
update_and_final_groestl256( &ctx.groestl, state, hash0, 256 );
update_and_final_groestl256( &ctx.groestl, hash0, hash0, 256 );
memcpy( &ctx.groestl, &allium_8way_ctx.groestl,
sizeof(hashState_groestl256) );
update_and_final_groestl256( &ctx.groestl, state+32, hash1, 256 );
update_and_final_groestl256( &ctx.groestl, hash1, hash1, 256 );
memcpy( &ctx.groestl, &allium_8way_ctx.groestl,
sizeof(hashState_groestl256) );
update_and_final_groestl256( &ctx.groestl, state+64, hash2, 256 );
update_and_final_groestl256( &ctx.groestl, hash2, hash2, 256 );
memcpy( &ctx.groestl, &allium_8way_ctx.groestl,
sizeof(hashState_groestl256) );
update_and_final_groestl256( &ctx.groestl, state+96, hash3, 256 );
update_and_final_groestl256( &ctx.groestl, hash3, hash3, 256 );
memcpy( &ctx.groestl, &allium_8way_ctx.groestl,
sizeof(hashState_groestl256) );
update_and_final_groestl256( &ctx.groestl, state+128, hash4, 256 );
update_and_final_groestl256( &ctx.groestl, hash4, hash4, 256 );
memcpy( &ctx.groestl, &allium_8way_ctx.groestl,
sizeof(hashState_groestl256) );
update_and_final_groestl256( &ctx.groestl, state+160, hash5, 256 );
update_and_final_groestl256( &ctx.groestl, hash5, hash5, 256 );
memcpy( &ctx.groestl, &allium_8way_ctx.groestl,
sizeof(hashState_groestl256) );
update_and_final_groestl256( &ctx.groestl, state+192, hash6, 256 );
update_and_final_groestl256( &ctx.groestl, hash6, hash6, 256 );
memcpy( &ctx.groestl, &allium_8way_ctx.groestl,
sizeof(hashState_groestl256) );
update_and_final_groestl256( &ctx.groestl, state+224, hash7, 256 );
update_and_final_groestl256( &ctx.groestl, hash7, hash7, 256 );
}
int scanhash_allium_8way( struct work *work, uint32_t max_nonce,
uint64_t *hashes_done, struct thr_info *mythr )
{
uint32_t hash[8*8] __attribute__ ((aligned (64)));
uint64_t hash[4*8] __attribute__ ((aligned (64)));
uint32_t vdata[20*8] __attribute__ ((aligned (64)));
uint32_t *pdata = work->data;
uint32_t *ptarget = work->target;
uint64_t *ptarget = (uint64_t*)work->target;
const uint32_t first_nonce = pdata[19];
const uint32_t last_nonce = max_nonce - 8;
uint32_t n = first_nonce;
const uint32_t Htarg = ptarget[7];
const uint64_t Htarg = ptarget[3];
__m256i *noncev = (__m256i*)vdata + 19; // aligned
int thr_id = mythr->id;
const int thr_id = mythr->id;
const bool bench = opt_benchmark;
if ( opt_benchmark )
if unlikely( bench )
( (uint32_t*)ptarget )[7] = 0x0000ff;
mm256_bswap32_intrlv80_8x32( vdata, pdata );
*noncev = _mm256_set_epi32( n+7, n+6, n+5, n+4, n+3, n+2, n+1, n );
blake256_8way_init( &allium_8way_ctx.blake );
blake256_8way_update( &allium_8way_ctx.blake, vdata, 64 );
do {
*noncev = mm256_bswap_32( _mm256_set_epi32( n+7, n+6, n+5, n+4,
n+3, n+2, n+1, n ) );
allium_8way_hash( hash, vdata );
pdata[19] = n;
for ( int lane = 0; lane < 8; lane++ ) if ( (hash+(lane<<3))[7] <= Htarg )
for ( int lane = 0; lane < 8; lane++ )
{
if ( fulltest( hash+(lane<<3), ptarget ) && !opt_benchmark )
const uint64_t *lane_hash = hash + (lane<<2);
if unlikely( lane_hash[3] <= Htarg )
{
pdata[19] = n + lane;
submit_lane_solution( work, hash+(lane<<3), mythr, lane );
if likely( ( lane_hash[3] < Htarg && !bench )
|| valid_hash( lane_hash, ptarget ) )
{
pdata[19] = bswap_32( n + lane );
submit_lane_solution( work, lane_hash, mythr, lane );
}
}
}
n += 8;
} while ( (n < last_nonce) && !work_restart[thr_id].restart);
*noncev = _mm256_add_epi32( *noncev, m256_const1_32( 8 ) );
} while likely( (n <= last_nonce) && !work_restart[thr_id].restart );
pdata[19] = n;
*hashes_done = n - first_nonce;
return 0;
}

View File

@@ -267,8 +267,13 @@ int scanhash_m7m_hash( struct work* work, uint64_t max_nonce,
SHA256_Final( (unsigned char*) hash, &ctxf_sha256 );
}
if ( unlikely( hash[7] <= ptarget[7] ) )
if ( likely( fulltest( hash, ptarget ) && !opt_benchmark ) )
if ( unlikely( valid_hash( (uint64_t*)hash, (uint64_t*)ptarget )
&& !opt_benchmark ) )
// if ( unlikely( hash[7] <= ptarget[7] ) )
// if ( likely( fulltest( hash, ptarget ) && !opt_benchmark ) )
{
if ( opt_debug )
{

View File

@@ -351,7 +351,7 @@ typedef union _x17_4way_context_overlay x17_4way_context_overlay;
void x17_4way_hash( void *state, const void *input )
{
uint64_t vhash[8*4] __attribute__ ((aligned (128)));
uint64_t vhash[8*4] __attribute__ ((aligned (64)));
uint64_t vhashA[8*4] __attribute__ ((aligned (64)));
uint64_t vhashB[8*4] __attribute__ ((aligned (64)));
uint64_t hash0[8] __attribute__ ((aligned (64)));
@@ -471,8 +471,8 @@ void x17_4way_hash( void *state, const void *input )
int scanhash_x17_4way( struct work *work, uint32_t max_nonce,
uint64_t *hashes_done, struct thr_info *mythr )
{
uint32_t hash[16*4] __attribute__ ((aligned (128)));
uint32_t vdata[24*4] __attribute__ ((aligned (64)));
uint32_t hash[16*4] __attribute__ ((aligned (64)));
uint32_t vdata[20*4] __attribute__ ((aligned (64)));
uint32_t lane_hash[8] __attribute__ ((aligned (64)));
uint32_t *hash7 = &(hash[7<<2]);
uint32_t *pdata = work->data;
@@ -483,27 +483,30 @@ int scanhash_x17_4way( struct work *work, uint32_t max_nonce,
uint32_t n = first_nonce;
const int thr_id = mythr->id;
const uint32_t Htarg = ptarget[7];
const bool bench = opt_benchmark;
mm256_bswap32_intrlv80_4x64( vdata, pdata );
*noncev = mm256_intrlv_blend_32(
_mm256_set_epi32( n+3, 0, n+2, 0, n+1, 0, n, 0 ), *noncev );
do
{
*noncev = mm256_intrlv_blend_32( mm256_bswap_32(
_mm256_set_epi32( n+3, 0, n+2, 0, n+1, 0, n, 0 ) ), *noncev );
x17_4way_hash( hash, vdata );
for ( int lane = 0; lane < 4; lane++ )
if unlikely( ( hash7[ lane ] <= Htarg ) )
if ( unlikely( hash7[ lane ] <= Htarg && !bench ) )
{
extr_lane_4x32( lane_hash, hash, lane, 256 );
if ( likely( fulltest( lane_hash, ptarget ) && !opt_benchmark ) )
if ( ( hash7[ lane ] < Htarg ) || valid_hash( lane_hash, ptarget ) )
{
pdata[19] = n + lane;
pdata[19] = bswap_32( n + lane );
submit_lane_solution( work, lane_hash, mythr, lane );
}
}
*noncev = _mm256_add_epi32( *noncev,
m256_const1_64( 0x0000000400000000 ) );
n += 4;
} while ( likely( ( n < last_nonce ) && !work_restart[thr_id].restart ) );
} while ( likely( ( n <= last_nonce ) && !work_restart[thr_id].restart ) );
pdata[19] = n;
*hashes_done = n - first_nonce;
return 0;
}

View File

@@ -135,7 +135,7 @@ bool register_yespower_algo( algo_gate_t* gate )
if ( yespower_params.pers )
applog( LOG_NOTICE,"Key= \"%s\"\n", yespower_params.pers );
gate->optimizations = SSE2_OPT;
gate->optimizations = SSE2_OPT | SHA_OPT;
gate->scanhash = (void*)&scanhash_yespower;
gate->hash = (void*)&yespower_hash;
opt_target_factor = 65536.0;
@@ -149,7 +149,7 @@ bool register_yespowerr16_algo( algo_gate_t* gate )
yespower_params.r = 16;
yespower_params.pers = NULL;
yespower_params.perslen = 0;
gate->optimizations = SSE2_OPT;
gate->optimizations = SSE2_OPT | SHA_OPT;
gate->scanhash = (void*)&scanhash_yespower;
gate->hash = (void*)&yespower_hash;
opt_target_factor = 65536.0;
@@ -223,7 +223,7 @@ bool register_power2b_algo( algo_gate_t* gate )
applog( LOG_NOTICE,"Key= \"%s\"", yespower_params.pers );
applog( LOG_NOTICE,"Key length= %d\n", yespower_params.perslen );
gate->optimizations = SSE2_OPT;
gate->optimizations = SSE2_OPT | SHA_OPT;
gate->scanhash = (void*)&scanhash_yespower_b2b;
gate->hash = (void*)&yespower_b2b_hash;
opt_target_factor = 65536.0;

20
configure vendored
View File

@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.69 for cpuminer-opt 3.11.5.
# Generated by GNU Autoconf 2.69 for cpuminer-opt 3.11.6.
#
#
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
@@ -577,8 +577,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='cpuminer-opt'
PACKAGE_TARNAME='cpuminer-opt'
PACKAGE_VERSION='3.11.5'
PACKAGE_STRING='cpuminer-opt 3.11.5'
PACKAGE_VERSION='3.11.6'
PACKAGE_STRING='cpuminer-opt 3.11.6'
PACKAGE_BUGREPORT=''
PACKAGE_URL=''
@@ -1332,7 +1332,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
\`configure' configures cpuminer-opt 3.11.5 to adapt to many kinds of systems.
\`configure' configures cpuminer-opt 3.11.6 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1404,7 +1404,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of cpuminer-opt 3.11.5:";;
short | recursive ) echo "Configuration of cpuminer-opt 3.11.6:";;
esac
cat <<\_ACEOF
@@ -1509,7 +1509,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
cpuminer-opt configure 3.11.5
cpuminer-opt configure 3.11.6
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2012,7 +2012,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
It was created by cpuminer-opt $as_me 3.11.5, which was
It was created by cpuminer-opt $as_me 3.11.6, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -2993,7 +2993,7 @@ fi
# Define the identity of the package.
PACKAGE='cpuminer-opt'
VERSION='3.11.5'
VERSION='3.11.6'
cat >>confdefs.h <<_ACEOF
@@ -6690,7 +6690,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
This file was extended by cpuminer-opt $as_me 3.11.5, which was
This file was extended by cpuminer-opt $as_me 3.11.6, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -6756,7 +6756,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
cpuminer-opt config.status 3.11.5
cpuminer-opt config.status 3.11.6
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"

View File

@@ -1,4 +1,4 @@
AC_INIT([cpuminer-opt], [3.11.5])
AC_INIT([cpuminer-opt], [3.11.6])
AC_PREREQ([2.59c])
AC_CANONICAL_SYSTEM

View File

@@ -820,20 +820,15 @@ out:
// returns the unit prefix and the hashrate appropriately scaled.
void scale_hash_for_display ( double* hashrate, char* prefix )
{
if ( *hashrate < 1e4 ) // 0 H/s to 9999 h/s
*prefix = 0;
else if ( *hashrate < 1e7 ) // 10 kH/s to 9999 kh/s
{ *prefix = 'k'; *hashrate /= 1e3; }
else if ( *hashrate < 1e10 ) // 10 Mh/s to 9999 Mh/s
{ *prefix = 'M'; *hashrate /= 1e6; }
else if ( *hashrate < 1e13 ) // 10 Gh/s to 9999 Gh/s
{ *prefix = 'G'; *hashrate /= 1e9; }
else if ( *hashrate < 1e16 ) // 10 Th/s to 9999 Th/s
{ *prefix = 'T'; *hashrate /= 1e12; }
else if ( *hashrate < 1e19 ) // 10 Ph/s to 9999 Ph
{ *prefix = 'P'; *hashrate /= 1e15; }
else // 10 Eh/s and higher
{ *prefix = 'E'; *hashrate /= 1e18; }
if ( *hashrate < 1e4 ) *prefix = 0;
else if ( *hashrate < 1e7 ) { *prefix = 'k'; *hashrate /= 1e3; }
else if ( *hashrate < 1e10 ) { *prefix = 'M'; *hashrate /= 1e6; }
else if ( *hashrate < 1e13 ) { *prefix = 'G'; *hashrate /= 1e9; }
else if ( *hashrate < 1e16 ) { *prefix = 'T'; *hashrate /= 1e12; }
else if ( *hashrate < 1e19 ) { *prefix = 'P'; *hashrate /= 1e15; }
else if ( *hashrate < 1e22 ) { *prefix = 'E'; *hashrate /= 1e18; }
else if ( *hashrate < 1e25 ) { *prefix = 'Z'; *hashrate /= 1e21; }
else { *prefix = 'Y'; *hashrate /= 1e24; }
}
static inline void sprintf_et( char *str, int seconds )
@@ -842,10 +837,13 @@ static inline void sprintf_et( char *str, int seconds )
unsigned int min = seconds / 60;
unsigned int sec = seconds % 60;
unsigned int hrs = min / 60;
if ( hrs )
if ( unlikely( hrs ) )
{
unsigned int years = hrs / (24*365);
unsigned int days = hrs / 24;
if ( days ) //0d00h
if ( years )
sprintf( str, "%uy%ud", years, years % 365 );
else if ( days ) //0d00h
sprintf( str, "%ud%02uh", days, hrs % 24 );
else // 0h00m
sprintf( str, "%uh%02um", hrs, min % 60 );
@@ -867,6 +865,7 @@ const double diff_to_hash = 4294967296.;
static struct timeval session_start;
static struct timeval five_min_start;
static uint64_t session_first_block = 0;
static double latency_sum = 0.;
static uint64_t submit_sum = 0;
static uint64_t accept_sum = 0;
@@ -874,7 +873,7 @@ static uint64_t stale_sum = 0;
static uint64_t reject_sum = 0;
static double norm_diff_sum = 0.;
static uint32_t last_block_height = 0;
static bool new_job = false;
//static bool new_job = false;
static double last_targetdiff = 0.;
static double ref_rate_hi = 0.;
static double ref_rate_lo = 1e100;
@@ -1019,15 +1018,18 @@ static int share_result( int result, struct work *null_work,
int latency = 0;
struct share_stats_t my_stats = {0};
struct timeval ack_time, latency_tv, et;
const char *sres = NULL;
char job_id[48];
char ares[48];
char sres[48];
char rres[48];
char bres[48];
// char job_id[48];
bool solved = false;
bool stale = false;
char *acol = NULL, *bcol = NULL, *scol = NULL, *rcol = NULL;
// Mutex while we grab a snapshot of the stats.
pthread_mutex_lock( &stats_lock );
if ( share_stats[ s_get_ptr ].submit_time.tv_sec )
if ( likely( share_stats[ s_get_ptr ].submit_time.tv_sec ) )
{
memcpy( &my_stats, &share_stats[ s_get_ptr], sizeof my_stats );
memset( &share_stats[ s_get_ptr ], 0, sizeof my_stats );
@@ -1077,7 +1079,6 @@ static int share_result( int result, struct work *null_work,
rejected_share_count++;
}
// update global counters for summary report
pthread_mutex_lock( &stats_lock );
@@ -1102,8 +1103,39 @@ static int share_result( int result, struct work *null_work,
pthread_mutex_unlock( &stats_lock );
sprintf( job_id, "job %s", my_stats.job_id );
bcol = acol = scol = rcol = "\0";
if ( likely( result ) )
{
if ( unlikely( solved ) )
{
sprintf( bres, "BLOCK SOLVED %d", solved_block_count );
sprintf( ares, "A%d", accepted_share_count );
}
else
{
sprintf( bres, "B%d", solved_block_count );
sprintf( ares, "Accepted %d", accepted_share_count );
}
sprintf( sres, "S%d", stale_share_count );
sprintf( rres, "R%d", rejected_share_count );
}
else
{
sprintf( ares, "A%d", accepted_share_count );
sprintf( bres, "B%d", solved_block_count );
if ( stale )
{
sprintf( sres, "Stale job %d", stale_share_count );
sprintf( rres, "R%d", rejected_share_count );
}
else
{
sprintf( sres, "S%d", stale_share_count );
sprintf( rres, "Rejected %d" , rejected_share_count );
}
}
bcol = acol = scol = rcol = CL_WHT;
if ( use_colors )
{
@@ -1111,56 +1143,30 @@ static int share_result( int result, struct work *null_work,
{
if ( unlikely( solved ) )
{
sres = CL_MAG "BLOCK SOLVED" CL_WHT;
bcol = CL_MAG;
acol = CL_GRN;
}
else
sres = CL_GRN "Accepted" CL_WHT;
acol = CL_GRN;
}
/*
if ( unlikely( solved ) )
{
sres = CL_MAG "BLOCK SOLVED" CL_WHT;
bcol = CL_MAG;
acol = CL_GRN;
}
else if ( likely( result ) )
{
sres = CL_GRN "Accepted" CL_WHT;
acol = CL_GRN;
}
*/
else if ( stale )
{
sres = CL_YL2 "Stale share" CL_WHT;
scol = CL_YL2;
sprintf( job_id, "%sjob %s%s", CL_YL2, my_stats.job_id, CL_N );
}
else
{
sres = CL_RED "Rejected" CL_WHT;
rcol = CL_RED;
}
}
else // monochrome
sres = solved ? "BLOCK SOLVED"
: ( result ? "Accepted"
: stale ? "Stale share" : "Rejected" );
applog( LOG_NOTICE, "%d: %s, %.3f secs (%dms), %sA:%d" CL_WHT " %sS:%d" CL_WHT " %sR:%d" CL_WHT " %sB:%d" CL_WHT,
my_stats.share_count, sres, share_time, latency, acol,
accepted_share_count, scol, stale_share_count, rcol,
rejected_share_count, bcol, solved_block_count );
applog( LOG_NOTICE, "%d %s%s %s%s %s%s %s%s" CL_WHT ", %.3f sec (%dms)",
my_stats.share_count, acol, ares, scol, sres, rcol, rres, bcol,
bres, share_time, latency );
if ( have_stratum && !opt_quiet )
applog2( LOG_INFO, "Share diff %.3g (%5f%%), block %d, %s",
my_stats.share_diff, share_ratio, stratum.block_height,
job_id );
applog2( LOG_NOTICE, "Diff %.3g (%.3g%), %sBlock %d, %sJob %s" CL_WHT,
my_stats.share_diff, share_ratio, bcol, stratum.block_height,
scol, my_stats.job_id );
if ( unlikely( reason && !result ) )
{
if ( !opt_quiet && !stale )
if ( !( opt_quiet || stale ) )
applog( LOG_WARNING, "Reject reason: %s", reason );
if ( opt_debug )
@@ -1695,7 +1701,7 @@ static void *workio_thread(void *userdata)
if ( jsonrpc_2 && !have_stratum )
ok = rpc2_workio_login( curl );
while (ok)
while ( likely(ok) )
{
struct workio_cmd *wc;
@@ -1771,7 +1777,8 @@ static bool get_work(struct thr_info *thr, struct work *work)
return true;
}
static bool submit_work( struct thr_info *thr, const struct work *work_in )
static bool submit_work( const struct thr_info *thr,
const struct work *work_in )
{
struct workio_cmd *wc;
@@ -1795,20 +1802,22 @@ err_out:
return false;
}
// Convert little endian 256 bit unsigned integer to
// double precision floating point.
static inline double u256_to_double( const uint64_t* u )
// __float128?
// Convert little endian 256 bit (38 decimal digits) unsigned integer to
// double precision floating point with 15 decimal digits precision.
// returns u * ( 2**256 )
static inline double u256_to_double( const uint64_t *u )
{
const double f = 4294967296.0 * 4294967296.0; // 2**64
return ( ( u[3] * f + u[2] ) * f + u[1] ) * f + u[0];
const double exp64 = 4294967296.0 * 4294967296.0; // 2**64
return ( ( u[3] * exp64 + u[2] ) * exp64 + u[1] ) * exp64 + u[0];
}
void work_set_target_ratio( struct work* work, uint32_t* hash )
void work_set_target_ratio( struct work* work, const void *hash )
{
double dhash;
dhash = u256_to_double( (const uint64_t*)hash );
if ( dhash > 0. )
if ( likely( dhash > 0. ) )
work->sharediff = work->targetdiff *
u256_to_double( (const uint64_t*)( work->target ) ) / dhash;
else
@@ -1833,38 +1842,38 @@ void work_set_target_ratio( struct work* work, uint32_t* hash )
pthread_mutex_unlock( &stats_lock );
}
bool submit_solution( struct work *work, void *hash,
struct thr_info *thr )
bool submit_solution( struct work *work, const void *hash,
const struct thr_info *thr )
{
if ( submit_work( thr, work ) )
if ( likely( submit_work( thr, work ) ) )
{
submitted_share_count++;
work_set_target_ratio( work, hash );
if ( !opt_quiet )
applog( LOG_NOTICE, "%d: submitted by thread %d, job %s",
applog( LOG_NOTICE, "%d submitted by thread %d, job %s",
submitted_share_count, thr->id, work->job_id );
return true;
}
else
applog( LOG_WARNING, "%d: failed to submit share.",
applog( LOG_WARNING, "%d failed to submit share.",
submitted_share_count );
return false;
}
bool submit_lane_solution( struct work *work, void *hash,
struct thr_info *thr, int lane )
bool submit_lane_solution( struct work *work, const void *hash,
const struct thr_info *thr, const int lane )
{
if ( submit_work( thr, work ) )
if ( likely( submit_work( thr, work ) ) )
{
submitted_share_count++;
work_set_target_ratio( work, hash );
if ( !opt_quiet )
applog( LOG_NOTICE, "%d: submitted by thread %d, lane %d, job %s",
applog( LOG_NOTICE, "%d submitted by thread %d, lane %d, job %s",
submitted_share_count, thr->id, lane, work->job_id );
return true;
}
else
applog( LOG_WARNING, "%d: failed to submit share.",
applog( LOG_WARNING, "%d failed to submit share.",
submitted_share_count );
return false;
}
@@ -1971,25 +1980,24 @@ double std_calc_network_diff( struct work* work )
return d;
}
uint32_t* std_get_nonceptr( uint32_t *work_data )
uint32_t *std_get_nonceptr( uint32_t *work_data )
{
return work_data + algo_gate.nonce_index;
}
uint32_t* jr2_get_nonceptr( uint32_t *work_data )
uint32_t *jr2_get_nonceptr( uint32_t *work_data )
{
// nonce is misaligned, use byte offset
return (uint32_t*) ( ((uint8_t*) work_data) + algo_gate.nonce_index );
}
void std_get_new_work( struct work* work, struct work* g_work, int thr_id,
uint32_t *end_nonce_ptr, bool clean_job )
{
uint32_t *nonceptr = algo_gate.get_nonceptr( work->data );
bool force_new_work = work->job_id ? strtoul( work->job_id, NULL, 16 )
!= strtoul( g_work->job_id, NULL, 16 )
bool force_new_work = work->job_id ? strtoul( work->job_id, NULL, 16 ) !=
strtoul( g_work->job_id, NULL, 16 )
: true;
if ( force_new_work || *nonceptr >= *end_nonce_ptr
@@ -2074,29 +2082,20 @@ static void *miner_thread( void *userdata )
#ifndef WIN32
prio = 18;
// note: different behavior on linux (-19 to 19)
switch (opt_priority)
switch ( opt_priority )
{
case 1:
prio = 5;
break;
case 2:
prio = 0;
break;
case 3:
prio = -5;
break;
case 4:
prio = -10;
break;
case 5:
prio = -15;
case 1: prio = 5; break;
case 2: prio = 0; break;
case 3: prio = -5; break;
case 4: prio = -10; break;
case 5: prio = -15;
}
if (opt_debug)
applog(LOG_DEBUG, "Thread %d priority %d (nice %d)", thr_id,
opt_priority, prio );
#endif
setpriority(PRIO_PROCESS, 0, prio);
if (opt_priority == 0)
if ( opt_priority == 0 )
drop_policy();
}
// CPU thread affinity
@@ -2150,7 +2149,7 @@ static void *miner_thread( void *userdata )
}
// wait for stratum to send first job
if ( have_stratum ) while ( !g_work.job_id ) sleep(1);
if ( have_stratum ) while ( unlikely( !g_work.job_id ) ) sleep(1);
while (1)
{
@@ -2159,7 +2158,7 @@ static void *miner_thread( void *userdata )
int64_t max64 = 1000;
int nonce_found = 0;
if ( algo_gate.do_this_thread( thr_id ) )
if ( likely( algo_gate.do_this_thread( thr_id ) ) )
{
if ( have_stratum )
{
@@ -2194,10 +2193,10 @@ static void *miner_thread( void *userdata )
} // do_this_thread
algo_gate.resync_threads( &work );
if ( !algo_gate.ready_to_mine( &work, &stratum, thr_id ) )
if ( unlikely( !algo_gate.ready_to_mine( &work, &stratum, thr_id ) ) )
continue;
// conditional mining
if (!wanna_mine(thr_id))
if ( unlikely( !wanna_mine( thr_id ) ) )
{
sleep(5);
continue;
@@ -2209,7 +2208,7 @@ static void *miner_thread( void *userdata )
max64 = g_work_time + ( have_longpoll ? LP_SCANTIME : opt_scantime )
- time(NULL);
// time limit
if ( opt_time_limit && firstwork_time )
if ( unlikely( opt_time_limit && firstwork_time ) )
{
int passed = (int)( time(NULL) - firstwork_time );
int remain = (int)( opt_time_limit - passed );
@@ -2267,7 +2266,7 @@ static void *miner_thread( void *userdata )
pthread_mutex_unlock( &stats_lock );
}
// If unsubmiited nonce(s) found, submit now.
if ( nonce_found && !opt_benchmark )
if ( unlikely( nonce_found && !opt_benchmark ) )
{
applog( LOG_WARNING, "BUG: See RELEASE_NOTES for reporting bugs. Algo = %s.",
algo_names[ opt_algo ] );
@@ -2292,7 +2291,7 @@ static void *miner_thread( void *userdata )
}
}
// display hashrate
if ( opt_hash_meter )
if ( unlikely( opt_hash_meter ) )
{
char hr[16];
char hr_units[2] = {0,0};
@@ -2310,8 +2309,8 @@ static void *miner_thread( void *userdata )
// Display benchmark total
// Update hashrate for API if no shares accepted yet.
if ( ( opt_benchmark || !accepted_share_count )
&& thr_id == opt_n_threads - 1 )
if ( unlikely( ( opt_benchmark || !accepted_share_count )
&& thr_id == opt_n_threads - 1 ) )
{
double hashrate = 0.;
for ( i = 0; i < opt_n_threads; i++ )
@@ -2630,12 +2629,11 @@ void std_stratum_gen_work( struct stratum_ctx *sctx, struct work *g_work )
algo_gate.build_extraheader( g_work, sctx );
net_diff = algo_gate.calc_network_diff( g_work );
algo_gate.set_work_data_endian( g_work );
pthread_mutex_unlock( &sctx->work_lock );
work_set_target( g_work, sctx->job.diff
/ ( opt_target_factor * opt_diff_factor ) );
pthread_mutex_unlock( &sctx->work_lock );
if ( opt_debug )
{
unsigned char *xnonce2str = abin2hex( g_work->xnonce2,
@@ -2645,12 +2643,7 @@ void std_stratum_gen_work( struct stratum_ctx *sctx, struct work *g_work )
free( xnonce2str );
}
// Log new block and/or stratum difficulty change.
if ( ( stratum_diff != sctx->job.diff )
|| ( last_block_height != sctx->block_height ) )
{
double hr = 0.;
new_job = false;
pthread_mutex_lock( &stats_lock );
for ( int i = 0; i < opt_n_threads; i++ )
@@ -2658,32 +2651,33 @@ void std_stratum_gen_work( struct stratum_ctx *sctx, struct work *g_work )
global_hashrate = hr;
pthread_mutex_unlock( &stats_lock );
if ( !opt_quiet )
{
if ( stratum_diff != sctx->job.diff )
applog( LOG_BLUE, "New stratum diff %g, block %d, job %s",
sctx->job.diff, sctx->block_height, g_work->job_id );
else if ( last_block_height != sctx->block_height )
applog( LOG_BLUE, "New block %d, job %s", sctx->block_height,
g_work->job_id );
applog( LOG_BLUE, "New block %d, job %s",
sctx->block_height, g_work->job_id );
else
applog( LOG_BLUE,"New job %s.", g_work->job_id );
}
applog( LOG_BLUE,"New job %s", g_work->job_id );
// Update data and calculate new estimates.
stratum_diff = sctx->job.diff;
if ( ( stratum_diff != sctx->job.diff )
|| ( last_block_height != sctx->block_height ) )
{
static bool multipool = false;
if ( stratum.block_height < last_block_height ) multipool = true;
if ( unlikely( !session_first_block ) )
session_first_block = stratum.block_height;
last_block_height = stratum.block_height;
stratum_diff = sctx->job.diff;
last_targetdiff = g_work->targetdiff;
if ( !opt_quiet )
{
applog2( LOG_INFO, "%s %s block %d", short_url,
algo_names[opt_algo], stratum.block_height );
applog2( LOG_INFO, "Diff: net %g, stratum %g, target %g",
applog2( LOG_INFO, "%s: %s", algo_names[opt_algo], short_url );
applog2( LOG_INFO, "Diff: Net %.3g, Stratum %.3g, Target %.3g",
net_diff, stratum_diff, last_targetdiff );
}
if ( hr > 0. )
if ( likely( hr > 0. ) )
{
char hr_units[4] = {0};
char block_ttf[32];
@@ -2693,12 +2687,28 @@ void std_stratum_gen_work( struct stratum_ctx *sctx, struct work *g_work )
sprintf_et( share_ttf, last_targetdiff * diff_to_hash / hr );
scale_hash_for_display ( &hr, hr_units );
if ( !opt_quiet )
{
applog2( LOG_INFO, "TTF @ %.2f %sh/s: block %s, share %s",
hr, hr_units, block_ttf, share_ttf );
if ( !multipool && net_diff > 0. )
{
struct timeval now, et;
gettimeofday( &now, NULL );
timeval_subtract( &et, &now, &session_start );
double net_hr = net_diff * diff_to_hash;
char net_ttf[32];
char net_hr_units[4] = {0};
sprintf_et( net_ttf,
( last_block_height - session_first_block ) == 0 ? 0 :
et.tv_sec / ( last_block_height - session_first_block ) );
scale_hash_for_display ( &net_hr, net_hr_units );
applog2( LOG_INFO, "TTF @ %.2f %sh/s: %s",
net_hr, net_hr_units, net_ttf );
}
}
} // hr > 0
} // !quiet
} // new diff/block
}
@@ -2726,7 +2736,7 @@ static void *stratum_thread(void *userdata )
{
int failures = 0;
if ( stratum_need_reset )
if ( unlikely( stratum_need_reset ) )
{
stratum_need_reset = false;
stratum_disconnect( &stratum );
@@ -2763,8 +2773,7 @@ static void *stratum_thread(void *userdata )
applog(LOG_ERR, "...retry after %d seconds", opt_fail_pause);
sleep(opt_fail_pause);
}
if (jsonrpc_2)
if ( unlikely( jsonrpc_2 ) )
{
work_free(&g_work);
work_copy(&g_work, &stratum.work);
@@ -2777,28 +2786,12 @@ static void *stratum_thread(void *userdata )
if ( stratum.job.job_id
&& ( !g_work_time || strcmp( stratum.job.job_id, g_work.job_id ) ) )
{
new_job = true;
pthread_mutex_lock(&g_work_lock);
algo_gate.stratum_gen_work( &stratum, &g_work );
time(&g_work_time);
pthread_mutex_unlock(&g_work_lock);
restart_threads();
if ( stratum.job.clean || jsonrpc_2 )
{
if ( !opt_quiet && last_block_height && new_job
&& ( last_block_height == stratum.block_height ) )
{
new_job = false;
applog( LOG_BLUE,"New job %s", g_work.job_id );
}
}
else if (opt_debug && !opt_quiet)
{
applog( LOG_BLUE, "%s asks job %d for block %d", short_url,
strtoul( stratum.job.job_id, NULL, 16 ), stratum.block_height );
}
} // stratum.job.job_id
if ( stratum_socket_full( &stratum, opt_timeout ) )
{
@@ -3751,6 +3744,7 @@ int main(int argc, char *argv[])
applog(LOG_WARNING,"available on Linux. Using default affinity.");
opt_affinity = -1;
}
/*
else
{
affine_to_cpu_mask( -1, opt_affinity );
@@ -3769,6 +3763,7 @@ int main(int argc, char *argv[])
#endif
}
}
*/
}
#ifdef HAVE_SYSLOG_H

12
miner.h
View File

@@ -313,12 +313,14 @@ size_t address_to_script( unsigned char *out, size_t outsz, const char *addr );
int timeval_subtract( struct timeval *result, struct timeval *x,
struct timeval *y);
bool fulltest( const uint32_t *hash, const uint32_t *target );
bool valid_hash( const void*, const void* );
void work_set_target( struct work* work, double diff );
double target_to_diff( uint32_t* target );
extern void diff_to_target(uint32_t *target, double diff);
double hash_target_ratio( uint32_t* hash, uint32_t* target );
void work_set_target_ratio( struct work* work, uint32_t* hash );
void work_set_target_ratio( struct work* work, const void *hash );
struct thr_info {
int id;
@@ -330,10 +332,10 @@ struct thr_info {
//struct thr_info *thr_info;
bool submit_solution( struct work *work, void *hash,
struct thr_info *thr );
bool submit_lane_solution( struct work *work, void *hash,
struct thr_info *thr, int lane );
bool submit_solution( struct work *work, const void *hash,
const struct thr_info *thr );
bool submit_lane_solution( struct work *work, const void *hash,
const struct thr_info *thr, const int lane );
//bool submit_work( struct thr_info *thr, const struct work *work_in );

View File

@@ -46,10 +46,11 @@
#define HWMON_PATH \
"/sys/class/hwmon/hwmon2/temp1_input"
/*
// need this for Ryzen
#define HWMON_ALT \
"/sys/class/hwmon/hwmon0/temp1_input"
/*
#define HWMON_ALT1 \
"/sys/devices/platform/coretemp.0/hwmon/hwmon1/temp1_input"
*/
@@ -84,6 +85,9 @@ static inline float linux_cputemp(int core)
if (!fd)
fd = fopen(HWMON_PATH, "r");
if (!fd)
fd = fopen(HWMON_ALT, "r");
if (!fd)
return tc;

47
util.c
View File

@@ -982,40 +982,59 @@ int timeval_subtract(struct timeval *result, struct timeval *x,
return x->tv_sec < y->tv_sec;
}
bool fulltest(const uint32_t *hash, const uint32_t *target)
// Use this when deinterleaved
// do 64 bit test 4 iterations
inline bool valid_hash( const void *hash, const void *target )
{
const uint64_t *h = (const uint64_t*)hash;
const uint64_t *t = (const uint64_t*)target;
if ( h[3] > t[3] ) return false;
if ( h[3] < t[3] ) return true;
if ( h[2] > t[2] ) return false;
if ( h[2] < t[2] ) return true;
if ( h[1] > t[1] ) return false;
if ( h[1] < t[1] ) return true;
if ( h[0] > t[0] ) return false;
return true;
}
bool fulltest( const uint32_t *hash, const uint32_t *target )
{
int i;
bool rc = true;
for (i = 7; i >= 0; i--) {
if (hash[i] > target[i]) {
for ( i = 7; i >= 0; i-- )
{
if ( hash[i] > target[i] )
{
rc = false;
break;
}
if (hash[i] < target[i]) {
if ( hash[i] < target[i] )
{
rc = true;
break;
}
}
if (opt_debug) {
if ( opt_debug )
{
uint32_t hash_be[8], target_be[8];
char hash_str[65], target_str[65];
for (i = 0; i < 8; i++) {
be32enc(hash_be + i, hash[7 - i]);
be32enc(target_be + i, target[7 - i]);
for ( i = 0; i < 8; i++ )
{
be32enc( hash_be + i, hash[7 - i] );
be32enc( target_be + i, target[7 - i] );
}
bin2hex(hash_str, (unsigned char *)hash_be, 32);
bin2hex(target_str, (unsigned char *)target_be, 32);
bin2hex( hash_str, (unsigned char *)hash_be, 32 );
bin2hex( target_str, (unsigned char *)target_be, 32 );
applog(LOG_DEBUG, "DEBUG: %s\nHash: %s\nTarget: %s",
applog( LOG_DEBUG, "DEBUG: %s\nHash: %s\nTarget: %s",
rc ? "hash <= target"
: "hash > target (false positive)",
hash_str,
target_str);
hash_str, target_str );
}
return rc;
}