Changeset: ac637e0e0709 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=ac637e0e0709
Modified Files:
        gdk/gdk_bbp.c
        gdk/gdk_sample.c
Branch: default
Log Message:

Use a global pseudo random number state for BATsample.
The global state is protected by a lock.  BATsample_with_seed does not
use this state but uses its own and therefore doesn't need or use a
lock.

Also some cleanup of the code.


diffs (125 lines):

diff --git a/gdk/gdk_bbp.c b/gdk/gdk_bbp.c
--- a/gdk/gdk_bbp.c
+++ b/gdk/gdk_bbp.c
@@ -1318,6 +1318,7 @@ BBPinit(void)
 #ifdef NEED_MT_LOCK_INIT
        MT_lock_init(&GDKunloadLock, "GDKunloadLock");
        ATOMIC_INIT(BBPsizeLock);
+       BATsample(NULL, 0);     /* initializes the lock */
 #endif
 
        if (BBPfarms[0].dirname == NULL) {
diff --git a/gdk/gdk_sample.c b/gdk/gdk_sample.c
--- a/gdk/gdk_sample.c
+++ b/gdk/gdk_sample.c
@@ -28,23 +28,6 @@
 #include "gdk_private.h"
 #include "xoshiro256starstar.h"
 
-#undef BATsample
-
-#ifdef STATIC_CODE_ANALYSIS
-#define DRAND (0.5)
-#else
-/* the range of rand() is [0..RAND_MAX], i.e. inclusive;
- * cast first, add later: on Linux RAND_MAX == INT_MAX, so adding 1
- * will overflow, but INT_MAX does fit in a double */
-#if RAND_MAX < 46340       /* 46340*46340 = 2147395600 < INT_MAX */
-/* random range is too small, double it */
-#define DRAND ((double)(rand() * (RAND_MAX + 1) + rand()) / ((double) 
((RAND_MAX + 1) * (RAND_MAX + 1))))
-#else
-#define DRAND ((double)rand() / ((double)RAND_MAX + 1))
-#endif
-#endif
-
-
 /* this is a straightforward implementation of a binary tree */
 struct oidtreenode {
        oid o;
@@ -107,9 +90,8 @@ OIDTreeToBATAntiset(struct oidtreenode *
                         ((oid *) bat->theap.base)[bat->batCount++] = noid;
 }
 
-/* BATsample implements sampling for void headed BATs */
-BAT *
-BATsample_with_seed(BAT *b, BUN n, unsigned seed)
+static BAT *
+do_batsample(BAT *b, BUN n, random_state_engine rse, MT_Lock *lock)
 {
        BAT *bn;
        BUN cnt, slen;
@@ -129,9 +111,7 @@ BATsample_with_seed(BAT *b, BUN n, unsig
        } else {
                oid minoid = b->hseqbase;
                oid maxoid = b->hseqbase + cnt;
-               random_state_engine rse;
-               
-               
+
                /* if someone samples more than half of our tree, we
                 * do the antiset */
                bool antiset = n > cnt / 2;
@@ -149,20 +129,19 @@ BATsample_with_seed(BAT *b, BUN n, unsig
                        return NULL;
                }
 
-               init_random_state_engine(&rse, seed);
-
                /* while we do not have enough sample OIDs yet */
+               if (lock)       /* serialize access to random state engine */
+                       MT_lock_set(lock);
                for (rescnt = 0; rescnt < n; rescnt++) {
                        oid candoid;
                        do {
-                               double random_double = next_double(rse);
-
-                               /* generate a new random OID */
-                               candoid = (oid) (minoid + random_double * 
(maxoid - minoid));
+                               candoid = minoid + next(rse) % cnt;
                                /* if that candidate OID was already
                                 * generated, try again */
                        } while (!OIDTreeMaybeInsert(tree, candoid, rescnt));
                }
+               if (lock)
+                       MT_lock_unset(lock);
                if (!antiset) {
                        OIDTreeToBAT(tree, bn);
                } else {
@@ -182,10 +161,35 @@ BATsample_with_seed(BAT *b, BUN n, unsig
        return bn;
 }
 
+/* BATsample implements sampling for BATs */
+BAT *
+BATsample_with_seed(BAT *b, BUN n, unsigned seed)
+{
+       random_state_engine rse;
+
+       init_random_state_engine(rse, (uint64_t) seed);
+
+       return do_batsample(b, n, rse, NULL);
+}
+
 BAT *
 BATsample(BAT *b, BUN n)
 {
-       unsigned some_random_seed = (unsigned) rand();
+       static random_state_engine rse;
+       static MT_Lock rse_lock MT_LOCK_INITIALIZER("rse_lock");
 
-       return BATsample_with_seed(b, n,some_random_seed);
+#ifdef NEED_MT_LOCK_INIT
+       static bool rse_lock_initialized = false;
+       if (!rse_lock_initialized) {
+               MT_lock_init(&rse_lock, "rse_lock");
+               rse_lock_initialized = true;
+               if (b == NULL && n == 0)
+                       return NULL;
+       }
+#endif
+       MT_lock_set(&rse_lock);
+       if (rse[0] == 0 && rse[1] == 0 && rse[2] == 0 && rse[3] == 0)
+               init_random_state_engine(rse, (uint64_t) GDKusec());
+       MT_lock_unset(&rse_lock);
+       return do_batsample(b, n, rse, &rse_lock);
 }
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to