Exemple #1
0
        //This function first creates the designated amount of matrices with randomly generated numbers in them and then multiplies the matrices with one another using threads to multiply different sections of the matrix simultaneously
        private RandomMatrix CreateAndMultiplayMatrices(int poolSize, int numOfMatrices, int matrixDim)
        {
            CustomThreadPool      threadPool       = new CustomThreadPool();      //Creates a thread pool
            List <RandomMatrix>   matrices         = new List <RandomMatrix>();   //Creates a vector of matrices
            MatrixConcurrentQueue multiMatrixQueue = new MatrixConcurrentQueue(); //A custom Queue class that holds the matrices and the amount of multiplications that have been completed

            threadPool.SetThreadPoolSize(poolSize);                               //Set the thread pool's pool size (amount of threads)

            //Initializes the matrix array with matrices
            for (int i = 0; i < numOfMatrices; i++)
            {
                //Initializes the current matrix
                RandomMatrix currMatrix = new RandomMatrix(matrixDim);
                matrices.Add(currMatrix);
                for (int j = 0; j < poolSize; j++)
                {
                    //Splits the matrix into segments so each thread will randomize values for a different segment of the matrix
                    int          threadRandPart = j;
                    WaitCallback task           = () => MatrixUtils.ThreadingCreateRandomMatrix(currMatrix, poolSize, threadRandPart, matrixDim); //Saves the task into a callback
                    threadPool.QueueTask(task);                                                                                                   //Queues the task so the thread pool will allocate a thread to run it
                }
            }

            threadPool.DoneWorking.WaitOne(); //Waits for all threads to finish before continuing

            //Enqueues all the matrices into a Concurrent Queue so it can run constantly until all the matrices have been multiplied and only the final result matrix remains
            foreach (RandomMatrix mat in matrices)
            {
                multiMatrixQueue.m_MatrixQueue.Enqueue(mat);
            }

            //Runs across the queue, sending 2 matrices at a time to the multiplication method
            while (multiMatrixQueue.numOfOperations < numOfMatrices - 1)
            {
                RandomMatrix matA = null;                                //matrix that will hold the 1st matrix
                RandomMatrix matB = null;                                //matrix that will hold the 2nd matrix

                if (multiMatrixQueue.m_MatrixQueue.Count > 1)            //checks if theres more than one matrix in the queue, so it won't attempt to multiply a null matrix
                {
                    multiMatrixQueue.m_MatrixQueue.TryDequeue(out matA); //Tries to dequeues the 1st matrix into matA
                    multiMatrixQueue.m_MatrixQueue.TryDequeue(out matB); ////Tries to dequeues the 2nd matrix into matA
                }

                if (matA != null && matB != null)
                {
                    RandomMatrix resMatrix = new RandomMatrix(matrixDim); //Creates a result matrix to hold the multiplication result
                    multiMatrixQueue.m_MatrixQueue.Enqueue(resMatrix);    //Insers the result matrix into the queue
                    int matrixPartsLeft = poolSize;                       //Amount of parts the matrix multiplication will be split into

                    //Divides the matrix multiplication work, so each thread calculates the matrix multiplication in different parts of the matrices
                    for (int i = 0; i < poolSize; i++)
                    {
                        int          threadMultiPart = i;              //saves the index in order to avoid it being different when the task is executed
                        WaitCallback task            = () => MatrixUtils.ThreadingMultiplyMatrices(resMatrix, matA, matB, multiMatrixQueue, ref matrixPartsLeft, poolSize, threadMultiPart, matrixDim);
                        threadPool.QueueTask(task);
                    }
                    // threadPool.DoneWorking.WaitOne();
                }
            }

            threadPool.DoneWorking.WaitOne();  //Waits for all threads to finish before continuing
            RandomMatrix finalMatrix;

            multiMatrixQueue.m_MatrixQueue.TryDequeue(out finalMatrix); //Dequeues the final result matrix and returns it.
            return(finalMatrix);
        }
        public static void  ThreadingMultiplyMatrices(RandomMatrix result, RandomMatrix matA, RandomMatrix matB, MatrixConcurrentQueue matrixQueue, ref int matrixPartsLeft, int numOfThreads, int threadPart, int matrixDim)
        {
            // Calculates the workload for the current thread
            int numOfElements = (matrixDim * matrixDim);         //Holds the number of elements in the matrix
            int numOfOperations = numOfElements / numOfThreads;  //Holds the number of operations (iterations) that will be done
            int restOfOperations = numOfElements % numOfThreads; //Holds the extra number of operations the first thread will have to do
            int startPosition, endPosition;                      //Holds the starting and ending indexes

            if (threadPart == 0)
            {
                //First thread does the extra work left by the other threads (the remainder)
                startPosition = numOfOperations * threadPart;
                endPosition   = (numOfOperations * (threadPart + 1)) + restOfOperations;
            }
            else
            {
                startPosition = numOfOperations * threadPart + restOfOperations;
                endPosition   = (numOfOperations * (threadPart + 1)) + restOfOperations;
            }
            //Randomizes the segment in the matrix the current thread is incharge of, in this case a segment of cells in the result matrix that will be calculated from multiplying Matrix A and Matrix B
            for (int pos = startPosition; pos < endPosition; ++pos)
            {
                int row     = pos % matrixDim; //Calcuates the current row
                int col     = pos / matrixDim; //Calculates the current column
                int resCell = 0;

                //Multiplies the current row in Matrix A with the current column in matrix B and saves the result in the appropriate cell in the result matrix
                for (int i = 0; i < matrixDim; ++i)
                {
                    int cellA = matA.Matrix[row, i];
                    int cellB = matB.Matrix[i, col];
                    resCell += cellA * cellB;
                }

                result.Matrix[row, col] = resCell;
            }

            //The current segment in the result matrix has been completed so the matrixPartsLeft counter gets decremented
            Interlocked.Decrement(ref matrixPartsLeft);
            //If the matrixPartsLeft counter reaches 0, we have finished calculating the multiplication of all the segments of the result matrix
            if (matrixPartsLeft == 0)
            {
                //Since the result matrix is complete we increment the number of completed matrix multiplication opreations in the matrix multiplication queue
                Interlocked.Increment(ref matrixQueue.numOfOperations);
            }
        }