Multiplying polynomials in C++ with threading

483 Views Asked by At

I am trying to rewrite some of my code to use threading, since I am trying to learn about it in C++. I have this method:

template <typename T>
Polynomial<T> Polynomial<T>::operator *(const Polynomial<T>& other) {
    std::vector<std::future<std::vector<T>>> tempResults;

    for (auto i = 0; i < Coefficients.size(); i++) {
        tempResults.push_back(std::async(std::launch::async, [&other, this](int i) {
            std::vector<T> result(i + other.GetCoefficientsSize() + 2);
            std::fill(result.begin(), result.end(), 0);

            for (auto j = 0; j < other.GetCoefficientsSize(); j++) {
                result.at(j + i + 1) = other.GetCoefficient(j) * Coefficients.at(i);
            }
        return result;
    }, Coefficients.at(i)));
}

std::mutex multiplyMutex;
std::vector<T> total(Coefficients.size() + other.Coefficients.size());

for (auto i = 0; i < tempResults.size(); i++) {
    std::vector<T> result = tempResults.at(i).get();
    std::lock_guard<std::mutex> lock(multiplyMutex);
    for (T value : result) {
        total.at(i) += value;
    }
}
Polynomial<T> result(total);
return result;

After much trial and error, i got the code to compile. On runtime however, i get an index out of bounds exception at this line:

    std::vector<T> result = tempResults.at(i).get();

Furthermore, step-by-step debugging shows me that some kind of exception handling in the file "future" is run at this line as well:

   result.at(j + i + 1) = other.GetCoefficient(j) * Coefficients.at(i);

Can you identify what is happening?

1

There are 1 best solutions below

0
On

I finally solved the problem myself. It turned out I had made a stupid mistake, storing the results of the async tasks on index Coefficients.at(i) which obviously is a coefficient of the polynomial. This in turn made the result of the async task go out of bounds on the tempResults vector. What I really needed was to store at i.

Once I had it working, I also found that the last for loop was faulty. The full working result can be seen below.

template <typename T>
Polynomial<T> Polynomial<T>::operator *(const Polynomial<T>& other) {
    std::vector<std::future<std::vector<T>>> tempResults; //Results from async will be stored here

    for (int i = 0; i < Coefficients.size(); i++) {
        tempResults.push_back(std::async(std::launch::async, [&other, this](int i) { //Start threads for each Coefficient
            std::vector<T> result(Coefficients.size() + other.GetCoefficientsSize()); //Size of result is the combined degree
            std::fill(result.begin(), result.end(), 0);

            for (auto j = 0; j < other.GetCoefficientsSize(); j++) {
                result.at(i + j + 1) += Coefficients.at(i) * other.GetCoefficient(j);
            }
            return result;
        }, i)); //save in tempResults at i
    }
    std::mutex multiplyMutex;
    std::vector<T> total(Coefficients.size() + other.Coefficients.size());

    for (auto i = 0; i < tempResults.size(); i++) { //Combine tempResults in total
        std::vector<T> result = tempResults.at(i).get(); //Get result of async task
        std::lock_guard<std::mutex> lock(multiplyMutex); //Disallow concurrent access to the final variable
        for (auto j = 0; j < result.size(); j++) {
            total.at(j) += result.at(j);
        }
    }
    Polynomial<T> result(total);
    return result;
}