Advertisement
Guest User

Untitled

a guest
Nov 14th, 2019
95
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.16 KB | None | 0 0
  1.  
  2. /* 10. Вычисление обратной матрицы для заданной матрицы*/
  3.  
  4.  
  5. #include <cuda.h>
  6. #include <cuda_runtime.h>
  7. #include "device_launch_parameters.h"
  8. #include <time.h>
  9. #include <iostream>
  10. #include <fstream>
  11. #include <stdlib.h>
  12. #include <stdio.h>
  13. using namespace std;
  14.  
  15. double *createMass1(double *mass, int x, int y, int N) //создание подматрицы путем вычеркивания столбца и строки
  16. {
  17. double *mass1 = new double[N*N];
  18. int mi = 0;
  19. for (int i = 0; i < N*N; i++, mi++)
  20. {
  21. while (mi / (N + 1) == x || mi % (N + 1) == y)
  22. mi++;
  23. mass1[i] = mass[mi];
  24. }
  25. return mass1;
  26. }
  27.  
  28. __device__ double* createMass( double *mass, int x, int y, int N)
  29. {
  30. double *mass1 = new double[N*N];
  31. int mi = 0;
  32. for (int i = 0; i < N*N; i++, mi++)
  33. {
  34. while (mi / (N + 1) == x || mi % (N + 1) == y)
  35. mi++;
  36. mass1[i] = mass[mi];
  37. }
  38. return mass1;
  39. }
  40.  
  41. double determinant1( double *mass, int N)
  42. {
  43. double determ = 1;
  44. for (int i = 0; i < N*N; i += (N + 1)) //идем по диагонали
  45. {
  46. bool d = false;
  47. for (int j = i; j < N*N; j += i%N)
  48. {
  49. double first = mass[j]; // Выбираем первый слева столбец матрицы
  50. determ *= first;
  51. do
  52. {
  53. mass[j] /= first; //Все элементы первой строки делят на верхний элемент выбранного столбца
  54. if (d)
  55. mass[j] -= mass[i + (j%N - i%N)]; //вычеркивается первая строка и первый столбец
  56. j++;
  57.  
  58. } while (j % N);
  59. d = true;
  60. }
  61. }
  62. return determ;
  63. }
  64.  
  65. __device__ double determinant(double *mass, int N)
  66. {
  67. double determ = 1;
  68. for (int i = 0; i < N*N; i += (N + 1)) //идем по диагонали
  69. {
  70. bool d = false;
  71. for (int j = i; j < N*N; j += i%N) // от текущего элемента главной диагонали до последней строки
  72. {
  73. double first = mass[j];// Выбираем первый слева столбец матрицы
  74. determ *= first;
  75. do
  76. {
  77. mass[j] /= first; //Все элементы первой строки делят на верхний элемент выбранного столбца
  78. if (d)
  79. mass[j] -= mass[i + (j%N - i%N)]; //вычеркивается первая строка и первый столбец
  80. j++;
  81.  
  82. } while (j % N);
  83. d = true;
  84. }
  85. }
  86. return determ;
  87. }
  88.  
  89. __global__ void division(int i, double m, double *mass)
  90. {
  91. mass[threadIdx.x + i] /= m;
  92.  
  93. }
  94.  
  95. __global__ void subtraction(int i, int j, double *mass)
  96. {
  97. mass[threadIdx.x + i] -= mass[threadIdx.x + j];
  98. }
  99.  
  100. double deter(int N, double *mass)
  101. {
  102. double *mass1 = 0;
  103. // Выделение памяти GPU
  104. cudaMalloc((void**)&mass1, N * N * sizeof(double));
  105. // Скопировать входные данные в GPU для обработки
  106. cudaMemcpy(mass1, mass, N * N * sizeof( double), cudaMemcpyHostToDevice);
  107. double determ = 1;
  108. for (int i = 0; i < N*N; i += (N + 1))
  109. {
  110. bool d = false;
  111. int j, k;
  112. k = j = i;
  113. do
  114. {
  115. determ *= mass[k]; // Выбираем первый слева столбец матрицы
  116. division <<<1, (N - i%N) >>>((i + N*(j - i)), mass[k], mass1);
  117. if (d)
  118. subtraction <<<1, (N - i%N) >>>((i + N*(j - i)), i, mass1);
  119. d = true;
  120. j++;
  121. k += N;
  122.  
  123. } while (j % N);
  124. // Переписать результаты работы GPU в память CPU:
  125. cudaMemcpy(mass, mass1, N * N * sizeof( double), cudaMemcpyDeviceToHost);
  126. }
  127. return determ;
  128. }
  129.  
  130. void start1( double *mass, double *temp, int N, double *d)
  131. {
  132. double det = determinant1(d, N);//вычисление детерминанта исходной матрицы
  133. if (det == 0)
  134. {
  135. cout << "Obratnoy matrici ne suchestvuet" << endl;
  136. return;
  137. }
  138. for (int p = 0; p < N*N; p++)
  139. {
  140. int i = p;
  141. int j = i / N;
  142. i = i % N;
  143. //создание подматрицы путем вычеркивания i-ого и j-ого столбца для нахождения минора
  144. double* A = createMass1(mass, i, j, N - 1);
  145. //нахождение алгебраического дополнения и деление его на определитель
  146. temp[p] = (determinant1(A, N - 1) * ((2 + i + j) % 2 ? -1 : 1)) / det;
  147. delete[]A;
  148. }
  149. }
  150.  
  151. __global__ void transp(double *mass, double det, int N)
  152. {
  153. int k = blockIdx.x * blockDim.x + threadIdx.x;
  154. mass[k] *= ((2 + (k % N) + (k / N)) % 2 ? -1 : 1);
  155. mass[k] /= det;
  156. }
  157.  
  158. __global__ void comp( double *mass, double *temp, int N, double det)
  159. {
  160. int i = threadIdx.x%N;
  161. int j = threadIdx.x / N;
  162. double* A = createMass(mass, i, j, N - 1);
  163. temp[threadIdx.x] = determinant(A, N - 1);
  164. delete[]A;
  165. }
  166.  
  167.  
  168. void start( double *mass, double *temp, int N, double *d)
  169. {
  170. size_t free, total;
  171. printf("\n");
  172.  
  173. cudaMemGetInfo(&free,&total);
  174.  
  175. printf("%d KB free of total %d KB\n",free/1024,total/1024);
  176.  
  177. if (N >= 32)
  178. {
  179. cout << "Matrica vichodit za granici pamyati GPU adaptera" << endl;
  180. return;
  181. }
  182.  
  183. double det = deter(N, d);
  184. if (det == 0)
  185. {
  186. cout << "Obratnoy matrici ne suchestvuet" << endl;
  187. return;
  188. }
  189. double *temp1 = 0, *mass1 = 0;
  190. // Выделение памяти GPU
  191. cudaMalloc((void**)&temp1, N * N * sizeof(double));
  192. cudaMalloc((void**)&mass1, N * N * sizeof(double));
  193. // Скопировать входные данные в GPU для обработки
  194. cudaMemcpy(mass1, mass, N * N * sizeof(double), cudaMemcpyHostToDevice);
  195. // Инициализация ядра в GPU
  196. comp<<< 1, N*N >>>(mass1, temp1, N, det);
  197. transp<<< 1, N*N >>>(temp1, det, N);
  198. // Переписать результаты работы GPU в память CPU:
  199. cudaMemcpy(temp, temp1, N * N * sizeof(double), cudaMemcpyDeviceToHost);
  200. cudaFree(temp1);
  201. cudaFree(mass1);
  202. }
  203.  
  204. bool compare(double *mass1, double *mass2, int N)
  205. {
  206. for (int i = 0; i < N; i++)
  207. {
  208. if (mass1[i] != mass2[i])
  209. return false;
  210. }
  211. return true;
  212. }
  213.  
  214. int main()
  215. {
  216. setlocale(LC_CTYPE, "rus");
  217. srand(time(0));
  218. int N;
  219. cout << "Vvedite razmer matrici: ";
  220. cin >> N;
  221. double *mass = new double[N*N];
  222. double *temp = new double[N*N];
  223. double *_mass = new double[N*N];
  224. double *_temp = new double[N*N];
  225. double *d = new double[N*N];
  226. double *_d = new double[N*N];
  227.  
  228. for (int i = 0; i < N*N; i++)
  229. mass[i] = _mass[i] = d[i] = _d[i] = ((double)rand()) / 100000;
  230.  
  231.  
  232.  
  233. double t1 = clock();
  234. start(mass, temp, N, d);
  235. t1 = clock() - t1;
  236. cout << endl << endl << "Parallel: " << t1 / CLOCKS_PER_SEC << " sec." << endl;
  237.  
  238. double t = clock();
  239. start1(_mass, _temp, N, _d);
  240. t = clock() - t;
  241. cout << endl << "Posledovat: " << t / CLOCKS_PER_SEC << " sec." << endl;
  242.  
  243. if (t - t1 > 0)
  244. cout << endl << endl << "Parallel bystree posledovat v " << int(t / t1) << " raz." << endl;
  245. else
  246. cout << endl << endl << "Parallel medlennee posledovat v " << int(t1 / t) << " raz." << endl;
  247.  
  248. if (compare(temp, _temp, N))
  249. cout << endl << "Resultat identichni!" << endl << endl;
  250. else
  251. cout << endl << "Resultat razlichni!" << endl << endl;
  252.  
  253. delete[]temp;
  254. delete[]mass;
  255. delete[]_temp;
  256. delete[]_mass;
  257. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement