示例#1
0
        private static StripeHandlerFactory <T, R> GenerateStripeHandlerFactory <T, R>(Expression <Kernel <T, R> > kernel)
            where T : unmanaged
            where R : unmanaged
        {
            var ab = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("ExprStripeHandler"), AssemblyBuilderAccess.RunAndSave);

            var tb = ab.DefineDynamicModule("ExprStripeHandler", "ExprStripeHandler.dll", true).DefineType("StripeHandler", TypeAttributes.Class | TypeAttributes.Public);

            var xmin = tb.DefineField("_xmin", typeof(int), FieldAttributes.Private);
            var xmax = tb.DefineField("_xmax", typeof(int), FieldAttributes.Private);
            var ymin = tb.DefineField("_ymin", typeof(int), FieldAttributes.Private);
            var ymax = tb.DefineField("_ymax", typeof(int), FieldAttributes.Private);
            //var delta = tb.DefineField("_delta", typeof(long), @private);
            //var stride = tb.DefineField("_stride", typeof(int), FieldAttributes.Private);
            var source = tb.DefineField("_source", typeof(UnsafeArray2d <T>), FieldAttributes.Private);
            var target = tb.DefineField("_target", UnsafeArray2d.GetTypeInstance <R>(), FieldAttributes.Private);

            ConstructorBuilder cb = BuildConstructor <T, R>(tb, xmin, xmax, ymin, ymax, source, target);

            MethodBuilder rm = BuildRunMethod(kernel, tb, xmin, xmax, ymin, ymax, source, target);

            var t           = tb.CreateType();
            var constructor = t.GetConstructor((from p in cb.GetParameters() select p.ParameterType).ToArray());
            var runMethod   = t.GetMethod(rm.Name); // there is only one method with this name

            ab.Save("ExprStripeHandler.dll");
            return(PrepareFactory <T, R>(constructor, runMethod));
        }
示例#2
0
        private static MethodBuilder BuildInstanceRun <T, R>(TypeBuilder tb, FieldInfo xmin, FieldInfo xmax, FieldInfo ymin, FieldInfo ymax, FieldInfo source, FieldInfo target, MethodBuilder staticRun)
            where T : unmanaged
            where R : unmanaged
        {
            var hss = tb.DefineMethod <Action>("Run", MethodAttributes.HideBySig | MethodAttributes.Public);
            var ilg = hss.GetILGenerator();

            ilg.Emit(OpCodes.Ldarg, 0);
            ilg.Emit(OpCodes.Ldfld, xmin);

            ilg.Emit(OpCodes.Ldarg, 0);
            ilg.Emit(OpCodes.Ldfld, xmax);

            ilg.Emit(OpCodes.Ldarg, 0);
            ilg.Emit(OpCodes.Ldfld, ymin);

            ilg.Emit(OpCodes.Ldarg, 0);
            ilg.Emit(OpCodes.Ldfld, ymax);


            ilg.Emit(OpCodes.Ldarg, 0);
            ilg.Emit(OpCodes.Ldfld, source);
            ilg.Emit(OpCodes.Call, typeof(UnsafeArray2d <T>).GetProperty(nameof(UnsafeArray2d <T> .Height)).GetGetMethod());

            ilg.Emit(OpCodes.Ldarg, 0);
            ilg.Emit(OpCodes.Ldfld, source);

            ilg.Emit(OpCodes.Ldarg, 0);
            ilg.Emit(OpCodes.Ldfld, xmin);

            ilg.Emit(OpCodes.Ldarg, 0);
            ilg.Emit(OpCodes.Ldfld, ymin);

            ilg.Emit(OpCodes.Call, typeof(UnsafeArray2d <T>).GetProperty("Item").GetGetMethod());


            ilg.Emit(OpCodes.Ldarg, 0);
            ilg.Emit(OpCodes.Ldfld, target);

            ilg.Emit(OpCodes.Ldarg, 0);
            ilg.Emit(OpCodes.Ldfld, xmin);

            ilg.Emit(OpCodes.Ldarg, 0);
            ilg.Emit(OpCodes.Ldfld, ymin);

            ilg.Emit(OpCodes.Call, UnsafeArray2d.GetTypeInstance <R>().GetProperty("Item").GetGetMethod());

            ilg.Emit(OpCodes.Call, staticRun);

            ilg.Emit(OpCodes.Ret);
            return(hss);
        }
示例#3
0
        private static MethodBuilder BuildInstanceRun <R>(TypeBuilder tb, FieldInfo xmin, FieldInfo xmax, FieldInfo ymin, FieldInfo ymax, IEnumerable <FieldInfo> sources, FieldInfo target, MethodBuilder staticRun)
        {
            var hss = tb.DefineMethod <Action>("Run", MethodAttributes.HideBySig | MethodAttributes.Public);
            var ilg = hss.GetILGenerator();

            ilg.Emit(OpCodes.Ldarg, 0);
            ilg.Emit(OpCodes.Ldfld, xmin);

            ilg.Emit(OpCodes.Ldarg, 0);
            ilg.Emit(OpCodes.Ldfld, xmax);

            ilg.Emit(OpCodes.Ldarg, 0);
            ilg.Emit(OpCodes.Ldfld, ymin);

            ilg.Emit(OpCodes.Ldarg, 0);
            ilg.Emit(OpCodes.Ldfld, ymax);

            ilg.Emit(OpCodes.Ldarg, 0);
            ilg.Emit(OpCodes.Ldfld, target);
            ilg.Emit(OpCodes.Call, UnsafeArray2d.GetTypeInstance <R>().GetProperty(nameof(UnsafeArray2d.Height)).GetGetMethod());

            foreach (var source in sources)
            {
                ilg.Emit(OpCodes.Ldarg, 0);
                ilg.Emit(OpCodes.Ldfld, source);

                ilg.Emit(OpCodes.Ldarg, 0);
                ilg.Emit(OpCodes.Ldfld, xmin);

                ilg.Emit(OpCodes.Ldarg, 0);
                ilg.Emit(OpCodes.Ldfld, ymin);

                ilg.Emit(OpCodes.Call, typeof(UnsafeArray2d <>).MakeGenericType(source.FieldType.GetGenericArguments()[0]).GetProperty("Item").GetGetMethod());
            }

            ilg.Emit(OpCodes.Ldarg, 0);
            ilg.Emit(OpCodes.Ldfld, target);

            ilg.Emit(OpCodes.Ldarg, 0);
            ilg.Emit(OpCodes.Ldfld, xmin);

            ilg.Emit(OpCodes.Ldarg, 0);
            ilg.Emit(OpCodes.Ldfld, ymin);

            ilg.Emit(OpCodes.Call, UnsafeArray2d.GetTypeInstance <R>().GetProperty("Item").GetGetMethod());

            ilg.Emit(OpCodes.Call, staticRun);

            ilg.Emit(OpCodes.Ret);
            return(hss);
        }
