Advertisement
3axap_010

AutoVectorization.cpp

Feb 10th, 2021
1,002
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 11.89 KB | None | 0 0
  1. #include <iostream>
  2. #include <vector>
  3. #include <algorithm>
  4. #include <random>
  5. #include <chrono>
  6.  
  7. #define INNER_MAT1_ROWS 8
  8. #define INNER_MAT1_COLS 8
  9. #define INNER_MAT2_COLS 8
  10.  
  11. #define OUTER_MAT1_ROWS 128
  12. #define OUTER_MAT1_COLS 128
  13. #define OUTER_MAT2_COLS 128
  14.  
  15. template <typename T>
  16. static std::ostream& outputMatrix(std::ostream& os, const std::vector<std::vector<T>>& matrix)
  17. {
  18.     os << std::endl;
  19.  
  20.     std::for_each(matrix.cbegin(), matrix.cend(), [&os](const std::vector<T>& row)
  21.     {
  22.         for (const auto& el : row)
  23.         {
  24.             os << el << " ";
  25.         }
  26.  
  27.         os << std::endl;
  28.     });
  29.  
  30.     return os;
  31. }
  32.  
  33. template <typename T>
  34. static void generateRandomRealMatrix(T** matrix, const int m, const int n)
  35. {
  36.     std::random_device rd;
  37.     std::mt19937 generator(rd());
  38.     std::uniform_real_distribution<T> dist(DBL_MIN, DBL_MAX);
  39.  
  40.     for (int i = 0; i < m; i++)
  41.     {
  42.         for (int j = 0; j < n; j++)
  43.         {
  44.             matrix[i][j] = dist(generator);
  45.         }
  46.     }
  47. }
  48.  
  49. template <typename T>
  50. static T** getMatrix(const int rows, const int columns)
  51. {
  52.     T** matrix = new T*[rows];
  53.  
  54.     for (int i = 0; i < rows; i++)
  55.     {
  56.         matrix[i] = new T[columns];
  57.     }
  58.  
  59.     return matrix;
  60. }
  61.  
  62. template <typename T>
  63. static void unvectMulpiply(T** res, T** mat1, T** mat2, const int rows, const int cols)
  64. {
  65.     for (int i = 0; i < rows; i++)
  66.     {
  67.         for (int j = 0; j < rows; j++)
  68.         {
  69. #pragma loop(no_vector)
  70.             for (int k = 0; k < cols; k++)
  71.             {
  72.                 res[i][j] += mat1[i][k] * mat2[k][j];
  73.             }
  74.         }
  75.     }
  76. }
  77.  
  78. template <typename T>
  79. static void vectMultiply(T** __restrict res, T** __restrict mat1, T** __restrict mat2, const int rows, const int cols, const int mat2Cols)
  80. {
  81.     for (int i = 0; i < rows; i++)
  82.     {
  83.         for (int j = 0; j < cols; j++)
  84.         {
  85.             T el = mat1[i][j];
  86.            
  87. #pragma vector aligned
  88. #pragma vector always
  89.             for (int k = 0; k < mat2Cols; k++)
  90.             {
  91.                 res[i][k] += el * mat2[j][k];
  92.             }
  93.         }
  94.     }
  95. }
  96.  
  97. template <typename T>
  98. static bool areEquals(T** mat1, T** mat2, const int rows, const int cols)
  99. {
  100.     for (int i = 0; i < rows; i++)
  101.     {
  102.         for (int j = 0; j < cols; j++)
  103.         {
  104.             if (mat1[i][j] != mat2[i][j])
  105.             {
  106.                 return false;
  107.             }
  108.         }
  109.     }
  110.  
  111.     return true;
  112. }
  113.  
  114. template <typename T>
  115. static void freeMatrix(T** matrix, const int rows)
  116. {
  117.     for (int i = 0; i < rows; i++)
  118.     {
  119.         delete[] matrix[i];
  120.     }
  121.  
  122.     delete[] matrix;
  123. }
  124.  
  125. template <typename Callable, typename ... Args>
  126. auto countTime(Callable function, Args&& ... args)
  127. {
  128.     auto start = std::chrono::high_resolution_clock::now();
  129.  
  130.     function(std::forward<Args>(args)...);
  131.  
  132.     auto finish = std::chrono::high_resolution_clock::now();
  133.  
  134.     return std::chrono::duration_cast<std::chrono::milliseconds>(finish - start).count();
  135. }
  136.  
  137. template <typename T>
  138. static bool _areEquals(T* mat1, T* mat2, const int rows, const int cols)
  139. {
  140.     int index = 0;
  141.  
  142.     for (int i = 0; i < rows; i++)
  143.     {
  144.         index = cols * i;
  145.  
  146.         for (int j = 0; j < cols; j++, index++)
  147.         {
  148.             if (mat1[index] != mat2[index])
  149.             {
  150.                 return false;
  151.             }
  152.         }
  153.     }
  154.  
  155.     return true;
  156. }
  157.  
  158. template <typename T>
  159. static T* _getMatrix(const int rows, const int cols)
  160. {
  161.     return new T[(static_cast<int64_t>(cols)) * (static_cast<int64_t>(rows))];
  162. }
  163.  
  164. template <typename T>
  165. static void _testMultiply(T* res, T* mat1, T* mat2, const int mat1Rows, const int mat1Cols, const int mat2Cols)
  166. {
  167.     int index0 = 0;
  168.     int index1 = 0;
  169.  
  170.     for (int i = 0; i < mat1Rows; i++)
  171.     {
  172.         for (int j = 0; j < mat1Cols; j++)
  173.         {
  174.             index0 = i * mat2Cols + j;
  175.             index1 = i * mat1Cols;
  176.  
  177.             for (int k = 0; k < mat1Cols; k++, index1++)
  178.             {
  179.                 res[index0] += mat1[index1] * mat2[mat2Cols * k + j];
  180.             }
  181.         }
  182.     }
  183. }
  184.  
  185. #pragma optimize("", off)
  186. template <typename T>
  187. static void _unvectMultiply(T** res, T** mat1, T** mat2, const int outerMat1Rows, const int outerMat1Cols, const int outerMat2Cols,
  188.                                                          const int innerMat1Rows, const int innerMat1Cols, const int innerMat2Cols)
  189. {
  190.     // mat1Cols == mat2Rows
  191.     // res.Rows == mat1Rows
  192.     // res.Cols == mat2Cols
  193.  
  194.     const int innerMatrixSize = innerMat1Rows * innerMat2Cols;
  195.     T* m = _getMatrix<T>(innerMat1Rows, innerMat2Cols);
  196.     T* r  = nullptr;
  197.     T* m1 = nullptr;
  198.     T* m2 = nullptr;
  199.     int index = 0;
  200.  
  201. #pragma loop(no_vector)
  202.     for (int oi = 0; oi < outerMat1Rows; oi++)
  203.     {
  204. #pragma loop(no_vector)
  205.         for (int oj = 0; oj < outerMat2Cols; oj++)
  206.         {
  207.             r = res[outerMat2Cols * oi + oj];
  208.  
  209. #pragma loop(no_vector)
  210.             for (int ok = 0; ok < outerMat1Cols; ok++)
  211.             {
  212.                 // res[i][j] += mat1[i][k] * mat2[k][j];
  213.  
  214.                 m1 = mat1[outerMat1Cols * oi + ok]; // inner matrix1
  215.                 m2 = mat2[outerMat2Cols * ok + oj]; // inner matrix2
  216.                 std::memset(m, 0, sizeof(T) * innerMatrixSize);
  217.  
  218. #pragma loop(no_vector)
  219.                 for (int ii = 0; ii < innerMat1Rows; ii++)
  220.                 {
  221. #pragma loop(no_vector)
  222.                     for (int ij = 0; ij < innerMat2Cols; ij++)
  223.                     {
  224. #pragma loop( no_vector )
  225.                         for (int ik = 0; ik < innerMat1Cols; ik++)
  226.                         {
  227.                             m[ii * innerMat2Cols + ij] += m1[innerMat1Cols * ii + ik] * m2[innerMat2Cols * ik + ij];
  228.                         }
  229.                     }
  230.                 }
  231.  
  232. #pragma loop(no_vector)
  233.                 for (int i = 0; i < innerMat1Rows; i++)
  234.                 {
  235.                     index = i * innerMat2Cols;
  236.  
  237. #pragma loop(no_vector)
  238.                     for (int j = 0; j < innerMat2Cols; j++, index++)
  239.                     {                      
  240.                         r[index] += m[index];
  241.                     }
  242.                 }
  243.             }
  244.         }
  245.     }
  246. }
  247. #pragma optimize("", on)
  248.  
  249. template <typename T>
  250. static void _vectMultiply(T** __restrict res, T** __restrict mat1, T** __restrict mat2,
  251.                           const int outerMat1Rows, const int outerMat1Cols, const int outerMat2Cols,
  252.                           const int innerMat1Rows, const int innerMat1Cols, const int innerMat2Cols)
  253. {
  254.     T* m1 = nullptr;
  255.     T* m2 = nullptr;
  256.     T* r  = nullptr;
  257.     T* m  = _getMatrix<T>(innerMat1Rows, innerMat2Cols);
  258.  
  259.     for (int oi = 0; oi < outerMat1Rows; oi++)
  260.     {
  261.         for (int oj = 0; oj < outerMat1Cols; oj++)
  262.         {
  263.             m1 = mat1[outerMat1Cols * oi + oj];
  264.  
  265.             for (int ok = 0; ok < outerMat2Cols; ok++)
  266.             {
  267.                 // res[i][k] += m1 * mat2[j][k]
  268.  
  269.                 r = res[outerMat2Cols * oi + ok];
  270.                 m2 = mat2[outerMat2Cols * oj + ok];
  271.                 std::memset(m, 0, sizeof(T) * innerMat1Rows * innerMat2Cols);
  272.  
  273.                 for (int ii = 0; ii < innerMat1Rows; ii++)
  274.                 {
  275.                     for (int ij = 0; ij < innerMat1Cols; ij++)
  276.                     {
  277.                         const T el = m1[innerMat1Cols * ii + ij];
  278.  
  279.                         for (int ik = 0; ik < innerMat2Cols; ik++)
  280.                         {
  281.                             m[innerMat2Cols * ii + ik] += el * m2[innerMat2Cols * ij + ik];
  282.                         }
  283.                     }
  284.                 }
  285.  
  286.                 for (int i = 0; i < innerMat1Rows; i++)
  287.                 {
  288.                     for (int j = 0; j < innerMat2Cols; j++)
  289.                     {
  290.                         r[innerMat2Cols * i + j] += m[innerMat2Cols * i + j];
  291.                     }
  292.                 }
  293.             }
  294.         }
  295.     }
  296. }
  297.  
  298. template <typename T>
  299. static void _intrinsicMultiply(T** __restrict res, T** __restrict mat1, T** __restrict mat2,
  300.                                const int outerMat1Rows, const int outerMat1Cols, const int outerMat2Cols,
  301.                                const int innerMat1Rows, const int innerMat1Cols, const int innerMat2Cols)
  302. {
  303.     T* m1 = nullptr;
  304.     T* m2 = nullptr;
  305.     T* r = nullptr;
  306.     T* m = _getMatrix<T>(innerMat1Rows, innerMat2Cols);
  307.  
  308.     for (int oi = 0; oi < outerMat1Rows; oi++)
  309.     {
  310.         for (int oj = 0; oj < outerMat1Cols; oj++)
  311.         {
  312.             m1 = mat1[outerMat1Cols * oi + oj];
  313.  
  314.             for (int ok = 0; ok < outerMat2Cols; ok++)
  315.             {
  316.                 // res[i][k] += m1 * mat2[j][k]
  317.  
  318.                 r = res[outerMat2Cols * oi + ok];
  319.                 m2 = mat2[outerMat2Cols * oj + ok];
  320.                 std::memset(m, 0, sizeof(T) * innerMat1Rows * innerMat2Cols);
  321.  
  322.                 for (int ii = 0; ii < innerMat1Rows; ii++)
  323.                 {
  324.                     for (int ij = 0; ij < innerMat1Cols; ij++)
  325.                     {
  326.                         const T el = m1[innerMat1Cols * ii + ij];
  327.  
  328.                         for (int ik = 0; ik < innerMat2Cols; ik++)
  329.                         {
  330.                             m[innerMat2Cols * ii + ik] += el * m2[innerMat2Cols * ij + ik];
  331.                         }
  332.                     }
  333.                 }
  334.  
  335.                 for (int i = 0; i < innerMat1Rows; i++)
  336.                 {
  337.                     for (int j = 0; j < innerMat2Cols; j++)
  338.                     {
  339.                         r[innerMat2Cols * i + j] += m[innerMat2Cols * i + j];
  340.                     }
  341.                 }
  342.             }
  343.         }
  344.     }
  345. }
  346.  
  347. template <typename T>
  348. static void _generateRandRealMatrix(T* m, const int rows, const int cols)
  349. {
  350.     std::random_device rd;
  351.     std::mt19937 generator(rd());
  352.     std::uniform_real_distribution<T> dist(DBL_MIN, DBL_MAX);
  353.  
  354.     for (int i = 0; i < rows; i++)
  355.     {
  356.         int index = cols * i;
  357.  
  358.         for (int j = 0; j < cols; j++, index++)
  359.         {
  360.             m[index] = dist(generator);
  361.         }
  362.     }
  363. }
  364.  
  365. template <typename T>
  366. static T** _getMatrixOfMatrixes(const int outerRows, const int outerCols, const int innerRows, const int innerCols, bool genRandomReal = true)
  367. {
  368.     T** matrix = new T*[(static_cast<int64_t>(outerCols)) * (static_cast<int64_t>(outerRows))];
  369.     const int innerSize = innerRows * innerCols;
  370.  
  371.     for (int i = 0; i < outerRows; i++)
  372.     {
  373.         int index = outerCols * i;
  374.  
  375.         for (int j = 0; j < outerCols; j++, index++)
  376.         {
  377.             matrix[index] = new T[innerSize];
  378.  
  379.             if (genRandomReal)
  380.             {
  381.                 _generateRandRealMatrix(matrix[index], innerRows, innerCols);
  382.             }
  383.         }
  384.     }
  385.  
  386.     return matrix;
  387. }
  388.  
  389. template <typename T>
  390. static void deleteMatrixOfMatrixes(T** matrix, const int outerRows, const int outerCols, const int innerRows, const int innerCols)
  391. {
  392.     for (int i = 0; i < outerRows; i++)
  393.     {
  394.         int index = outerCols * i;
  395.  
  396.         for (int j = 0; j < outerCols; j++, index++)
  397.         {
  398.             delete[] matrix[index];
  399.         }
  400.     }
  401.  
  402.     delete[] matrix;
  403. }
  404.  
  405. template <typename T>
  406. static bool areEqualMatrixesOfMatrixes(T** mat1, T** mat2, const int outerRows, const int outerCols, const int innerRows, const int innerCols)
  407. {
  408.     T* m1 = nullptr;
  409.     T* m2 = nullptr;
  410.  
  411.     for (int oi = 0; oi < outerRows; oi++)
  412.     {
  413.         for (int oj = 0; oj < outerCols; oj++)
  414.         {
  415.             m1 = mat1[outerCols * oi + oj];
  416.             m2 = mat2[outerCols * oi + oj];
  417.  
  418.             for (int ii = 0; ii < innerRows; ii++)
  419.             {
  420.                 for (int ij = 0; ij < innerCols; ij++)
  421.                 {
  422.                     if (m1[innerCols * ii + ij] != m2[innerCols * ii + ij])
  423.                     {
  424.                         return false;
  425.                     }
  426.                 }
  427.             }
  428.         }
  429.     }
  430.  
  431.     return true;
  432. }
  433.  
  434. int main()
  435. {
  436.     double** mat1 = _getMatrixOfMatrixes<double>(OUTER_MAT1_ROWS, OUTER_MAT1_COLS, INNER_MAT1_ROWS, INNER_MAT1_COLS);
  437.     double** mat2 = _getMatrixOfMatrixes<double>(OUTER_MAT1_COLS, OUTER_MAT2_COLS, INNER_MAT1_COLS, INNER_MAT2_COLS);
  438.     double** res  = _getMatrixOfMatrixes<double>(OUTER_MAT1_ROWS, OUTER_MAT2_COLS, INNER_MAT1_ROWS, INNER_MAT2_COLS, false);
  439.     double** res1 = _getMatrixOfMatrixes<double>(OUTER_MAT1_ROWS, OUTER_MAT2_COLS, INNER_MAT1_ROWS, INNER_MAT2_COLS, false);
  440.     //double** res2 = _getMatrixOfMatrixes<double>(OUTER_MAT1_ROWS, OUTER_MAT2_COLS, INNER_MAT1_ROWS, INNER_MAT2_COLS, false);
  441.  
  442.     std::cout <<
  443.         countTime<decltype(_vectMultiply<double>)>(_vectMultiply, res1, mat1, mat2, OUTER_MAT1_ROWS, OUTER_MAT1_COLS, OUTER_MAT2_COLS, INNER_MAT1_ROWS, INNER_MAT1_COLS, INNER_MAT2_COLS) << std::endl;
  444.  
  445.     std::cout << countTime<decltype(_unvectMultiply<double>)>(_unvectMultiply, res, mat1, mat2, OUTER_MAT1_ROWS, OUTER_MAT1_COLS, OUTER_MAT2_COLS, INNER_MAT1_ROWS, INNER_MAT1_COLS, INNER_MAT2_COLS) << std::endl;
  446.     //_vectMultiply(res1, mat1, mat2, OUTER_MAT1_ROWS, OUTER_MAT1_COLS, OUTER_MAT2_COLS, INNER_MAT1_ROWS, INNER_MAT1_COLS, INNER_MAT2_COLS);
  447.     //_unvectMultiply(res, mat1, mat2, OUTER_MAT1_ROWS, OUTER_MAT1_COLS, OUTER_MAT2_COLS, INNER_MAT1_ROWS, INNER_MAT1_COLS, INNER_MAT2_COLS);
  448.  
  449.     //_intrinsicMultiply(res2, mat1, mat2, OUTER_MAT1_ROWS, OUTER_MAT1_COLS, OUTER_MAT2_COLS, INNER_MAT1_ROWS, INNER_MAT1_COLS, INNER_MAT2_COLS);
  450.  
  451.     std::cout << areEqualMatrixesOfMatrixes(res, res1, OUTER_MAT1_ROWS, OUTER_MAT1_COLS, INNER_MAT1_ROWS, INNER_MAT2_COLS) << std::endl;
  452.     //std::cout << areEqualMatrixesOfMatrixes(res1, res2, OUTER_MAT1_ROWS, OUTER_MAT1_COLS, INNER_MAT1_ROWS, INNER_MAT2_COLS) << std::endl;
  453.  
  454.     deleteMatrixOfMatrixes(mat1, OUTER_MAT1_ROWS, OUTER_MAT1_COLS, INNER_MAT1_ROWS, INNER_MAT1_COLS);
  455.     deleteMatrixOfMatrixes(mat2, OUTER_MAT1_COLS, OUTER_MAT2_COLS, INNER_MAT1_COLS, INNER_MAT2_COLS);
  456.     deleteMatrixOfMatrixes(res, OUTER_MAT1_ROWS, OUTER_MAT2_COLS, INNER_MAT1_ROWS, INNER_MAT2_COLS);
  457.     deleteMatrixOfMatrixes(res1,  OUTER_MAT1_ROWS, OUTER_MAT2_COLS, INNER_MAT1_ROWS, INNER_MAT2_COLS);
  458.     //deleteMatrixOfMatrixes(res2, OUTER_MAT1_ROWS, OUTER_MAT2_COLS, INNER_MAT1_ROWS, INNER_MAT2_COLS);
  459.    
  460.     return 0;
  461. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement