Changeset: 638d8ccaaee4 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/638d8ccaaee4
Branch: pp_hashjoin
Log Message:

Merge with cnting_sketches branch.


diffs (truncated from 8193 to 300 lines):

diff --git a/gdk/CMakeLists.txt b/gdk/CMakeLists.txt
--- a/gdk/CMakeLists.txt
+++ b/gdk/CMakeLists.txt
@@ -91,6 +91,9 @@ target_sources(bat
   gdk_tracer.c gdk_tracer.h
   gdk_rtree.c
   gdk_strimps.c
+  murmurhash3.h
+  xxhash.h
+  gdk_sketch.c
   PUBLIC
   ${gdk_public_headers})
 
diff --git a/gdk/gdk.h b/gdk/gdk.h
--- a/gdk/gdk.h
+++ b/gdk/gdk.h
@@ -367,6 +367,13 @@ typedef struct pipeline_io {
 
 #define ORDERIDXOFF            3
 
+#define HLL_BITS 6
+#define BITS_MASK   ((1ULL << HLL_BITS) - 1)
+#define MAX_CLZ     (64 - HLL_BITS)
+#define BUCKETS     (1U << HLL_BITS)
+#define CLZ_BUCKETS (MAX_CLZ + 1)
+#define HLLSEED     0xadc83b19ULL
+
 /* assert that atom width is power of 2, i.e., width == 1<<shift */
 #define assert_shift_width(shift,width) assert(((shift) == 0 && (width) == 0) 
|| ((unsigned)1<<(shift)) == (unsigned)(width))
 
@@ -1427,6 +1434,11 @@ gdk_export void STRMPdestroy(BAT *b);
 gdk_export bool BAThasstrimps(BAT *b);
 gdk_export gdk_return BATsetstrimps(BAT *b);
 
+gdk_export void sketch_populate(BAT* n, BATiter *ni, struct canditer *nci, 
uint8_t cnting_sketch[BUCKETS][CLZ_BUCKETS]);
+/* gdk_export void sketch_merge(BAT* b, BAT* n); */
+gdk_export double sketch_estimate(uint8_t cnt_sketch[BUCKETS][CLZ_BUCKETS]);
+gdk_export double bat_guess_uniques(BAT *b, BATiter *bi, struct canditer *bci);
+
 /* Rtree structure functions */
 #ifdef HAVE_RTREE
 gdk_export bool RTREEexists(BAT *b);
diff --git a/gdk/gdk_join.c b/gdk/gdk_join.c
--- a/gdk/gdk_join.c
+++ b/gdk/gdk_join.c
@@ -3635,7 +3635,8 @@ BATguess_uniques(BAT *b, struct canditer
                canditer_init(&lci, b, NULL);
                ci = &lci;
        }
-       double uniques = guess_uniques(b, ci);
+       /* double uniques = guess_uniques(b, ci); */
+       double uniques = bat_guess_uniques(b, NULL, ci);
        return uniques < 0 ? 0 : (BUN) uniques;
 }
 
