public override void Execute()
            {
                // Let only one node init the shared thing
                if ((Owner.VectorMode == VectorGenerationMode.AverageBaseVectors && !_firstBase) || !_first)
                {
                    return;
                }


                var random = new Random(Owner.Seed);

                var dotKernel       = MyReductionFactory.Kernel(Owner.GPU, MyReductionFactory.Mode.f_DotProduct_f);
                var multKernel      = MyKernelFactory.Instance.Kernel(Owner.GPU, @"common\CombineVectorsKernel", "CombineTwoVectorsKernelVarSize");
                var transposeKernel = MyKernelFactory.Instance.Kernel(Owner.GPU, @"VSA\RandomMapper", "Transpose");

                int xDim, yDim;
                AxisToNormalizeEnum axisToNormalize = AxisToNormalize;

                if (!Owner.DoDecoding)
                {
                    xDim = Owner.InputSize;
                    yDim = Owner.OutputSize;
                }
                else
                {
                    xDim            = Owner.OutputSize;
                    yDim            = Owner.InputSize;
                    axisToNormalize = axisToNormalize == AxisToNormalizeEnum.xDim
                        ? AxisToNormalizeEnum.yDim
                        : AxisToNormalizeEnum.xDim;
                }

                GenerateTransformMatrix(
                    Owner.UnmanagedVectors, Owner.UnmanagedBaseVectors, Owner.Temp,
                    random, xDim, yDim,
                    dotKernel, multKernel, transposeKernel, Owner.GPU,
                    Owner.VectorMode, axisToNormalize);

                MyMemoryManager.Instance.ClearGlobalVariable(Owner.GlobalVariableBasesName, Owner.GPU);
                MyMemoryManager.Instance.RemoveBlock(Owner, Owner.UnmanagedBaseVectors);
            }
