Rust Program: Matrix Multiplication with Parallel Threads
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.
- Weekly Trends and Language Statistics
- Weekly Trends and Language Statistics