Changeset: 84422ee91c69 for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=84422ee91c69
Modified Files:
        
Branch: default
Log Message:

merge from Jun2010:
"
 changeset:   35959:20153e10ec8a
 branch:      Jun2010
 tag:         tip
 parent:      35946:a5ef8be5bf23
 parent:      35958:15ebf7087032
 user:        Stefan Manegold <[email protected]>
 date:        Sun May 16 10:07:11 2010 +0200
 files:       MonetDB5/src/modules/kernel/group.mx
 description:
 merge from Feb2010:
 "
  changeset:   35958:15ebf7087032
  branch:      Feb2010
  tag:         tip
  parent:      35945:4e039e33fe3c
  user:        Stefan Manegold <[email protected]>
  date:        Sun May 16 10:05:18 2010 +0200
  files:       MonetDB5/src/modules/kernel/group.mx
  description:
  performance bug fix: revived refined clustered derive over ordered groups

  Due to its inherent random access, hash-based grouping and sub-grouping
  (derive) of BATs that exceed main-memory size is very "painful" (slow).

  However, it appears that in many practical cases, at least on of the
  group-by columns is sorted. SQL translation already ensures that this
  column is used first for grouping, enabling a simple sequential access
  scan-based grouping, and resulting in ordered disjoint outer groups.
  Subsequent derives can then exploit this property to limit random
  access during derive as follows:
  (1)
  instead of and actual derive step, perform a simple grouping step
  on each outer group, i.e., for each outer value, possibly even
  exploiting per outer group (sub-) sortedness;
  (2)
  perform individual and independent in-memory derives over
  disjoint slices that collect multiple complete outer groups.

  Experimentation suggests that (1) is too sensitive to data distribution,
  in particular with many small outer groups the overhead appears to be
  too large.
  With chuck sizes tuned to be large but fit in memory, (2) appears to
  perform quite well, e.g., reducing a two-cloumn grouped count (with
  one column sorted) over a 2.2 billion records table (32 GB CSV)
  on a 8 GB machine from 25 h to just over 1 h.

  Caveat:
  Due to a different translation path (for insiders: group by on
  mkey-like combined hashes over all relevant columns), this has
  no effect (improvement) on creating (multi-column) primary keys.
 "
"


diffs (176 lines):

diff -r 82fea21df3be -r 84422ee91c69 MonetDB5/src/modules/kernel/group.mx
--- a/MonetDB5/src/modules/kernel/group.mx      Sun May 16 00:29:17 2010 +0200
+++ b/MonetDB5/src/modules/kernel/group.mx      Sun May 16 10:08:15 2010 +0200
@@ -809,6 +809,7 @@
                        *hdst++ = *(oid*) BUNhead(bi,p);
                *dst++ = e->use.gid;
        }
+       bn->tsorted = 0;
        BATsetcount(bn, (BUN) (dst - (oid *) bn->T->heap.base)); 
        if (hash)
                GDKfree(hash);
@@ -927,10 +928,10 @@
 
 Of course, with inputs that exceed main memory size, ordered data allows for
 rather straight forward partitioning into (few) large chunks that fit into
-main memory to perform the derive step of each chunk independintly in
+main memory to perform the derive step of each chunk independently in
 memory. These chunks can consist of multiple "outer" groups, provided each
 chunk contains only complete outer groups.
-I will prepare the respective code.
+This is what "CTderive_clustered()" (see below) does.
 */
 
 /* partion based sub-order derive */
@@ -1027,8 +1028,123 @@
 
 @c
 static int