Example #2
0
        /// <summary>
        /// Generates a matrix with <paramref name="xDim"/> being the leading dimension in column-major storage.
        /// </summary>
        /// <param name="unmanagedVectors">A memory block to store the generated matrix.
        /// Must be as large as <paramref name="xDim"/> x <paramref name="yDim"/>.</param>
        /// <param name="unmanagedBaseVectors">A temporary block to store all the base vectors.
        /// Must be as large as Max(<paramref name="xDim"/>, <paramref name="yDim"/>)^2.
        /// Only neccessary when <paramref name="mode"/> is set to <see cref="VectorGenerationMode.AverageBaseVectors"/>.</param>
        /// <param name="temp">The temporary storage. It should be as long as the longer of the dimensions.</param>
        /// <param name="random">The random object for number generation.</param>
        /// <param name="xDim">The size of the other dimension.</param>
        /// <param name="yDim">The size of the leading dimension.</param>
        /// <param name="mode">If true, the vectors along the longer dimension will be orthonormalized.</param>
        /// <param name="axisToNormalize">The axis along which to normalize vectors after orthonormalization.</param>
        public static void GenerateTransformMatrix(
            MyMemoryBlock<float> unmanagedVectors, MyMemoryBlock<float> unmanagedBaseVectors, MyMemoryBlock<float> temp,
            Random random, int xDim, int yDim,
            MyProductKernel<float> dotKernel, MyCudaKernel multKernel, MyCudaKernel transposeKernel, int GPU,
            VectorGenerationMode mode = VectorGenerationMode.Normal, AxisToNormalizeEnum axisToNormalize = AxisToNormalizeEnum.yDim)
        {
            Debug.Assert(random != null, "Missing random object");
            Debug.Assert(unmanagedVectors != null && (mode != VectorGenerationMode.AverageBaseVectors || unmanagedBaseVectors != null) && temp != null, "Missing data!");
            Debug.Assert(dotKernel != null && multKernel != null && transposeKernel != null, "Missing a kernel!");

            // Mapping to rows --- Column-major storage --- rows will the leading dimension
            // The larger dimension vectors will be orthogonal; the cols dimension vectors will be normalized

            switch (mode)
            {
                case VectorGenerationMode.Normal:
                    if (axisToNormalize == AxisToNormalizeEnum.xDim)
                    {
                        // Generate normalized vectors with xDim as the leading dim
                        GenerateRandomNormalVectors(unmanagedVectors.Host, random, xDim, yDim);
                        unmanagedVectors.SafeCopyToDevice();

                        // Transpose to the correct position
                        transposeKernel.Run(unmanagedVectors, unmanagedVectors, xDim, yDim);
                    }
                    else
                    {
                        GenerateRandomNormalVectors(unmanagedVectors.Host, random, yDim, xDim);
                        unmanagedVectors.SafeCopyToDevice();
                    }
                    break;

                case VectorGenerationMode.Orthonormalize:
                    int largerDim = Math.Max(xDim, yDim);
                    int smallerDim = Math.Min(xDim, yDim);

                    // Generate vectors with larger leading dimension
                    GenerateRandomNormalVectors(unmanagedVectors.Host, random, largerDim, smallerDim, normalize: false);
                    unmanagedVectors.SafeCopyToDevice();

                    // Orthonormalize along the larger dimension
                    OrthonormalizeVectors(unmanagedVectors, temp, largerDim, smallerDim, dotKernel, multKernel, GPU);

                    if (xDim > yDim)
                    {
                        // xDim is leading and is normalized
                        // We need to transpose to get the correct dims
                        transposeKernel.Run(unmanagedVectors, unmanagedVectors, xDim, yDim);

                        if (axisToNormalize == AxisToNormalizeEnum.yDim)
                            NormalizeLeadingDim(unmanagedVectors, temp, yDim, xDim, dotKernel, multKernel, GPU);
                    }
                    else
                    {
                        // yDim is leading and is normalized
                        // The matrix is in correct position

                        if (axisToNormalize == AxisToNormalizeEnum.xDim)
                        {
                            // TODO: generate the matrix with transposed dims?
                            // TODO: SMELLY VERSION:
                            transposeKernel.Run(unmanagedVectors, unmanagedVectors, yDim, xDim);
                            NormalizeLeadingDim(unmanagedVectors, temp, xDim, yDim, dotKernel, multKernel, GPU);
                            transposeKernel.Run(unmanagedVectors, unmanagedVectors, xDim, yDim);
                        }
                    }
                    break;

                case VectorGenerationMode.AverageBaseVectors:
                    int longerDim = Math.Max(xDim, yDim);
                    int shorterDim = Math.Min(xDim, yDim);

                    GenerateTransformMatrix(
                        unmanagedBaseVectors, null, temp,
                        random, longerDim, longerDim,
                        dotKernel, multKernel, transposeKernel, GPU,
                        VectorGenerationMode.Orthonormalize);

                    if (shorterDim == longerDim)
                        break;

                    float it = 0f;
                    float step = longerDim / (float)shorterDim;
                    int beg, end = 0;

                    for (int i = 0; i < shorterDim; i++)
                    {
                        beg = end;
                        it += step;
                        end = (int)it;

                        var vect = unmanagedVectors.GetDevicePtr(GPU, i * longerDim);

                        for (int j = beg; j < end; j++)
                        {
                            var baseVect = unmanagedBaseVectors.GetDevicePtr(GPU, j * longerDim);
                            multKernel.Run(baseVect, vect, vect, (int)MyJoin.MyJoinOperation.Addition, longerDim,
                                longerDim);
                        }
                    }

                    if (xDim > yDim)
                    {
                        // xDim is leading and is not normalized
                        // We need to transpose to get the correct dims

                        if (axisToNormalize == AxisToNormalizeEnum.xDim)
                        {
                            NormalizeLeadingDim(unmanagedVectors, temp, xDim, yDim, dotKernel, multKernel, GPU);

                            transposeKernel.Run(unmanagedVectors, unmanagedVectors, xDim, yDim);
                        }
                        else
                        {
                            transposeKernel.Run(unmanagedVectors, unmanagedVectors, xDim, yDim);

                            NormalizeLeadingDim(unmanagedVectors, temp, yDim, xDim, dotKernel, multKernel, GPU);
                        }
                    }
                    else
                    {
                        // yDim is leading and is not normalized
                        // The matrix is in correct position

                        if (axisToNormalize == AxisToNormalizeEnum.yDim)
                            NormalizeLeadingDim(unmanagedVectors, temp, yDim, xDim, dotKernel, multKernel, GPU);
                        else
                        {
                            // TODO: SMELLY VERSION:
                            transposeKernel.Run(unmanagedVectors, unmanagedVectors, yDim, xDim);
                            NormalizeLeadingDim(unmanagedVectors, temp, xDim, yDim, dotKernel, multKernel, GPU);
                            transposeKernel.Run(unmanagedVectors, unmanagedVectors, xDim, yDim);
                        }
                    }
                    break;
            }
        }
