コード例 #1
0
 public SingleSelectWrapper(IArray2d <T> source, Kernel <T, R> kernel)
 {
     _source = source ?? throw new ArgumentNullException(nameof(source));
     _kernel = kernel ?? throw new ArgumentNullException(nameof(kernel));
     _h      = source.GetLength(0);
     _w      = source.GetLength(1);
     _km     = KernelMeasure.Measure(kernel);
     if (source is IRelQueryableArray2d <T> rqa)
     {
         if (rqa.BoundOptions[BoundsDirection.Top] != Bounds.Skip)
         {
             _km.xmin = 0;
         }
         if (rqa.BoundOptions[BoundsDirection.Bottom] != Bounds.Skip)
         {
             _km.xmax = 0;
         }
         if (rqa.BoundOptions[BoundsDirection.Left] != Bounds.Skip)
         {
             _km.ymin = 0;
         }
         if (rqa.BoundOptions[BoundsDirection.Right] != Bounds.Skip)
         {
             _km.ymax = 0;
         }
     }
 }
コード例 #2
0
ファイル: Common.cs プロジェクト: Nuzhny007/linq2d
 public static KernelMeasure Measure(LambdaExpression kernel, KernelMeasure m = null)
 {
     m = m ?? new KernelMeasure();
     // TODO: perform the analysis of the kernel lambda to see what's going on
     new KernelMeasureVisitor(kernel, m).Visit(kernel);
     return(m);
 }
コード例 #3
0
        public static Expression <Filter <T, R> > GenerateExprFilter <T, R>(Expression <Kernel <T, R> > kernelExpr)
            where R : unmanaged
        {
            var km            = KernelMeasure.Measure(kernelExpr.Compile());
            var data_arg      = Parameter(typeof(T[, ]), "data");
            var result_var    = Variable(typeof(R[, ]), "result");
            var i_var         = Variable(typeof(int), "i");
            var j_var         = Variable(typeof(int), "j");
            var h_var         = Variable(typeof(int), "h");
            var w_var         = Variable(typeof(int), "w");
            var inlinedKernel = new CellAccessInliner <T>(kernelExpr.Parameters[0], data_arg, i_var, j_var).Visit(kernelExpr.Body);

            var fe = Block(typeof(R[, ]), new[] { data_arg, h_var, w_var, result_var },
                           new[] {
                Assign(h_var, Call(data_arg, typeof(T[, ]).GetMethod("GetLength", new [] { typeof(int) }), Constant(0))),
                Assign(w_var, Call(data_arg, typeof(T[, ]).GetMethod("GetLength", new [] { typeof(int) }), Constant(1))),
                Assign(result_var, New(typeof(R[, ]).GetConstructor(new[] { typeof(int), typeof(int) }), h_var, w_var)),
                ExpressionHelper.For(i_var,
                                     Constant(-km.xmin),
                                     LessThan(i_var, Subtract(h_var, Constant(km.xmax))),
                                     AddAssign(i_var, Constant(1)),
                                     ExpressionHelper.For(j_var,
                                                          Constant(-km.ymin),
                                                          LessThan(j_var, Subtract(h_var, Constant(km.xmax))),
                                                          AddAssign(j_var, Constant(1)),
                                                          Assign(MakeIndex(result_var, typeof(R[, ]).GetProperty("Item", new Type[] { typeof(int), typeof(int) }), new[] { i_var, j_var }),
                                                                 inlinedKernel))
                                     ),
                result_var
            }
                           );
            var nne = Lambda <Filter <T, R> >(fe, data_arg);

            return(nne);
        }
コード例 #4
0
ファイル: Common.cs プロジェクト: Nuzhny007/linq2d
        public static KernelMeasure Measure <T, R>(Kernel <T, R> kernel, KernelMeasure m = null)
        {
            m = m ?? new KernelMeasure();
            var km = new KernelMeasure <T>(m);

            kernel(km);
            return(m);
        }
