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)); }
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); }
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); }
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)); }
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); }
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)); }
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)); }
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); }