Example #3
0
        /// <summary>
        /// Generates a matrix with <paramref name="yDim"/> being the leading dimension in column-major storage.
        /// </summary>
        /// <param name="random">The random object for number generation.</param>
        /// <param name="xDim">The size of the leading dimension.</param>
        /// <param name="yDim">The size of the other dimension.</param>
        /// <param name="orthonormalize">If true, the vectors along the longer dimension will be orthonormalized.</param>
        /// <param name="axisToNormalize">The axis along which to normalize vectors after orthonormalization.</param>
        /// <returns>The generated matrix.</returns>
        public static float[] GenerateTransformMatrix(Random random, int xDim, int yDim, bool orthonormalize = false, AxisToNormalizeEnum axisToNormalize = AxisToNormalizeEnum.yDim)
        {
            Debug.Assert(random != null, "Missing random object");

            var buffer = new float[xDim * yDim];

            // Mapping to rows --- Column-major storage --- rows will the leading dimension
            // The larger dimension vectors will be orthogonal; the cols dimension vectors will be normalized

            if (!orthonormalize)
            {
                // Generate normalized vectors along the cols dim
                if (axisToNormalize == AxisToNormalizeEnum.xDim)
                {
                    GenerateRandomNormalVectors(buffer, random, xDim, yDim);

                    // Transpose to the correct position
                    Transpose(ref buffer, xDim, yDim);
                }
                else
                {
                    GenerateRandomNormalVectors(buffer, random, yDim, xDim);
                }
            }
            else
            {
                int largerDim = Math.Max(xDim, yDim);
                int smallerDim = Math.Min(xDim, yDim);

                // Generate vectors with larger leading dimension
                GenerateRandomNormalVectors(buffer, random, largerDim, smallerDim, normalize: false);
                // Orthonormalize along the larger dimension
                OrthonormalizeVectors(buffer, largerDim, smallerDim);

                if (xDim > yDim)
                {
                    // cols is leading and is normalized
                    // We need to transpose to get the correct dims
                    Transpose(ref buffer, largerDim, smallerDim);

                    if (axisToNormalize == AxisToNormalizeEnum.xDim)
                        NormalizeLeadingDim(buffer, yDim, xDim);
                }
                else
                {
                    // rows is leading and is normalized
                    // The matrix is in correct position

                    if (axisToNormalize == AxisToNormalizeEnum.yDim)
                    {
                        // TODO: SMELLY VERSION:
                        Transpose(ref buffer, yDim, xDim);
                        NormalizeLeadingDim(buffer, xDim, yDim);
                        Transpose(ref buffer, xDim, yDim);
                    }
                }
            }

            return buffer;
        }
        /// <summary>
        /// Generates a matrix with <paramref name="xDim"/> being the leading dimension in column-major storage.
        /// </summary>
        /// <param name="unmanagedVectors">A memory block to store the generated matrix.
        /// Must be as large as <paramref name="xDim"/> x <paramref name="yDim"/>.</param>
        /// <param name="unmanagedBaseVectors">A temporary block to store all the base vectors.
        /// Must be as large as Max(<paramref name="xDim"/>, <paramref name="yDim"/>)^2.
        /// Only neccessary when <paramref name="mode"/> is set to <see cref="VectorGenerationMode.AverageBaseVectors"/>.</param>
        /// <param name="temp">The temporary storage. It should be as long as the longer of the dimensions.</param>
        /// <param name="random">The random object for number generation.</param>
        /// <param name="xDim">The size of the other dimension.</param>
        /// <param name="yDim">The size of the leading dimension.</param>
        /// <param name="mode">If true, the vectors along the longer dimension will be orthonormalized.</param>
        /// <param name="axisToNormalize">The axis along which to normalize vectors after orthonormalization.</param>
        public static void GenerateTransformMatrix(
            MyMemoryBlock <float> unmanagedVectors, MyMemoryBlock <float> unmanagedBaseVectors, MyMemoryBlock <float> temp,
            Random random, int xDim, int yDim,
            MyCudaKernel dotKernel, MyCudaKernel multKernel, MyCudaKernel transposeKernel, int GPU,
            VectorGenerationMode mode = VectorGenerationMode.Normal, AxisToNormalizeEnum axisToNormalize = AxisToNormalizeEnum.yDim)
        {
            Debug.Assert(random != null, "Missing random object");
            Debug.Assert(unmanagedVectors != null && (mode != VectorGenerationMode.AverageBaseVectors || unmanagedBaseVectors != null) && temp != null, "Missing data!");
            Debug.Assert(dotKernel != null && multKernel != null && transposeKernel != null, "Missing a kernel!");


            // Mapping to rows --- Column-major storage --- rows will the leading dimension
            // The larger dimension vectors will be orthogonal; the cols dimension vectors will be normalized

            switch (mode)
            {
            case VectorGenerationMode.Normal:
                if (axisToNormalize == AxisToNormalizeEnum.xDim)
                {
                    // Generate normalized vectors with xDim as the leading dim
                    GenerateRandomNormalVectors(unmanagedVectors.Host, random, xDim, yDim);
                    unmanagedVectors.SafeCopyToDevice();

                    // Transpose to the correct position
                    transposeKernel.Run(unmanagedVectors, unmanagedVectors, xDim, yDim);
                }
                else
                {
                    GenerateRandomNormalVectors(unmanagedVectors.Host, random, yDim, xDim);
                    unmanagedVectors.SafeCopyToDevice();
                }
                break;

            case VectorGenerationMode.Orthonormalize:
                int largerDim  = Math.Max(xDim, yDim);
                int smallerDim = Math.Min(xDim, yDim);

                // Generate vectors with larger leading dimension
                GenerateRandomNormalVectors(unmanagedVectors.Host, random, largerDim, smallerDim, normalize: false);
                unmanagedVectors.SafeCopyToDevice();

                // Orthonormalize along the larger dimension
                OrthonormalizeVectors(unmanagedVectors, temp, largerDim, smallerDim, dotKernel, multKernel, GPU);

                if (xDim > yDim)
                {
                    // xDim is leading and is normalized
                    // We need to transpose to get the correct dims
                    transposeKernel.Run(unmanagedVectors, unmanagedVectors, xDim, yDim);

                    if (axisToNormalize == AxisToNormalizeEnum.yDim)
                    {
                        NormalizeLeadingDim(unmanagedVectors, temp, yDim, xDim, dotKernel, multKernel, GPU);
                    }
                }
                else
                {
                    // yDim is leading and is normalized
                    // The matrix is in correct position

                    if (axisToNormalize == AxisToNormalizeEnum.xDim)
                    {
                        // TODO: generate the matrix with transposed dims?
                        // TODO: SMELLY VERSION:
                        transposeKernel.Run(unmanagedVectors, unmanagedVectors, yDim, xDim);
                        NormalizeLeadingDim(unmanagedVectors, temp, xDim, yDim, dotKernel, multKernel, GPU);
                        transposeKernel.Run(unmanagedVectors, unmanagedVectors, xDim, yDim);
                    }
                }
                break;

            case VectorGenerationMode.AverageBaseVectors:
                int longerDim  = Math.Max(xDim, yDim);
                int shorterDim = Math.Min(xDim, yDim);

                GenerateTransformMatrix(
                    unmanagedBaseVectors, null, temp,
                    random, longerDim, longerDim,
                    dotKernel, multKernel, transposeKernel, GPU,
                    VectorGenerationMode.Orthonormalize);

                if (shorterDim == longerDim)
                {
                    break;
                }


                float it = 0f;
                float step = longerDim / (float)shorterDim;
                int   beg, end = 0;

                for (int i = 0; i < shorterDim; i++)
                {
                    beg = end;
                    it += step;
                    end = (int)it;

                    var vect = unmanagedVectors.GetDevicePtr(GPU, i * longerDim);

                    for (int j = beg; j < end; j++)
                    {
                        var baseVect = unmanagedBaseVectors.GetDevicePtr(GPU, j * longerDim);
                        multKernel.Run(baseVect, vect, vect, (int)MyJoin.MyJoinOperation.Addition, longerDim,
                                       longerDim);
                    }
                }

                if (xDim > yDim)
                {
                    // xDim is leading and is not normalized
                    // We need to transpose to get the correct dims

                    if (axisToNormalize == AxisToNormalizeEnum.xDim)
                    {
                        NormalizeLeadingDim(unmanagedVectors, temp, xDim, yDim, dotKernel, multKernel, GPU);

                        transposeKernel.Run(unmanagedVectors, unmanagedVectors, xDim, yDim);
                    }
                    else
                    {
                        transposeKernel.Run(unmanagedVectors, unmanagedVectors, xDim, yDim);

                        NormalizeLeadingDim(unmanagedVectors, temp, yDim, xDim, dotKernel, multKernel, GPU);
                    }
                }
                else
                {
                    // yDim is leading and is not normalized
                    // The matrix is in correct position

                    if (axisToNormalize == AxisToNormalizeEnum.yDim)
                    {
                        NormalizeLeadingDim(unmanagedVectors, temp, yDim, xDim, dotKernel, multKernel, GPU);
                    }
                    else
                    {
                        // TODO: SMELLY VERSION:
                        transposeKernel.Run(unmanagedVectors, unmanagedVectors, yDim, xDim);
                        NormalizeLeadingDim(unmanagedVectors, temp, xDim, yDim, dotKernel, multKernel, GPU);
                        transposeKernel.Run(unmanagedVectors, unmanagedVectors, xDim, yDim);
                    }
                }
                break;
            }
        }
        /// <summary>
        /// Generates a matrix with <paramref name="yDim"/> being the leading dimension in column-major storage.
        /// </summary>
        /// <param name="random">The random object for number generation.</param>
        /// <param name="xDim">The size of the leading dimension.</param>
        /// <param name="yDim">The size of the other dimension.</param>
        /// <param name="orthonormalize">If true, the vectors along the longer dimension will be orthonormalized.</param>
        /// <param name="axisToNormalize">The axis along which to normalize vectors after orthonormalization.</param>
        /// <returns>The generated matrix.</returns>
        public static float[] GenerateTransformMatrix(Random random, int xDim, int yDim, bool orthonormalize = false, AxisToNormalizeEnum axisToNormalize = AxisToNormalizeEnum.yDim)
        {
            Debug.Assert(random != null, "Missing random object");


            var buffer = new float[xDim * yDim];

            // Mapping to rows --- Column-major storage --- rows will the leading dimension
            // The larger dimension vectors will be orthogonal; the cols dimension vectors will be normalized

            if (!orthonormalize)
            {
                // Generate normalized vectors along the cols dim
                if (axisToNormalize == AxisToNormalizeEnum.xDim)
                {
                    GenerateRandomNormalVectors(buffer, random, xDim, yDim);

                    // Transpose to the correct position
                    Transpose(ref buffer, xDim, yDim);
                }
                else
                {
                    GenerateRandomNormalVectors(buffer, random, yDim, xDim);
                }
            }
            else
            {
                int largerDim  = Math.Max(xDim, yDim);
                int smallerDim = Math.Min(xDim, yDim);

                // Generate vectors with larger leading dimension
                GenerateRandomNormalVectors(buffer, random, largerDim, smallerDim, normalize: false);
                // Orthonormalize along the larger dimension
                OrthonormalizeVectors(buffer, largerDim, smallerDim);

                if (xDim > yDim)
                {
                    // cols is leading and is normalized
                    // We need to transpose to get the correct dims
                    Transpose(ref buffer, largerDim, smallerDim);

                    if (axisToNormalize == AxisToNormalizeEnum.xDim)
                    {
                        NormalizeLeadingDim(buffer, yDim, xDim);
                    }
                }
                else
                {
                    // rows is leading and is normalized
                    // The matrix is in correct position

                    if (axisToNormalize == AxisToNormalizeEnum.yDim)
                    {
                        // TODO: SMELLY VERSION:
                        Transpose(ref buffer, yDim, xDim);
                        NormalizeLeadingDim(buffer, xDim, yDim);
                        Transpose(ref buffer, xDim, yDim);
                    }
                }
            }

            return(buffer);
        }