コード例 #5
0
        public DualSelectWrapper(IArray2d <T> left, IArray2d <A> right, Expression <Func <ICell <T>, ICell <A>, R> > kernel)
        {
            _left           = left ?? throw new ArgumentNullException(nameof(left));
            _right          = right ?? throw new ArgumentNullException(nameof(right));
            _kernel         = kernel ?? throw new ArgumentNullException(nameof(kernel));
            _compiledKernel = _kernel.Compile();

            _h = Min(left.GetLength(0), right.GetLength(0));
            _w = Min(left.GetLength(1), right.GetLength(1));

            _km = new KernelMeasure();
            var km1 = new KernelMeasure <T>(_km);
            var km2 = new KernelMeasure <A>(_km);

            _compiledKernel(km1, km2);
        }
コード例 #6
0
        public RecurrentSelectWrapper(IArray2d <T> source, Func <ICell <T>, ICell <R>, R> kernel)
        {
            _source = source ?? throw new ArgumentNullException(nameof(source));
            _kernel = kernel ?? throw new ArgumentNullException(nameof(kernel));
            _h      = source.GetLength(0);
            _w      = source.GetLength(1);
            var m   = new KernelMeasure();
            var km1 = new KernelMeasure <T>(m);
            var km2 = new KernelMeasure <R>(m);

            kernel(km1, km2);
            _xmin = m.xmin;
            _xmax = m.xmax;
            _ymin = m.ymin;
            _ymax = m.ymax;
        }
コード例 #7
0
        public DualSelectWrapper(IArray2d <T> left, IArray2d <A> right, Func <ICell <T>, ICell <A>, R> kernel)
        {
            _left   = left ?? throw new ArgumentNullException(nameof(left));
            _right  = right ?? throw new ArgumentNullException(nameof(right));
            _kernel = kernel ?? throw new ArgumentNullException(nameof(kernel));

            _h = Math.Min(left.GetLength(0), right.GetLength(0));
            _w = Math.Min(left.GetLength(1), right.GetLength(1));

            var m   = new KernelMeasure();
            var km1 = new KernelMeasure <T>(m);
            var km2 = new KernelMeasure <A>(m);

            kernel(km1, km2);
            _xmin = m.xmin;
            _xmax = m.xmax;
            _ymin = m.ymin;
            _ymax = m.ymax;
        }
コード例 #8
0
ファイル: FastUnsafeArray2d.cs プロジェクト: Nuzhny007/linq2d
        private unsafe static R[,] FilterParallel <T, R>(Kernel <T, R> kernel, T[,] source)
        where T : unmanaged
        where R : unmanaged
        {
            var h      = source.GetLength(0);
            var w      = source.GetLength(1);
            var result = new R[h, w];
            var km     = KernelMeasure.Measure(kernel);

            h -= km.xmax; // decrease to use as the cycle limit

            var factory = GetStripeHandlerFactory(kernel);


            var linesCount = h + km.xmin;
            var taskCount  = Min(linesCount, Environment.ProcessorCount);

            fixed(T *psource = &source[-km.xmin, -km.ymin])
            fixed(R * presult = &result[-km.xmin, -km.ymin])
            {
                var  tasks = new Task[taskCount - 1];
                long delta = 0;

                for (var taskNum = 0; taskNum < taskCount; taskNum++)
                {
                    int startInclusive = taskNum * linesCount / taskCount;
                    int endExclusive   = (taskNum + 1) * linesCount / taskCount;
                    var psourcetmp     = psource + startInclusive * w;
                    delta = (long)presult - (long)psource + startInclusive * w * (sizeof(R) - sizeof(T));
                    var stripeHandler = factory(psourcetmp, endExclusive - startInclusive, delta, w, kernel.Target);
                    if (taskNum + 1 == taskCount)                   // the last task
                    {
                        stripeHandler();                            // is executed in the main thread
                    }
                    else                                            // the others
                    {
                        tasks[taskNum] = Task.Run(stripeHandler);   // are executed in the worker threads
                    }
                }
                Task.WaitAll(tasks);
            }
            return(result);
        }
