Changeset: 5943a45db61e for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/5943a45db61e
Modified Files:
        gdk/gdk_sample.c
Branch: default
Log Message:

Create negative candidate list for sample if appropriate.
Also fix calculation for when to do masked candidate list.


diffs (230 lines):

diff --git a/gdk/gdk_sample.c b/gdk/gdk_sample.c
--- a/gdk/gdk_sample.c
+++ b/gdk/gdk_sample.c
@@ -32,14 +32,9 @@
 
 /* this is a straightforward implementation of a binary tree */
 struct oidtreenode {
-       union {
-               struct {        /* use as a binary tree */
-                       oid o;
-                       struct oidtreenode *left;
-                       struct oidtreenode *right;
-               };
-               uint64_t r;     /* temporary storage for random numbers */
-       };
+       oid o;
+       struct oidtreenode *left;
+       struct oidtreenode *right;
 };
 
 static bool
@@ -69,51 +64,41 @@ OIDTreeMaybeInsert(struct oidtreenode *t
 
 /* inorder traversal, gives us a sorted BAT */
 static void
-OIDTreeToBAT(struct oidtreenode *node, BAT *bn)
+OIDTreeToBAT(struct oidtreenode *node, oid *oids, BUN *n)
 {
        if (node->left != NULL)
-               OIDTreeToBAT(node->left, bn);
-       ((oid *) bn->theap->base)[bn->batCount++] = node->o;
+               OIDTreeToBAT(node->left, oids, n);
+       oids[*n] = node->o;
+       (*n)++;
        if (node->right != NULL )
-               OIDTreeToBAT(node->right, bn);
-}
-
-/* Antiset traversal, give us all values but the ones in the tree */
-static void
-OIDTreeToBATAntiset(struct oidtreenode *node, BAT *bn, oid start, oid stop)
-{
-       oid noid;
-
-       if (node->left != NULL)
-               OIDTreeToBATAntiset(node->left, bn, start, node->o);
-       else
-               for (noid = start; noid < node->o; noid++)
-                       ((oid *) bn->theap->base)[bn->batCount++] = noid;
-
-       if (node->right != NULL)
-               OIDTreeToBATAntiset(node->right, bn, node->o + 1, stop);
-       else
-               for (noid = node->o+1; noid < stop; noid++)
-                       ((oid *) bn->theap->base)[bn->batCount++] = noid;
+               OIDTreeToBAT(node->right, oids, n);
 }
 
 static BAT *
 do_batsample(oid hseq, BUN cnt, BUN n, random_state_engine rse)
 {
        BAT *bn;
-       BUN slen;
-       BUN rescnt;
-       struct oidtreenode *tree = NULL;
+       BUN rescnt;             /* counter used for several purposes */
 
        ERRORcheck(n > BUN_MAX, "sample size larger than BUN_MAX\n", NULL);
-       /* empty sample size */
        if (n == 0) {
-               bn = BATdense(0, 0, 0);
-       } else if (cnt <= n) {
+               /* empty sample size */
+               return BATdense(0, 0, 0);
+       }
+       if (cnt <= n) {
                /* sample size is larger than the input BAT, return
                 * all oids */
-               bn = BATdense(0, hseq, cnt);
-       } else if (cnt > n / 8) {
+               return BATdense(0, hseq, cnt);
+       }
+       bool antiset = n > cnt / 2;
+       if (antiset)
+               n = cnt - n;
+       /* temp use: approximate size of mask if we were to create one */
+       rescnt = cnt / 8;
+       /* n * sizeof(oid) is size of BAT if we were to not use a mask */
+       if (n * sizeof(oid) > rescnt) {
+               /* create a mask candidate list since it is smaller than
+                * a list of oids */
                bn = COLnew(0, TYPE_void, 0, TRANSIENT);
                Heap *msks = GDKmalloc(sizeof(Heap));
                if (bn == NULL || msks == NULL) {
@@ -145,9 +130,9 @@ do_batsample(oid hseq, BUN cnt, BUN n, r
                };
                msks->free = sizeof(ccand_t) + nmask * sizeof(uint32_t);
                uint32_t *r = (uint32_t *) (msks->base + sizeof(ccand_t));
-               BATsetcount(bn, n);
-               bn->tunique_est = (double) n;
-               if (n <= cnt / 2) {
+               BATsetcount(bn, antiset ? cnt - n : n);
+               bn->tunique_est = (double) bn->batCount;
+               if (!antiset) {
                        memset(r, 0, nmask * sizeof(uint32_t));
                        for (rescnt = 0; rescnt < n; rescnt++) {
                                BUN i;
@@ -163,7 +148,6 @@ do_batsample(oid hseq, BUN cnt, BUN n, r
                        /* clear last few bits */
                        if (cnt % 32 != 0)
                                r[nmask - 1] &= (1U << (cnt % 32)) - 1;
-                       n = cnt - n;
                        for (rescnt = 0; rescnt < n; rescnt++) {
                                BUN i;
                                do {
@@ -180,52 +164,77 @@ do_batsample(oid hseq, BUN cnt, BUN n, r
                }
                bn->tvheap = msks;
                BATtseqbase(bn, hseq + c->firstbit);
-       } else {
-               oid minoid = hseq;
-               oid maxoid = hseq + cnt;
-               allocator *ta = MT_thread_getallocator();
-               allocator_state ta_state = ma_open(ta);
-
-               /* if someone samples more than half of our tree, we
-                * do the antiset */
-               bool antiset = n > cnt / 2;
-               slen = n;
-               if (antiset)
-                       n = cnt - n;
-
-               tree = ma_alloc(ta, n * sizeof(struct oidtreenode));
-               if (tree == NULL) {
-                       ma_close(&ta_state);
+               return bn;
+       }
+       oid *oids;
+       if (antiset) {
+               /* create negative candidate list */
+               bn = COLnew(0, TYPE_void, 0, TRANSIENT);
+               Heap *dels = GDKmalloc(sizeof(Heap));
+               if (bn == NULL || dels == NULL) {
+                       GDKfree(dels);
+                       BBPreclaim(bn);
                        return NULL;
                }
-               bn = COLnew(0, TYPE_oid, slen, TRANSIENT);
-               if (bn == NULL) {
-                       ma_close(&ta_state);
+               *dels = (Heap) {
+                       .farmid = BBPselectfarm(TRANSIENT, TYPE_void, varheap),
+                       .parentid = bn->batCacheid,
+                       .dirty = true,
+                       .refs = ATOMIC_VAR_INIT(1),
+               };
+               strtconcat(dels->filename, sizeof(dels->filename),
+                          BBP_physical(bn->batCacheid), ".theap", NULL);
+               if (dels->farmid < 0 ||
+                   HEAPalloc(dels, n + sizeof(ccand_t) / sizeof(oid),
+                             sizeof(oid)) != GDK_SUCCEED) {
+                       GDKfree(dels);
+                       BBPreclaim(bn);
                        return NULL;
                }
-
-               /* while we do not have enough sample OIDs yet */
-               for (rescnt = 0; rescnt < n; rescnt++) {
-                       oid candoid;
-                       do {
-                               candoid = minoid + next(rse) % cnt;
-                               /* if that candidate OID was already
-                                * generated, try again */
-                       } while (!OIDTreeMaybeInsert(tree, candoid, rescnt));
-               }
-               if (!antiset) {
-                       OIDTreeToBAT(tree, bn);
-               } else {
-                       OIDTreeToBATAntiset(tree, bn, minoid, maxoid);
-               }
-               ma_close(&ta_state);
-
-               BATsetcount(bn, slen);
+               ccand_t *c = (ccand_t *) dels->base;
+               *c = (ccand_t) {
+                       .type = CAND_NEGOID,
+               };
+               dels->free = sizeof(ccand_t) + n * sizeof(oid);
+               bn->tvheap = dels;
+               oids = (oid *) ccand_first(bn);
+               BATsetcount(bn, cnt - n); /* ??? */
+               BATtseqbase(bn, hseq);
+       } else {
+               /* create a positive candidate list */
+               bn = COLnew(0, TYPE_oid, n, TRANSIENT);
+               if (bn == NULL)
+                       return NULL;
+               BATsetcount(bn, n);
+               oids = (oid *) Tloc(bn, 0);
                bn->trevsorted = bn->batCount <= 1;
                bn->tsorted = true;
                bn->tkey = true;
                bn->tseqbase = bn->batCount == 0 ? 0 : bn->batCount == 1 ? 
*(oid *) Tloc(bn, 0) : oid_nil;
        }
+
+       allocator *ta = MT_thread_getallocator();
+       allocator_state ta_state = ma_open(ta);
+
+       struct oidtreenode *tree = ma_alloc(ta, n * sizeof(struct oidtreenode));
+       if (tree == NULL) {
+               ma_close(&ta_state);
+               return NULL;
+       }
+
+       /* while we do not have enough sample OIDs yet */
+       for (rescnt = 0; rescnt < n; rescnt++) {
+               oid candoid;
+               do {
+                       candoid = hseq + next(rse) % cnt;
+                       /* if that candidate OID was already generated,
+                        * try again */
+               } while (!OIDTreeMaybeInsert(tree, candoid, rescnt));
+       }
+       rescnt = 0;
+       OIDTreeToBAT(tree, oids, &rescnt);
+       ma_close(&ta_state);
+
        return bn;
 }
 
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to