+derive(BAT **H, BAT **M, BAT *ct_histo, BAT *ct_map, BAT *b, int tt);
+
+/* break large (out-of-memory) derive over ordered outer groups into
+ * disjoint slices that fit into memory and perform in-memory derive step
+ * independently on each slice
+ */
+static int
+CTderive_clustered(BAT **H, BAT **M, BAT *_histo, BAT *_map, BAT *_b, int tt, 
wrd limit)
+{
+       wrd s0 = 0, s1 = 0, *t = 0;
+       BUN i0 = 0, i1 = 0, j = 0;
+       BAT *mn = 0, *hn = 0;
+
+       if (!_histo || !_map || !_b)
+               return GDK_FAIL;
+
+       /* complete result map */
+       mn = BATnew(TYPE_void, TYPE_oid, BATcount(_b));
+       if (!mn)
+               return GDK_FAIL;
+       /* complete result histo */
+       hn = BATnew(TYPE_oid, TYPE_wrd, BATcount(_b));
+       if (!mn) {
+               BBPreclaim(mn);
+               return GDK_FAIL;
+       }
+       /* outer group sizes */
+       t = (wrd*)Tloc(_histo, BUNfirst(_histo));
+       /* number of outer groups */
+       j = BATcount(_histo);
+
+       /* iterate over outer groups */
+       while (i1 < j) {
+               BAT *ct_histo, *ct_map, *b, *histo = 0, *bn = 0;
+
+               /* collect outer groups for large in-memory slice */
+               s1 = t[i1++];
+               while (i1 < j && s1 + t[i1] < limit)
+                       s1 += t[i1++];
+               s1 += s0;
+
+               /* get disjoint slices of input */
+               b = BATslice(_b, (BUN)s0, (BUN)s1);
+               ct_map = BATslice(_map, (BUN)s0, (BUN)s1);
+               ct_histo = BATslice(_histo, (BUN)i0, (BUN)i1);
+               if (!b || !ct_map || !ct_histo) {
+                       if (b)
+                               BBPreleaseref(b->batCacheid);
+                       if (ct_map)
+                               BBPreleaseref(ct_map->batCacheid);
+                       if (ct_histo)
+                               BBPreleaseref(ct_histo->batCacheid);
+                       BBPreclaim(mn);
+                       BBPreclaim(hn);
+                       return GDK_FAIL;
+               }
+               /* invest in scan to check tail-sortedness */
+               /* (net effect: make required data hot) */
+               (void)BATordered(BATmirror(b));
+
+               bn = BATnew(TYPE_void, TYPE_oid, BATcount(b));
+               if (bn == NULL) {
+                       BBPreleaseref(b->batCacheid);
+                       BBPreleaseref(ct_map->batCacheid);
+                       BBPreleaseref(ct_histo->batCacheid);
+                       BBPreclaim(mn);
+                       BBPreclaim(hn);
+                       return GDK_FAIL;
+               }
+
+               /* perform derive on independent slice */
+               @:choosederive(sync,clustered)@
+               if (histo == NULL) {
+                       BBPreleaseref(b->batCacheid);
+                       BBPreleaseref(ct_map->batCacheid);
+                       BBPreleaseref(ct_histo->batCacheid);
+                       BBPreclaim(mn);
+                       BBPreclaim(hn);
+                       BBPreclaim(bn);
+                       return GDK_FAIL;
+               }
+
+               BBPreleaseref(b->batCacheid);
+               BBPreleaseref(ct_map->batCacheid);
+               BBPreleaseref(ct_histo->batCacheid);
+
+               /* invest in scan to check tail-sortedness */
+               /* (data is still hot) */
+               (void)BATordered(BATmirror(bn));
+               /* append partial map to total map */
+               BATappend(mn, bn, FALSE);
+               BBPreclaim(bn);
+
+               /* invest in scan to check head- & tail-sortedness */
+               /* (data is still hot) */
+               (void)BATordered(histo);
+               (void)BATordered(BATmirror(histo));
+               /* append partial histo to total histo */
+               BATins(hn, histo, FALSE);
+               BBPreclaim(histo);
+
+               s0 = s1;
+               i0 = i1;
+       }
+
+       /* initialize map head */
+       ALIGNsetH(mn, _b);
+
+       *H = hn;
+       *M = mn;
+       return grp_new(mn, hn);;
+}
+
+static int
 derive(BAT **H, BAT **M, BAT *ct_histo, BAT *ct_map, BAT *b, int tt)
 {
+       wrd limit = (wrd)((MT_npages() * MT_pagesize()) / (100 * 
GDKnr_threads));
        BAT *histo = NULL, *bn = NULL;
        int synced = ALIGNsynced(ct_map, b);
 
@@ -1036,6 +1152,19 @@
        int ht = (synced && BAThdense(b)) ? TYPE_void : TYPE_oid;
 
        if (!ct_map->tkey) { /* cannot derive more groups */
+               if (synced &&
+                   !BATtkey(b) &&
+                   BAThdense(b) &&
+                   BATtordered(ct_map)&1 &&
+                   BAThordered(ct_histo) &&
+                   (wrd)BATcount(b) > 2 * limit) {
+                       /* break large (out-of-memory) derive over ordered
+                        * outer groups into disjoint slices that fit into
+                        * memory and perform in-memory derive step
+                        * independently on each slice
+                        */
+                       return CTderive_clustered(H, M, ct_histo, ct_map, b, 
tt, limit);
+               }
 #if 0
                /* see comment above */
                if (!b->tkey && BATcount(b) > 1 && BATtordered(ct_map)&1 && 
@@ -1077,7 +1206,6 @@
                }
 
                /* postprocess the result bat 'bn' */
-               bn->tsorted = 0;
                if (BATcount(bn) == BATcount(b)) {
                        ALIGNsetH(bn, b);
                } else {
_______________________________________________
Checkin-list mailing list
[email protected]
http://mail.monetdb.org/mailman/listinfo/checkin-list

Reply via email to