12
12
#include < chrono>
13
13
#endif
14
14
15
+ #include < sstream>
15
16
#include < stdio.h>
16
17
#include < stdint.h>
17
18
#include < time.h>
@@ -86,6 +87,8 @@ bool MomentChi2Test ( struct HashInfo *info, int inputSize );
86
87
// -----------------------------------------------------------------------------
87
88
// This is the list of all hashes that SMHasher can test.
88
89
90
+ #define COUNT_OF (x ) ((sizeof (x)/sizeof (0 [x])) / ((size_t )(!(sizeof (x) % sizeof (0 [x])))))
91
+
89
92
const char * quality_str[3 ] = { " SKIP" , " POOR" , " GOOD" };
90
93
91
94
// sorted by quality and speed. the last is the list of internal secrets to be tested against bad seeds.
@@ -979,6 +982,17 @@ void SelfTest(bool verbose) {
979
982
980
983
// ----------------------------------------------------------------------------
981
984
985
+ static std::pair<double , double > CalcWAvg (const double *x, const double *dist, size_t imin, size_t imax)
986
+ {
987
+ double sum = 0 , prb = 0 ;
988
+ for (size_t i = imin; i <= imax; i++) {
989
+ sum += dist[i] * x[i];
990
+ prb += dist[i];
991
+ }
992
+ sum /= prb;
993
+ return std::make_pair (sum, prb);
994
+ }
995
+
982
996
template < typename hashtype >
983
997
void test ( hashfunc<hashtype> hash, HashInfo* info )
984
998
{
@@ -1027,7 +1041,6 @@ void test ( hashfunc<hashtype> hash, HashInfo* info )
1027
1041
1028
1042
if (g_testSpeedBulk || g_testSpeedSmall || g_testAll)
1029
1043
{
1030
- double sum = 0.0 ;
1031
1044
printf (" [[[ Speed Tests ]]]\n\n " );
1032
1045
if (timer_counts_ns ())
1033
1046
printf (" WARNING: no cycle counter, cycle == 1ns\n " );
@@ -1050,17 +1063,43 @@ void test ( hashfunc<hashtype> hash, HashInfo* info )
1050
1063
}
1051
1064
1052
1065
if (g_testSpeedSmall || g_testAll) {
1053
- const char * const envsmin = getenv ( " SMHASHER_SMALLKEY_MIN " ) ;
1054
- const char * const envsmax = getenv ( " SMHASHER_SMALLKEY_MAX " );
1055
- const int minkey = max ( min (envsmin ? atoi (envsmin) : 1 , 255 ), 1 );
1056
- const int maxkey = max ( min (envsmax ? atoi (envsmax) : 32 , 255 ), minkey) ;
1066
+ const int dflmax = g_testExtra ? 64 : 32 ;
1067
+ const int minkey = getenvlong ( " SMHASHER_SMALLKEY_MIN " , 1 , 1 , TIMEHASH_SMALL_LEN_MAX );
1068
+ const int maxkey = getenvlong ( " SMHASHER_SMALLKEY_MAX " , minkey, dflmax, TIMEHASH_SMALL_LEN_MAX );
1069
+ double cph[TIMEHASH_SMALL_LEN_MAX + 1 ] ;
1057
1070
for (int i = minkey; i <= maxkey; i++)
1058
1071
{
1059
1072
volatile int j = i;
1060
- sum += TinySpeedTest (hashfunc<hashtype>(info->hash ),sizeof (hashtype),j,info->verification ,true );
1073
+ cph[j] = TinySpeedTest (hashfunc<hashtype>(info->hash ),sizeof (hashtype),j,info->verification ,true );
1074
+ }
1075
+ {
1076
+ double sum = 0 ;
1077
+ for (int i = minkey; i <= maxkey; i++)
1078
+ sum += cph[i];
1079
+ sum /= (maxkey - minkey + 1 );
1080
+ g_speed = sum;
1081
+ printf (" Average %8.3f cycles/hash\n " ,sum);
1082
+ }
1083
+ if (const char *weights = getenv (" SMHASHER_SMALLKEY_WEIGHTS" ))
1084
+ {
1085
+ // Weighted average exist under assumption that hash speed does not depend on input,
1086
+ // which is not true due to multiplication instruction having certain amount of variance.
1087
+ std::vector<double > lenprob;
1088
+ std::istringstream ssws (weights);
1089
+ double sum = 0.0 ;
1090
+ for (double f; ssws >> f; ) {
1091
+ lenprob.push_back (f);
1092
+ sum += f;
1093
+ }
1094
+ for (size_t i = 0 ; i < lenprob.size (); i++)
1095
+ lenprob[i] /= sum;
1096
+ if (maxkey < lenprob.size ()) {
1097
+ const auto m = CalcWAvg (cph, lenprob.data (), minkey, maxkey);
1098
+ printf (" Weighted average, %5.1f%% of weights %8.3f cycles/hash\n " ,100 .*m.second ,m.first );
1099
+ } else {
1100
+ printf (" Weighted average needs %u more weights (SKIP it)\n " , (unsigned )(maxkey - lenprob.size () + 1 ));
1101
+ }
1061
1102
}
1062
- g_speed = sum = sum / (maxkey - minkey + 1 );
1063
- printf (" Average %6.3f cycles/hash\n " ,sum);
1064
1103
printf (" \n " );
1065
1104
fflush (NULL );
1066
1105
}
0 commit comments