//----------------------------------------------------------------------- // ----------------------------------------------------------------------- // file="MatrixCompute.Float" // Project: StgSharp // AuthorGroup: Nitload // Copyright (c) Nitload. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. // // ----------------------------------------------------------------------- // ----------------------------------------------------------------------- using StgSharp.Collections; using StgSharp.Internal; using StgSharp.Mathematics; using StgSharp.Mathematics.Internal; using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations.Schema; using System.Linq; using System.Numerics; using System.Security.AccessControl; using System.Text; using System.Threading.Tasks; namespace StgSharp.Mathematics.Numeric { public static partial class MatrixCompute { public static unsafe void Add( Matrix left, Matrix right, Matrix ans ) { MatrixElementType f32 = MatrixElementType.F32; if (left.ColumnLength != right.ColumnLength || left.RowLength != right.RowLength || left.ColumnLength != ans.ColumnLength || left.RowLength != ans.RowLength) { throw new IndexOutOfRangeException("Matrix dimensions must agree."); } long count = (long)left.KernelColumnLength * left.KernelRowLength; if (count <= 256) { MatrixKernel* leftPtr = left.Buffer; MatrixKernel* rightPtr = right.Buffer; MatrixKernel* ansPtr = ans.Buffer; NumericalModule.GlobalContext.mat_mk[f32].buffer_add(leftPtr, rightPtr, ansPtr, count); return; } else if (count <= 1024) { MatrixParallelThread[] pool = MatrixParallel.LeadParallel(1); MatrixKernel* leftPtr = left.Buffer; MatrixKernel* rightPtr = right.Buffer; MatrixKernel* ansPtr = ans.Buffer; NumericalModule.GlobalContext.mat_mk[f32].buffer_add(leftPtr, rightPtr, ansPtr, count); MatrixParallel.ReturnParallelResources(ref pool); return; } MatrixParallelTask* package = MatrixParallelFactory.CreateBaseTask(); package->Mat1 = (MatrixKernel*)left.Buffer; package->Mat2 = (MatrixKernel*)right.Buffer; package->Mat3 = (MatrixKernel*)ans.Buffer; package->ElementSize = sizeof(float); package->PrimCount = ans.KernelColumnLength; package->SecCount = ans.KernelRowLength; package->ComputeMode = new MatrixOpMode(MatrixIndexStyle.BUFFER_INDEX, MatrixOperationParam.LEFT_RIGHT_ANS_PARAM); package->ComputeHandle = (IntPtr)NumericalModule.GlobalContext.mat_sk[f32].buffer_add; MatrixParallelWrap taskGroup = MatrixParallel.ScheduleTask(package); taskGroup.LaunchParallel(SleepMode.DeepSleep); taskGroup.Dispose(); return; } public static unsafe void Fill( Matrix ans, float value ) { MatrixElementType f32 = MatrixElementType.F32; long count = (long)ans.KernelColumnLength * ans.KernelRowLength; ScalarPacket* scalar = MatrixParallelFactory.CreateScalarPacket(); scalar->Data(0) = value; if (count <= 256) { NumericalModule.GlobalContext.mat_sk[f32].buffer_fill(ans.Buffer, scalar, count); return; } else if (count <= 1024) { MatrixParallelThread[] pool = MatrixParallel.LeadParallel(1); NumericalModule.GlobalContext.mat_sk[f32].buffer_fill(ans.Buffer, scalar, count); MatrixParallel.ReturnParallelResources(ref pool); return; } MatrixParallelTask* package = MatrixParallelFactory.CreateBaseTask(); package->Answer = (nint)ans.Buffer; package->ElementSize = sizeof(float); package->PrimCount = ans.KernelColumnLength; package->SecCount = ans.KernelRowLength; package->ComputeMode = new MatrixOpMode(MatrixIndexStyle.BUFFER_INDEX, MatrixOperationParam.ANS_SCALAR_PARAM); package->ComputeHandle = (IntPtr)NumericalModule.GlobalContext.mat_sk[f32].buffer_fill; package->Scalar = scalar; MatrixParallelWrap taskGroup = MatrixParallel.ScheduleTask(package); taskGroup.LaunchParallel(SleepMode.DeepSleep); MatrixParallelFactory.Release(scalar); taskGroup.Dispose(); } public static unsafe void Mul( Matrix left, Matrix right, Matrix ans ) { MatrixElementType f32 = MatrixElementType.F32; // For matrix multiplication (left: MxK) * (right: KxN) => ans: MxN // ColumnLength = number of columns (N), RowLength = number of rows (M) if (left.ColumnLength != right.RowLength || ans.ColumnLength != right.ColumnLength || ans.RowLength != left.RowLength) { throw new IndexOutOfRangeException("Matrix dimensions must agree."); } if (left.Layout != MatrixLayout.DenseRectangle || right.Layout != MatrixLayout.DenseRectangle || ans.Layout != MatrixLayout.DenseRectangle) { throw new NotSupportedException("Only dense rectangle matrices are supported."); } long count = (long)left.KernelColumnLength * left.KernelRowLength; if (count <= 1024) { MatrixParallelThread[] pool = null; if (count > 256) { pool = MatrixParallel.LeadParallel(1); } M128* enumeration = stackalloc M128[1]; enumeration->Member(2) = left.KernelColumnLength; enumeration->Member(3) = ans.KernelColumnLength; for (int i = 0; i < ans.KernelRowLength; i++) { for (int j = 0; j < ans.KernelColumnLength; j++) { enumeration->Member(0) = i; enumeration->Member(1) = j; NumericalModule.GlobalContext .mat_sk[f32].kernel_tile_fma((MatrixKernel*)left.Buffer, (MatrixKernel*)right.Buffer, (MatrixKernel*)ans.Buffer, enumeration); } } if (count > 256) { MatrixParallel.ReturnParallelResources(ref pool!); } return; } MatrixParallelTask* package = MatrixParallelFactory.CreateBaseTask(); package->Left = (nint)left.Buffer; package->Right = (nint)right.Buffer; package->Answer = (nint)ans.Buffer; package->AnsPrimOffset = ans.KernelRowLength; package->AnsSecOffset = ans.KernelColumnLength; package->LeftPrimOffset = left.KernelColumnLength; package->PrimCount = ans.KernelColumnLength; package->SecCount = ans.KernelRowLength; package->ElementSize = (int)MatrixElementType.F32; package->ComputeMode = new MatrixOpMode(MatrixIndexStyle.SPECIAL, MatrixOperationSpecial.SEQ_FMA); MatrixParallelWrap taskGroup = MatrixParallel.ScheduleTask(package); taskGroup.LaunchParallel(SleepMode.DeepSleep); taskGroup.Dispose(); return; } public static unsafe void Mul( Matrix left, float right, Matrix ans ) { MatrixElementType f32 = MatrixElementType.F32; if (left.ColumnLength != ans.ColumnLength || left.RowLength != ans.RowLength) { throw new IndexOutOfRangeException("Matrix dimensions must agree."); } if (left.Layout != MatrixLayout.DenseRectangle || ans.Layout != MatrixLayout.DenseRectangle) { throw new NotSupportedException("Only dense rectangle matrices are supported."); } long count = (long)left.KernelColumnLength * left.KernelRowLength; ScalarPacket* scalar = MatrixParallelFactory.CreateScalarPacket(); scalar->Data(0) = right; if (count <= 256) { MatrixKernel* leftPtr = left.Buffer; MatrixKernel* ansPtr = ans.Buffer; NumericalModule.GlobalContext.mat_sk[f32].buffer_scalar_mul(leftPtr, ansPtr, scalar, count); return; } else if (count <= 1024) { MatrixParallelThread[] pool = MatrixParallel.LeadParallel(1); MatrixKernel* leftPtr = left.Buffer; MatrixKernel* ansPtr = ans.Buffer; NumericalModule.GlobalContext.mat_sk[f32].buffer_scalar_mul(leftPtr, ansPtr, scalar, count); MatrixParallel.ReturnParallelResources(ref pool); return; } MatrixParallelTask* package = MatrixParallelFactory.CreateBaseTask(); package->Right = (nint)left.Buffer; package->Answer = (nint)ans.Buffer; package->ElementSize = sizeof(float); package->PrimCount = left.KernelColumnLength; package->SecCount = left.KernelRowLength; package->Scalar = scalar; package->ComputeMode = new MatrixOpMode(MatrixIndexStyle.BUFFER_INDEX, MatrixOperationParam.RIGHT_ANS_SCALAR_PARAM); package->ComputeHandle = (IntPtr)NumericalModule.GlobalContext.mat_sk[f32].buffer_scalar_mul; MatrixParallelWrap taskGroup = MatrixParallel.ScheduleTask(package); taskGroup.LaunchParallel(SleepMode.DeepSleep); taskGroup.Dispose(); MatrixParallelFactory.Release(scalar); return; } public static unsafe void Sub( Matrix left, Matrix right, Matrix ans ) { MatrixElementType f32 = MatrixElementType.F32; if (left.ColumnLength != right.ColumnLength || left.RowLength != right.RowLength || left.ColumnLength != ans.ColumnLength || left.RowLength != ans.RowLength) { throw new IndexOutOfRangeException("Matrix dimensions must agree."); } if (left.Layout != MatrixLayout.DenseRectangle || right.Layout != MatrixLayout.DenseRectangle || ans.Layout != MatrixLayout.DenseRectangle) { throw new NotSupportedException("Only dense rectangle matrices are supported."); } long count = (long)left.KernelColumnLength * left.KernelRowLength; if (count <= 256) { MatrixKernel* leftPtr = left.Buffer; MatrixKernel* rightPtr = right.Buffer; MatrixKernel* ansPtr = ans.Buffer; NumericalModule.GlobalContext.mat_sk[f32].buffer_sub(leftPtr, rightPtr, ansPtr, count); return; } else if (count <= 1024) { MatrixParallelThread[] pool = MatrixParallel.LeadParallel(1); MatrixKernel* leftPtr = left.Buffer; MatrixKernel* rightPtr = right.Buffer; MatrixKernel* ansPtr = ans.Buffer; NumericalModule.GlobalContext.mat_sk[f32].buffer_sub(leftPtr, rightPtr, ansPtr, count); MatrixParallel.ReturnParallelResources(ref pool); return; } MatrixParallelTask* package = MatrixParallelFactory.CreateBaseTask(); package->Left = (nint)left.Buffer; package->Right = (nint)right.Buffer; package->Answer = (nint)ans.Buffer; package->ElementSize = sizeof(float); package->PrimCount = left.KernelColumnLength; package->SecCount = left.KernelRowLength; package->ComputeMode = new MatrixOpMode(MatrixIndexStyle.BUFFER_INDEX, MatrixOperationParam.LEFT_RIGHT_ANS_PARAM); package->ComputeHandle = (IntPtr)NumericalModule.GlobalContext.mat_sk[f32].buffer_sub; MatrixParallelWrap taskGroup = MatrixParallel.ScheduleTask(package); taskGroup.LaunchParallel(SleepMode.DeepSleep); taskGroup.Dispose(); return; } } }