Achek

AVS

Nov 30th, 2020
57
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 7.34 KB | None | 0 0
  1. #include <iostream>
  2. #include <vector>
  3. #include <cmath>
  4. #include <fstream>
  5. #include <ctime>
  6. #include "omp.h"
  7.  
  8. using namespace std;
  9.  
  10. // Функция ищет максимальный элемент в {col} столбце матрицы {matrix}.
  11. int col_max(const vector<vector<double>>& matrix, int col) {
  12.     int n = matrix.size();
  13.     double max = abs(matrix[col][col]);
  14.     int maxPos = col;
  15.  
  16.     #pragma omp parallel shared(matrix)
  17.     {
  18.         // локальный максимум в потоке.
  19.         double loc_max = max;
  20.         int loc_max_pos = maxPos;
  21.         #pragma omp for
  22.         for (int i = col + 1; i < n; ++i) {
  23.             double element = abs(matrix[i][col]);
  24.             if (element > loc_max) {
  25.                 loc_max = element;
  26.                 loc_max_pos = i;
  27.             }
  28.         }
  29.         #pragma omp critical    // ищем максимум среди всех потоков.
  30.         {
  31.             if (max < loc_max) {
  32.                 max = loc_max;
  33.                 maxPos = loc_max_pos;
  34.             }
  35.         }
  36.     }
  37.     return maxPos;
  38. }
  39.  
  40. int col_maxSimple (const vector<vector<double>>& matrix, int col) {
  41.     int n = matrix.size();
  42.     double max = abs(matrix[col][col]);
  43.     int maxPos = col;
  44.  
  45.     //#pragma omp parallel shared(matrix)
  46.     {
  47.         // локальный максимум в потоке.
  48.         double loc_max = max;
  49.         int loc_max_pos = maxPos;
  50.         //#pragma omp for
  51.         for (int i = col + 1; i < n; ++i) {
  52.             double element = abs(matrix[i][col]);
  53.             if (element > loc_max) {
  54.                 loc_max = element;
  55.                 loc_max_pos = i;
  56.             }
  57.         }
  58.         //#pragma omp critical  // ищем максимум среди всех потоков.
  59.         {
  60.             if (max < loc_max) {
  61.                 max = loc_max;
  62.                 maxPos = loc_max_pos;
  63.             }
  64.         }
  65.     }
  66.     return maxPos;
  67. }
  68.  
  69. // Функция меняет местами {origin} и {sub} строки матрицы.
  70. void swap(vector<vector<double>>& matrix, int origin, int sub) {
  71.     vector<double> temp = matrix[origin];
  72.     matrix[origin] = matrix[sub];
  73.     matrix[sub] = temp;
  74. }
  75.  
  76. // Функция, вычитающая i-ю строку из остальных строк, находящихся ниже неё так, чтобы i-й элемент каждой строки был равен 0.
  77. void elementaryСonversion(vector<vector<double>>& matrix, int mainRow) {
  78.     int n = matrix.size();
  79.  
  80.     // параллельно вычитаем {mainRow} строку из всех строк, ниже неё.
  81.     #pragma omp parallel for
  82.     for (int j = mainRow + 1; j < n; ++j) {
  83.         // множитель для {mainRow} строки.
  84.         double mul = -matrix[j][mainRow] / matrix[mainRow][mainRow];
  85.         for (int k = mainRow; k < n; ++k)
  86.             matrix[j][k] += matrix[mainRow][k] * mul;
  87.     }
  88.  
  89. }
  90.  
  91. void elementaryСonversionSimple(vector<vector<double>>& matrix, int mainRow) {
  92.     int n = matrix.size();
  93.  
  94.     // параллельно вычитаем {mainRow} строку из всех строк, ниже неё.
  95.     //#pragma omp parallel for
  96.     for (int j = mainRow + 1; j < n; ++j) {
  97.         // множитель для {mainRow} строки.
  98.         double mul = -matrix[j][mainRow] / matrix[mainRow][mainRow];
  99.         for (int k = mainRow; k < n; ++k)
  100.             matrix[j][k] += matrix[mainRow][k] * mul;
  101.     }
  102.  
  103. }
  104.  
  105. // Функция, приводящая матрицу, переданную в неё к треугольному виду.
  106. void triangulation(vector<vector<double>> &matrix) {
  107.     int n = matrix.size();
  108.  
  109.     // проходимся по всей матрице.
  110.     for (int i = 0; i < n; ++i) {
  111.  
  112.         // находим строку, в которой i-й элемент самый большой в своем столбце.
  113.         // ПАРАЛЛЕЛЬНО.
  114.         int sub = col_max(matrix, i);
  115.  
  116.  
  117.         // меняем найденную строку с i-й местами.
  118.         swap(matrix, i, sub);
  119.  
  120.  
  121.         // вычитаем i-ю строку из остальных строк, находящихся ниже неё так чтобы i-й элемент каждой строки был равен 0.
  122.         // ПАРАЛЛЕЛЬНО.
  123.         elementaryСonversion(matrix, i);
  124.     }
  125. }
  126.  
  127. void triangulationSimple(vector<vector<double>>& matrix) {
  128.     int n = matrix.size();
  129.  
  130.     // проходимся по всей матрице.
  131.     for (int i = 0; i < n; ++i) {
  132.  
  133.         // находим строку, в которой i-й элемент самый большой в своем столбце.
  134.         // ПАРАЛЛЕЛЬНО.
  135.         int sub = col_maxSimple(matrix, i);
  136.  
  137.  
  138.         // меняем найденную строку с i-й местами.
  139.         swap(matrix, i, sub);
  140.  
  141.  
  142.         // вычитаем i-ю строку из остальных строк, находящихся ниже неё так чтобы i-й элемент каждой строки был равен 0.
  143.         // ПАРАЛЛЕЛЬНО.
  144.         elementaryСonversionSimple(matrix, i);
  145.     }
  146. }
  147.  
  148. // Функция, вычисляющая определитель переданной в нее матрицы.
  149. int calculateGaussDeterminant(vector<vector<double>> matrix) {
  150.     int n = matrix.size();
  151.  
  152.     // приводим матрицу к треугольному виду.
  153.     triangulation(matrix);
  154.  
  155.     // подсчитываем определитель.
  156.     double det = 1;
  157.     #pragma omp parallel reduction (*: det)
  158.     {
  159.         # pragma omp for
  160.         for (int i = 0; i < n; ++i)
  161.             det *= matrix[i][i];
  162.        
  163.     }
  164.     return round(det);
  165. }
  166.  
  167. int calculateGaussDeterminantSimple(vector<vector<double>> matrix) {
  168.     int n = matrix.size();
  169.  
  170.     // приводим матрицу к треугольному виду.
  171.     triangulationSimple(matrix);
  172.  
  173.     // подсчитываем определитель.
  174.     double det = 1;
  175.     //#pragma omp parallel reduction (*: det)
  176.     {
  177.         //# pragma omp for
  178.         for (int i = 0; i < n; ++i)
  179.             det *= matrix[i][i];
  180.  
  181.     }
  182.     return round(det);
  183. }
  184.  
  185.  
  186. // Функция, читающая матрицу {matrix} из файла.
  187. void readMatrixFromFile(vector<vector<double>>& matrix, ifstream& input) {
  188.     // первая строка в файле - размерность матрицы.
  189.     int n = matrix[0].size();
  190.  
  191.     for (int i = 0; i < n; ++i) {
  192.         for (int j = 0; j < n; ++j) {
  193.             input >> matrix[i][j];
  194.         }
  195.     }
  196. }
  197.  
  198. double checkTime(bool isMP, vector<vector<double>> matrix, int &determinant) {
  199.     int start = clock();
  200.  
  201.     if (isMP) {
  202.         // запускаем многопоточную версию функции вычисления определителя методом Гаусса.
  203.         determinant = calculateGaussDeterminant(matrix);
  204.     }
  205.     else {
  206.         determinant = calculateGaussDeterminantSimple(matrix);
  207.     }
  208.     int end = clock();
  209.  
  210.     return (double)(end - start) / CLOCKS_PER_SEC;
  211. }
  212.  
  213. int main(int argc, char* argv[]) {
  214.  
  215.     ifstream input;
  216.     ofstream output;
  217.     input.open(argv[1]);
  218.     output.open(argv[2]);
  219.  
  220.     int n;
  221.     input >> n;
  222.  
  223.     // инициализируем матрицу с которой будем работать.
  224.     vector<vector<double>> matrix(n, vector<double>(n));
  225.  
  226.     // считываем матрицу из файла с именем {argv[1]}.
  227.     readMatrixFromFile(matrix, input);
  228.  
  229.     int determinant = 0;
  230.     double time1 = checkTime(true, matrix, determinant);
  231.     double time2 = checkTime(false, matrix, determinant);
  232.  
  233.     output << "При размере матрицы == " << n << endl;
  234.     output << "Определитель == " << determinant << endl;
  235.     output << "Время работы обычной программы : " << time2 << " cек." << endl;
  236.     output << "Время работы многопоточной программы : " << time1 << " cек.";
  237. }
Add Comment
Please, Sign In to add comment