示例#4
0
        internal static StripeMultiHandlerFactory GenerateStripeHandlerFactory <R>(LambdaExpression kernel, bool recurrent)
        {
            var ab = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("ExprStripeHandler"), AssemblyBuilderAccess.RunAndSave);

            var tb = ab.DefineDynamicModule("ExprStripeHandler", "ExprStripeHandler.dll", true).DefineType("StripeHandler", TypeAttributes.Class | TypeAttributes.Public);

            var xmin    = tb.DefineField("_xmin", typeof(int), FieldAttributes.Private);
            var xmax    = tb.DefineField("_xmax", typeof(int), FieldAttributes.Private);
            var ymin    = tb.DefineField("_ymin", typeof(int), FieldAttributes.Private);
            var ymax    = tb.DefineField("_ymax", typeof(int), FieldAttributes.Private);
            var sources = new List <FieldBuilder>();

            foreach (var p in kernel.Parameters)
            {
                var pType = p.Type;
                if (pType.IsConstructedGenericType && pType.GetGenericTypeDefinition() == typeof(ICell <>))
                {
                    pType = pType.GetGenericArguments()[0];
                }

                sources.Add(tb.DefineField("_source." + p.Name, UnsafeArray2d.GetTypeInstance(pType), FieldAttributes.Private));
            }
            var target = tb.DefineField("_target", UnsafeArray2d.GetTypeInstance(typeof(R)), FieldAttributes.Private);

            if (recurrent)
            {
                sources.RemoveAt(sources.Count - 1);
            }

            ConstructorBuilder cb = BuildConstructor <R>(tb, xmin, xmax, ymin, ymax, sources, target);

            MethodBuilder rm = BuildRunMethod <R>(kernel, tb, xmin, xmax, ymin, ymax, sources, target, recurrent);

            var t           = tb.CreateType();
            var constructor = t.GetConstructor((from p in cb.GetParameters() select p.ParameterType).ToArray());
            var runMethod   = t.GetMethod(rm.Name); // there is only one method with this name

            ab.Save("ExprStripeHandler.dll");
            return(PrepareFactory <R>(constructor, runMethod));
        }
示例#5
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);
        }
示例#6
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));
        }
示例#7
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));
        }
示例#8
0
        private static ConstructorBuilder BuildConstructor <R>(TypeBuilder tb, FieldInfo xmin, FieldInfo xmax, FieldInfo ymin, FieldInfo ymax, IEnumerable <FieldInfo> sources, FieldInfo target)
        {
            var paramTypes = Enumerable.Repeat(typeof(int), 4).Concat(from s in sources select s.FieldType).Append(UnsafeArray2d.GetTypeInstance <R>()).ToArray();

            var c = tb.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, paramTypes);

            c.DefineParameter(1, ParameterAttributes.None, "xmin");
            c.DefineParameter(2, ParameterAttributes.None, "xmax");
            c.DefineParameter(3, ParameterAttributes.None, "ymin");
            c.DefineParameter(4, ParameterAttributes.None, "ymax");

            var cilg = c.GetILGenerator();

            cilg.Emit(OpCodes.Ldarg, 0);
            cilg.Emit(OpCodes.Ldarg, 1);
            cilg.Emit(OpCodes.Stfld, xmin);

            cilg.Emit(OpCodes.Ldarg, 0);
            cilg.Emit(OpCodes.Ldarg, 2);
            cilg.Emit(OpCodes.Stfld, xmax);

            cilg.Emit(OpCodes.Ldarg, 0);
            cilg.Emit(OpCodes.Ldarg, 3);
            cilg.Emit(OpCodes.Stfld, ymin);

            cilg.Emit(OpCodes.Ldarg, 0);
            cilg.Emit(OpCodes.Ldarg, 4);
            cilg.Emit(OpCodes.Stfld, ymax);

            var i = 5;

            foreach (var sourceField in sources)
            {
                c.DefineParameter(i, ParameterAttributes.None, sourceField.Name.Substring(1));
                cilg.Emit(OpCodes.Ldarg, 0);
                cilg.Emit(OpCodes.Ldarg, i);
                cilg.Emit(OpCodes.Stfld, sourceField);
                i++;
            }
            c.DefineParameter(i, ParameterAttributes.None, "target");

            cilg.Emit(OpCodes.Ldarg, 0);
            cilg.Emit(OpCodes.Ldarg, i);
            cilg.Emit(OpCodes.Stfld, target);
            cilg.Emit(OpCodes.Ret);

            return(c);
        }