コード例 #9
0
ファイル: SlowArray2d.cs プロジェクト: Nuzhny007/linq2d
        public static R[,] Select <T, R>(this IRelQueryableArray2d <T> source, Kernel <T, R> kernel)
        {
            var h      = source.GetLength(0);
            var w      = source.GetLength(1);
            var result = new R[h, w];

            var km = KernelMeasure.Measure(kernel);

            var cell = new Cell <T>(source);

            for (cell._x = -km.xmin; cell._x < h - km.xmax; cell._x++)
            {
                for (cell._y = -km.ymin; cell._y < w - km.ymax; cell._y++)
                {
                    result[cell._x, cell._y] = kernel(cell);
                }
            }

            return(result);
        }
コード例 #10
0
        public unsafe static R[,] FilterParallel <T, R>(Expression <Kernel <T, R> > kernel, T[,] source)
        where T : unmanaged
        where R : unmanaged
        {
            var h      = source.GetLength(0);
            var w      = source.GetLength(1);
            var result = new R[h, w];
            var km     = KernelMeasure.Measure(kernel.Compile());

            //h -= km.xmax; // decrease to use as the cycle limit

            var factory = GenerateStripeHandlerFactory(kernel);


            var linesCount = h + km.xmin - km.xmax;
            var taskCount  = Min(linesCount, Environment.ProcessorCount);

            using (var sourceRef = new UnsafeArray2d <T>(source))
                using (var resultRef = new UnsafeArray2d <R>(result))
                {
                    var tasks = new Task[taskCount - 1];
                    for (var taskNum = 0; taskNum < taskCount; taskNum++)
                    {
                        int xmin          = -km.xmin + taskNum * linesCount / taskCount;
                        int xmax          = -km.xmin + (taskNum + 1) * linesCount / taskCount;
                        var stripeHandler = factory(xmin, xmax, -km.ymin, w - km.ymax, sourceRef, resultRef);
                        if (taskNum + 1 == taskCount)                 // the last task
                        {
                            stripeHandler();                          // is executed in the main thread
                        }
                        else                                          // the others
                        {
                            tasks[taskNum] = Task.Run(stripeHandler); // are executed in the worker threads
                        }
                    }
                    Task.WaitAll(tasks);
                }
            return(result);
        }
コード例 #11
0
ファイル: Common.cs プロジェクト: Nuzhny007/linq2d
 internal KernelMeasureVisitor(LambdaExpression kernel, KernelMeasure m)
 {
     _kernel = kernel ?? throw new ArgumentNullException(nameof(kernel));
     _m      = m ?? throw new ArgumentNullException(nameof(m));
 }
