mercredi 5 septembre 2018

C++ How to add two vectors asynchronously

Good morning everyone.

I am new to C++ 11 multithreading theme and trying to write down a code that add two vectors of equal sizes in asynchronous way. This means, if I have two vectors:

vector<int> fisrt = {1, 2, 3};
vector<int> second = {3, 2, 1};
first += second; // first = {4, 4, 4}

I wrote Paginator class which splits vector on "pages" with appropriate page_size. My idea of vectors addition in asynchronous way is next: split vectors on pages with choosen page_size, and add pages of first and second vectors in asynchronous way.

Paginator class implementation

template<class Iter>
class IterRange {
public:
    explicit IterRange(Iter first, Iter last) : first_(first), last_(last) {}

    Iter begin() { return first_; }
    const Iter begin() const { return first_; }

    Iter end() { return last_; }
    const Iter end() const { return last_; }

private:
    Iter first_;
    Iter last_;
};

template<class Iter>
IterRange<Iter> MakeIterRange(Iter first, Iter last) {
    return IterRange<Iter> {first, last };
}

template<class Iter>
class Paginator {
public:
    Paginator(Iter first, Iter last, size_t page_size) : page_size_(page_size) {
        size_t pages_count = static_cast<size_t> (floor((double)distance(first, last) / page_size_));
        pages_.reserve(pages_count);

        size_t page_id = 0u;
        Iter begin_page = first;
        for (page_id, begin_page; page_id < pages_count; ++page_id, begin_page += page_size_) {
            pages_.push_back(MakeIterRange( begin_page,  begin_page + page_size ));
        }

        // If some elements less than page_size_ is left
        if (begin_page != last) {
            pages_.push_back(MakeIterRange(begin_page, begin_page + distance(begin_page, last)));
        }
    }

    auto begin() { return pages_.begin(); }
    auto begin() const { return pages_.begin(); }

    auto end() { return pages_.end(); }
    auto end() const { return pages_.end(); }

private:
    size_t page_size_;
    vector<IterRange<Iter>> pages_;
};

template<class Iter>
Paginator<Iter> MakePaginator(Iter first, Iter last, size_t page_size) {
    return{ first, last, page_size };
}

template<class Container> // And the same for non constant Container
auto Paginate(const Container & c, size_t page_size) {
    return MakePaginator(begin(c), end(c), page_size);
}

This Paginate procedure is used in operator+= in my Matrix class.

Matrix class fields are:

  1. Matrix sizes along Ox and Oy direction respectively: size_t nx_, size_t ny_.
  2. Vector of (nx_ * ny_) size, which stores all elements in matrix: vector body_.

Operator += for Matrix

template inline Matrix & Matrix::operator+=(const Matrix & other) {

size_t threads_numb = thread::hardware_concurrency();
size_t page_size = static_cast<size_t> (ceil((double)body_.size() / threads_numb));
    vector<future<void>> futures;

    auto page_1 = page::Paginate(body_, page_size);
    auto page_2 = page::Paginate(other.body_, page_size);

    auto it_2 = page_2.begin();

    for (auto it = page_1.begin(); it != page_1.end(); ++it, ++it_2) {
        futures.push_back(
            async([it, it_2] { transform(it->begin(), it->end(), it_2->begin(), it->begin(), plus<T>()); })
        );
    }

    return *this;
}

But as a result I get iterator out of range error! How could I fix this?

P.S. Sorry for bad representation of first string in operator +=. Could not fix this problem :(

Aucun commentaire:

Enregistrer un commentaire