Changeset: 0744eb2ee044 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/0744eb2ee044
Modified Files:
        sql/backends/monet5/rel_bin.c
        sql/backends/monet5/sql_statement.c
        sql/backends/monet5/sql_statement.h
Branch: default
Log Message:

Merge branch 'parappend' into 'default'


diffs (truncated from 375 to 300 lines):

diff --git a/monetdb5/optimizer/opt_dataflow.c 
b/monetdb5/optimizer/opt_dataflow.c
--- a/monetdb5/optimizer/opt_dataflow.c
+++ b/monetdb5/optimizer/opt_dataflow.c
@@ -49,8 +49,25 @@ typedef char *States;
 #define setState(S,P,K,F)  ( assert(getArg(P,K) < vlimit), (S)[getArg(P,K)] |= 
F)
 #define getState(S,P,K)  ((S)[getArg(P,K)])
 
+typedef enum {
+       no_region,
+       singleton_region, // always a single statement
+       dataflow_region,  // statements without or with controlled side 
effects, in parallel
+       existing_region,  // existing barrier..exit region, copied as-is
+       sql_region,       // region of nonconflicting sql.append/sql.updates 
only
+} region_type;
+
+typedef struct {
+       region_type type;
+       union {
+               struct {
+                       int level;  // level of nesting
+               } existing_region;
+       } st;
+} region_state;
+
 static int