コード例 #12
0
        private static MethodBuilder BuildRunMethod <T, R>(Expression <Kernel <T, R> > kernel, TypeBuilder tb, FieldInfo xmin, FieldInfo xmax, FieldInfo ymin, FieldInfo ymax, FieldInfo source, FieldInfo target)
            where T : unmanaged
            where R : unmanaged
        {
            var km = KernelMeasure.Measure(kernel.Compile()); //TODO: perform an expression-only measure

            var staticRun = tb.DefineMethod("RunStatic", MethodAttributes.HideBySig | MethodAttributes.Private | MethodAttributes.Static, null, new[]
                                            { typeof(int), typeof(int), typeof(int), typeof(int), typeof(int), typeof(UnsafeArray2dPtr <T>), UnsafeArray2d.GetRefType <R>() });

            var xmin_arg   = Parameter(typeof(int), "xmin");
            var xmax_arg   = Parameter(typeof(int), "xmax");
            var ymin_arg   = Parameter(typeof(int), "ymin");
            var ymax_arg   = Parameter(typeof(int), "ymax");
            var height_arg = Parameter(typeof(int), "height");

            var sourcePtr_arg = Parameter(typeof(UnsafeArray2dPtr <T>), "sourcePtr");
            var targetPtr_arg = Parameter(UnsafeArray2d.GetRefType <R>(), "targetPtr");


            var i_var         = Variable(typeof(int), "i");
            var j_var         = Variable(typeof(int), "j");
            var w_var         = Variable(typeof(int), "w");
            var inlinedKernel = new CellAccessUnsafeInliner(kernel.Parameters[0], sourcePtr_arg, i_var, j_var, height_arg, w_var).Visit(kernel.Body);

            BlockExpression fe = null;

            if (typeof(T) == typeof(R)) // slight optimization
            {
                var l           = Label();
                var d_var       = Variable(typeof(int), "d");
                var lineEnd_var = Variable(typeof(UnsafeArray2dPtr <T>), "lineEnd");
                fe = Block(
                    new[] { w_var, d_var, lineEnd_var },
                    Assign(w_var, Property(sourcePtr_arg, typeof(UnsafeArray2dPtr <T>).GetProperty(nameof(UnsafeArray2dPtr <T> .Stride)))),
                    Assign(d_var, Subtract(targetPtr_arg, sourcePtr_arg)),
                    For(i_var,
                        xmin_arg,
                        LessThan(i_var, xmax_arg),
                        Constant(1),
                        Block(
                            Assign(lineEnd_var, Subtract(Add(sourcePtr_arg, ymax_arg), ymin_arg)),
                            Loop(
                                IfThenElse(
                                    LessThan(sourcePtr_arg, lineEnd_var),
                                    Block(
                                        Assign(
                                            MakeIndex(
                                                sourcePtr_arg,
                                                typeof(UnsafeArray2dPtr <T>).GetProperty("Item", new[] { typeof(int) }),
                                                new[] { d_var }
                                                ),
                                            inlinedKernel
                                            ),
                                        AddAssign(sourcePtr_arg, Constant(1)) // skip to the next element
                                        ),
                                    Break(l)
                                    ),
                                l
                                ),
                            AddAssign(sourcePtr_arg, Constant(km.ymax - km.ymin)) // skip to the next row
                            )
                        )
                    );
            }
            else
            {
                fe = Block(
                    new[] { w_var },
                    Assign(w_var, Property(sourcePtr_arg, typeof(UnsafeArray2dPtr <T>).GetProperty(nameof(UnsafeArray2dPtr <T> .Stride)))),
                    For(i_var,
                        xmin_arg,
                        LessThan(i_var, xmax_arg),
                        Constant(1),
                        Block(
                            For(
                                j_var,
                                ymin_arg,
                                LessThan(j_var, ymax_arg),
                                Constant(1),
                                Block(
                                    Assign(
                                        MakeIndex(
                                            targetPtr_arg,
                                            UnsafeArray2d.GetRefType <R>().GetProperty("Item", new[] { typeof(int) }),
                                            new[] { Constant(0) }
                                            ),
                                        inlinedKernel
                                        ),
                                    AddAssign(sourcePtr_arg, Constant(1)), // skip to the next element
                                    AddAssign(targetPtr_arg, Constant(1))
                                    )
                                ),
                            AddAssign(sourcePtr_arg, Constant(km.ymax - km.ymin)), // skip to the next row
                            AddAssign(targetPtr_arg, Constant(km.ymax - km.ymin))
                            )
                        )
                    );
            }
            LambdaExpression staticRunLambda = Lambda(fe, xmin_arg, xmax_arg, ymin_arg, ymax_arg, height_arg, sourcePtr_arg, targetPtr_arg);

            staticRunLambda.CompileToMethod(staticRun);


            return(BuildInstanceRun <T, R>(tb, xmin, xmax, ymin, ymax, source, target, staticRun));
        }
