mercredi 1 novembre 2023

C++ Thread dot product doesn't compile

I am writing a class for a mathematical vector.

The class was fine, but when I tried to change the implementation of the operator* (dot product) to work with threads, I got some errors and I don't have any idea of how to fix them.

Code is below, I omitted the implementation of some functions I deemed unnecessary:

matVec.h

#ifndef ATLIB_MATVEC
#define ATLIB_MATVEC
#include <vector>
#include <iostream>
#include <cmath>
#include <thread>

namespace atlib{
    template <class T>
    class matVec{
    public:
        matVec();
        matVec(size_t n);
        matVec(size_t n, bool vert);
        matVec(size_t n, T cons);
        matVec(size_t n, T cons, bool vert);
        ~matVec();
        int Size() const; //tested
        bool Colm() const; //tested
        static T Precision();
        void push_back(T cons);
        bool operator==(const matVec& mv) const; //tested
        matVec operator+(const matVec& mv) const; //tested
        matVec operator-() const &; //tested
        matVec operator*(const T& scalar) const; //tested
        T operator*(const matVec& mv) const; //tested
        matVec operator-(const matVec& mv) const; //tested
        T& operator[](std::size_t n); //tested
        matVec Transpose();
        atlib::matVec<T> operator=(matVec<T> mv);
        atlib::matVec<T> Copy() const;
        void push(T val);
        friend std::ostream& operator<<(std::ostream& os, const matVec<T>& vec){
            if (vec.Colm()){
                for (const T& element : vec.data_) {
                    os << element << '\n';
                }
            }else{
                size_t n = vec.data_.size();
                for (size_t i = 0;i<n-1;i++) {
                    os << vec.data_[i] << "; ";
                }
                os << vec.data_[n-1];
            }
            return os;
        }
    private:
        static T prec_;
        std::vector<T> data_;
        size_t size_;
        bool col_;
        
    };
}

template class atlib::matVec<int>;
template class atlib::matVec<double>;

//NON-Member functions
template<class T>
atlib::matVec<T> operator*(T scalar,atlib::matVec<T> mv){
    return mv*scalar;
}

template<class T>
void thread_dotprod(atlib::matVec<T> &v, atlib::matVec<T> &w, unsigned int start, unsigned int end, T& t_ans);

#endif //ATLIB_MATVEC

matVec.cpp

#include <thread>
#include <pthread.h>
#include <vector>
#include "matVec.h"

template<>
double atlib::matVec<double>::prec_ = 0.00001;

template<>
int atlib::matVec<int>::prec_ = 0;

template<class T>
atlib::matVec<T>::matVec():size_(0),data_(std::vector<T>()),col_(true){
    //blank
}

template<class T>
atlib::matVec<T>::matVec(size_t n):size_(n),data_(std::vector<T>()),col_(true){
    data_.resize(n);
}

template<class T>
atlib::matVec<T>::matVec(size_t n, bool vert):size_(n),data_(std::vector<T>()),col_(vert){
    data_.resize(n);
}

template<class T>
atlib::matVec<T>::matVec(size_t n, T cons):size_(n),data_(std::vector<T>(n,cons)),col_(true){
    //blank
}

template<class T>
atlib::matVec<T>::matVec(size_t n, T cons, bool vert):size_(n),data_(std::vector<T>(n,cons)),col_(vert){
    //blank
}

template<class T>
void thread_dotprod(atlib::matVec<T> &v, atlib::matVec<T> &w, unsigned int start, unsigned int end, T& t_ans){
    t_ans = 0;
    for(unsigned int i = start; i<end; i++){
        t_ans += v[i]*w[i];
    }
}


template<class T>
T atlib::matVec<T>::operator*(const atlib::matVec<T>& mv) const{
    try{
        bool works = (size_ == mv.Size());
        if(!works) throw std::out_of_range("The sizes of the vectors aren't equal");
    } catch(const std::out_of_range& ex){
        std::cout<<"Exception: "<<ex.what()<<std::endl;
    }
    const unsigned int cores = std::thread::hardware_concurrency();
    T ans = 0;
    if (cores==0){
        for(size_t i = 0;i<size_;i++){
            ans += data_[i]*mv[i];
        }
        return ans;
    }
    std::vector<std::thread> threads;
    unsigned int slice = size_/cores;
    std::vector<T> t_ans_vec;
    t_ans_vec.push_back(0);
    T t_ans = t_ans_vec[0];
    threads.push_back(std::thread(thread_dotprod, std::ref(*this), std::ref(mv), (cores-1)*slice, size_, std::ref(t_ans)));

    for(unsigned int i = 0; i<cores-1; i++){
        t_ans_vec.push_back(0);
        t_ans = t_ans_vec[i+1];
        threads.push_back(std::thread(thread_dotprod, std::ref(*this), std::ref(mv), i*slice, (i+1)*slice), std::ref(t_ans));
    }


    for (unsigned int i = 0; i<cores; i++){
        threads[i].join();
        ans+=t_ans_vec[i];
    }

    return ans;
}

