w3resource

Rust Program: Matrix Multiplication with Parallel Threads

Rust Threads and Synchronization: Exercise-4 with Solution

Write a Rust program to perform matrix multiplication using parallel computation with threads.

Sample Solution:

Rust Code:

use std::thread;

fn main() {
    // Define the input matrices
    let matrix_a = vec![
        vec![1, 2, 3],
        vec![4, 5, 6],
    ];
    let matrix_b = vec![
        vec![7, 8],
        vec![9, 10],
        vec![11, 12],
    ];

    // Determine the dimensions of the input matrices
    let rows_a = matrix_a.len();
    let cols_a = matrix_a[0].len();
    let _rows_b = matrix_b.len(); // Unused variable, prefixed with underscore
    let cols_b = matrix_b[0].len();

    // Initialize the result matrix with zeros
    let _result = vec![vec![0; cols_b]; rows_a]; // Unused variable, prefixed with underscore

    // Create handles to store thread handles
    let mut handles = vec![];

    // Iterate over each row of matrix A
    for i in 0..rows_a {
        // Clone matrix A for each row of matrix A
        let matrix_a_clone = matrix_a.clone();
        // Clone matrix B for each row of matrix A
        let matrix_b_clone = matrix_b.clone();
        
        // Spawn a thread to compute each row of the result matrix
        let handle = thread::spawn(move || {
            let mut row_result = vec![0; cols_b];
            for j in 0..cols_b {
                let mut temp = 0;
                for k in 0..cols_a {
                    temp += matrix_a_clone[i][k] * matrix_b_clone[k][j];
                }
                row_result[j] = temp;
            }
            row_result // Return the computed row of the result matrix
        });
        handles.push(handle);
    }

    // Collect the rows of the result matrix computed by each thread
    let mut result_rows = vec![];
    for handle in handles {
        result_rows.push(handle.join().unwrap());
    }

    // Print the result matrix
    println!("Result of matrix multiplication: {:?}", result_rows);
}

Output:

Result of matrix multiplication: [[58, 64], [139, 154]]

Explanation:

In the exercise above,

  • Input Matrices: Two matrices, 'matrix_a' and 'matrix_b', are defined as vectors of vectors. These matrices represent the input matrices for multiplication.
  • Dimensions of Matrices: The dimensions of the input matrices ('rows_a', 'cols_a', 'rows_b', and 'cols_b') are determined using the len() method.
  • Result Matrix Initialization: A result matrix '_result' is initialized as a vector of vectors filled with zeros. However, this variable is unused and is just there to indicate the expected shape of the result.
  • Thread Handles: A vector handles is created to store thread handles for each row of the result matrix.
  • Thread Spawning: A loop iterates over each row of 'matrix_a'. Inside the loop, a new thread is spawned using thread::spawn(). Each thread computes one row of the result matrix.
  • Cloning Matrices: Before spawning a thread, 'matrix_a' and 'matrix_b' are cloned. This is necessary to avoid moving the matrices into the closure, which would cause borrowing issues.
  • Thread Execution: Inside the thread closure, matrix multiplication is performed to compute one row of the result matrix. The computed row is stored in a vector 'row_result'.
  • Joining Threads: After all threads are spawned, another loop iterates over the thread handles. Each thread is joined, and the computed row of the result matrix is collected.
  • Printing Result: Finally, the computed rows of the result matrix are printed to the console using println!().

Rust Code Editor:

Previous: Rust Program: Calculate Factorial with Threads.
Next: Rust Concurrent Web Server with Threads.

What is the difficulty level of this exercise?

Test your Programming skills with w3resource's quiz.



Follow us on Facebook and Twitter for latest update.