コード例 #13
0
        private static MethodBuilder BuildRunMethod <R>(LambdaExpression kernel, TypeBuilder tb, FieldInfo xmin, FieldInfo xmax, FieldInfo ymin, FieldInfo ymax, IEnumerable <FieldInfo> sources, FieldInfo target, bool recurrent)
        {
            var km          = KernelMeasure.Measure(kernel); //TODO: perform an expression-only measure
            var sourceTypes = (from s in sources let elemType = s.FieldType.GetGenericArguments()[0] select typeof(UnsafeArray2dPtr <>).MakeGenericType(elemType)).ToArray();
            var paramTypes  = Enumerable.Repeat(typeof(int), 5)
                              .Concat(sourceTypes)
                              .Append(UnsafeArray2d.GetRefType <R>()).ToArray();

            var staticRun = tb.DefineMethod("RunStatic", MethodAttributes.HideBySig | MethodAttributes.Private | MethodAttributes.Static, null, paramTypes);

            var xmin_arg   = Parameter(typeof(int), "xmin");
            var xmax_arg   = Parameter(typeof(int), "xmax");
            var ymin_arg   = Parameter(typeof(int), "ymin");
            var ymax_arg   = Parameter(typeof(int), "ymax");
            var height_arg = Parameter(typeof(int), "height");

            var sourceArgs = new List <ParameterExpression>();
            var i          = 0;

            foreach (var s in sources)
            {
                sourceArgs.Add(Parameter(sourceTypes[i++], s.Name.Substring(1) + "Ptr"));
            }

            var targetPtr_arg = Parameter(UnsafeArray2d.GetRefType <R>(), "targetPtr");

            var paramMap = new Dictionary <ParameterExpression, ParameterExpression>();

            for (i = 0; i < sourceArgs.Count; i++)
            {
                //if(kernel.Parameters[i].Type.IsConstructedGenericType && kernel.Parameters[i].Type.GetGenericTypeDefinition() == typeof(ICell<>))
                paramMap.Add(kernel.Parameters[i], sourceArgs[i]);
            }

            if (recurrent)
            {
                paramMap.Add(kernel.Parameters[i], targetPtr_arg);
            }

            var i_var             = Variable(typeof(int), "i");
            var j_var             = Variable(typeof(int), "j");
            var w_var             = Variable(typeof(int), "w");
            var inlinedKernelBody = new CellAccessUnsafeInliner(paramMap, i_var, j_var, height_arg, w_var).Visit(kernel.Body);

            BlockExpression fe = null;
            {
                fe = Block(
                    new[] { w_var },
                    Assign(w_var, Property(targetPtr_arg, UnsafeArray2d.GetRefType <R>().GetProperty("Stride"))),
                    For(i_var,
                        xmin_arg,
                        LessThan(i_var, xmax_arg),
                        Constant(1),
                        Block(
                            For(
                                j_var,
                                ymin_arg,
                                LessThan(j_var, ymax_arg),
                                Constant(1),
                                Block(
                                    Assign(
                                        MakeIndex(
                                            targetPtr_arg,
                                            UnsafeArray2d.GetRefType <R>().GetProperty("Item", new[] { typeof(int) }),
                                            new[] { Constant(0) }
                                            ),
                                        inlinedKernelBody
                                        ),
                                    Block(from s in sourceArgs select AddAssign(s, Constant(1))), // skip to the next element
                                    AddAssign(targetPtr_arg, Constant(1))
                                    )
                                ),
                            Block(from s in sourceArgs select AddAssign(s, Constant(km.ymax - km.ymin))), // skip to the next row
                            AddAssign(targetPtr_arg, Constant(km.ymax - km.ymin))
                            )
                        )
                    );
            }
            LambdaExpression staticRunLambda = Lambda(fe, (new[] { xmin_arg, xmax_arg, ymin_arg, ymax_arg, height_arg }).Concat(sourceArgs).Append(targetPtr_arg));

            staticRunLambda.CompileToMethod(staticRun);


            return(BuildInstanceRun <R>(tb, xmin, xmax, ymin, ymax, sources, target, staticRun));
        }
