#include "mylib.h" #include // assert() #include #include #include // multiplies<>{} #include #include // iota() #ifdef _OPENMP #include #endif #include using namespace std; double scalar(vector const &x, vector const &y) { assert(x.size() == y.size()); // switch off via compile flag: -DNDEBUG size_t const N = x.size(); double sum = 0.0; // int check; // for using omp_in_parallel //#pragma omp parallel for default(none) shared(x,y,N,check) reduction(+:sum) #pragma omp parallel for default(none) shared(x,y,N) reduction(+:sum) for (size_t i = 0; i < N; ++i) { sum += x[i] * y[i]; // check = omp_in_parallel(); //sum += exp(x[i])*log(y[i]); } // cout << "in parallel: " << check << endl; return sum; } double scalar_manual(vector const &x, vector const &y) { assert(x.size() == y.size()); size_t const N = x.size(); double sum = 0.0; #pragma omp parallel default(none) shared(x,y,N,sum) { int tid = omp_get_thread_num(); int nt = omp_get_num_threads(); // manual splitting of the index area size_t start = (N * tid) / nt; size_t end = (N * (tid+1)) / nt; double local_sum = 0.0; for (size_t i = start; i < end; ++i) { local_sum += x[i] * y[i]; } // local subtotal combined to global sum #pragma omp atomic sum += local_sum; } return sum; } double norm(vector const &x) { size_t const N = x.size(); double sum = 0.0; #pragma omp parallel for default(none) shared(x,N) reduction(+:sum) for (size_t i = 0; i < N; ++i) { sum += x[i]*x[i]; } return sum; } vector reduction_vec(int n) { vector vec(n); #pragma omp parallel default(none) shared(cout) reduction(VecAdd:vec) { #pragma omp barrier #pragma omp critical cout << omp_get_thread_num() << " : " << vec.size() << endl; #pragma omp barrier iota( vec.begin(),vec.end(), omp_get_thread_num() ); #pragma omp barrier } return vec; } vector reduction_vec_append(int n) { vector vec; #pragma omp parallel default(none) shared(n,cout) reduction(VecAppend:vec) { std::vector local(n); // local vector of each thread // consecutive numbers starting from thread ID iota(local.begin(), local.end(), omp_get_thread_num()); // output for checking #pragma omp critical cout << "Thread " << omp_get_thread_num() << " local size = " << local.size() << std::endl; // append local to vec vec.insert(vec.end(), local.begin(), local.end()); } return vec; } double scalar_trans(vector const &x, vector const &y) { assert(x.size() == y.size()); // switch off via compile flag: -DNDEBUG vector z(x.size()); //list z(x.size()); // parallel for-loop on iterators not possible (missing 'operator-') // c++-20 CLANG_, ONEAPI_:condition of OpenMP for loop must be a relational comparison transform(cbegin(x),cend(x),cbegin(y),begin(z),std::multiplies<>{}); double sum = 0.0; #pragma omp parallel for default(none) shared(z) reduction(+:sum) for (auto pi = cbegin(z); pi!=cend(z); ++pi) { sum += *pi; } //for (auto val: z) //{ //sum += val; //} return sum; }