The errors:

source/matVec.cpp: In instantiation of ‘T atlib::matVec<T>::operator*(const atlib::matVec<T>&) const [with T = int]’:
./header/matVec.h:56:23:   required from here
source/matVec.cpp:120:31: error: passing ‘const atlib::matVec<int>’ as ‘this’ argument discards qualifiers [-fpermissive]
  120 |             ans += data_[i]*mv[i];
      |                             ~~^
In file included from source/matVec.cpp:4:
./header/matVec.h:28:12: note:   in call to ‘T& atlib::matVec<T>::operator[](std::size_t) [with T = int; std::size_t = long unsigned int]’
   28 |         T& operator[](std::size_t n); //tested
      |            ^~~~~~~~
source/matVec.cpp:129:28: error: no matching function for call to ‘std::thread::thread(<unresolved overloaded function type>, std::reference_wrapper<const atlib::matVec<int> >, std::reference_wrapper<const atlib::matVec<int> >, unsigned int, const size_t&, std::reference_wrapper<int>)’
  129 |     threads.push_back(std::thread(thread_dotprod, std::ref(*this), std::ref(mv), (cores-1)*slice, size_, std::ref(t_ans)));
      |                            ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/c++/11/thread:43,
                 from source/matVec.cpp:1:
/usr/include/c++/11/bits/std_thread.h:127:7: note: candidate: ‘template<class _Callable, class ... _Args, class> std::thread::thread(_Callable&&, _Args&& ...)’
  127 |       thread(_Callable&& __f, _Args&&... __args)
      |       ^~~~~~
/usr/include/c++/11/bits/std_thread.h:127:7: note:   template argument deduction/substitution failed:
source/matVec.cpp:129:28: note:   couldn’t deduce template parameter ‘_Callable’
  129 |     threads.push_back(std::thread(thread_dotprod, std::ref(*this), std::ref(mv), (cores-1)*slice, size_, std::ref(t_ans)));
      |                            ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/c++/11/thread:43,
                 from source/matVec.cpp:1:
/usr/include/c++/11/bits/std_thread.h:157:5: note: candidate: ‘std::thread::thread(std::thread&&)’
  157 |     thread(thread&& __t) noexcept
      |     ^~~~~~
/usr/include/c++/11/bits/std_thread.h:157:5: note:   candidate expects 1 argument, 6 provided
/usr/include/c++/11/bits/std_thread.h:121:5: note: candidate: ‘std::thread::thread()’
  121 |     thread() noexcept = default;
      |     ^~~~~~
/usr/include/c++/11/bits/std_thread.h:121:5: note:   candidate expects 0 arguments, 6 provided
source/matVec.cpp:134:32: error: no matching function for call to ‘std::thread::thread(<unresolved overloaded function type>, std::reference_wrapper<const atlib::matVec<int> >, std::reference_wrapper<const atlib::matVec<int> >, unsigned int, unsigned int)’
  134 |         threads.push_back(std::thread(thread_dotprod, std::ref(*this), std::ref(mv), i*slice, (i+1)*slice), std::ref(t_ans));
      |                                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/c++/11/thread:43,
                 from source/matVec.cpp:1:
/usr/include/c++/11/bits/std_thread.h:127:7: note: candidate: ‘template<class _Callable, class ... _Args, class> std::thread::thread(_Callable&&, _Args&& ...)’
  127 |       thread(_Callable&& __f, _Args&&... __args)
      |       ^~~~~~
/usr/include/c++/11/bits/std_thread.h:127:7: note:   template argument deduction/substitution failed:
source/matVec.cpp:134:32: note:   couldn’t deduce template parameter ‘_Callable’
  134 |         threads.push_back(std::thread(thread_dotprod, std::ref(*this), std::ref(mv), i*slice, (i+1)*slice), std::ref(t_ans));
      |                                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/c++/11/thread:43,
                 from source/matVec.cpp:1:
/usr/include/c++/11/bits/std_thread.h:157:5: note: candidate: ‘std::thread::thread(std::thread&&)’
  157 |     thread(thread&& __t) noexcept
      |     ^~~~~~
/usr/include/c++/11/bits/std_thread.h:157:5: note:   candidate expects 1 argument, 5 provided
/usr/include/c++/11/bits/std_thread.h:121:5: note: candidate: ‘std::thread::thread()’
  121 |     thread() noexcept = default;
      |     ^~~~~~