コード例 #14
0
ファイル: InliningArray2D.cs プロジェクト: Nuzhny007/linq2d
        public static Filter <T, R> GenerateFilter <T, R>(Kernel <T, R> kernel)
        {
            var km = KernelMeasure.Measure(kernel);

            DynamicMethod dm = new DynamicMethod("Filter" + kernel.Method.Name, typeof(IArray2d <R>), new[] { typeof(object), typeof(IArray2d <T>) });

            var ilg = dm.GetILGenerator();

            var h_var      = ilg.DeclareLocal(typeof(int));
            var w_var      = ilg.DeclareLocal(typeof(int));
            var result_var = ilg.DeclareLocal(typeof(R[, ]));
            var i_var      = ilg.DeclareLocal(typeof(int));
            var j_var      = ilg.DeclareLocal(typeof(int));


            ilg.Emit(OpCodes.Ldarg_1);  // source
            ilg.Emit(OpCodes.Ldc_I4_0); // 0
            MethodInfo getLength = typeof(IArray2d).GetMethod(nameof(IArray2d.GetLength), new [] { typeof(int) });

            ilg.Emit(OpCodes.Callvirt, getLength);
            ilg.Emit(OpCodes.Stloc, h_var);


            ilg.Emit(OpCodes.Ldarg_1);  // source
            ilg.Emit(OpCodes.Ldc_I4_1); // 0
            ilg.Emit(OpCodes.Callvirt, getLength);
            ilg.Emit(OpCodes.Stloc, w_var);

            ilg.Emit(OpCodes.Ldloc, h_var);
            ilg.Emit(OpCodes.Ldloc, w_var);
            ilg.Emit(OpCodes.Newobj, typeof(R[, ]).GetConstructor(new[] { typeof(int), typeof(int) }));
            ilg.Emit(OpCodes.Stloc, result_var);

            ilg.EmitIncrease(h_var, -km.ymax);
            ilg.EmitIncrease(w_var, -km.xmax);

            ilg.EmitFor(i_var, 0 - km.xmin, h_var, () =>
            {
                ilg.EmitFor(j_var, 0 - km.ymin, w_var, () =>
                {
                    ilg.Emit(OpCodes.Ldloc, result_var);
                    ilg.Emit(OpCodes.Ldloc, i_var);
                    ilg.Emit(OpCodes.Ldloc, j_var);
                    // call the kernel - begin
                    var ki = new SafeInliningILInstructionVisitor <T>(ilg, i_var, j_var);
                    new ILReader(kernel.Method).Accept(ki);
                    // call the kernel - end

                    ilg.Emit(OpCodes.Call, typeof(R[, ]).GetMethod("Set", new [] { typeof(int), typeof(int), typeof(R) }));
                });
            });

            ilg.Emit(OpCodes.Ldloc, result_var);
            ilg.Emit(OpCodes.Newobj, typeof(ArrayWrapper <R>).GetConstructor(new[] { typeof(R[, ]) }));
            ilg.Emit(OpCodes.Box, typeof(ArrayWrapper <R>));
            ilg.Emit(OpCodes.Ret);

            var inlined = (Func <object, IArray2d <T>, IArray2d <R> >)dm.CreateDelegate(typeof(Func <object, IArray2d <T>, IArray2d <R> >));

            //Print(inlined.Method);
            return(data => inlined(kernel.Target, data));
        }
