example.cpp

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#include <iostream>
#include <vector>
#include <future>
#include <mutex>
#include <shared_mutex>
#include <chrono>
#include <random>
#include <algorithm>

using Matrix = std::vector<std::vector<double>>;

std::shared_mutex mtx;

// Function to generate a random matrix
Matrix generateRandomMatrix(int rows, int cols) {
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_real_distribution<> dis(0.0, 1.0);

    Matrix matrix(rows, std::vector<double>(cols));
    for (auto& row : matrix) {
        for (auto& elem : row) {
            elem = dis(gen);
        }
    }
    return matrix;
}

// Function to multiply two matrices
Matrix multiplyMatrices(const Matrix& A, const Matrix& B) {
    int m = A.size();
    int n = B[0].size();
    int p = B.size();

    Matrix result(m, std::vector<double>(n, 0.0));

    for (int i = 0; i < m; ++i) {
        for (int j = 0; j < n; ++j) {
            for (int k = 0; k < p; ++k) {
                result[i][j] += A[i][k] * B[k][j];
            }
        }
    }

    return result;
}

// Function to multiply a portion of matrices (for parallel execution)
void multiplyMatricesPortion(const Matrix& A, const Matrix& B, Matrix& result, int start_row, int end_row) {
    int n = B[0].size();
    int p = B.size();

    for (int i = start_row; i < end_row; ++i) {
        for (int j = 0; j < n; ++j) {
            double sum = 0.0;
            for (int k = 0; k < p; ++k) {
                sum += A[i][k] * B[k][j];
            }
            std::scoped_lock lock(mtx);
            result[i][j] = sum;
        }
    }
}

// Function to perform parallel matrix multiplication
Matrix parallelMultiplyMatrices(const Matrix& A, const Matrix& B) {
    int m = A.size();
    int n = B[0].size();

    Matrix result(m, std::vector<double>(n, 0.0));

    int num_threads = std::thread::hardware_concurrency(); // 12 on my mac
    num_threads = 2;
    std::cout << "num_threads= " << num_threads << std::endl;
    int rows_per_thread = m / num_threads;

    std::vector<std::future<void>> futures;

    for (int i = 0; i < num_threads; ++i) {
        int start_row = i * rows_per_thread;
        int end_row = (i == num_threads - 1) ? m : (i + 1) * rows_per_thread;

        futures.push_back(std::async(std::launch::async, multiplyMatricesPortion, 
                                     std::ref(A), std::ref(B), std::ref(result), start_row, end_row));
    }

    for (auto& future : futures) {
        future.wait();
    }

    return result;
}

// Function to measure execution time
template<typename Func, typename... Args>
auto measureTime(Func func, Args&&... args) {
    auto start = std::chrono::high_resolution_clock::now();
    auto result = func(std::forward<Args>(args)...);
    auto end = std::chrono::high_resolution_clock::now();

    std::chrono::duration<double, std::milli> duration = end - start;
    return std::make_pair(result, duration.count());
}

int main() {
    const int size = 1000;

    Matrix A = generateRandomMatrix(size, size);
    Matrix B = generateRandomMatrix(size, size);

    std::cout << "Matrix size: " << size << "x" << size << std::endl;

    auto [result_serial, time_serial] = measureTime(multiplyMatrices, A, B);
    std::cout << "Serial multiplication time: " << time_serial << " ms" << std::endl;

    auto [result_parallel, time_parallel] = measureTime(parallelMultiplyMatrices, A, B);
    std::cout << "Parallel multiplication time: " << time_parallel << " ms" << std::endl;

    // Check if results are the same
    bool results_match = (result_serial == result_parallel);
    std::cout << "Results match: " << (results_match ? "Yes" : "No") << std::endl;

    return 0;
}
Back to wk13_concurrency_2