public override HeronValue Eval(VM vm) { SeqValue sv = vm.Eval(list) as SeqValue; if (sv == null) throw new Exception("Expected list: " + list.ToString()); // internal structure for indexing lists IInternalIndexable ii = sv.GetIndexable(); if (ii.InternalCount() < 2) return sv; HeronValue[] output = new HeronValue[ii.InternalCount()]; ParallelOptions po = new ParallelOptions(); po.MaxDegreeOfParallelism = Config.maxThreads; var p = Partitioner.Create(1, ii.InternalCount()); HeronValue result = ii.InternalAt(0); object resultLock = new Object(); Parallel.ForEach( p, po, () => { LoopParams lp = new LoopParams(); lp.op = new OptimizationParams(); lp.acc = lp.op.AddNewAccessor(a); lp.acc2 = lp.op.AddNewAccessor(b); lp.vm = vm.Fork(); lp.expr = yield.Optimize(lp.op); return lp; }, (Tuple<int, int> range, ParallelLoopState state, LoopParams lp) => { if (range.Item1 == range.Item2) return lp; lp.acc.Set(ii.InternalAt(range.Item1)); for (int i = range.Item1 + 1; i < range.Item2; ++i) { lp.acc2.Set(ii.InternalAt(i)); lp.acc.Set(lp.vm.Eval(lp.expr)); } // Update the result lock (resultLock) { lp.acc2.Set(result); result = lp.vm.Eval(lp.expr); } return lp; }, (LoopParams lp) => { } ); return new ArrayValue(new HeronValue[] { result }, sv.GetElementType()); }
/// <summary> /// Evaluates the map operation /// </summary> /// <param name="vm">Current state of virtual machine</param> /// <returns>An ArrayValue containing new values</returns> public override HeronValue Eval(VM vm) { SeqValue sv = vm.Eval(list) as SeqValue; if (sv == null) throw new Exception("Expected list: " + list.ToString()); // internal structure for indexing lists IInternalIndexable ii = sv.GetIndexable(); if (ii.InternalCount() == 0) return sv; // Array of values used for output of map operations HeronValue[] output = new HeronValue[ii.InternalCount()]; // Create a parallel options object to limit parallelism ParallelOptions po = new ParallelOptions(); po.MaxDegreeOfParallelism = Config.maxThreads; // Create a partitioner var partitioner = Partitioner.Create(0, ii.InternalCount()); Parallel.ForEach( // Breaks the for loop up into sub-ranges partitioner, // Parellel options po, // Initialization of thread-local variables () => { LoopParams lp = new LoopParams(); lp.op = new OptimizationParams(); lp.acc = lp.op.AddNewAccessor(name); lp.vm = vm.Fork(); lp.expr = yield.Optimize(lp.op); return lp; }, // Loop body (Tuple<int, int> range, ParallelLoopState state, LoopParams lp) => { for (int i = range.Item1; i < range.Item2; ++i) { lp.acc.Set(ii.InternalAt(i)); output[i] = lp.vm.Eval(lp.expr); } return lp; }, // Finalization function (LoopParams lp) => { } ); return new ArrayValue(output, sv.GetElementType()); }
public override HeronValue Eval(VM vm) { SeqValue sv = vm.Eval(list) as SeqValue; if (sv == null) throw new Exception("Expected list: " + list.ToString()); // internal structure for indexing lists IInternalIndexable ii = sv.GetIndexable(); if (ii.InternalCount() == 0) return sv; bool[] bools = new bool[ii.InternalCount()]; ParallelOptions po = new ParallelOptions(); po.MaxDegreeOfParallelism = Config.maxThreads; var p = Partitioner.Create(0, ii.InternalCount()); Parallel.ForEach( p, po, () => { LoopParams lp = new LoopParams(); lp.op = new OptimizationParams(); lp.acc = lp.op.AddNewAccessor(name); lp.vm = vm.Fork(); lp.expr = predicate.Optimize(lp.op); return lp; }, (Tuple<int, int> range, ParallelLoopState state, LoopParams lp) => { for (int i = range.Item1; i < range.Item2; ++i) { lp.acc.Set(ii.InternalAt(i)); bools[i] = lp.vm.Eval(lp.expr).ToBool(); } return lp; }, (LoopParams lp) => { } ); List<HeronValue> r = new List<HeronValue>(ii.InternalCount()); for (int i = 0; i < ii.InternalCount(); ++i) if (bools[i]) r.Add(ii.InternalAt(i)); r.Capacity = r.Count; return new ListValue(r, sv.GetElementType()); }