コード例 #15
0
ファイル: FastUnsafeArray2d.cs プロジェクト: Nuzhny007/linq2d
        private unsafe static Filter <T, R> GenerateUnsafeFilter <T, R>(Kernel <T, R> kernel)
            where T : unmanaged
            where R : unmanaged
        {
            var km = KernelMeasure.Measure(kernel);

            var dm = new DynamicMethod <Func <object, T[, ], R[, ]> >("Filter." + kernel.Method.Name, typeof(Array2D).Module);


            var ilg = dm.GetILGenerator();

            var h         = ilg.DeclareLocal(typeof(int));
            var w         = ilg.DeclareLocal(typeof(int));
            var psource   = ilg.DeclareLocal(typeof(T *));
            var sourcePin = ilg.DeclareLocal(typeof(T[, ]), true); // a replica of the arg1, to force the GC pinning
            var targetPin = ilg.DeclareLocal(typeof(R[, ]), true); // a target structure
            var i         = ilg.DeclareLocal(typeof(int));
            var j         = ilg.DeclareLocal(typeof(int));
            var W         = ilg.DeclareLocal(typeof(int));
            var delta     = ilg.DeclareLocal(typeof(int));


            ilg.Emit(OpCodes.Ldarg_1);  // source
            ilg.Emit(OpCodes.Ldc_I4_0); // 0
            var getLength = typeof(T[, ]).GetMethod(nameof(Array.GetLength), new [] { typeof(int) });

            ilg.Emit(OpCodes.Call, getLength);
            ilg.Emit(OpCodes.Stloc, h);


            ilg.Emit(OpCodes.Ldarg_1);  // source
            ilg.Emit(OpCodes.Ldc_I4_1); // 1
            ilg.Emit(OpCodes.Call, getLength);
            ilg.Emit(OpCodes.Stloc, w);

            ilg.Emit(OpCodes.Ldloc, h);
            ilg.Emit(OpCodes.Ldloc, w);
            ilg.Emit(OpCodes.Newobj, typeof(R[, ]).GetConstructor(new[] { typeof(int), typeof(int) }));
            ilg.Emit(OpCodes.Stloc, targetPin); // pinning the target

            ilg.Emit(OpCodes.Ldarg_1);          // source
            ilg.Emit(OpCodes.Stloc, sourcePin); // pinning the source

            ilg.Emit(OpCodes.Ldloc, sourcePin);
            ilg.Emit(OpCodes.Ldc_I4, -km.xmin); // -km.xmin, source
            ilg.Emit(OpCodes.Ldc_I4, -km.ymin); // -km.ymin, -km.xmin, source
            MethodInfo arrayofTAddressGetter = typeof(T[, ]).GetMethod("Address", new[] { typeof(int), typeof(int) });

            ilg.Emit(OpCodes.Call, arrayofTAddressGetter);// &source[1,1];
            ilg.Emit(OpCodes.Conv_U);
            ilg.Emit(OpCodes.Stloc, psource);

            ilg.Emit(OpCodes.Ldloc, targetPin);            // load result
            ilg.Emit(OpCodes.Ldc_I4, -km.xmin);            // -km.xmin, target
            ilg.Emit(OpCodes.Ldc_I4, -km.ymin);            // -km.ymin, -km.xmin, target
            ilg.Emit(OpCodes.Call, arrayofTAddressGetter); // &target[1,1];
            ilg.Emit(OpCodes.Conv_U);
            ilg.Emit(OpCodes.Ldloc, psource);
            ilg.Emit(OpCodes.Sub);
            ilg.Emit(OpCodes.Stloc, delta);

            ilg.Emit(OpCodes.Ldloc, w);
            ilg.Emit(OpCodes.Stloc, W);

            ilg.EmitIncrease(h, -km.ymax);
            ilg.EmitIncrease(w, -km.xmax);


            ilg.EmitFor(i, 0 - km.xmin, h, () =>
            {
                ilg.EmitFor(j, 0 - km.ymin, w, () =>
                {
                    ilg.Emit(OpCodes.Ldloc, psource);
                    ilg.Emit(OpCodes.Ldloc, delta);
                    ilg.Emit(OpCodes.Add); // source+delta = target;

                    var usilv = new UnsafeInliningILInstructionVisitor <T>(ilg, i, j, W, psource);
                    //new ILReader(kernel.Method).Accept(usilv);

                    ilg.Emit(OpCodes.Stind_I4);

                    ilg.EmitIncrease(psource, sizeof(T));           // psource ++
                    ilg.EmitIncrease(delta, sizeof(R) - sizeof(T)); // delta += sizediff; zero in case of same-type;
                });
                ilg.EmitIncrease(psource, sizeof(T) * (km.ymax - km.ymin));
            });

            ilg.Emit(OpCodes.Ldloc, targetPin);
            ilg.Emit(OpCodes.Ret);

            var inlined = dm.CreateDelegate();

            R[,] filter(T[,] data) => inlined(kernel.Target, data);

            return(filter);
        }