-simpleFlow(InstrPtr *old, int start, int last)
+simpleFlow(InstrPtr *old, int start, int last, region_state *state)
 {
        int i, j, k, simple = TRUE;
        InstrPtr p = NULL, q;
@@ -58,6 +75,9 @@ simpleFlow(InstrPtr *old, int start, int
        /* ignore trivial blocks */
        if ( last - start == 1)
                return TRUE;
+       if ( state->type == existing_region )
+               // don't add additional barriers and garbage collection around 
existing region.
+               return TRUE;
        /* skip sequence of simple arithmetic first */
        for( ; simple && start < last; start++)
        if ( old[start] ) {
@@ -149,18 +169,196 @@ dflowGarbagesink(Client cntxt, MalBlkPtr
        return top;
 }
 
+
+static str
+get_str_arg(MalBlkPtr mb, InstrPtr p, int argno)
+{
+       int var = getArg(p, argno);
+       return getVarConstant(mb, var).val.sval;
+}
+
+static str
+get_sql_sname(MalBlkPtr mb, InstrPtr p)
+{
+       return get_str_arg(mb, p, 2);
+}
+
+static str
+get_sql_tname(MalBlkPtr mb, InstrPtr p)
+{
+       return get_str_arg(mb, p, 3);
+}
+
+static str
+get_sql_cname(MalBlkPtr mb, InstrPtr p)
+{
+       return get_str_arg(mb, p, 4);
+}
+
+
+static bool
+isSqlAppendUpdate(MalBlkPtr mb, InstrPtr p)
+{
+       if (p->modname != sqlRef)
+               return false;
+       if (p->fcnname != appendRef && p->fcnname != updateRef)
+               return false;
+
+       // pattern("sql", "append", mvc_append_wrap, false, "...", args(1,7, 
arg("",int),
+       //              arg("mvc",int
+       //              arg("sname",str
+       //              arg("tname",str
+       //              arg("cname",str
+       //              arg("offset",lng
+       //              argany("ins",0))),
+
+       // pattern("sql", "update", mvc_update_wrap, false, "...", args(1,7, 
arg("",int
+       //              arg("mvc",int),
+       //              arg("sname",str
+       //              arg("tname",str
+       //              arg("cname",str
+       //              argany("rids",0
+       //              argany("upd",0))
+
+       if (p->argc != 7)
+               return false;
+
+       int mvc_var = getArg(p, 1);
+       if (getVarType(mb, mvc_var) != TYPE_int)
+               return false;
+
+       int sname_var = getArg(p, 2);
+       if (getVarType(mb, sname_var) != TYPE_str || !isVarConstant(mb, 
sname_var))
+               return false;
+
+       int tname_var = getArg(p, 3);
+       if (getVarType(mb, tname_var) != TYPE_str || !isVarConstant(mb, 
tname_var))
+               return false;
+
+       int cname_var = getArg(p, 4);
+       if (getVarType(mb, cname_var) != TYPE_str || !isVarConstant(mb, 
cname_var))
+               return false;
+
+       return true;
+}
+
+static bool
+sqlBreakpoint(MalBlkPtr mb, InstrPtr *first, InstrPtr *p)
+{
+       InstrPtr instr = *p;
+       if (!isSqlAppendUpdate(mb, instr))
+               return true;
+
+       str my_sname = get_sql_sname(mb, instr);
+       str my_tname = get_sql_tname(mb, instr);
+       str my_cname = get_sql_cname(mb, instr);
+       for (InstrPtr *q = first; q < p; q++) {
+               str cname = get_sql_cname(mb, *q);
+               if (strcmp(my_cname, cname) != 0) {
+                       // different cname, no conflict
+                       continue;
+               }
+               str tname = get_sql_tname(mb, *q);
+               if (strcmp(my_tname, tname) != 0) {
+                       // different tname, no conflict
+                       continue;
+               }
+               str sname = get_sql_sname(mb, *q);
+               if (strcmp(my_sname, sname) != 0) {
+                       // different sname, no conflict
+                       continue;
+               }
+               // Found a statement in the region that works on the same 
column so this is a breakpoint
+               return true;
+       }
+
+       // None of the statements in the region works on this column so no 
breakpoint necessary
+       return false;
+}
+
+static bool
+checkBreakpoint(Client cntxt, MalBlkPtr mb, InstrPtr *first, InstrPtr *p, 
States states, region_state *state)
+{
+       InstrPtr instr = *p;
+       switch (state->type) {
+               case singleton_region:
+                       // by definition
+                       return true;
+               case dataflow_region:
+                       return dataflowBreakpoint(cntxt, mb, instr, states);
+               case existing_region:
+                       if (state->st.existing_region.level == 0) {
+                               // previous statement ended the region so we 
break here
+                               return true;
+                       }
+                       if (blockStart(instr)) {
+                               state->st.existing_region.level += 1;
+                       } else if (blockExit(instr)) {
+                               state->st.existing_region.level -= 1;
+                       }
+                       return false;
+               case sql_region:
+                       return sqlBreakpoint(mb, first, p);
+               default:
+                       // serious corruption has occurred.
+                       assert(0 && "corrupted region_type");
+                       abort();
+       }
+       assert(0 && "unreachable");
+       return true;
+}
+
+static void
+decideRegionType(Client cntxt, MalBlkPtr mb, InstrPtr p, States states, 
region_state *state)
+{
+       (void) cntxt;
+
+       state->type = no_region;
+       if (blockStart(p)) {
+               state->type = existing_region;
+               state->st.existing_region.level = 1;
+       } else if (p->token == ENDsymbol) {
+               state->type = existing_region;
+       } else if (isSqlAppendUpdate(mb,p)) {
+               state->type = sql_region;
+       } else if (p->barrier) {
+               state->type = singleton_region;
+       } else if (isUnsafeFunction(p)) {
+               state->type = singleton_region;
+       } else if (
+               isUpdateInstruction(p)
+               && getModuleId(p) != sqlRef
+               && (getState(states, p, p->retc) & (VARREAD | VARBLOCK)) == 0
+       ) {
+               // Special case. Unless they're from the sql module, 
instructions with
+               // names like 'append', 'update', 'delete', 'grow', etc., are 
expected
+               // to express their side effects as data dependencies, for 
example,
+               //     X5 := bat.append(X_5, ...)
+               state->type = dataflow_region;
+       } else if (hasSideEffects(mb, p, false)) {
+               state->type = singleton_region;
+       } else if (isMultiplex(p)) {
+               state->type = singleton_region;
+       } else {
+               state->type = dataflow_region;
+       }
+       assert(state->type != no_region);
+}
+
+
 /* dataflow blocks are transparent, because they are always
    executed, either sequentially or in parallel */
 
 str
 OPTdataflowImplementation(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr 
p)
 {
-       int i,j,k, start=1, slimit, breakpoint, actions=0, simple = TRUE;
+       int i,j,k, start, slimit, breakpoint, actions=0, simple = TRUE;
        int flowblock= 0;
        InstrPtr *sink = NULL, *old = NULL, q;
        int limit, vlimit, top = 0;
        States states;
        char  buf[256];
+       region_state state = { singleton_region };
        lng usec = GDKusec();
        str msg = MAL_SUCCEED;
 
@@ -193,16 +391,17 @@ OPTdataflowImplementation(Client cntxt, 
                actions = -1;
                goto wrapup;
        }
-       pushInstruction(mb,old[0]);
 
        /* inject new dataflow barriers using a single pass through the program 
*/
+       start = 0;
+       state.type = singleton_region;
        for (i = 1; i<limit; i++) {
                p = old[i];
                assert(p);
-               breakpoint = dataflowBreakpoint(cntxt, mb, p ,states);
+               breakpoint = checkBreakpoint(cntxt, mb, &old[start], &old[i], 
states, &state);
                if ( breakpoint ){
                        /* close previous flow block */
-                       simple = simpleFlow(old,start,i);
+                       simple = simpleFlow(old,start,i, &state);
 
                        if ( !simple){
                                flowblock = newTmpVariable(mb,TYPE_bit);
@@ -237,37 +436,14 @@ OPTdataflowImplementation(Client cntxt, 
                                                pushInstruction(mb,old[i]);
                                break;
                        }
-                       // implicitly a new flow block starts unless we have a 
hard side-effect
+
+                       // Start a new region
                        memset((char*) states, 0, vlimit * sizeof(char));
                        top = 0;
-                       if ( p->token == ENDsymbol  || 
(hasSideEffects(mb,p,FALSE) && !blockStart(p)) || isMultiplex(p)){
-                               start = i+1;
-                               pushInstruction(mb,p);
-                               continue;
-                       }
                        start = i;
+                       decideRegionType(cntxt, mb, p, states, &state);
                }
 
-               if (blockStart(p)){
-                       /* barrier blocks are kept out of the dataflow */
-                       /* assumes that barrier entry/exit pairs are correct. */
-                       /* A refinement is parallelize within a barrier block */
-                       int copy= 1;
-                       pushInstruction(mb,p);
-                       for ( i++; i<limit; i++) {
-                               p = old[i];
-                               pushInstruction(mb,p);
-
-                               if (blockStart(p))
-                                       copy++;
-                               if (blockExit(p)) {
-                                       copy--;
-                                       if ( copy == 0) break;
-                               }
-                       }
-                       // reset admin
-                       start = i+1;
-               }
                // remember you assigned/read variables
                for ( k = 0; k < p->retc; k++)
                        setState(states, p, k, VARWRITE);
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to