/usr/include/c++/11/bits/std_thread.h:121:5: note:   candidate expects 0 arguments, 5 provided
source/matVec.cpp: In instantiation of ‘T atlib::matVec<T>::operator*(const atlib::matVec<T>&) const [with T = double]’:
./header/matVec.h:57:23:   required from here
source/matVec.cpp:120:31: error: passing ‘const atlib::matVec<double>’ as ‘this’ argument discards qualifiers [-fpermissive]
  120 |             ans += data_[i]*mv[i];
      |                             ~~^
In file included from source/matVec.cpp:4:
./header/matVec.h:28:12: note:   in call to ‘T& atlib::matVec<T>::operator[](std::size_t) [with T = double; std::size_t = long unsigned int]’
   28 |         T& operator[](std::size_t n); //tested
      |            ^~~~~~~~
source/matVec.cpp:129:28: error: no matching function for call to ‘std::thread::thread(<unresolved overloaded function type>, std::reference_wrapper<const atlib::matVec<double> >, std::reference_wrapper<const atlib::matVec<double> >, unsigned int, const size_t&, std::reference_wrapper<double>)’
  129 |     threads.push_back(std::thread(thread_dotprod, std::ref(*this), std::ref(mv), (cores-1)*slice, size_, std::ref(t_ans)));
      |                            ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/c++/11/thread:43,
                 from source/matVec.cpp:1:
/usr/include/c++/11/bits/std_thread.h:127:7: note: candidate: ‘template<class _Callable, class ... _Args, class> std::thread::thread(_Callable&&, _Args&& ...)’
  127 |       thread(_Callable&& __f, _Args&&... __args)
      |       ^~~~~~
/usr/include/c++/11/bits/std_thread.h:127:7: note:   template argument deduction/substitution failed:
source/matVec.cpp:129:28: note:   couldn’t deduce template parameter ‘_Callable’
  129 |     threads.push_back(std::thread(thread_dotprod, std::ref(*this), std::ref(mv), (cores-1)*slice, size_, std::ref(t_ans)));
      |                            ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/c++/11/thread:43,
                 from source/matVec.cpp:1:
/usr/include/c++/11/bits/std_thread.h:157:5: note: candidate: ‘std::thread::thread(std::thread&&)’
  157 |     thread(thread&& __t) noexcept
      |     ^~~~~~
/usr/include/c++/11/bits/std_thread.h:157:5: note:   candidate expects 1 argument, 6 provided
/usr/include/c++/11/bits/std_thread.h:121:5: note: candidate: ‘std::thread::thread()’
  121 |     thread() noexcept = default;
      |     ^~~~~~
/usr/include/c++/11/bits/std_thread.h:121:5: note:   candidate expects 0 arguments, 6 provided
source/matVec.cpp:134:32: error: no matching function for call to ‘std::thread::thread(<unresolved overloaded function type>, std::reference_wrapper<const atlib::matVec<double> >, std::reference_wrapper<const atlib::matVec<double> >, unsigned int, unsigned int)’
  134 |         threads.push_back(std::thread(thread_dotprod, std::ref(*this), std::ref(mv), i*slice, (i+1)*slice), std::ref(t_ans));
      |                                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/c++/11/thread:43,
                 from source/matVec.cpp:1:
/usr/include/c++/11/bits/std_thread.h:127:7: note: candidate: ‘template<class _Callable, class ... _Args, class> std::thread::thread(_Callable&&, _Args&& ...)’
  127 |       thread(_Callable&& __f, _Args&&... __args)
      |       ^~~~~~
/usr/include/c++/11/bits/std_thread.h:127:7: note:   template argument deduction/substitution failed:
source/matVec.cpp:134:32: note:   couldn’t deduce template parameter ‘_Callable’
  134 |         threads.push_back(std::thread(thread_dotprod, std::ref(*this), std::ref(mv), i*slice, (i+1)*slice), std::ref(t_ans));
      |                                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/c++/11/thread:43,
                 from source/matVec.cpp:1:
/usr/include/c++/11/bits/std_thread.h:157:5: note: candidate: ‘std::thread::thread(std::thread&&)’
  157 |     thread(thread&& __t) noexcept
      |     ^~~~~~
/usr/include/c++/11/bits/std_thread.h:157:5: note:   candidate expects 1 argument, 5 provided
/usr/include/c++/11/bits/std_thread.h:121:5: note: candidate: ‘std::thread::thread()’
  121 |     thread() noexcept = default;
      |     ^~~~~~
/usr/include/c++/11/bits/std_thread.h:121:5: note:   candidate expects 0 arguments, 5 provided
make: *** [Makefile:34: objects/matVec.o] Error 1

Aucun commentaire:

Enregistrer un commentaire