Guest User

Untitled

a guest
Jun 24th, 2018
97
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 13.81 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <conio.h>
  3. #include <stdlib.h>
  4. #include <math.h>
  5.  
  6. #include <mpi.h>
  7.  
  8. #define DIM 8
  9.  
  10. /*****************************************************************************/
  11. /*
  12. Вычисление факториала.
  13. x - .
  14. функция возвращает факториал числа x. (x!)
  15. */
  16. int fact( int x )
  17. {
  18. int i, res = 1;
  19. for( i = 2; i <= x; i++ )
  20. res *= i;
  21. return res;
  22. }
  23. /*
  24. Вычисление числа сочетаний C sup n sub m.
  25. n - .
  26. m - .
  27. функция возвращает число сочетаний из n по m.
  28. */
  29. int CNM( int n, int m )
  30. { return fact( n ) / (fact( m ) * fact( n - m )); }
  31. /*****************************************************************************/
  32. /*
  33. Печать матрицы на экран.
  34. M - исходная матрица.
  35. функция не имеет возвращаемого значения.
  36. */
  37. void MPrint( double M[DIM][DIM] )
  38. {
  39. int i, j;
  40. printf( " Matrix\n " );
  41. for( i = 0; i < DIM; i++ )
  42. {
  43. printf( " " );
  44. for( j = 0; j < DIM; j++ )
  45. printf( "%6.3f ", M[i][j] );
  46. printf( "\n" );
  47. }
  48. }
  49. /*
  50. Копирование матрицы Src в матрицу Dest. (Dest = Src)
  51. функция не имеет возвращаемого значения. Результат возвращается
  52. косвенно через аргумент Dest.
  53. */
  54. void MCopy( double Dest[DIM][DIM], double Src[DIM][DIM] )
  55. {
  56. int i, j;
  57. for( i = 0; i < DIM; i++ )
  58. for( j = 0; j < DIM; j++ )
  59. Dest[i][j] = Src[i][j];
  60. }
  61. /*
  62. произведение квадратных матриц размерности DIM. (DIM = 8)
  63. A, B - матрицы, произведение которых вычисляется. (A * B)
  64. C - матрица, в которую записывается результат. (C = A * B)
  65. функция не имеет возвращаемого значения. Результат возвращается
  66. косвенно через аргумент C.
  67. */
  68. void MMul( double A[DIM][DIM], double B[DIM][DIM], double C[DIM][DIM] )
  69. {
  70. double tmpMatr[DIM][DIM];
  71. double sum;
  72. int i, j, k;
  73. for( i = 0; i < DIM; i++ )
  74. for( j = 0; j < DIM; j++ )
  75. {
  76. sum = 0;
  77. for( k = 0; k < DIM; k++ )
  78. sum += A[i][k] * B[k][j];
  79. tmpMatr[i][j] = sum;
  80. }
  81. MCopy( C, tmpMatr );
  82. }
  83. /*
  84. матричное возведение в степень (C = A ^ power)
  85. A - исходная матрица
  86. power - степень (должна быть больше 1 )
  87. C - результат
  88. функция не имеет возвращаемого значения. Результат возвращается
  89. косвенно через аргумент C.
  90. */
  91. void MPow( double A[DIM][DIM], int power, double C[DIM][DIM] )
  92. {
  93. int i, repeatTimes = 100;
  94. double tmpMatr[DIM][DIM];
  95. while( repeatTimes-- )
  96. {
  97. MCopy( tmpMatr, A );
  98. MCopy( C, A );
  99. for( i = 1; i < power; i++ )
  100. MMul( C, tmpMatr, C );
  101. }
  102. }
  103. /*****************************************************************************/
  104. /*
  105. Поиск числа K.
  106. M - исходная матрица
  107. delta - погрешность вычислений
  108. Функция возвращает число K.
  109. */
  110. int FindK( double M[DIM][DIM], double delta )
  111. {
  112. double tmpMatr[DIM][DIM];
  113. int k = 1, numprocs, myid;
  114. MPI_Comm_size( MPI_COMM_WORLD, &numprocs );
  115. MPI_Comm_rank( MPI_COMM_WORLD, &myid );
  116. k += myid;
  117. do
  118. {
  119. k += numprocs;
  120. MPow( M, k, tmpMatr );
  121. } while( (1 - tmpMatr[0][DIM - 1]) >= delta );
  122. return k;
  123. }
  124. /*
  125. Функция вычисления плотности распределния
  126. M - исходная матрица
  127. K - размерность плотности
  128. f - указатель на массив, содержащий плотность распределения
  129. функция не имеет возвращаемого значения. Результат возвращается
  130. косвенно через аргумент f.
  131. */
  132. void FindF( double M[DIM][DIM], int K, double *f )
  133. {
  134. double m1[DIM][DIM], m2[DIM][DIM];
  135. int i, numprocs, myid;
  136. MPI_Comm_size( MPI_COMM_WORLD, &numprocs );
  137. MPI_Comm_rank( MPI_COMM_WORLD, &myid );
  138. for( i = 1 + myid; i <= K; i += numprocs )
  139. {
  140. MPow( M, i, m1 );
  141. MPow( M, i - 1, m2 );
  142. f[i - 1] = m1[0][DIM - 1] - m2[0][DIM - 1];
  143. }
  144. }
  145. /*
  146. функция распечатывает на экран значения плотности распределния.
  147. f - указатель на массив со значениями плотности распределния.
  148. K - длинна массива.
  149. функция не имеет возвращаемого значения.
  150. */
  151. void FPrint( double *f, int K )
  152. {
  153. int i;
  154. printf( " f.Size = %i\n {\n", K );
  155. for( i = 0; i < K; i++ )
  156. printf( " f[%i] = \t%e\n", i + 1, f[i] );
  157. printf( " }\n" );
  158. }
  159. /*
  160. Проверка суммы значений плотности распределения.
  161. f - указатель на массив значений плотности распределения.
  162. K - размерность массива.
  163. delta - допустимая погрешность.
  164. Функция не имеет возвращаемого значения.
  165. */
  166. void CheckSum( double *f, int K, double delta )
  167. {
  168. double sum = 0;
  169. int i;
  170. for( i = 0; i < K; i++ )
  171. sum += f[i];
  172. printf( "sum f[i] = %f\n", sum );
  173. }
  174. /*
  175. Вычисления математического ожидания.
  176. f - указатель на массив значений плотности распределения.
  177. K - размерность массива.
  178. Функция возвращает значение математического ожидания.
  179. */
  180. double FindM( double *f, int K )
  181. {
  182. double res = 0;
  183. int i;
  184. for( i = 0; i < K; i++ )
  185. res += i * f[i];
  186. return res;
  187. }
  188. /*
  189. Вычисление дисперсии.
  190. f - указатель на массив значений плотности распределения.
  191. K - размерность массива.
  192. Функция возвращает значение дисперсии.
  193. */
  194. double FindD( double *f, int K )
  195. {
  196. double res = 0, M = FindM( f, K );
  197. int i;
  198. for( i = 0; i < K; i++ )
  199. res += pow( i - M, 2 ) * f[i];
  200. return res;
  201. }
  202. /*****************************************************************************/
  203. /*
  204. объединение группы процессов по AND.
  205. N - количество процессов для объединения.
  206. f - указатель на массив с
  207. плотностями распределения исходных процессов.
  208. fAnd - указатель на массив с результирующей плотностью распределения.
  209. K - длинна плотностей распределения f и fAnd.
  210. функция не имеет возвращаемого значения. Результат возвращается
  211. косвенно через аргумент fAnd.
  212. */
  213. void And( int N, double *f, double *fAnd, int K )
  214. {
  215. double S, M, res;
  216. int k, n, i, ki;
  217. for( k = 0; k < K; k++ )
  218. {
  219. S = 0;
  220. for( n = 1; n <= N; n++ )
  221. {
  222. M = 1;
  223. for( i = 1; i <= N; i++ )
  224. {
  225. res = 0;
  226. if( n == i )
  227. res = 1;
  228. else
  229. for( ki = 0; ki < K; ki++ )
  230. if( (i < n && ki < k) || (i >= n && ki <= k) )
  231. res += f[ki];
  232. M *= res;
  233. }
  234. S += f[k] * M;
  235. }
  236. fAnd[k] = S;
  237. }
  238. }
  239. /*
  240. объединение группы процессов по OR.
  241. N - количество процессов для объединения.
  242. f - указатель на массив с
  243. плотностями распределения исходных процессов.
  244. fOr - указатель на массив с результирующей плотностью распределения.
  245. K - длинна плотностей распределения f и fOr.
  246. функция не имеет возвращаемого значения. Результат возвращается
  247. косвенно через аргумент fMN.
  248. */
  249. void Or( int N, double *f, double *fOr, int K )
  250. {
  251. double S, M, res;
  252. int k, n, i, ki;
  253. for( k = 0; k < K; k++ )
  254. {
  255. S = 0;
  256. for( n = 1; n <= N; n++ )
  257. {
  258. M = 1;
  259. for( i = 1; i <= N; i++ )
  260. {
  261. res = 0;
  262. if( n == i )
  263. res = 1;
  264. else
  265. for( ki = 0; ki < K; ki++ )
  266. if( (i < n && ki > k) || (i >= n && ki >= k) )
  267. res += f[ki];
  268. M *= res;
  269. }
  270. S += f[k] * M;
  271. }
  272. fOr[k] = S;
  273. }
  274. }
  275. /*
  276. объединение группы процессов по M из N.
  277. N - количество процессов для объединения.
  278. f - указатель на массив с
  279. плотностями распределения исходных процессов.
  280. fMN - указатель на массив с результирующей плотностью распределения.
  281. K - длинна плотностей распределения f и fMN.
  282. функция не имеет возвращаемого значения. Результат возвращается
  283. косвенно через аргумент fMN.
  284. */
  285. void MfromN( int N, int M, double *f, double *fMN, int K )
  286. {
  287. int Cnm = CNM( N, M );
  288. double *fAnd = (double*)malloc( sizeof( double ) * K );
  289. And( M, f, fAnd, K );
  290. Or( Cnm, fAnd, fMN, K );
  291. free( fAnd );
  292. }
  293. /*
  294. последовательное объединение группы процессов.
  295. N - количество процессов для объединения.
  296. f - указатель на массивы с
  297. плотностями распределения исходных процессов.
  298. fP - указатель на массив с результирующей плотностью распределения.
  299. K - длинна плотностей распределения f[i] и fP.
  300. функция не имеет возвращаемого значения. Результат возвращается
  301. косвенно через аргумент fP.
  302. */
  303. void Posl( int N, double *f[], double *fP, int K )
  304. {
  305. double S;
  306. double *f1 = (double*)malloc( sizeof( double ) * K * N );
  307. int i, j, l, m;
  308. for( i = 0; i < K * N; i++ )
  309. fP[i] = f1[i] = 0;
  310. for( i = 0; i < K; i++ )
  311. fP[i] = f[0][i];
  312. for( j = 2; j <= N; j++ ){
  313. for( l = 1;l <= K * j; l++ ){
  314. S = 0;
  315. for( m = 1; m <= K * N; m++ )
  316. if( m < l && m <= K * (j - 1) && l - m <= K )
  317. S += fP[m - 1] * f[j - 1][l - m - 1];
  318. f1[l - 1] = S;
  319. }
  320. for( i = 0; i < K * j; i++ )
  321. fP[i] = f1[i];
  322. }
  323. free( f1 );
  324. }
  325. /*****************************************************************************/
  326. /* Entry point */
  327. int main( int argc, char *argv, char *envp )
  328. {
  329. double delta = 0.00001;
  330. double MyMatrix[DIM][DIM] = {
  331. {0, 1, 0, 0, 0, 0, 0, 0},
  332. {0, 0, 0.5, 0.5, 0, 0, 0, 0},
  333. {0, 0, 0.5, 0.5, 0, 0, 0, 0},
  334. {0.5, 0, 0, 0, 0.5, 0, 0, 0},
  335. {0, 0, 0, 0, 0, 1, 0, 0},
  336. {0, 0, 0, 0, 0.5, 0, 0.5, 0},
  337. {0, 0, 0, 0, 0.5, 0, 0, 0.5},
  338. {0, 0, 0, 0, 0, 0, 0, 1}
  339. };
  340. int K, K1, m = 3, i = 5, l = 7;
  341. double M, D;
  342. double *f, *fAll[3], *fRes;
  343. double start, end;
  344. int numprocs, myid;
  345. MPI_Init( &argc, &argv );
  346. MPI_Comm_size( MPI_COMM_WORLD, &numprocs );
  347. MPI_Comm_rank( MPI_COMM_WORLD, &myid );
  348. if( myid == 0 )
  349. {
  350. printf( "proc count = %i\n", numprocs );
  351. printf( "Used " );
  352. MPrint( MyMatrix );
  353. printf( "Matrix K = " );
  354. start = MPI_Wtime( );
  355. }
  356. K = FindK( MyMatrix, delta );
  357. MPI_Reduce( &K, &K1, 1, MPI_DOUBLE, MPI_MAX, 0, MPI_COMM_WORLD );
  358. K = K1;
  359. MPI_Bcast( &K, 1, MPI_INT, 0, MPI_COMM_WORLD );
  360. /* Вычисление плотности распределения для процесса 0 */
  361. f = (double*)calloc( K, sizeof( double ) );
  362. fAll[0] = (double*)calloc( K, sizeof( double ) );
  363. FindF( MyMatrix, K, f );
  364. MPI_Reduce( f, fAll[0], K, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD );
  365. if( myid == 0 )
  366. {
  367. /* Вычисление плотности распределения для объединения
  368. группы процессов с 1 по I по функции M из N */
  369. fAll[1] = (double*)malloc( sizeof( double ) * K );
  370. MfromN( i, m, fAll[0], fAll[1], K );
  371. /* Вычисление плотности распределения для объединения
  372. группы процессов с I + 1 по I + L по функции AND */
  373. fAll[2] = (double*)malloc( sizeof( double ) * K );
  374. Or( l, fAll[0], fAll[2], K );
  375. /* Вычисление результирующей плотности распределения
  376. последовательное объединение. */
  377. fRes = (double*)malloc( sizeof( double ) * 3 * K );
  378. Posl( 3, fAll, fRes, K );
  379. K *= 3;
  380. end = MPI_Wtime( );
  381. printf( "%i\n==============================\n", K1 );
  382. /* вывод плотности распределения */
  383. FPrint( fRes, K );
  384. /* проверка суммы */
  385. CheckSum( fRes, K, delta );
  386. /* вычисление математического ожидания */
  387. M = FindM( fRes, K );
  388. /* вычисление дисперсии */
  389. D = FindD( fRes, K );
  390. printf( "M = %f\nD = %f\n time = %f s\n", M, D, end - start );
  391. fflush( stdout );
  392. free( fAll[1] );
  393. free( fAll[2] );
  394. free( fRes );
  395. }
  396. free( f );
  397. free( fAll[0] );
  398. //_getch( );
  399. /* очищаем динамическую память */
  400. MPI_Finalize( );
  401. return 0;
  402. }
Add Comment
Please, Sign In to add comment