diff --git a/gdk/gdk_sketch.c b/gdk/gdk_sketch.c
new file mode 100644
--- /dev/null
+++ b/gdk/gdk_sketch.c
@@ -0,0 +1,168 @@
+/*
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0.  If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * For copyright information, see the file debian/copyright.
+ */
+
+#include "gdk.h"
+
+#include <sys/random.h>
+// #include "murmurhash3.h"
+#define XXH_STATIC_LINKING_ONLY
+#define XXH_IMPLEMENTATION
+#include "xxhash.h"
+
+// Helper function sigma as defined in
+// "New cardinality estimation algorithms for HyperLogLog sketches"
+// Otmar Ertl, arXiv:1702.01284
+static inline double
+sigma(double x)
+{
+       if (x == 1.) return INFINITY;
+       double y = 1;
+       double z = x;
+       double z_prime;
+       do {
+               x *= x;
+               z_prime = z;
+               z += x * y;
+               y += y;
+       } while(z_prime != z);
+       return z;
+}
+
+// Helper function tau as defined in
+// "New cardinality estimation algorithms for HyperLogLog sketches"
+// Otmar Ertl, arXiv:1702.01284
+static inline double
+tau(double x)
+{
+       if (x == 0. || x == 1.) return 0.;
+       double y = 1.0;
+       double z = 1 - x;
+       double z_prime;
+       do {
+               x = sqrt(x);
+               z_prime = z;
+               y *= 0.5;
+               z -= pow(1 - x, 2) * y;
+       } while(z_prime != z);
+       return z / 3;
+}
+
+/// Estimator as defined in
+/// "New cardinality estimation algorithms for HyperLogLog sketches"
+/// Otmar Ertl, arXiv:1702.01284.
+/// Only difference is how the multiplicity array is computed
+double
+sketch_estimate(uint8_t cnt_sketch[BUCKETS][CLZ_BUCKETS])
+{
+       int8_t C[CLZ_BUCKETS + 1] = {0};
+       for (size_t bucket = 0; bucket < BUCKETS; bucket++) {
+               int K = -1;
+               for (size_t clz = 0; clz < CLZ_BUCKETS; clz++)
+                       if (cnt_sketch[bucket][clz] > 0)
+                               K = clz;
+               K == -1 ? C[0]++ : C[K + 1]++;
+       }
+       double t = tau(1.0 - ((double)C[CLZ_BUCKETS] / BUCKETS));
+       double z = (double)BUCKETS * t;
+       for (int k = CLZ_BUCKETS; k >= 1; k--)
+               z = 0.5 * (z + (double)C[k]);
+       double s = sigma((double)C[0] / BUCKETS);
+       z += (double)BUCKETS * s;
+       const double alpha = 0.7213475204444817;
+       return alpha * (double)BUCKETS * BUCKETS / z;
+}
+
+void
+sketch_populate(BAT* b, BATiter *bi, struct canditer *bci,
+               uint8_t cnting_sketch[BUCKETS][CLZ_BUCKETS])
+{
+       oid hseq = b->hseqbase;
+       /* uint64_t murmur3_out[2]; */
+       uint64_t hash;
+       uint8_t bucket;
+
+       uint8_t clz;
+
+       QryCtx *qry_ctx = MT_thread_get_qry_ctx();
+       canditer_reset(bci);
+       TIMEOUT_LOOP(bci->ncand, qry_ctx) {
+               BUN p = canditer_next(bci) - hseq;
+               const void *ptr = BUNtail(bi, p);
+               switch (bi->type) {
+               case TYPE_int:
+                       if (is_int_nil(*(int *)ptr))
+                               continue;
+                       else
+                               /* MurmurHash3_x64_128(ptr, sizeof(int), 
HLLSEED, murmur3_out); */
+                               /* hash = murmur3_out[1]; */
+                               hash = XXH64(ptr, sizeof(int), HLLSEED);
+                       break;
+               case TYPE_lng:
+                       if (is_lng_nil(*(lng *)ptr))
+                               continue;
+                       else
+                               /* MurmurHash3_x64_128(ptr, sizeof(lng), 
HLLSEED, murmur3_out); */
+                               /* hash = murmur3_out[1]; */
+                               hash = XXH64(ptr, sizeof(lng), HLLSEED);
+                       break;
+               case TYPE_str:
+                       if (strNil(ptr))
+                               continue;
+                       else
+                               /* MurmurHash3_x64_128(ptr, strlen(ptr), 
HLLSEED, murmur3_out); */
+                               /* hash = murmur3_out[1]; */
+                               hash = XXH64(ptr, strlen(ptr), HLLSEED);
+                       break;
+               default:
+                       return;
+               }
+               bucket = hash & BITS_MASK;
+               hash |= BITS_MASK;
+               clz = __builtin_clzll(hash);
+               assert(clz <= 58);
+               if (cnting_sketch[bucket][clz] <= 128) {
+                       cnting_sketch[bucket][clz]++;
+               } else {
+                       uint8_t k = cnting_sketch[bucket][clz] - 128;
+                       uint64_t rng;
+                       getrandom(&rng, sizeof(rng), 0);
+                       if ((rng & ((1ULL << k) - 1)) == 0)
+                               cnting_sketch[bucket][clz]++;
+               }
+       }
+}
+
+/* void */
+/* sketch_merge(BAT* b, BAT* n) */
+/* { */
+/*     MT_lock_set(&b->batIdxLock); */
+/*     for (size_t i = 0; i < BUCKETS; i++) */
+/*             for (size_t j = 0; j < CLZ_BUCKETS; j++) */
+/*                     if (n->cnting_sketch[i][j] > b->cnting_sketch[i][j]) */
+/*                             b->cnting_sketch[i][j] = 
n->cnting_sketch[i][j]; */
+/*     b->unique_guess = sketch_estimate(b->cnting_sketch); */
+/*     MT_lock_unset(&b->batIdxLock); */
+/* } */
+
+double
+bat_guess_uniques(BAT *b, BATiter *bi, struct canditer *bci)
+{
+       uint8_t cnting_sketch[BUCKETS][CLZ_BUCKETS] = {0};
+
+       BATiter nbi = bi ? *bi : bat_iterator(b);
+
+       sketch_populate(b, &nbi, bci, cnting_sketch);
+       double unique_guess = sketch_estimate(cnting_sketch);
+
+       if (bi == NULL)
+               bat_iterator_end(&nbi);
+
+       return unique_guess;
+}
diff --git a/gdk/murmurhash3.h b/gdk/murmurhash3.h
new file mode 100644
--- /dev/null
+++ b/gdk/murmurhash3.h
@@ -0,0 +1,374 @@
+//-----------------------------------------------------------------------------
+// MurmurHash3 was written by Austin Appleby, and is placed in the public
+// domain. The author hereby disclaims copyright to this source code.
+
+// Note - The x86 and x64 versions do _not_ produce the same results, as the
+// algorithms are optimized for their respective platforms. You can still
+// compile and run any of them on any platform, but your performance with the
+// non-native version will be less than optimal.
+
+#ifndef _MURMURHASH3_H_
+#define _MURMURHASH3_H_
+
+//-----------------------------------------------------------------------------
+// Platform-specific functions and macros
+
+// Microsoft Visual Studio
+
+#if defined(_MSC_VER) && (_MSC_VER < 1600)
+
+typedef unsigned char uint8_t;
+typedef unsigned int uint32_t;
+typedef unsigned __int64 uint64_t;
+
+// Other compilers
+
+#else  // defined(_MSC_VER)
+
+#include <stdint.h>
+
+#endif // !defined(_MSC_VER)
+
+//-----------------------------------------------------------------------------
+
+void MurmurHash3_x86_32  ( const void * key, int len, uint32_t seed, void * 
out );
+
+void MurmurHash3_x86_128 ( const void * key, int len, uint32_t seed, void * 
out );
+
+void MurmurHash3_x64_128 ( const void * key, int len, uint32_t seed, void * 
out );
+
+//-----------------------------------------------------------------------------
+// Platform-specific functions and macros
+
+// Microsoft Visual Studio
+
+#if defined(_MSC_VER)
+
+#define FORCE_INLINE   __forceinline
+
+#include <stdlib.h>
+
+#define ROTL32(x,y)    _rotl(x,y)
+#define ROTL64(x,y)    _rotl64(x,y)
+
+#define BIG_CONSTANT(x) (x)
+
+// Other compilers
+
+#else  // defined(_MSC_VER)
+
+#define        FORCE_INLINE inline __attribute__((always_inline))
+
+static inline uint32_t
+rotl32 ( uint32_t x, int8_t r )
+{
+  return (x << r) | (x >> (32 - r));
+}
+
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to