コード例 #16
0
ファイル: FastUnsafeArray2d.cs プロジェクト: Nuzhny007/linq2d
        private static unsafe MethodBuilder BuildRunMethod <T, R>(Kernel <T, R> kernel, TypeBuilder tb, FieldInfo length, FieldInfo sourcePtr, FieldInfo delta, FieldInfo width, FieldInfo target)
            where T : unmanaged
            where R : unmanaged
        {
            var km = KernelMeasure.Measure(kernel);

            var hs = tb.DefineMethod("Run", MethodAttributes.HideBySig | MethodAttributes.Public, null, new Type[0]);

            //var hs = new DynamicMethod("HandleStripe." + kernel.Method.Name, null, new[] { typeof(object), typeof(T*), typeof(int), typeof(int), typeof(long), typeof(int) }, typeof(Array2D).Module);
            var ilg       = hs.GetILGenerator();
            var tempw     = ilg.DeclareLocal(typeof(int));
            var tempW     = ilg.DeclareLocal(typeof(int));
            var tempI     = ilg.DeclareLocal(typeof(int));
            var tempJ     = ilg.DeclareLocal(typeof(int));
            var lengthVar = ilg.DeclareLocal(typeof(int));
            var deltaVar  = ilg.DeclareLocal(typeof(long));
            var srcPtr    = ilg.DeclareLocal(typeof(T *));

            ilg.Emit(OpCodes.Ldarg_0); // this
            ilg.Emit(OpCodes.Ldfld, width);
            ilg.Emit(OpCodes.Dup);
            ilg.Emit(OpCodes.Stloc, tempW); // W = width;

            ilg.Emit(OpCodes.Ldc_I4, km.ymax);
            ilg.Emit(OpCodes.Sub);
            ilg.Emit(OpCodes.Stloc, tempw);    // w = width-1;

            ilg.Emit(OpCodes.Ldarg_0);         // this
            ilg.Emit(OpCodes.Ldfld, sourcePtr);
            ilg.Emit(OpCodes.Stloc, srcPtr);   // srcPtr = sourcePtr;

            ilg.Emit(OpCodes.Ldarg_0);         // this
            ilg.Emit(OpCodes.Ldfld, delta);
            ilg.Emit(OpCodes.Stloc, deltaVar); // delta = delta;

            ilg.Emit(OpCodes.Ldarg_0);         // this
            ilg.Emit(OpCodes.Ldfld, length);
            ilg.Emit(OpCodes.Stloc, lengthVar);


            ilg.EmitFor(tempI, 0, lengthVar, () =>
            {
                ilg.EmitFor(tempJ, -km.ymin, tempw, () =>
                {
                    ilg.Emit(OpCodes.Ldloc, srcPtr);
                    ilg.Emit(OpCodes.Ldloc, deltaVar);
                    ilg.Emit(OpCodes.Conv_I); // (int) delta;
                    ilg.Emit(OpCodes.Add);    // srcPtr+delta = target;


                    var usilv = new UnsafeParallelInliningILInstructionVisitor <T>(ilg, tempI, tempJ, tempW, srcPtr, target);
                    new ILReader(kernel.Method).Accept(usilv);

                    ilg.Emit(OpCodes.Stind_I4);          //todo: work with different types

                    ilg.EmitIncrease(srcPtr, sizeof(T)); // srcPtr++;

                    ilg.EmitIncrease(deltaVar, sizeof(R) - sizeof(T));
                });

                ilg.EmitIncrease(srcPtr, sizeof(T) * (km.ymax - km.ymin));
                ilg.EmitIncrease(deltaVar, ((km.ymax - km.ymin)) * (sizeof(R) - sizeof(T)));
            });
            ilg.Emit(OpCodes.Ret);
            return(hs);
        }