Добавил:
ivanov666
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Методы Монте-Карло для параллельных вычислений. Учебное пособие
.pdf
с вероятностью 1
lim
ˆa1(K, t) = a,
t→∞
lim
ˆa1(K, t) = a + O(1/t),
K→∞
lim
¯a(K, t) = a;
t→∞
если существует константа B, такая что τ
6 B с вероятностью 1, и
i,j
если B < t, то
M(¯a(K, t)) = a,
и также с вероятностью 1 будет
lim
¯a(K, t) = a;
K→∞
если существует k > 0, такое что
i,j
|τ
k
) < ∞,
i,j
M(|X
тогда
M(¯a(K, t)) = a + o(t−k),
и с вероятностью 1
lim
¯a(K, t) = a + o(t−k).
K→∞
На содержательном уровне эти свойства означают, что если повышения
точности пытаются добиться за счет увеличения числа вычислительных устройств в условиях малого времени моделирования t, то оценка
среднего не обязана сходиться к истинному значению M(X) = a.
Улучшить свойства оценки ˆa1(K, t) можно следующим образом.
Если на i-м вычислительном устройстве в момент t имеется незавершенный процесс моделирования, то позволим ему завершиться и рассмотрим оценку
Ni(t)+1
K
P
P
X
i,j
. (4.10)
ˆa2(K, t) =
i=1
j=1
K
P
(Ni(t) + 1)
i=1
91

Здесь величины Ni(t) и X
i,1
, X
, . . . являются зависимыми, тем не
i,2
менее из фундаментальных результатов теории восстановления следует
равенство
Ni(t)+1
X
X
= M(Ni(t) + 1) M(X).
i,j
j=1
Поэтому при K → ∞ можно применить усиленный закон больших чисел
и получить
lim
ˆa2(K, t) = a.
K→∞
Определим случайную величину˜Ni(t) = max{1, Ni(t)} и рас-
смотрим новую оценку
K
X
1
¯a1(K, t) =
K
¯
Xi(˜Ni(t)). (4.11)
i=1
Она отличается от оценок (4.9) и (4.10) тем, что если какое-то вычислительное устройство не успевает завершить генерирования хотя бы одной
случайной величины, то время работы этого устройства продлевается
до завершения текущего акта генерации. В противном случае, используются все полученные к моменту t значения. Оказывается (см. [42, 43]),
что оценка ¯a1(K, t) является несмещенной, M ¯a1(K, t) = a и с вероят-
ностью 1 имеют место предельные соотношения
lim
¯a1(K, t) = a, lim
t→∞
¯a1(K, t) = a.
K→∞
Введем величину
K
X
ˆσ1(K, t) =
1
1 −K
(¯Xi(˜Ni(t)) −¯a1(K, t))2.
i=1
В работах [42, 43] доказано, что
lim
ˆσ1(K, t) = D(¯Xi(˜Ni(t))
K→∞
с вероятностью 1. Тогда имеет место сходимость по распределению при
K → ∞ величины
√
K(¯a1(K, t) −a)/ˆσ1(K, t)
92

к стандартному нормальному закону. На основании этого факта возможно строить доверительный интервал для величины a. При фиксированном K положим
˜
¯τ (K, t) =
K
K
X
1
i=1
1
˜
Ni(t)
Ni(t)
X
j=1
τ
i,j
и определим величину
˜
Ni(t)
X
1
˜
j=1
X
2
i,j
− ¯a1(K, t)
2
.
2
ˆσ
(K, t) = ˜τ (K, t)
2
K
K
X
1
Ni(t)
i=1
Тогда
lim
t→∞
2
ˆσ
(K, t) = M(τ
2
i,j
) D(X
i,j
)
с вероятностью 1 и величина
√
Kt(¯a1(K, t) −a)/ˆσ2(K, t)
сходится по распределению при t → ∞ к стандартному нормальному
распределению. Это также дает возможность построить доверительный
интервал для a.
В качестве примера возьмем задачу приближенного вычисления
кратного интеграла
Z
Z
···
| {z }
x1>0, ..., xn>0
x1+...+xn61
x
p1−1
1
···x
Γ(p1+ .. . + pn+ 1)
pn−1
n
Γ(p1) ··· Γ(pn)
dx1···dxn= 1. (4.12)
Пусть случайный вектор X = (X1, X2, . . . , Xn) имеет равномерное
распределение в области
D = {(x1, x2, . . . , xn): x1> 0, x2> 0, . . . , xn> 0, x1+x2+. . .+xn6 1}
с плотностью
p(x1, x2, . . . , xn) = n!, (x1, x2, . . . , xn) ∈ D.
Введем функцию
f(x1, x2, . . . , xn) = x
p1−1
1
···x
93
Γ(p1+ .. . + pn+ 1)
pn−1
n
Γ(p1) ··· Γ(pn)Γ(n + 1)
.

Тогда справедливо представление
Z
Z
···
| {z }
x1>0, ..., xn>0
x1+...+xn61
x
p1−1
1
···x
Γ(p1+ .. . + pn+ 1)
pn−1
n
Γ(p1) ··· Γ(pn)
dx1···dxn= M f(X ).
Для получения значений величин X1, X2,. . . , Xnвоспользуемся следующим функциональным преобразованием: пусть независимые величины U1, U2, .. . , Unс равномерным распределением в промежутке
(0, 1), расположенные в возрастающем порядке, образуют величины
U
(1)
6 U
6 . . . 6 U
(2)
(n)
,
тогда можно положить
X1= U
, X2= U
(1)
(2)
− U
, . . . , Xn= U
(1)
(n)
− U
(n−1)
.
Мы рассмотрим несколько реализаций метода Монте-Карло для
вычисления интеграла. Каждая из реализаций использует версию генератора псевдослучайных чисел с поддержкой нескольких потоков чисел. Программа 4.1 содержит текст заголовочного файла и реализации
явного обратного конгруэнтного генератора.
Программа 4.1. Явный обратный конгруэнтный генератор с поддержкой
нескольких потоков псевдослучайных чисел
1 / / se i c grng .h - о б ъ явл е н и е м н о г опо т о ч но г о явного
2 / / обр а т н о го ко н гру э н т но г о ген е р а т ора
3 / / x[ n ,j ] = i n v (a [ j ] * x [n - 1 , j ] + b [ j ]) m o d m
4 # ifnde f SEICG R N G _H
5 # defin e SEICG R N G _H
6
7 # inc l u d e <cma t h >
8 # inc l u d e <vecto r >
9
10 u s i ng n a mes p a c e std ;
11
12 c l a ss s e icgr n g {
13 ve c t o r < u n s igned > s e e d ;
14 uns i g n e d a , c ;
15 sei c g r n g ();
16 publ i c :
94

17 sei c g r n g ( u n s i gned a , un sign e d c , u n s i gned _seed ,
18 int L);
19 float n e x t ( int s n u m );
20 };
21
22 # endif / / SE I CRN G _ H
23
24 / / se i c grng . cc - р еали з а ц ия
25 / / мн о го п о т очн о г о явн о г о обра т н о г о
26 / / ко н гру э н т но г о ген е р а т ора
27 # inc l u d e "s e i c g rng .h "
28 # inc l u d e "v e c t y pes .h "
29 # inc l u d e <stdi o .h >
30 # inc l u d e <algori t h m >
31
32 / /
33 / / a *( a ^ -1 ) + 2 1 4748 3 6 4 7 * b =1;
34 / /
35
36 i n line
37 i n t i n v m o d ( u n s i gned a ){
38 i4vec u ={ 1 , 0 , a , 0 } ,
39 v = { 0 , 1, ( unsi g n e d )214 7 4 8 3 6 4 7 , 0} , t ;
40 in t q;
41 while ( v . i [2] >0){
42 q = u .i [ 2 ] / v .i [ 2 ] ;
43 t. v = u . v - ( v .v * ( v 4 s i ){ q , q , q , q } ) ;
44 u. v = v . v ;
45 v. v = t . v ;
46 };
47 if ( u. i [0] >=0) r e t u rn u . i [ 0 ] ;
48 else {
49 q = u .i [ 0 ] % 21 474 8 3 6 47;
50 r e t u r n 21 4 7 4 836 4 7 + q ;
51 }
52 };
53
54 s eicg r n g : : s e i c grng ( u nsig n e d _a , u n s i gned _c ,
55 uns i g n e d _ seed , i n t L )
56 :a ( _ a ), c( _ c )
57 {
58 seed . r e s i z e ( L );
59 fill ( seed . b e g i n ( ) , s e e d . en d () , _s e e d %2 1 4 7 483 6 4 7 );
95

60 };
61
62 f l o at s e icgr n g : : next ( i n t sn u m ){
63 float a n s =
64 invm o d ( seed [ snum ]* a + a* s num + c ) / 21 4 7 4 836 4 7 . 0;
65 ++ s e e d [ s n u m ] ;
66 retur n an s ;
67 }
В Программе 4.2 приведена процедура оценки интеграла (4.12)
с помощью нескольких вычислительных потоков. Именно между потоками распределяется цикл в строках 50–62. Находятся оценки математического ожидания J = M f (X) и дисперсии σ2= D f(X) величины
f(X) в строках 65, 66. Для контроля точности вычисляется абсолютная погрешность |J − J | и стандартная погрешность среднего σ/√n по
n реализациям.
Программа 4.2. Вычисление интеграла (4.12) с помощью параллельных потоков в библиотеке OpenMP
1 # inc l u d e <vecto r >
2 # inc l u d e <cti m e >
3 # inc l u d e <cstdi o >
4 # inc l u d e <cma t h >
5 # inc l u d e <algori t h m >
6 # inc l u d e <iostream >
7 # inc l u d e <omp . h >
8 # inc l u d e "s e i c g rng .h "
9
10 u s i ng n a mes p a c e std ;
11
12 t ypede f ve c tor < double > dv e c ;
13
14 d o uble f ( d v e c x , dvec p ){
15 doubl e r es , s u m p ;
16 bool fl = f a l s e ;
17 in t sz = x . size ();
18 re s = 0 . 0 ;
19 sump = 1 . 0 ;
20 fo r ( in t i=0; i < s z ; ++ i ){
21 res + = ( p [i ] - 1 . 0 ) * l o g ( x [ i]) - l g a m m a ( p [ i ]);
22 su m p + = p [i ] ;
23 };
96

24 re s = e x p ( re s - l g a m m a ( sz + 1 .0)+ l g a m m a ( sump ) ) ;
25 retur n re s ;
26 };
27
28 i n t ma i n ( i n t argc , c h a r * a r g v [ ] ) {
29
30 struc t da t a {
31 u n s i gned in t s e ed , n , d i m ;
32 } s p ;
33
34 sp . s e e d = t i m e ( 0 ) ;
35 sp .n = 1 0 0 0 00;
36 sp . d i m = 5 ;
37 doubl e va l = 0 .0 , v a l 2 = 0. 0 ;
38
39 dvec p ( sp . d i m );
40 sei c g r n g r n g (17 , 2543 , sp . see d ,
41 om p _ge t _ max _ t hre a d s ());
42
43 fo r ( dvec : : i t erat o r it =p . begin (); it ! = p . e n d ( ) ; it + + )
44 * it = 1 . 4 0 ;
45
46 # pragm a om p pa r alle l sh ared ( r ng ) \
47 red u c t i on (+: v al , v a l 2 )
48 {
49 # pragm a om p for
50 for ( int i =0; i < s p .n ; i ++){
51 dvec x ( sp. dim ) ;
52 for ( int k = 0 ; k < sp . dim ; ++ k ){
53 x[ k ] = r n g . next ( o m p _g e t _ th r e a d_ n u m ());
54 };
55 sort ( x. begin () , x . e nd ());
56 for ( int j= s p . dim - 1 ; j >0; - - j ){
57 x[ j ] -= x [ j - 1 ] ;
58 };
59 doub l e y = f ( x , p );
60 val += y ;
61 val2 += y *y ;
62 }; // # pragma omp f o r
63 }; / / # p r a g m a o m p pa r alle l
64
65 va l /= s p .n ;
66 val2 = v a l 2 / s p . n - val * val ;
97

67
68 co ut < < " r esult ␣ is ␣ " < < v a l
69 << " ,␣ a bsol u t e ␣ error ␣ is ␣ " < < fabs (val - 1 . 0 )
70 << " ,␣ s t d . e r r ␣ i s ␣" < < sq r t ( v a l 2 ) / s q r t ( sp . n ) < < e n d l ;
71
72 retur n 0;
73 };
Программа 4.3 демонстрирует пример вычисления интеграла (4.12) на вычислительном кластере с помощью технологии MPI.
В строке 2 подключается заголовочный файл, содержащий объявления функций MPI. Каждый процессор получает задание в виде заполненной структуры struct sp, объявленной в строках 25–27. Поля
этой структуры содержат начальные данные для генератора псевдослучайных чисел (seed), число реализаций случайного вектора X (n).
Для инициализации вычислительной среды вызывается библиотечная
функция MPI_Init, которая, в частности, создает обязательный коммуникатор MPI_COMM_WORLD. Затем последовательно определяется число
numproc процессов в этом коммуникаторе (строка 33) и номер текущего
процесса, его ранг среди всех процессов в данном коммуникаторе (строка 34). Формированием вычислительного задания занимается процесс с
рангом 0 (строки 36–39). Затем заполненная структура с заданием распространяется среди всех процессов в коммуникаторе MPI_COMM_WORLD
с помощью функции MPI_Bcast широковещательной рассылки. Строки
44–61 выполняются каждым процессом и в ходе их выполнения каждый
процесс находит свою оценку J величины интеграла J в переменной
val. В строках 62–63 происходит сбор результатов вычислений: каждый
и эти значения сохраняются в массиве vals. Далее все процессы кроме
процесса с рангом 0 завершаются, а последний находит окончательную
оценку величины J в строках 64–75 и выводит ее пользователю. В целом расчет организован по формуле (4.7). Для учета времени работы
программы процесс ранга 0 фиксирует время начала работы (строка
36) и время окончания работы (строка 71).
Программа 4.3. Вычисление интеграла на вычислительном кластере с помощью технологии MPI
1 # inc l u d e <vecto r >
2 # inc l u d e <mpi . h >
3 # inc l u d e <cti m e >
4 # inc l u d e <cma t h >
98

5 # inc l u d e <algori t h m >
6 # inc l u d e <iostream >
7 # inc l u d e "s e i c g rng .h "
8
9 u s i ng n a mes p a c e std ;
10 t ypede f ve c tor < double > dv e c ;
11
12 d o uble f ( d v e c x , dvec p ){
13 doubl e r es , s u m p ;
14 in t sz = x . size ();
15 re s = 0 . 0 ;
16 sump = 1 . 0 ;
17 fo r ( in t i=0; i < s z ; ++ i ){
18 res + = ( p [i ] - 1 . 0 ) * l o g ( x [ i]) - l g a m m a ( p [ i ]);
19 su m p + = p [i ] ;
20 };
21 re s = e x p ( re s - l g a m m a ( sz + 1 .0)+ l g a m m a ( sump ) ) ;
22 retur n re s ;
23 };
24
25 s t ruct d ata {
26 in t seed , n , d i m ;
27 } sp ;
28
29 i n t ma i n ( i n t argc , c h a r * a r g v [ ] ) {
30 in t myid , n u mpro c ;
31 cloc k _ t st , et ;
32 MPI _ I n i t ( & argc , & a r g v ) ;
33 MP I _ C omm _ s i ze ( M P I_COM M _ W O RLD , & n u m proc );
34 MP I _ C omm _ r a nk ( M P I_COM M _ W O RLD , & m y i d );
35 if ( myid ==0) {
36 st = c l o c k ( ) ;
37 sp . seed = t i m e ( 0 ) ;
38 sp . n = 10 0 0 000/ n u m p roc ;
39 sp . dim = 50;
40 };
41 MPI _ B c a st (( c h a r * ) & sp , si z e of ( sp ) ,
42 MP I_CHAR , 0 , MP I_C O M M _W O R L D );
43
44 sei c g r n g r n g (17 , 25 43+1 7 * myid , sp . see d , 1);
45 dvec x ( sp . d i m ) , p ( s p . d im );
46 doubl e va l = 0 .0 , v a l s [ s p . d i m ];
47 fo r ( dvec : : i t erat o r it =p . begin (); it ! = p . e n d ( ) ; + + i t )
99

48 * it = 1 . 4 0 ;
49
50 fo r ( in t i=0; i < s p . n ; i ++){
51 for ( int k =0; k < s p . d i m ; ++ k )
52 x[k ] = r ng . n e x t ( 0 ) ;
53 so r t (x . beg i n () , x. e n d ( ) ) ;
54 for ( int j = sp . d im - 1 ; j > = 0 ; -- j )
55 x[j ] -= x [ j - 1 ] ;
56 val + = f ( x , p );
57 };
58 va l /= s p .n ;
59 co ut < < " M y ␣ Id ␣ is : ␣ " < < m y i d
60 << " ,␣ l o c al ␣ r e s u l t ␣ is ␣ " << val
61 << " ,␣ a bsol u t e ␣ error ␣ is ␣ " < < fabs (val -1.0) < < endl ;
62 MPI _ G a the r (& v al , 1 , M PI_DOUBLE , vals ,
63 1, MPI_ D O U B L E , 0 , MP I _C O M M _WO R L D ) ;
64 if (0 == m y i d ) {
65 for ( int j =1; j < nump r o c ; ++ j )
66 vals [0] += v a l s [ j ];
67 va l s [0] / = ( do u b l e ) num p r o c ;
68 cout < < " F i n a l ␣ est i m a t e ␣ is ␣ " << v a ls [ 0 ]
69 << " ,␣ a bsol u t e ␣ error ␣ is ␣ " < < fabs ( v a l s [ 0 ] - 1 . 0 )
70 << endl ;
71 et = c l o c k ( ) ;
72 cout < < " Time ␣ e l apsed :␣ "
73 < <( double (et - st ))/ CL O C K S_P E R _ SE C
74 << e n d l ;
75 };
76 MP I _ F ina l i z e ();
77 retur n 0;
78 };
Для компиляции в среде mpich необходимо выполнить команду
“mpiCC -o mcint mcint.cc seicgrng.cc”. Результаты запуска с одним
вычислительным процессом (командой “ mpirun -np 1 mcint”) и с двумя вычислительными процессами (командой “mpirun -np 2 mcint”) на
компьютере с процессором AMD Athlon 64 X2 Dual Core Processor 6000+
дают время работы в 32,87 секунды и 16,52 секунды соответственно, то
есть достигнуто двукратное ускорение работы программы в соответствии со вторым законом Амдала [2].
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
