Пример #1
0
        public ICudaResult <double[][]> Multiply(
            CUBLAS_OP a_op,
            CUBLAS_OP b_op,
            double alpha,
            double[][] a,
            double[][] b,
            double beta)
        {
            // C(m, n) = A(m, k) * B(k, n)
            var matrix_a_dimensions = MatrixSizeByOperation(a.Length, a[0].Length, a_op);
            var matrix_b_dimensions = MatrixSizeByOperation(b.Length, b[0].Length, b_op);

            if (matrix_a_dimensions.Columns != matrix_b_dimensions.Rows)
            {
                throw new ArgumentOutOfRangeException($"Matrices provided cannot be multipled. Columns in matrix A: {matrix_a_dimensions.Columns} vs rows in matrix B: {matrix_b_dimensions.Rows}");
            }

            var result = DTM.MatrixMultiplyDouble(
                DeviceId,
                a_op, b_op,
                alpha,
                a,
                b,
                beta);

            return(new CudaResult <double[][]>(result.Error, result.Result));
        }
Пример #2
0
        internal static (CudaError Error, double[][] Result) MatrixMultiplyDouble(
            int device_id,
            CUBLAS_OP a_op, CUBLAS_OP b_op,
            double alpha,
            double[][] a,
            double[][] b,
            double beta)
        {
            // .NET does not support marshaling nested arrays between C++ and e.g. C#.
            // If you try, you will get the error message, "There is no marshaling support for nested arrays."
            // Further, the cuBLAS function cublasSgemm/cublasDgemm does not have pointer-to-pointers as arguments (e.g., float**), so we cannot
            // supply a multidimensional array anyway.
            // The solution: flatten arrays so that they can passed to CudaSharperLibrary, and then unflatten whatever it passes back.
            var d_a = FlattenArray(a.Length, a[0].Length, a);
            var d_b = FlattenArray(b.Length, b[0].Length, b);

            // C(m,n) = A(m,k) * B(k,n)
            // Despite the definition above, this will return the correct size for C. Go figure.
            var d_c = new double[a.Length * b.Length];

            var transa_op = (int)a_op;
            var transb_op = (int)b_op;

            var error = SafeNativeMethods.MatrixMultiplyDouble(
                device_id,
                transa_op, transb_op,
                a.Length, b[0].Length, a[0].Length,
                alpha,
                d_a,
                d_b,
                beta,
                d_c);

            return(CudaErrorCodes(error), UnflattenArray(a.Length, b.Length, d_c));
        }
Пример #3
0
        private (int Rows, int Columns) MatrixSizeByOperation(int rows, int columns, CUBLAS_OP operation)
        {
            int matrix_rows    = 0;
            int matric_columns = 0;

            switch (operation)
            {
            case CUBLAS_OP.DO_NOT_TRANSPOSE:
                matrix_rows    = rows;
                matric_columns = columns;
                break;

            case CUBLAS_OP.TRANSPOSE:
                matrix_rows    = columns;
                matric_columns = rows;
                break;
            }

            return(matrix_rows, matric_columns);
        }