Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
09/29/11 13:27:46 (13 years ago)
Author:
gkronber
Message:

#1480 experimental change to potentially improve performance of interpreters.

Location:
trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisExpressionTreeILEmittingInterpreter.cs

    r6809 r6849  
    5050    #region private classes
    5151    private class InterpreterState {
    52       private double[] argumentStack;
    53       private int argumentStackPointer;
    5452      private Instruction[] code;
    5553      private int pc;
     54
    5655      public int ProgramCounter {
    5756        get { return pc; }
    5857        set { pc = value; }
    5958      }
    60       internal InterpreterState(Instruction[] code, int argumentStackSize) {
     59
     60      private bool inLaggedContext;
     61      public bool InLaggedContext {
     62        get { return inLaggedContext; }
     63        set { inLaggedContext = value; }
     64      }
     65      internal InterpreterState(Instruction[] code) {
     66        this.inLaggedContext = false;
    6167        this.code = code;
    6268        this.pc = 0;
    63         if (argumentStackSize > 0) {
    64           this.argumentStack = new double[argumentStackSize];
    65         }
    66         this.argumentStackPointer = 0;
    67       }
    68 
    69       internal void Reset() {
    70         this.pc = 0;
    71         this.argumentStackPointer = 0;
    7269      }
    7370
    7471      internal Instruction NextInstruction() {
    7572        return code[pc++];
    76       }
    77       private void Push(double val) {
    78         argumentStack[argumentStackPointer++] = val;
    79       }
    80       private double Pop() {
    81         return argumentStack[--argumentStackPointer];
    82       }
    83 
    84       internal void CreateStackFrame(double[] argValues) {
    85         // push in reverse order to make indexing easier
    86         for (int i = argValues.Length - 1; i >= 0; i--) {
    87           argumentStack[argumentStackPointer++] = argValues[i];
    88         }
    89         Push(argValues.Length);
    90       }
    91 
    92       internal void RemoveStackFrame() {
    93         int size = (int)Pop();
    94         argumentStackPointer -= size;
    95       }
    96 
    97       internal double GetStackFrameValue(ushort index) {
    98         // layout of stack:
    99         // [0]   <- argumentStackPointer
    100         // [StackFrameSize = N + 1]
    101         // [Arg0] <- argumentStackPointer - 2 - 0
    102         // [Arg1] <- argumentStackPointer - 2 - 1
    103         // [...]
    104         // [ArgN] <- argumentStackPointer - 2 - N
    105         // <Begin of stack frame>
    106         return argumentStack[argumentStackPointer - index - 2];
    10773      }
    10874    }
     
    241207        }
    242208      }
    243       var state = new InterpreterState(code, necessaryArgStackSize);
     209      var state = new InterpreterState(code);
    244210
    245211      Type[] methodArgs = { typeof(int), typeof(IList<double>[]) };
     
    465431            il.Emit(System.Reflection.Emit.OpCodes.Add);
    466432            il.Emit(System.Reflection.Emit.OpCodes.Starg, 0);
     433            var prevLaggedContext = state.InLaggedContext;
     434            state.InLaggedContext = true;
    467435            CompileInstructions(il, state, ds);
    468436            il.Emit(System.Reflection.Emit.OpCodes.Ldarg_0); // row += lag
     
    470438            il.Emit(System.Reflection.Emit.OpCodes.Sub);
    471439            il.Emit(System.Reflection.Emit.OpCodes.Starg, 0);
     440            state.InLaggedContext = prevLaggedContext;
    472441            return;
    473442          }
     
    479448            il.Emit(System.Reflection.Emit.OpCodes.Add);
    480449            il.Emit(System.Reflection.Emit.OpCodes.Starg, 0);
     450            var prevLaggedContext = state.InLaggedContext;
     451            state.InLaggedContext = true;
    481452            CompileInstructions(il, state, ds);
    482453            for (int l = laggedTreeNode.Lag; l < 0; l++) {
     
    489460              il.Emit(System.Reflection.Emit.OpCodes.Add);
    490461            }
     462            state.InLaggedContext = prevLaggedContext;
    491463            return;
    492464          }
     
    504476            il.Emit(System.Reflection.Emit.OpCodes.Starg, 0);
    505477            state.ProgramCounter = savedPc;
     478            var prevLaggedContext = state.InLaggedContext;
     479            state.InLaggedContext = true;
    506480            CompileInstructions(il, state, ds);
    507481            il.Emit(System.Reflection.Emit.OpCodes.Ldc_R8, 2.0); // f_0 + 2 * f_1
     
    533507            il.Emit(System.Reflection.Emit.OpCodes.Add);
    534508            il.Emit(System.Reflection.Emit.OpCodes.Starg, 0);
     509            state.InLaggedContext = prevLaggedContext;
    535510            return;
    536511          }
     
    542517          }
    543518        case OpCodes.Variable: {
     519            VariableTreeNode varNode = (VariableTreeNode)currentInstr.dynamicNode;
     520            il.Emit(System.Reflection.Emit.OpCodes.Ldarg_1); // load columns array
     521            il.Emit(System.Reflection.Emit.OpCodes.Ldc_I4, (int)currentInstr.iArg0);
     522            // load correct column of the current variable
     523            il.Emit(System.Reflection.Emit.OpCodes.Ldelem_Ref);
     524            il.Emit(System.Reflection.Emit.OpCodes.Ldarg_0); // rowIndex
     525            if (!state.InLaggedContext) {
     526              il.Emit(System.Reflection.Emit.OpCodes.Call, listGetValue);
     527              il.Emit(System.Reflection.Emit.OpCodes.Ldc_R8, varNode.Weight); // load weight
     528              il.Emit(System.Reflection.Emit.OpCodes.Mul);
     529            } else {
     530              var nanResult = il.DefineLabel();
     531              var normalResult = il.DefineLabel();
     532              il.Emit(System.Reflection.Emit.OpCodes.Dup);
     533              il.Emit(System.Reflection.Emit.OpCodes.Ldc_I4_0);
     534              il.Emit(System.Reflection.Emit.OpCodes.Blt, nanResult);
     535              il.Emit(System.Reflection.Emit.OpCodes.Dup);
     536              il.Emit(System.Reflection.Emit.OpCodes.Ldc_I4, ds.Rows);
     537              il.Emit(System.Reflection.Emit.OpCodes.Bge, nanResult);
     538              il.Emit(System.Reflection.Emit.OpCodes.Call, listGetValue);
     539              il.Emit(System.Reflection.Emit.OpCodes.Ldc_R8, varNode.Weight); // load weight
     540              il.Emit(System.Reflection.Emit.OpCodes.Mul);
     541              il.Emit(System.Reflection.Emit.OpCodes.Br, normalResult);
     542              il.MarkLabel(nanResult);
     543              il.Emit(System.Reflection.Emit.OpCodes.Pop); // rowIndex
     544              il.Emit(System.Reflection.Emit.OpCodes.Pop); // column reference
     545              il.Emit(System.Reflection.Emit.OpCodes.Ldc_R8, double.NaN);
     546              il.MarkLabel(normalResult);
     547            }
     548            return;
     549          }
     550        case OpCodes.LagVariable: {
    544551            var nanResult = il.DefineLabel();
    545552            var normalResult = il.DefineLabel();
    546             VariableTreeNode varNode = (VariableTreeNode)currentInstr.dynamicNode;
     553            LaggedVariableTreeNode varNode = (LaggedVariableTreeNode)currentInstr.dynamicNode;
    547554            il.Emit(System.Reflection.Emit.OpCodes.Ldarg_1); // load columns array
    548555            il.Emit(System.Reflection.Emit.OpCodes.Ldc_I4, (int)currentInstr.iArg0); // load correct column of the current variable
    549556            il.Emit(System.Reflection.Emit.OpCodes.Ldelem_Ref);
    550             il.Emit(System.Reflection.Emit.OpCodes.Ldarg_0); // sampleIndex
     557            il.Emit(System.Reflection.Emit.OpCodes.Ldc_I4, varNode.Lag); // lag
     558            il.Emit(System.Reflection.Emit.OpCodes.Ldarg_0); // rowIndex
     559            il.Emit(System.Reflection.Emit.OpCodes.Add); // actualRowIndex = rowIndex + sampleOffset
    551560            il.Emit(System.Reflection.Emit.OpCodes.Dup);
    552561            il.Emit(System.Reflection.Emit.OpCodes.Ldc_I4_0);
     
    566575            return;
    567576          }
    568         case OpCodes.LagVariable: {
    569             var nanResult = il.DefineLabel();
    570             var normalResult = il.DefineLabel();
    571             LaggedVariableTreeNode varNode = (LaggedVariableTreeNode)currentInstr.dynamicNode;
    572             il.Emit(System.Reflection.Emit.OpCodes.Ldarg_1); // load columns array
    573             il.Emit(System.Reflection.Emit.OpCodes.Ldc_I4, (int)currentInstr.iArg0); // load correct column of the current variable
    574             il.Emit(System.Reflection.Emit.OpCodes.Ldelem_Ref);
    575             il.Emit(System.Reflection.Emit.OpCodes.Ldc_I4, varNode.Lag); // lag
    576             il.Emit(System.Reflection.Emit.OpCodes.Ldarg_0); // sampleIndex
    577             il.Emit(System.Reflection.Emit.OpCodes.Add); // row = sampleIndex + sampleOffset
    578             il.Emit(System.Reflection.Emit.OpCodes.Dup);
    579             il.Emit(System.Reflection.Emit.OpCodes.Ldc_I4_0);
    580             il.Emit(System.Reflection.Emit.OpCodes.Blt, nanResult);
    581             il.Emit(System.Reflection.Emit.OpCodes.Dup);
    582             il.Emit(System.Reflection.Emit.OpCodes.Ldc_I4, ds.Rows);
    583             il.Emit(System.Reflection.Emit.OpCodes.Bge, nanResult);
    584             il.Emit(System.Reflection.Emit.OpCodes.Call, listGetValue);
    585             il.Emit(System.Reflection.Emit.OpCodes.Ldc_R8, varNode.Weight); // load weight
    586             il.Emit(System.Reflection.Emit.OpCodes.Mul);
    587             il.Emit(System.Reflection.Emit.OpCodes.Br, normalResult);
    588             il.MarkLabel(nanResult);
    589             il.Emit(System.Reflection.Emit.OpCodes.Pop); // sample index
    590             il.Emit(System.Reflection.Emit.OpCodes.Pop); // column reference
    591             il.Emit(System.Reflection.Emit.OpCodes.Ldc_R8, double.NaN);
    592             il.MarkLabel(normalResult);
    593             return;
    594           }
    595577        case OpCodes.Constant: {
    596578            ConstantTreeNode constNode = (ConstantTreeNode)currentInstr.dynamicNode;
     
    614596        throw new NotSupportedException("Symbol: " + treeNode.Symbol);
    615597    }
    616 
    617     // skips a whole branch
    618     private void SkipInstructions(InterpreterState state) {
    619       int i = 1;
    620       while (i > 0) {
    621         i += state.NextInstruction().nArguments;
    622         i--;
    623       }
    624     }
    625598  }
    626599}
  • trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisExpressionTreeInterpreter.cs

    r6769 r6849  
    132132
    133133      public const byte VariableCondition = 27;
     134
     135      public const byte UncheckedVariable = 28;
     136      public const byte UncheckedVariableCondition = 29;
    134137    }
    135138    #endregion
    136139
     140    private Dictionary<Type, byte> symbolToUncheckedOpcode = new Dictionary<Type, byte>() {
     141      { typeof(HeuristicLab.Problems.DataAnalysis.Symbolic.Variable), OpCodes.UncheckedVariable },
     142      { typeof(VariableCondition),OpCodes.UncheckedVariableCondition}
     143    };
    137144    private Dictionary<Type, byte> symbolToOpcode = new Dictionary<Type, byte>() {
    138145      { typeof(Addition), OpCodes.Add },
     
    206213      for (int i = 0; i < code.Length; i++) {
    207214        Instruction instr = code[i];
    208         if (instr.opCode == OpCodes.Variable) {
     215        if (instr.opCode == OpCodes.Variable || instr.opCode == OpCodes.UncheckedVariable) {
    209216          var variableTreeNode = instr.dynamicNode as VariableTreeNode;
    210217          instr.iArg0 = dataset.GetReadOnlyDoubleValues(variableTreeNode.VariableName);
     
    214221          instr.iArg0 = dataset.GetReadOnlyDoubleValues(laggedVariableTreeNode.VariableName);
    215222          code[i] = instr;
    216         } else if (instr.opCode == OpCodes.VariableCondition) {
     223        } else if (instr.opCode == OpCodes.VariableCondition || instr.opCode == OpCodes.UncheckedVariableCondition) {
    217224          var variableConditionTreeNode = instr.dynamicNode as VariableConditionTreeNode;
    218225          instr.iArg0 = dataset.GetReadOnlyDoubleValues(variableConditionTreeNode.VariableName);
     
    410417            return ((IList<double>)currentInstr.iArg0)[row] * variableTreeNode.Weight;
    411418          }
     419        case OpCodes.UncheckedVariable: {
     420            var variableTreeNode = (VariableTreeNode)currentInstr.dynamicNode;
     421            return ((IList<double>)currentInstr.iArg0)[row] * variableTreeNode.Weight;
     422          }
    412423        case OpCodes.LagVariable: {
    413424            var laggedVariableTreeNode = (LaggedVariableTreeNode)currentInstr.dynamicNode;
     
    437448            return trueBranch * p + falseBranch * (1 - p);
    438449          }
     450        case OpCodes.UncheckedVariableCondition: {
     451            var variableConditionTreeNode = (VariableConditionTreeNode)currentInstr.dynamicNode;
     452            double variableValue = ((IList<double>)currentInstr.iArg0)[row];
     453            double x = variableValue - variableConditionTreeNode.Threshold;
     454            double p = 1 / (1 + Math.Exp(-variableConditionTreeNode.Slope * x));
     455
     456            double trueBranch = Evaluate(dataset, ref row, state);
     457            double falseBranch = Evaluate(dataset, ref row, state);
     458
     459            return trueBranch * p + falseBranch * (1 - p);
     460          }
    439461        default: throw new NotSupportedException();
    440462      }
     
    442464
    443465    private byte MapSymbolToOpCode(ISymbolicExpressionTreeNode treeNode) {
    444       if (symbolToOpcode.ContainsKey(treeNode.Symbol.GetType()))
    445         return symbolToOpcode[treeNode.Symbol.GetType()];
    446       else
    447         throw new NotSupportedException("Symbol: " + treeNode.Symbol);
     466      if ((treeNode.Symbol.GetType() == typeof(Variable) || treeNode.Symbol.GetType() == typeof(VariableCondition)) && !InLaggedContext(treeNode)) {
     467        return symbolToUncheckedOpcode[treeNode.Symbol.GetType()];
     468      } else {
     469        if (symbolToOpcode.ContainsKey(treeNode.Symbol.GetType()))
     470          return symbolToOpcode[treeNode.Symbol.GetType()];
     471        else
     472          throw new NotSupportedException("Symbol: " + treeNode.Symbol);
     473      }
     474    }
     475
     476    private bool InLaggedContext(ISymbolicExpressionTreeNode treeNode) {
     477      if (treeNode.Parent == null) return false;
     478      if (treeNode.Parent is ILaggedTreeNode) return true;
     479      if (treeNode.Parent.Symbol is Derivative) return true;
     480      return InLaggedContext(treeNode.Parent);
    448481    }
    449482
Note: See TracChangeset for help on using the changeset viewer.