/// <summary> /// Generates an intrinsic reduce. /// </summary> /// <typeparam name="T">The element type.</typeparam> /// <typeparam name="TReduction">The type of the reduction logic.</typeparam> /// <param name="backend">The current backend.</param> /// <param name="codeGenerator">The code generator.</param> /// <param name="value">The value to generate code for.</param> public static void GenerateReduce <T, TReduction>( CLBackend backend, CLCodeGenerator codeGenerator, Value value) where T : unmanaged where TReduction : struct, IScanReduceOperation <T> => GenerateAllReduce <T, TReduction>( backend, codeGenerator, value);
/// <summary> /// Generates intrinsic math instructions for the following kinds: /// Rcp /// </summary> /// <param name="backend">The current backend.</param> /// <param name="codeGenerator">The code generator.</param> /// <param name="value">The value to generate code for.</param> public static void GenerateMathIntrinsic( CLBackend backend, CLCodeGenerator codeGenerator, Value value) { // Manually generate code for "1.0 / argument" var arithmeticValue = value as UnaryArithmeticValue; var argument = codeGenerator.Load(arithmeticValue.Value); var target = codeGenerator.Allocate(arithmeticValue); var operation = CLInstructions.GetArithmeticOperation( BinaryArithmeticKind.Div, arithmeticValue.BasicValueType.IsFloat(), out var isFunction); using var statement = codeGenerator.BeginStatement(target); statement.AppendCast(arithmeticValue.ArithmeticBasicValueType); if (isFunction) { statement.AppendCommand(operation); statement.BeginArguments(); } else { statement.OpenParen(); } statement.AppendCast(arithmeticValue.ArithmeticBasicValueType); if (arithmeticValue.BasicValueType == BasicValueType.Float32) { statement.AppendConstant(1.0f); } else { statement.AppendConstant(1.0); } if (!isFunction) { statement.AppendCommand(operation); } statement.AppendArgument(); statement.AppendCast(arithmeticValue.ArithmeticBasicValueType); statement.Append(argument); if (isFunction) { statement.EndArguments(); } else { statement.CloseParen(); } }
/// <summary> /// Generates an intrinsic scan. /// </summary> /// <typeparam name="T">The element type.</typeparam> /// <typeparam name="TScanOperation">The type of the warp scan logic.</typeparam> /// <param name="backend">The current backend.</param> /// <param name="codeGenerator">The code generator.</param> /// <param name="value">The value to generate code for.</param> public static void GenerateInclusiveScan <T, TScanOperation>( CLBackend backend, CLCodeGenerator codeGenerator, Value value) where T : unmanaged where TScanOperation : struct, IScanReduceOperation <T> => CLContext.GenerateScanReduce <T, TScanOperation>( backend, codeGenerator, value, "work_group_scan_inclusive_");
/// <summary> /// Generates an intrinsic reduce. /// </summary> /// <typeparam name="T">The element type.</typeparam> /// <typeparam name="TReduction">The type of the reduction logic.</typeparam> /// <param name="backend">The current backend.</param> /// <param name="codeGenerator">The code generator.</param> /// <param name="value">The value to generate code for.</param> public static void GenerateAllReduce <T, TReduction>( CLBackend backend, CLCodeGenerator codeGenerator, Value value) where T : unmanaged where TReduction : struct, IScanReduceOperation <T> => CLContext.GenerateScanReduce <T, TReduction>( backend, codeGenerator, value, "work_group_reduce_");
/// <summary> /// Generates an intrinsic scan. /// </summary> /// <typeparam name="T">The element type.</typeparam> /// <typeparam name="TScanOperation">The type of the warp scan logic.</typeparam> /// <param name="backend">The current backend.</param> /// <param name="codeGenerator">The code generator.</param> /// <param name="value">The value to generate code for.</param> public static void GenerateExclusiveScan <T, TScanOperation>( CLBackend backend, CLCodeGenerator codeGenerator, Value value) where T : struct where TScanOperation : struct, IScanReduceOperation <T> => CLContext.GenerateScanReduce <T, TScanOperation>( backend, codeGenerator, value, "sub_group_scan_exclusive_");
/// <summary> /// The OpenCL implementation. /// </summary> /// <remarks> /// Note that this function signature corresponds to the OpenCL-backend specific /// delegate type <see cref="CLIntrinsic.Handler"/>. /// </remarks> static void GenerateCLCode( CLBackend backend, CLCodeGenerator codeGenerator, Value value) { // The passed value will be the call node in this case // Load X parameter variable (first argument) var xVariable = codeGenerator.Load(value[0]); // Allocate target variable to write our result to var target = codeGenerator.Allocate(value); // Emit our desired instructions using var statement = codeGenerator.BeginStatement(target); statement.Append(xVariable); statement.AppendCommand( CLInstructions.GetArithmeticOperation( BinaryArithmeticKind.Mul, false, out var _)); statement.AppendConstant(2); }
public static void Main2() { using (var context = new Context()) { foreach (var acceleratorId in Accelerator.Accelerators) { if (acceleratorId.AcceleratorType == AcceleratorType.CPU) { continue; } using (var accelerator = Accelerator.Create(context, acceleratorId)) { CompiledKernel compiledKernel; using (Backend b = new CLBackend(context, ILGPU.Runtime.OpenCL.CLAcceleratorVendor.AMD)) { MethodInfo methodInfo = typeof(GPU).GetMethod("PixelKernel"); KernelSpecialization spec = KernelSpecialization.Empty; compiledKernel = b.Compile(EntryPointDescription.FromImplicitlyGroupedKernel(methodInfo), spec); // debug: check kernel.Source for source text } var kernel = accelerator.LoadAutoGroupedKernel(compiledKernel); // var kernel = accelerator.LoadAutoGroupedStreamKernel<Index2, ArrayView2D<FSMUnit>>(MathKernel); // kernel = accelerator.LoadAutoGroupedStreamKernel<Index2, ArrayView2D<Color3>, ArrayView<byte>, ArrayView2D<Neuron>>(PixelKernel); MemoryBuffer2D <Color3> buffer = accelerator.Allocate <Color3>(pixelMap.GetLength(0), pixelMap.GetLength(1)); MemoryBuffer <byte> buffer2 = accelerator.Allocate <byte>(imageBytes.Length); MemoryBuffer2D <Neuron> buffer3 = accelerator.Allocate <Neuron>(nrn.GetLength(0), nrn.GetLength(1)); buffer3.CopyFrom(nrn, new LongIndex2(0, 0), new LongIndex2(0, 0), new LongIndex2(nrn.GetLength(0), nrn.GetLength(1))); while (running == true) { Stopwatch sw = new Stopwatch(); sw.Start(); Index2 gridSize = new Index2(pixelMap.GetLength(0), pixelMap.GetLength(1)); //kernel(gridSize, buffer.View, buffer2.View, buffer3.View); sw.OutputDelta("Kernel"); accelerator.Synchronize(); sw.OutputDelta("Sync"); // imageBytes = buffer2.GetAsArray(); buffer2.CopyTo(imageBytes, 0, 0, imageBytes.Length); sw.OutputDelta("Copy ImageBytes"); // Resolve and verify data //pixelMap = buffer.GetAs2DArray(); // buffer.CopyTo(pixelMap, new LongIndex2(0, 0), new LongIndex2(0, 0), new LongIndex2(pixelMap.GetLength(0), pixelMap.GetLength(1))); // Color3[] pixelMap1D = buffer.GetAsArray(); //Copy1DTo2DArray(pixelMap1D, pixelMap); // ~36ms, a bit faster //Array.Copy(pixelMap1D, imageBytes, pixelMap1D.Length); // fails //Buffer.BlockCopy(pixelMap1D, 0, pixelMap, 0, pixelMap1D.Length * Marshal.SizeOf(typeof(Color3))); // fails // pixelMap = Make2DArray(pixelMap1D, pixelMap.GetLength(0), pixelMap.GetLength(1)); // still slow //sw.OutputDelta("Copy PixelMap"); // MainForm.form.DrawPixels(pixelMap); MainForm.form.DrawPixels(imageBytes, pixelMap.GetLength(0), pixelMap.GetLength(1)); Application.DoEvents(); //Debugger.Break(); sw.OutputDelta("DrawPixels"); } buffer.Dispose(); buffer2.Dispose(); buffer3.Dispose(); Application.Exit(); //Debugger.Break(); } } } }