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.
It will be nice if you may share this link in any developer community or anywhere else, from where other developers may find this content. Thanks.
https://w3resource.com/rust/threads_and_synchronization/rust-threads-and-synchronization-exercise-4.php
- Weekly Trends and Language Statistics
- Weekly Trends and Language Statistics