#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; #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]; //sum += exp(x[i])*log(y[i]); } return sum; } double scalar_trans(vector const &x, vector const &y) { assert(x.size() == y.size()); // switch off via compile flag: -DNDEBUG vector z(x.size()); 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; } 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; } // ------------------------------------------------------------------ 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) reduction(+:sum) { int tid = omp_get_thread_num(); int nth = omp_get_num_threads(); // manual cyclic distribution for (size_t i = static_cast(tid); i < N; i += static_cast(nth)) { sum += x[i] * y[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) { // determine number of threads that will be used int nth = 1; #pragma omp parallel { #pragma omp master nth = omp_get_num_threads(); } vector result; result.resize(static_cast(n) * static_cast(nth)); // Each thread will fill its own contiguous block [tid*n, tid*n + n) #pragma omp parallel default(none) shared(result,n) { int tid = omp_get_thread_num(); // create local vector and initialize with a pattern (e.g., tid + k) vector local(n); iota(local.begin(), local.end(), tid); // local[k] = tid + k size_t offset = static_cast(tid) * static_cast(n); for (int k = 0; k < n; ++k) { result[offset + static_cast(k)] = local[static_cast(k)]; } } return result; }