Advertisement
Guest User

task-for-matrix-vector-multiplication-and-adding-by-openmp-parallel

a guest
Mar 9th, 2022
178
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.44 KB | None | 0 0
  1. # include <Eigen/Dense>
  2. # include <iostream>
  3.  
  4. // # include <mpc_omp_task_label.h>
  5.  
  6. # define EPSILON 10e-6
  7.  
  8. using Eigen::MatrixXd;
  9. using Eigen::VectorXd;
  10. using std::cout;
  11. using std::cerr;
  12. using std::endl;
  13.  
  14. int
  15. main(int argc, char ** argv)
  16. {
  17.     if (argc != 3)
  18.     {
  19.         cerr << "usage: " << argv[0] << " [n] [m]" << endl;
  20.         return 1;
  21.     }
  22.     int n = atoi(argv[1]);
  23.     int m = atoi(argv[2]);
  24.     # pragma omp parallel
  25.     {
  26.         # pragma omp single
  27.         {
  28.             // random matrices, vector
  29.             MatrixXd A   = MatrixXd::Random(n, n);
  30.             MatrixXd C   = MatrixXd::Random(n, n);
  31.             MatrixXd R   = MatrixXd::Random(n, n);
  32.             MatrixXd D1  = MatrixXd::Random(n, n);
  33.             MatrixXd D2  = MatrixXd::Random(n, n);
  34.             MatrixXd CT  = C.transpose();
  35.             MatrixXd RT  = R.transpose();
  36.             MatrixXd D1T = D1.transpose();
  37.             MatrixXd D2T = D2.transpose();
  38.             VectorXd x   = VectorXd::Random(n);
  39.  
  40.             // sequential result storage
  41.             VectorXd y_seq(n);
  42.             double t0 = omp_get_wtime();
  43.             // MPC_OMP_TASK_SET_LABEL("sequential");
  44.             # pragma omp task if(0) default(shared)
  45.             {
  46.                 y_seq = (A + C + CT + R + RT + D1 + D1T + D2 + D2T) * x;
  47.             }
  48.             double t1 = omp_get_wtime();
  49.             cout << "sequential version took " << (t1 - t0) << " s." << endl;
  50.  
  51.             // taskwait result storage
  52.             VectorXd y_tw(n);
  53.             VectorXd yA(n),yC(n), yCt(n), yR(n), yRt(n), yD1(n), yD1t(n), yD2(n), yD2t(n);
  54.  
  55.             double t2 = omp_get_wtime();
  56.  
  57.             #pragma omp task default(shared)
  58.             yA = A * x;
  59.  
  60.             #pragma omp task default(shared)
  61.             yC = C * x;
  62.  
  63.             #pragma omp task default(shared)
  64.             yCt = CT * x;
  65.  
  66.             #pragma omp task default(shared)
  67.             yR = R * x;
  68.  
  69.             #pragma omp task default(shared)
  70.             yRt = RT * x;
  71.  
  72.             #pragma omp task default(shared)
  73.             yD1 = D1 * x;
  74.  
  75.             #pragma omp task default(shared)
  76.             yD1t = D1T * x;
  77.  
  78.             #pragma omp task default(shared)
  79.             yD2 = D2 * x;
  80.  
  81.             #pragma omp task default(shared)
  82.             yD2t = D2T * x;
  83.  
  84.             #pragma omp taskwait
  85.             y_tw = yA + yC + yCt + yR + yRt + yD1 + yD1t + yD2 + yD2t;
  86.             double t3 = omp_get_wtime();
  87.  
  88.             cout << "taskwait version took " << (t3 - t2) << " s.";
  89.             cout << '(' << ((y_seq - y_tw).norm() < EPSILON ? "SUCCESS" : "FAILURE") << ')';
  90.             cout << endl;
  91.  
  92.             // with task dependences and block operations
  93.             MatrixXd M(n, n);
  94.             VectorXd y_task(n);
  95.  
  96.             // 1 memory address per block
  97.             int b = n / m;
  98.             char Md[m][m];  (void)Md; // 'fake' data dependences
  99.             char yd[m];     (void)yd; // 'fake' data dependences
  100.             int m1, m2;
  101.  
  102.             double t4 = omp_get_wtime();
  103.             for (m1 = 0 ; m1 < m ; ++m1)
  104.             {
  105.                 for (m2 = 0 ; m2 < m ; ++m2)
  106.                 {
  107.                     // MPC_OMP_TASK_SET_LABEL("add(%d, %d)", m1, m2);
  108.                     # pragma omp task default(shared) firstprivate(m1, m2) depend(out: Md[m1][m2]) priority(1)
  109.                     {
  110.                         int b1 = m1 * b;
  111.                         int b2 = m2 * b;
  112.                         int i1 = b1;
  113.                         int i2 = ((b1 + b < n) ? (b1 + b) : n);
  114.                         int j1 = b2;
  115.                         int j2 = ((b2 + b < n) ? (b2 + b) : n);
  116.                         int si = i2 - i1;
  117.                         int sj = j2 - j1;
  118.                         M.block(i1, j1, si, sj) = ( A.block  (i1, j1, si, sj) +
  119.                                                     C.block  (i1, j1, si, sj) +
  120.                                                     CT.block (i1, j1, si, sj) +
  121.                                                     R.block  (i1, j1, si, sj) +
  122.                                                     RT.block (i1, j1, si, sj) +
  123.                                                     D1.block (i1, j1, si, sj) +
  124.                                                     D1T.block(i1, j1, si, sj) +
  125.                                                     D2.block (i1, j1, si, sj) +
  126.                                                     D2T.block(i1, j1, si, sj));
  127.                     }
  128.                 }
  129.             }
  130.             for (m1 = 0 ; m1 < m ; ++m1)
  131.             {
  132.                 // MPC_OMP_TASK_SET_LABEL("mult(%d)", m1);
  133.                 # pragma omp task default(shared) firstprivate(m1) depend(iterator(m2=0:m), in: Md[m1][m2]) depend(out: yd[m1])
  134.                 {
  135.                     int b1 = m1 * b;
  136.                     int i1 = b1;
  137.                     int i2 = ((b1 + b < n) ? (b1 + b) : n);
  138.                     int s  = i2 - i1;
  139.                     y_task.segment(i1, s) = M.block(i1, 0, s, n) * x;
  140.                 }
  141.             }
  142.  
  143.             //MPC_OMP_TASK_SET_LABEL("norm");
  144.             # pragma omp task default(shared) depend(iterator(m2=0:m), in: yd[m2])
  145.             {
  146.                 double t5 = omp_get_wtime();
  147.                 cout << "task version took " << (t5 - t4) << " s.";
  148.                 cout << '(' << ((y_seq - y_task).norm() < EPSILON ? "SUCCESS" : "FAILURE") << ')';
  149.                 cout << endl;
  150.             }
  151.         }
  152.     }
  153.     return 0;
  154. }
  155.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement