1
00:00:00,469 --> 00:00:03,859
in our lecture on numerical methods


2
00:00:03,859 --> 00:00:06,810
today I'd like to do a small coding


3
00:00:06,810 --> 00:00:11,130
session and we discussed the Monte Carlo


4
00:00:11,130 --> 00:00:14,969
methods and somewhere in the middle


5
00:00:14,969 --> 00:00:18,600
there was this little experiment


6
00:00:18,600 --> 00:00:21,630
described how you can use a Monte Carlo


7
00:00:21,630 --> 00:00:26,910
approximation to approximate P okay so


8
00:00:26,910 --> 00:00:31,560
you find this in the script the thing is


9
00:00:31,560 --> 00:00:33,950
that four times the moniker integral of


10
00:00:33,950 --> 00:00:39,930
the indicator function on a two


11
00:00:39,930 --> 00:00:46,470
dimensional random vector ax so


12
00:00:46,470 --> 00:00:51,870
eggs and why


13
00:00:51,870 --> 00:01:00,539
uniform on zero one gives you an


14
00:01:00,539 --> 00:01:06,250
integral and this integral is actually


15
00:01:06,250 --> 00:01:11,310
equal to P so we can approximate P by


16
00:01:11,310 --> 00:01:14,380
calculating this on the counter in


17
00:01:14,380 --> 00:01:17,259
sequence and the idea behind this was


18
00:01:17,259 --> 00:01:18,549
also in the script


19
00:01:18,549 --> 00:01:21,280
just to have you this if you sample


20
00:01:21,280 --> 00:01:26,590
random points in the unit hypercube then


21
00:01:26,590 --> 00:01:30,270
the probability to be inside the circle


22
00:01:30,270 --> 00:01:35,069
is the ratio of the area of the circle


23
00:01:35,069 --> 00:01:39,190
with respect to the area of the unit


24
00:01:39,190 --> 00:01:42,970
hypercube okay and so then we do the


25
00:01:42,970 --> 00:01:47,830
transformation to just the upper


26
00:01:47,830 --> 00:01:50,920
secretary of the quarter from 0 to 1 and


27
00:01:50,920 --> 00:01:55,989
then we get four times where this


28
00:01:55,989 --> 00:02:03,310
integral okay this gives us P okay so


29
00:02:03,310 --> 00:02:07,269
and then later in the script we have the


30
00:02:07,269 --> 00:02:12,470
remark that Monte Carlo


31
00:02:12,470 --> 00:02:17,060
is a very good technique if you like to


32
00:02:17,060 --> 00:02:21,460
perform parallelization so why is that


33
00:02:21,460 --> 00:02:28,460
okay so there was the experiment here


34
00:02:28,460 --> 00:02:32,840
that we should use this algorithm of


35
00:02:32,840 --> 00:02:38,780
approximating P and parallelize it say


36
00:02:38,780 --> 00:02:41,290
for example to make use of multiple


37
00:02:41,290 --> 00:02:47,630
processor cores so I would like to do a


38
00:02:47,630 --> 00:02:50,330
small excursion on parallelization so


39
00:02:50,330 --> 00:02:53,090
teach you a little bit about this and


40
00:02:53,090 --> 00:02:55,040
actually you will see that with some


41
00:02:55,040 --> 00:02:57,920
frameworks some Java frameworks it's


42
00:02:57,920 --> 00:03:00,050
actually very easy it's just writing one


43
00:03:00,050 --> 00:03:03,280
additional board and you are done


44
00:03:03,280 --> 00:03:06,920
okay so the point here is that the Monte


45
00:03:06,920 --> 00:03:15,620
Carlo method uses a sequence of iid so


46
00:03:15,620 --> 00:03:18,610
it uses a sequence of independent


47
00:03:18,610 --> 00:03:21,860
identically distributed random variables


48
00:03:21,860 --> 00:03:25,580
and the important aspect here is the


49
00:03:25,580 --> 00:03:27,950
independent so if the random variables


50
00:03:27,950 --> 00:03:31,370
are independent actually this directly


51
00:03:31,370 --> 00:03:34,370
implies that the calculations we have to


52
00:03:34,370 --> 00:03:38,420
perform on these samples are independent


53
00:03:38,420 --> 00:03:44,549
so each individual calculation


54
00:03:44,549 --> 00:03:48,760
can be performed independently so we can


55
00:03:48,760 --> 00:03:52,719
very easily split the vac into say


56
00:03:52,719 --> 00:03:57,549
smaller parts and then distribute these


57
00:03:57,549 --> 00:04:00,489
smaller parts to their own processor


58
00:04:00,489 --> 00:04:06,879
core or like on the GPU - or to a GPU


59
00:04:06,879 --> 00:04:16,090
set okay so the idea is that we use a


60
00:04:16,090 --> 00:04:23,050
random sequence and we just split it in


61
00:04:23,050 --> 00:04:30,550
two blocks so say we have blocks of size


62
00:04:30,550 --> 00:04:41,680
M so then we have J times M plus I


63
00:04:41,680 --> 00:04:46,840
from i from 0 to m minus 1 so each


64
00:04:46,840 --> 00:04:52,070
subsequence has m elements and then we


65
00:04:52,070 --> 00:04:56,720
have K such sucks subsequence such that


66
00:04:56,720 --> 00:05:02,830
K times M is the total number so we have


67
00:05:02,830 --> 00:05:14,979
K sub sequences J from 0 to K minus 1


68
00:05:14,979 --> 00:05:19,280
okay and then we can perform a Monte


69
00:05:19,280 --> 00:05:23,120
Carlo integral on each of these sub


70
00:05:23,120 --> 00:05:25,819
sequences calculate the sum and then the


71
00:05:25,819 --> 00:05:28,300
total sum is just the sum of the


72
00:05:28,300 --> 00:05:35,289
individuals okay so to implement this


73
00:05:35,289 --> 00:05:38,900
parallelization actually sometimes there


74
00:05:38,900 --> 00:05:42,740
are frameworks that help us in splitting


75
00:05:42,740 --> 00:05:47,150
up things so actually we don't even have


76
00:05:47,150 --> 00:05:53,419
to do this splitting so how do we get


77
00:05:53,419 --> 00:05:57,259
these sub sequences so we have several


78
00:05:57,259 --> 00:06:04,129
options of generating such sub sequences


79
00:06:04,129 --> 00:06:07,639
so first of all if you get back to this


80
00:06:07,639 --> 00:06:14,010
slide you see here that


81
00:06:14,010 --> 00:06:26,550
this sequence here starts at XJ times M


82
00:06:26,550 --> 00:06:31,350
plus zero and


83
00:06:31,350 --> 00:06:43,230
hence at XJ times M plus n minus 1 so if


84
00:06:43,230 --> 00:06:45,330
we would like to do Monte Carlo we would


85
00:06:45,330 --> 00:06:51,150
like to start all the sub tasks at the


86
00:06:51,150 --> 00:06:54,780
same time so actually we like to have a


87
00:06:54,780 --> 00:06:59,400
sequence where we can cut out a sub


88
00:06:59,400 --> 00:07:04,230
sequence and perform Monte Carlo on this


89
00:07:04,230 --> 00:07:05,870
sub sequence so if you have for example


90
00:07:05,870 --> 00:07:11,460
1,000 Monte Carlo samples so n is 1,000


91
00:07:11,460 --> 00:07:13,590
and you would like to have 10 sub


92
00:07:13,590 --> 00:07:16,350
sequences each with 100 Monte Carlo


93
00:07:16,350 --> 00:07:19,050
samples you would like to have a


94
00:07:19,050 --> 00:07:23,910
sequence that can start at X 100 X 200 X


95
00:07:23,910 --> 00:07:29,030
300 and so on so in order to do this a


96
00:07:29,030 --> 00:07:31,890
sequence where you can calculate the


97
00:07:31,890 --> 00:07:35,190
number at a certain index directly from


98
00:07:35,190 --> 00:07:38,390
that index has a certain advantage


99
00:07:38,390 --> 00:07:44,150
recall that for linear congruential


100
00:07:44,150 --> 00:07:56,260
generator


101
00:07:56,260 --> 00:08:08,180
we generated the next point from the


102
00:08:08,180 --> 00:08:12,950
previous point okay and so if we would


103
00:08:12,950 --> 00:08:15,740
like to start at X 100 maybe we have to


104
00:08:15,740 --> 00:08:21,620
run from X 0 to X 99 to actually get the


105
00:08:21,620 --> 00:08:24,770
starting point which is a bit useless


106
00:08:24,770 --> 00:08:26,330
because it means that we have to


107
00:08:26,330 --> 00:08:30,350
generate all other random numbers in in


108
00:08:30,350 --> 00:08:32,630
a sequence so we cannot paralyze the


109
00:08:32,630 --> 00:08:35,029
general generation of the random numbers


110
00:08:35,029 --> 00:08:37,310
so sometimes this is not an issue


111
00:08:37,310 --> 00:08:39,020
because the generation of the random


112
00:08:39,020 --> 00:08:41,300
numbers is fast so you first generate


113
00:08:41,300 --> 00:08:43,460
all the random numbers and then you


114
00:08:43,460 --> 00:08:46,820
calculate your function f of X when you


115
00:08:46,820 --> 00:08:49,430
do the Montecarlo integral so sometimes


116
00:08:49,430 --> 00:08:53,180
you only paralyze the evaluation of the


117
00:08:53,180 --> 00:08:55,430
function but you do not paralyze the


118
00:08:55,430 --> 00:09:01,130
generation of the random numbers if you


119
00:09:01,130 --> 00:09:04,360
are sold by going from the bottom


120
00:09:04,360 --> 00:09:07,070
through the top if you are in the


121
00:09:07,070 --> 00:09:11,290
special situation that your secrets


122
00:09:11,290 --> 00:09:15,410
calculates an element X I explicitly


123
00:09:15,410 --> 00:09:20,839
from the index so like for example in


124
00:09:20,839 --> 00:09:22,960
the funda coreboot and Horton sequence


125
00:09:22,960 --> 00:09:26,030
so then you can very easily paralyze


126
00:09:26,030 --> 00:09:28,400
this because you just say start at a


127
00:09:28,400 --> 00:09:34,660
certain index if this is not possible


128
00:09:34,660 --> 00:09:37,760
sometimes there are certain random


129
00:09:37,760 --> 00:09:41,650
number generators that have some kind of


130
00:09:41,650 --> 00:09:50,990
skip ahead possibility so you can find a


131
00:09:50,990 --> 00:09:55,130
formula that generates element 100 from


132
00:09:55,130 --> 00:09:58,400
say element 0 so you can find a formula


133
00:09:58,400 --> 00:10:01,459
that generates an archer step so you


134
00:10:01,459 --> 00:10:04,970
first have to do


135
00:10:04,970 --> 00:10:08,960
this step and if this is not possible


136
00:10:08,960 --> 00:10:11,180
say for example you have a pseudo-random


137
00:10:11,180 --> 00:10:13,940
number generator for example like math


138
00:10:13,940 --> 00:10:16,340
and twister and you do not find a


139
00:10:16,340 --> 00:10:18,650
formula that allows you to do this skip


140
00:10:18,650 --> 00:10:22,220
ahead then there is a dirty trick you


141
00:10:22,220 --> 00:10:24,160
can do yeah but it's maybe not


142
00:10:24,160 --> 00:10:27,740
recommended so if the sequence is


143
00:10:27,740 --> 00:10:29,300
generated from a seed


144
00:10:29,300 --> 00:10:32,270
yes so there is some initial value then


145
00:10:32,270 --> 00:10:35,510
you can consider to generate different


146
00:10:35,510 --> 00:10:41,300
sequences with different random seeds so


147
00:10:41,300 --> 00:10:43,220
this works there


148
00:10:43,220 --> 00:10:45,590
you know it's but it's maybe not an


149
00:10:45,590 --> 00:10:49,400
accurate solution because if you just


150
00:10:49,400 --> 00:10:53,950
consider that your sequence is like that


151
00:10:53,950 --> 00:10:58,550
okay these are now your numbers you


152
00:10:58,550 --> 00:11:01,610
generated and you are Montecarlo seed of


153
00:11:01,610 --> 00:11:04,310
the sequence is here this initial value


154
00:11:04,310 --> 00:11:06,710
this is the seed the starting point and


155
00:11:06,710 --> 00:11:09,050
it's generating the next point from the


156
00:11:09,050 --> 00:11:11,210
previous point and then you choose a


157
00:11:11,210 --> 00:11:16,640
random lis other seat and here you


158
00:11:16,640 --> 00:11:19,160
generate now a different Monte Carlo


159
00:11:19,160 --> 00:11:25,490
sequence then it may happen by chance


160
00:11:25,490 --> 00:11:28,930
that actually your Monte Carlo seed is


161
00:11:28,930 --> 00:11:32,170
identically to some number that appeared


162
00:11:32,170 --> 00:11:35,600
early in the other sequence which then


163
00:11:35,600 --> 00:11:38,180
means that actually the other sequence


164
00:11:38,180 --> 00:11:40,910
already contains


165
00:11:40,910 --> 00:11:45,610
these numbers and you see that the


166
00:11:45,610 --> 00:11:49,490
second sequence only has three


167
00:11:49,490 --> 00:11:52,519
additional points so the gain in


168
00:11:52,519 --> 00:11:57,110
accuracy is a little bit lower okay


169
00:11:57,110 --> 00:12:03,079
but still this technique of using random


170
00:12:03,079 --> 00:12:08,060
seats different seats to generate a


171
00:12:08,060 --> 00:12:10,560
sequence


172
00:12:10,560 --> 00:12:14,579
yeah so this is the seat


173
00:12:14,579 --> 00:12:22,080
and it may happen that the seed appears


174
00:12:22,080 --> 00:12:29,010
in the other sequence so it might happen


175
00:12:29,010 --> 00:12:35,030
there two sequences


176
00:12:35,030 --> 00:12:51,090
overlap overlap eloped okay so these are


177
00:12:51,090 --> 00:12:53,760
some options on how we can parallel eyes


178
00:12:53,760 --> 00:12:57,240
and now before I discuss something here


179
00:12:57,240 --> 00:13:03,930
on the coding let's do a code session on


180
00:13:03,930 --> 00:13:07,470
this so today I like to do coding with


181
00:13:07,470 --> 00:13:13,440
you and I will use two to api's two


182
00:13:13,440 --> 00:13:16,740
frameworks this Java stream API and the


183
00:13:16,740 --> 00:13:18,470
execute offender


184
00:13:18,470 --> 00:13:22,840
okay so let's go here and create a new


185
00:13:22,840 --> 00:13:24,500
[Music]


186
00:13:24,500 --> 00:13:27,090
experiment a new class so let's call


187
00:13:27,090 --> 00:13:33,890
this Monte Carlo integration experiment


188
00:13:33,890 --> 00:13:38,880
or Monte Carlo integration then


189
00:13:38,880 --> 00:13:42,270
experiment I would like to have a main


190
00:13:42,270 --> 00:13:50,840
method and I just implement some ways of


191
00:13:50,840 --> 00:13:58,310
paralyzing this approximation of P here


192
00:13:58,310 --> 00:14:03,090
okay so first as a benchmark maybe I


193
00:14:03,090 --> 00:14:07,940
would like to know the analytic value so


194
00:14:07,940 --> 00:14:14,690
let's define this as a constant here


195
00:14:14,690 --> 00:14:20,130
so this is our analytic value okay and


196
00:14:20,130 --> 00:14:27,750
later I will try to compare this absurd


197
00:14:27,750 --> 00:14:32,340
has to go here compare our numerical


198
00:14:32,340 --> 00:14:34,259
solution with this so


199
00:14:34,259 --> 00:14:37,799
the first one is to use a heart and


200
00:14:37,799 --> 00:14:44,479
sequence and let's define the number of


201
00:14:44,479 --> 00:14:47,699
Montecarlo samples let's be a little bit


202
00:14:47,699 --> 00:14:51,569
bold I would like to be twenty million


203
00:14:51,569 --> 00:14:54,809
one two three one two three this is 10


204
00:14:54,809 --> 00:14:57,419
to the power of seven well let's use 10


205
00:14:57,419 --> 00:15:03,089
to the power of eight 200 million so


206
00:15:03,089 --> 00:15:07,609
this is two times ten to the power of


207
00:15:07,609 --> 00:15:16,470
eight and with 20 to 200 million samples


208
00:15:16,470 --> 00:15:21,079
I would like to approximate P so let's


209
00:15:21,079 --> 00:15:25,679
test with the Horten sequence and I


210
00:15:25,679 --> 00:15:28,759
would like to test this with the Java


211
00:15:28,759 --> 00:15:33,509
stream API and it may be first I do an


212
00:15:33,509 --> 00:15:37,289
example where we are not using the


213
00:15:37,289 --> 00:15:39,709
parallelization so let's call this


214
00:15:39,709 --> 00:15:43,230
sequential okay I create dedicated


215
00:15:43,230 --> 00:15:48,449
masses to do this okay so we have a


216
00:15:48,449 --> 00:15:51,749
little bit more nicer overview in our


217
00:15:51,749 --> 00:15:53,179
kochiya


218
00:15:53,179 --> 00:16:01,079
okay so approximation of P using Monte


219
00:16:01,079 --> 00:16:04,259
Carlo with the Horton sequence so the


220
00:16:04,259 --> 00:16:08,220
Horton sequence we had it in our course


221
00:16:08,220 --> 00:16:14,220
before so in random numbers we had the


222
00:16:14,220 --> 00:16:16,379
funder corporate sequence and the Horton


223
00:16:16,379 --> 00:16:19,289
sequence so Horton sequence is just a


224
00:16:19,289 --> 00:16:21,359
funder corporate sequence where each


225
00:16:21,359 --> 00:16:24,539
dimension has a different base and the


226
00:16:24,539 --> 00:16:28,970
funder corporate sequence was this


227
00:16:28,970 --> 00:16:36,499
algorithm here that


228
00:16:36,499 --> 00:16:41,689
performed the calculation of the old


229
00:16:41,689 --> 00:16:46,219
number of under corporate number by form


230
00:16:46,219 --> 00:16:52,249
directly from the index okay so we have


231
00:16:52,249 --> 00:16:54,639
a sequence of indices and we can


232
00:16:54,639 --> 00:16:58,069
directly calculate the number from the


233
00:16:58,069 --> 00:17:02,089
index so I create a stream so a stream


234
00:17:02,089 --> 00:17:06,049
is just a sequence in in this framework


235
00:17:06,049 --> 00:17:12,459
I create a stream of numbers from 0 to


236
00:17:12,459 --> 00:17:17,059
number of samples so if you look here


237
00:17:17,059 --> 00:17:20,000
this first one is included the last one


238
00:17:20,000 --> 00:17:22,370
is not included so this is just 0 to n


239
00:17:22,370 --> 00:17:29,360
minus 1 ok then this stream I would like


240
00:17:29,360 --> 00:17:33,139
to apply a function that map's each


241
00:17:33,139 --> 00:17:36,740
index on a floating point double number


242
00:17:36,740 --> 00:17:39,679
so I use here map to double and the


243
00:17:39,679 --> 00:17:42,230
argument should be a function that map's


244
00:17:42,230 --> 00:17:48,769
an integer an integer to a floating


245
00:17:48,769 --> 00:17:53,389
point double number ok so how do we


246
00:17:53,389 --> 00:17:55,399
calculate this floating for double


247
00:17:55,399 --> 00:17:58,879
number so first we calculate our hand


248
00:17:58,879 --> 00:18:02,600
and vector so we calculate x and y so X


249
00:18:02,600 --> 00:18:09,070
is 2 times the port number so


250
00:18:09,070 --> 00:18:21,759
Horten sequence George let's part this


251
00:18:21,759 --> 00:18:26,500
that's yours


252
00:18:26,500 --> 00:18:33,400
a heart in sequence from here no obvious


253
00:18:33,400 --> 00:18:35,290
wasn't any missing that's what's the


254
00:18:35,290 --> 00:18:38,230
reason we cannot find it okay and this


255
00:18:38,230 --> 00:18:40,540
this function get heart and number four


256
00:18:40,540 --> 00:18:46,260
given base and I pass the index I and


257
00:18:46,260 --> 00:18:50,800
then the base so we was base - for the


258
00:18:50,800 --> 00:18:55,300
first time ention and we was base 3 for


259
00:18:55,300 --> 00:18:59,230
the second dimension so horton sequence


260
00:18:59,230 --> 00:19:00,670
is between 0 & 1


261
00:19:00,670 --> 00:19:03,310
i subtract 1/2 then it's between minus


262
00:19:03,310 --> 00:19:04,780
1/2 and plus 1/2


263
00:19:04,780 --> 00:19:07,090
i multiplied with 2 then it is between


264
00:19:07,090 --> 00:19:11,290
minus 1 and plus 1 so x is 2 okay so


265
00:19:11,290 --> 00:19:16,630
next number is the horton sequence for


266
00:19:16,630 --> 00:19:20,160
base 3 so we generate a two dimensional


267
00:19:20,160 --> 00:19:23,620
horton sequences with base two and three


268
00:19:23,620 --> 00:19:28,000
for the two dimensions next thing is


269
00:19:28,000 --> 00:19:31,600
that we have to check the indicator


270
00:19:31,600 --> 00:19:38,950
function so we integrate from 0 from


271
00:19:38,950 --> 00:19:42,370
minus 1 to 1 in both dimensions and the


272
00:19:42,370 --> 00:19:44,170
next thing is that we have to calculate


273
00:19:44,170 --> 00:19:48,370
F which is the indicator function are we


274
00:19:48,370 --> 00:19:54,940
in the unit circle or not so if x


275
00:19:54,940 --> 00:20:00,370
squared plus y squared is smaller than 1


276
00:20:00,370 --> 00:20:04,780
we are in the unit circle so we return 1


277
00:20:04,780 --> 00:20:11,979
otherwise we return 0


278
00:20:11,979 --> 00:20:16,009
okay so this maps the sequence of


279
00:20:16,009 --> 00:20:19,820
integers to a sequence of indicator


280
00:20:19,820 --> 00:20:22,849
function values which we then just sum


281
00:20:22,849 --> 00:20:28,039
up okay so this is now on our Monte


282
00:20:28,039 --> 00:20:31,940
Carlo some so we have to divide by the


283
00:20:31,940 --> 00:20:35,629
number of symbols so divided by the


284
00:20:35,629 --> 00:20:39,589
number of samples and actually the


285
00:20:39,589 --> 00:20:44,929
integral is just as we just transformed


286
00:20:44,929 --> 00:20:51,259
here two times so that the new DX is two


287
00:20:51,259 --> 00:20:54,019
times the old DX so we have to multiply


288
00:20:54,019 --> 00:21:00,849
by four okay so that was our little


289
00:21:00,849 --> 00:21:06,909
integration problem and let's print out


290
00:21:06,909 --> 00:21:11,739
the result so we are using here a


291
00:21:11,739 --> 00:21:23,349
sequential and the Java stream RP and


292
00:21:23,349 --> 00:21:29,239
what is the error the error is P orchard


293
00:21:29,239 --> 00:21:36,619
minus P analytic is Tierra okay so let's


294
00:21:36,619 --> 00:21:43,009
try if this box so I run this little


295
00:21:43,009 --> 00:21:51,549
program okay so now this takes a while


296
00:21:51,549 --> 00:21:54,559
you see here processors are working a


297
00:21:54,559 --> 00:21:58,190
little bit now but not too much you are


298
00:21:58,190 --> 00:22:03,460
not not everyone is here busy


299
00:22:03,460 --> 00:22:06,049
hmm maybe I should have got used here


300
00:22:06,049 --> 00:22:10,219
the number of samples okay so we get a


301
00:22:10,219 --> 00:22:14,059
10 to the minus 6 and it took a few


302
00:22:14,059 --> 00:22:15,880
seconds


303
00:22:15,880 --> 00:22:19,210
at reasons we like to do paralyzation i


304
00:22:19,210 --> 00:22:24,809
would like to know how long it takes so


305
00:22:24,809 --> 00:22:28,539
if we like to have a half measure for


306
00:22:28,539 --> 00:22:32,529
time we can ask here the system for the


307
00:22:32,529 --> 00:22:35,769
current time in milliseconds before we


308
00:22:35,769 --> 00:22:39,399
do the calculation and after we do the


309
00:22:39,399 --> 00:22:46,299
calculation okay and then we calculate


310
00:22:46,299 --> 00:22:53,950
the time in seconds as the time and -


311
00:22:53,950 --> 00:22:58,200
the time start converted to a double


312
00:22:58,200 --> 00:23:06,700
divided by 1000 okay and we can prevent


313
00:23:06,700 --> 00:23:09,789
in addition here maybe the time that it


314
00:23:09,789 --> 00:23:17,190
took to calculate this


315
00:23:17,190 --> 00:23:24,549
Monte Carlo integral okay so maybe add


316
00:23:24,549 --> 00:23:28,300
it to use here a little bit


317
00:23:28,300 --> 00:23:35,679
the numbers 2f the result a little bit


318
00:23:35,679 --> 00:23:39,670
faster okay so you see this took here


319
00:23:39,670 --> 00:23:45,130
five seconds so if I go back to 20 it


320
00:23:45,130 --> 00:23:48,850
will take maybe 20 seconds to calculate


321
00:23:48,850 --> 00:23:52,929
this okay so wait while it's running


322
00:23:52,929 --> 00:23:59,350
let's do this now in parallel okay so I


323
00:23:59,350 --> 00:24:06,480
just copy this code here I rename this


324
00:24:06,480 --> 00:24:11,770
with stream say parallel and here on the


325
00:24:11,770 --> 00:24:14,890
top I also call this other test which


326
00:24:14,890 --> 00:24:19,900
performs the calculation in panel okay


327
00:24:19,900 --> 00:24:22,360
so now it's actually in the same code I


328
00:24:22,360 --> 00:24:25,090
haven't done the parallelization yet so


329
00:24:25,090 --> 00:24:27,880
and I would like to show you how easy it


330
00:24:27,880 --> 00:24:30,880
is to colonize this because you can tell


331
00:24:30,880 --> 00:24:34,360
the stream API that he should perform


332
00:24:34,360 --> 00:24:37,870
calculations in parallel and actually


333
00:24:37,870 --> 00:24:40,300
you can also decide when he should do


334
00:24:40,300 --> 00:24:44,320
this so here he is generating a stream


335
00:24:44,320 --> 00:24:48,100
of integer numbers and I would like to


336
00:24:48,100 --> 00:24:50,740
tell him after you have generated this


337
00:24:50,740 --> 00:24:53,590
everything that comes after this can be


338
00:24:53,590 --> 00:24:56,620
done in parallel and you can do this by


339
00:24:56,620 --> 00:25:00,940
just adding here the Verte parallel okay


340
00:25:00,940 --> 00:25:05,200
actually that's it yeah so this code is


341
00:25:05,200 --> 00:25:08,860
now performing this calculation here in


342
00:25:08,860 --> 00:25:19,840
parallel okay so let's print this using


343
00:25:19,840 --> 00:25:25,260
stream so this is parallel


344
00:25:25,260 --> 00:25:34,420
oops so let's check how long it takes if


345
00:25:34,420 --> 00:25:37,480
we perform it in parallel so I run the


346
00:25:37,480 --> 00:25:47,250
program


347
00:25:47,250 --> 00:25:52,030
okay and while it's running you see the


348
00:25:52,030 --> 00:25:54,790
reason why he can easily paralyze this


349
00:25:54,790 --> 00:25:58,150
is that the stuff which is inside here


350
00:25:58,150 --> 00:26:02,410
is completely independent yeah so for


351
00:26:02,410 --> 00:26:05,320
every eye he's doing something but the


352
00:26:05,320 --> 00:26:07,570
other eye doesn't need to know what he's


353
00:26:07,570 --> 00:26:11,110
doing okay so maybe I add a few more


354
00:26:11,110 --> 00:26:14,440
dots here and so on to to have the


355
00:26:14,440 --> 00:26:17,830
output a bit nicer and you see that if


356
00:26:17,830 --> 00:26:19,990
you now look here in the lower left on


357
00:26:19,990 --> 00:26:23,380
the processors the first run is


358
00:26:23,380 --> 00:26:28,090
currently running sequential so it does


359
00:26:28,090 --> 00:26:30,550
not use up a lot of my processors


360
00:26:30,550 --> 00:26:33,480
actually this conference here takes


361
00:26:33,480 --> 00:26:36,310
takes up consumes up some time and then


362
00:26:36,310 --> 00:26:40,990
it just consumes say in in in some one


363
00:26:40,990 --> 00:26:44,320
processor it took 24 seconds now every


364
00:26:44,320 --> 00:26:47,490
processor is in use you see


365
00:26:47,490 --> 00:26:51,090
and it took five seconds okay so we get


366
00:26:51,090 --> 00:26:55,290
a performance increase of say a factor


367
00:26:55,290 --> 00:26:58,350
of five No roughly four point something


368
00:26:58,350 --> 00:27:01,290
reason is that he does not have all


369
00:27:01,290 --> 00:27:05,190
eight process was and this may be a


370
00:27:05,190 --> 00:27:07,100
small overhead and doing this


371
00:27:07,100 --> 00:27:11,760
colonization okay


372
00:27:11,760 --> 00:27:20,420
so there was a good question in the chat


373
00:27:20,420 --> 00:27:24,510
how does he know how to split up the


374
00:27:24,510 --> 00:27:29,250
stream so how many numbers of compute


375
00:27:29,250 --> 00:27:32,309
tasks is he using and this is actually a


376
00:27:32,309 --> 00:27:36,900
very good question so um he can check


377
00:27:36,900 --> 00:27:38,429
how many course


378
00:27:38,429 --> 00:27:41,550
how many parallel CPUs or how many CPUs


379
00:27:41,550 --> 00:27:46,740
the machine has and he uses


380
00:27:46,740 --> 00:27:52,159
as many worker threats as I have cause


381
00:27:52,159 --> 00:27:57,450
okay so and then he is cutting the


382
00:27:57,450 --> 00:28:02,370
problem into smaller packages but in


383
00:28:02,370 --> 00:28:06,169
this cutting there is maybe an issue


384
00:28:06,169 --> 00:28:09,330
remember the code of the Harton sequence


385
00:28:09,330 --> 00:28:12,210
or the funder corporate sequence if you


386
00:28:12,210 --> 00:28:13,860
look at the code of the front Accord


387
00:28:13,860 --> 00:28:16,380
sequence then you see that he is


388
00:28:16,380 --> 00:28:18,870
calculating the number from the index


389
00:28:18,870 --> 00:28:22,230
and actually this algorithm takes longer


390
00:28:22,230 --> 00:28:28,740
for larger indices so if you now cut


391
00:28:28,740 --> 00:28:33,929
your sequence into smaller packages it


392
00:28:33,929 --> 00:28:37,169
may happen that one package takes a lot


393
00:28:37,169 --> 00:28:40,380
longer than another package which means


394
00:28:40,380 --> 00:28:42,390
that for example if you have eight


395
00:28:42,390 --> 00:28:48,029
packages of work and seven of them just


396
00:28:48,029 --> 00:28:51,960
need one second but the last one needs


397
00:28:51,960 --> 00:28:56,399
10 second then in some if you do it


398
00:28:56,399 --> 00:29:00,690
sequentially you have maybe 17 seconds 7


399
00:29:00,690 --> 00:29:03,720
plus 10 but if you paralyze it you have


400
00:29:03,720 --> 00:29:06,149
10 seconds because it takes the time of


401
00:29:06,149 --> 00:29:09,779
the slowest package and you just have a


402
00:29:09,779 --> 00:29:12,840
factor of 1.7 performance and increase


403
00:29:12,840 --> 00:29:14,700
in this engine example which is a bit


404
00:29:14,700 --> 00:29:17,510
disappointing if you had eight cores


405
00:29:17,510 --> 00:29:21,029
so the question how he is actually


406
00:29:21,029 --> 00:29:25,350
splitting this up is important and this


407
00:29:25,350 --> 00:29:28,679
may be a reason to use another framework


408
00:29:28,679 --> 00:29:32,309
where you have more control on splitting


409
00:29:32,309 --> 00:29:35,010
this up you can of course use more


410
00:29:35,010 --> 00:29:40,450
threads which which somehow also will


411
00:29:40,450 --> 00:29:43,039
[Music]


412
00:29:43,039 --> 00:29:48,029
increase this parallelism you know but I


413
00:29:48,029 --> 00:29:50,880
have another example where we need more


414
00:29:50,880 --> 00:29:55,720
control on how to split these tasks


415
00:29:55,720 --> 00:29:58,440
so actually internally he has some some


416
00:29:58,440 --> 00:30:02,559
logic to split this up I can send you


417
00:30:02,559 --> 00:30:04,570
maybe some some reference where you can


418
00:30:04,570 --> 00:30:07,210
read about this I would like to make


419
00:30:07,210 --> 00:30:10,690
another example let's do the same with


420
00:30:10,690 --> 00:30:16,799
smears and twister for Mersenne twister


421
00:30:16,799 --> 00:30:23,710
I do not have skipped ahead at hand yeah


422
00:30:23,710 --> 00:30:29,009
so for example I would like to do this


423
00:30:29,009 --> 00:30:32,710
technique of starting Mason twister with


424
00:30:32,710 --> 00:30:34,659
different seats with different


425
00:30:34,659 --> 00:30:47,470
multicolored seats


426
00:30:47,470 --> 00:30:51,890
but actually I have a small question why


427
00:30:51,890 --> 00:30:55,940
not just use one Mason twister for all


428
00:30:55,940 --> 00:31:00,170
the parallel calculations and everybody


429
00:31:00,170 --> 00:31:03,890
just picks from the sequence a number


430
00:31:03,890 --> 00:31:06,590
and performs the calculation and then


431
00:31:06,590 --> 00:31:08,900
another one picks a number and performs


432
00:31:08,900 --> 00:31:11,470
the calculation so actually all the


433
00:31:11,470 --> 00:31:14,600
parallel calculations could share the


434
00:31:14,600 --> 00:31:17,150
same method twister and this is actually


435
00:31:17,150 --> 00:31:20,330
OK for Monte Carlo because the order in


436
00:31:20,330 --> 00:31:24,110
which we actually sum these sequences up


437
00:31:24,110 --> 00:31:29,660
does not matter so actually this example


438
00:31:29,660 --> 00:31:32,420
here of splitting a sequence in these


439
00:31:32,420 --> 00:31:35,240
packages it's just one possibility we


440
00:31:35,240 --> 00:31:38,230
could also just have a sequence which is


441
00:31:38,230 --> 00:31:45,860
index 0 1 2 3 4 5 6 7 and then we have


442
00:31:45,860 --> 00:31:49,580
index 8 9 10 and the first thread takes


443
00:31:49,580 --> 00:31:54,170
index 0 and 8 and so on here are 16 and


444
00:31:54,170 --> 00:31:57,560
the next one takes index 1 and even


445
00:31:57,560 --> 00:31:59,960
sometimes they skip one and they just


446
00:31:59,960 --> 00:32:04,520
consume the whole sequence that's sir


447
00:32:04,520 --> 00:32:06,920
possibility which is actually not on


448
00:32:06,920 --> 00:32:10,910
this slide you know just try and use the


449
00:32:10,910 --> 00:32:13,220
sequence in parallel now so maybe I


450
00:32:13,220 --> 00:32:20,210
write here one more alternative if the


451
00:32:20,210 --> 00:32:27,180
sequence allows this


452
00:32:27,180 --> 00:32:35,890
we can make a single sequence generator


453
00:32:35,890 --> 00:32:38,800
so you was a singular sequence generator


454
00:32:38,800 --> 00:32:50,710
from parallel slits


455
00:32:50,710 --> 00:32:54,710
okay so in order to be able to do this


456
00:32:54,710 --> 00:32:58,250
to generator has to be some kind has to


457
00:32:58,250 --> 00:33:01,340
have some kind of property yeah that


458
00:33:01,340 --> 00:33:03,320
allows this this is sometimes called


459
00:33:03,320 --> 00:33:07,190
thread safety so generator has to be


460
00:33:07,190 --> 00:33:10,659
thread safe


461
00:33:10,659 --> 00:33:16,930
you


462
00:33:16,930 --> 00:33:20,240
okay and this is a nice example which I


463
00:33:20,240 --> 00:33:25,280
would like to show you next so next


464
00:33:25,280 --> 00:33:30,740
example is test this integration of P


465
00:33:30,740 --> 00:33:40,360
with the Mezen Twista okay so uh let's


466
00:33:40,360 --> 00:33:50,180
you are quite a new test here let's call


467
00:33:50,180 --> 00:33:54,500
it test Mills end with stream maybe I


468
00:33:54,500 --> 00:34:01,570
also do first the sequential version


469
00:34:01,570 --> 00:34:12,110
okay so the P medicine the approximation


470
00:34:12,110 --> 00:34:20,230
with the Mason twister okay I have some


471
00:34:20,230 --> 00:34:23,330
generator maybe I'd like to use here the


472
00:34:23,330 --> 00:34:26,600
same code as here above so with the


473
00:34:26,600 --> 00:34:28,700
integer stream just to make it more


474
00:34:28,700 --> 00:34:30,500
similar you can also directly generate a


475
00:34:30,500 --> 00:34:33,200
Babel stream with some generator


476
00:34:33,200 --> 00:34:36,770
but to make it more similar let's just


477
00:34:36,770 --> 00:34:40,730
copy this code here so you really see


478
00:34:40,730 --> 00:34:43,070
that it's a fair comparison because we


479
00:34:43,070 --> 00:34:46,419
are doing the same thing again so let's


480
00:34:46,419 --> 00:34:57,650
call this here P MSN and okay and I


481
00:34:57,650 --> 00:35:00,020
remove the parallel so it is sequential


482
00:35:00,020 --> 00:35:03,740
and here inside I would like to create


483
00:35:03,740 --> 00:35:06,470
this random number from a Mersenne


484
00:35:06,470 --> 00:35:08,510
twister and the Mayerson twister


485
00:35:08,510 --> 00:35:10,550
implementation which i would like to use


486
00:35:10,550 --> 00:35:15,740
is that of Apache Commons math so there


487
00:35:15,740 --> 00:35:20,200
is a library that has a Mersenne twister


488
00:35:20,200 --> 00:35:22,550
implementation


489
00:35:22,550 --> 00:35:25,410
so let me write to see explicitly it so


490
00:35:25,410 --> 00:35:26,640
that you see which kind of


491
00:35:26,640 --> 00:35:30,870
implementation I use okay and the


492
00:35:30,870 --> 00:35:33,840
argument here is some seed of the


493
00:35:33,840 --> 00:35:35,640
Mersenne twister so let's use some


494
00:35:35,640 --> 00:35:37,890
number as an initial value of the


495
00:35:37,890 --> 00:35:40,290
generator and we have here a random


496
00:35:40,290 --> 00:35:42,330
number generator and you know that the


497
00:35:42,330 --> 00:35:44,490
Mersenne twister is a soy de vendor


498
00:35:44,490 --> 00:35:46,620
number generator so in order to generate


499
00:35:46,620 --> 00:35:48,900
a two dimensional sequence from a one


500
00:35:48,900 --> 00:35:50,730
dimensional sequence we can make the


501
00:35:50,730 --> 00:35:53,790
click to populate the random vector one


502
00:35:53,790 --> 00:35:57,050
by the other now so the first element is


503
00:35:57,050 --> 00:36:03,900
here the random number from the sequence


504
00:36:03,900 --> 00:36:06,360
generator and then we just pick another


505
00:36:06,360 --> 00:36:11,640
independent so iid simple number for the


506
00:36:11,640 --> 00:36:14,130
second component so very easy this is


507
00:36:14,130 --> 00:36:17,850
the medicine twister implementation okay


508
00:36:17,850 --> 00:36:20,160
you see here the index is actually I is


509
00:36:20,160 --> 00:36:21,600
not used huh


510
00:36:21,600 --> 00:36:24,090
so it's maybe a bit strange to use here


511
00:36:24,090 --> 00:36:26,130
this integer sequence and then transform


512
00:36:26,130 --> 00:36:30,050
it to the dab and never use the I but


513
00:36:30,050 --> 00:36:33,540
that's just to keep the example similar


514
00:36:33,540 --> 00:36:36,870
to the previous one so this here is an


515
00:36:36,870 --> 00:36:42,030
SN it is sequential and as is using the


516
00:36:42,030 --> 00:36:46,560
stream API okay so let's check how this


517
00:36:46,560 --> 00:36:50,160
performs so I have to do this test here


518
00:36:50,160 --> 00:36:59,400
I call this test here with our twenty


519
00:36:59,400 --> 00:37:04,350
million twenty two hundred million 200


520
00:37:04,350 --> 00:37:13,460
million sample points okay so let's try


521
00:37:13,460 --> 00:37:16,950
so maybe I should cut out the first one


522
00:37:16,950 --> 00:37:18,960
because it is always taking twenty


523
00:37:18,960 --> 00:37:21,900
seconds but again you see now the first


524
00:37:21,900 --> 00:37:24,240
approximation is running sequentially


525
00:37:24,240 --> 00:37:27,810
the computer cause are not very busy


526
00:37:27,810 --> 00:37:30,780
yeah you will print out the result and


527
00:37:30,780 --> 00:37:33,450
after that the second simulation run


528
00:37:33,450 --> 00:37:36,400
starts in parallel and the computer core


529
00:37:36,400 --> 00:37:40,810
we'll become very busy now for a few


530
00:37:40,810 --> 00:37:44,080
seconds now and he has the result after


531
00:37:44,080 --> 00:37:47,140
five seconds okay now it's not busy


532
00:37:47,140 --> 00:37:48,940
enough the computer of course are not


533
00:37:48,940 --> 00:37:51,420
busy we are in the example of methane


534
00:37:51,420 --> 00:37:55,090
okay and it takes seven seconds so maybe


535
00:37:55,090 --> 00:37:58,750
I move here a few points away one two or


536
00:37:58,750 --> 00:38:08,980
three okay and you see that mess then I


537
00:38:08,980 --> 00:38:12,060
actually took seven seconds without


538
00:38:12,060 --> 00:38:15,490
paralyzation yeah so it is a factor of


539
00:38:15,490 --> 00:38:19,060
three faster then using the heart in


540
00:38:19,060 --> 00:38:21,190
sequence and this difference will


541
00:38:21,190 --> 00:38:23,170
actually increase because the Horten


542
00:38:23,170 --> 00:38:25,720
sequence becomes slower and slower for


543
00:38:25,720 --> 00:38:29,410
higher indices and also the Horten


544
00:38:29,410 --> 00:38:31,870
sequence is now two dimensional if you


545
00:38:31,870 --> 00:38:34,210
use a three dimensional the difference


546
00:38:34,210 --> 00:38:37,360
will also be even more prominent yeah so


547
00:38:37,360 --> 00:38:40,990
you see now it is not parallel this is


548
00:38:40,990 --> 00:38:42,940
the methane calculation currently


549
00:38:42,940 --> 00:38:46,660
running and it takes seven seconds you


550
00:38:46,660 --> 00:38:49,450
also see here that the pseudo-random


551
00:38:49,450 --> 00:38:57,030
number generator is a bit


552
00:38:57,030 --> 00:39:04,120
less accurate no so if you go back here


553
00:39:04,120 --> 00:39:06,730
you see this is 10 to the minus 6 for


554
00:39:06,730 --> 00:39:13,780
Holton 10 to the minus 4 for the math


555
00:39:13,780 --> 00:39:16,420
and Trista yeah so if we go back here


556
00:39:16,420 --> 00:39:24,400
and I'll make a small remark here so we


557
00:39:24,400 --> 00:39:29,610
perform this simulation with n equal to


558
00:39:29,610 --> 00:39:35,880
2 times 10 to the 8th which means that


559
00:39:35,880 --> 00:39:40,450
Monte Carlo now so Monte Carlo is 1


560
00:39:40,450 --> 00:39:45,060
divided by square root of n which is


561
00:39:45,060 --> 00:39:49,270
approximately one point four so one


562
00:39:49,270 --> 00:39:50,590
divided by one point four which is


563
00:39:50,590 --> 00:39:53,770
approximately 10 to the minus four which


564
00:39:53,770 --> 00:39:57,670
is actually what we see here 10 to the


565
00:39:57,670 --> 00:40:05,310
minus four


566
00:40:05,310 --> 00:40:09,280
so for pseudo-random number generator


567
00:40:09,280 --> 00:40:16,290
and for the Horten sequence we had log n


568
00:40:16,290 --> 00:40:25,180
to the power of T divided by n so


569
00:40:25,180 --> 00:40:30,960
which is approximately 10 to the minus 6


570
00:40:30,960 --> 00:40:39,130
for Alton okay that's nice now so we see


571
00:40:39,130 --> 00:40:42,420
that actually the mathematical result is


572
00:40:42,420 --> 00:40:46,660
coming out exactly from from this so you


573
00:40:46,660 --> 00:40:50,200
see there's a factor of 100 between the


574
00:40:50,200 --> 00:40:54,069
two in accuracy but there's also some


575
00:40:54,069 --> 00:40:58,150
kind of a factor of 3 something in the


576
00:40:58,150 --> 00:41:01,180
performance and this ratio will change


577
00:41:01,180 --> 00:41:04,119
if you have higher dimensional problems


578
00:41:04,119 --> 00:41:06,130
and some at a certain level monitor car


579
00:41:06,130 --> 00:41:09,039
was with pseudo pseudo-random number


580
00:41:09,039 --> 00:41:12,880
generator this is better okay but look


581
00:41:12,880 --> 00:41:15,819
that this is Mayor Zen with our


582
00:41:15,819 --> 00:41:18,609
parallelization so we can become even


583
00:41:18,609 --> 00:41:24,690
faster so let's do mayor send with a


584
00:41:24,690 --> 00:41:29,559
parallel stream okay so I just do a new


585
00:41:29,559 --> 00:41:32,650
test here called it's parallel I call


586
00:41:32,650 --> 00:41:38,550
this test here true


587
00:41:38,550 --> 00:41:43,480
perform the calculation okay and I do


588
00:41:43,480 --> 00:41:47,319
this tiny little change that I call here


589
00:41:47,319 --> 00:41:50,500
please perform all the calculations in


590
00:41:50,500 --> 00:41:52,930
parallel on your computer on your


591
00:41:52,930 --> 00:41:56,619
threads on your course okay so let's run


592
00:41:56,619 --> 00:42:00,760
this little program so in order to save


593
00:42:00,760 --> 00:42:03,849
a little bit time yeah we know by now


594
00:42:03,849 --> 00:42:06,670
that the sequential Halton takes about


595
00:42:06,670 --> 00:42:10,059
20 seconds let's comment this out so I


596
00:42:10,059 --> 00:42:12,790
only run the other examples so he will


597
00:42:12,790 --> 00:42:18,300
start with parallel Halton okay so he's


598
00:42:18,300 --> 00:42:23,540
getting fast


599
00:42:23,540 --> 00:42:26,690
okay so parallel Horton and I get some


600
00:42:26,690 --> 00:42:31,280
kind of ever okay so that's strange


601
00:42:31,280 --> 00:42:34,160
so where does this arrow come from so it


602
00:42:34,160 --> 00:42:36,380
must come from our new part of code and


603
00:42:36,380 --> 00:42:38,750
so let's comment all the others out and


604
00:42:38,750 --> 00:42:46,180
run again so I run again


605
00:42:46,180 --> 00:42:52,789
you


606
00:42:52,789 --> 00:42:54,250
oops I


607
00:42:54,250 --> 00:42:57,370
I made a mistake I did the parallel here


608
00:42:57,370 --> 00:43:00,190
in the sequential and not here and the


609
00:43:00,190 --> 00:43:04,150
parallel okay so here here it should be


610
00:43:04,150 --> 00:43:06,570
this is our court where we want to do


611
00:43:06,570 --> 00:43:09,310
the power because that was just a


612
00:43:09,310 --> 00:43:16,480
sequential okay so if I now run this


613
00:43:16,480 --> 00:43:20,500
part of code here just messin streamers


614
00:43:20,500 --> 00:43:22,390
parallel we get an error


615
00:43:22,390 --> 00:43:28,150
so if I remove the word parallel the


616
00:43:28,150 --> 00:43:31,660
error is gone it's calculating the mess


617
00:43:31,660 --> 00:43:38,290
n sampling in sequential so 6 seconds 10


618
00:43:38,290 --> 00:43:40,300
to the minus 4 if I add the word


619
00:43:40,300 --> 00:43:50,250
parallel


620
00:43:50,250 --> 00:43:53,640
I get some stranger


621
00:43:53,640 --> 00:43:57,480
so let's investigate this error so you


622
00:43:57,480 --> 00:43:59,970
see there is some index out of bounds


623
00:43:59,970 --> 00:44:04,980
exception here a strange number 624


624
00:44:04,980 --> 00:44:07,800
actually this number reminds us of the


625
00:44:07,800 --> 00:44:10,610
dimension in which Mersenne twister is


626
00:44:10,610 --> 00:44:13,890
uniform distributed at most so the


627
00:44:13,890 --> 00:44:15,810
highest dimension we can we can we can


628
00:44:15,810 --> 00:44:20,520
use or we should use and we get this


629
00:44:20,520 --> 00:44:22,950
index out of bounds exception if we run


630
00:44:22,950 --> 00:44:33,090
in parallel and this problem is due to


631
00:44:33,090 --> 00:44:34,890
the fact that actually the Mersenne


632
00:44:34,890 --> 00:44:37,710
twister application implemented is not


633
00:44:37,710 --> 00:44:41,940
set safe so there is an issue called


634
00:44:41,940 --> 00:44:45,840
sketch safety which is important so if


635
00:44:45,840 --> 00:44:48,830
you have multiple threads yeah so


636
00:44:48,830 --> 00:44:53,880
multiple parallel worker threads which


637
00:44:53,880 --> 00:44:57,360
access say a common variable so some


638
00:44:57,360 --> 00:45:00,510
counter was the Montecarlo seed or


639
00:45:00,510 --> 00:45:04,320
whatever and they access this variable


640
00:45:04,320 --> 00:45:07,140
in parallel then this may lead to


641
00:45:07,140 --> 00:45:12,180
inconsistent States for example you have


642
00:45:12,180 --> 00:45:15,150
say some variable where you count


643
00:45:15,150 --> 00:45:19,410
something one sweat is counting up then


644
00:45:19,410 --> 00:45:22,320
the sweat is assuming that this variable


645
00:45:22,320 --> 00:45:28,260
is one larger than the previous value


646
00:45:28,260 --> 00:45:31,050
he's performing some calculations which


647
00:45:31,050 --> 00:45:34,560
used his variable but then another


648
00:45:34,560 --> 00:45:38,730
parallel set is also counting up then it


649
00:45:38,730 --> 00:45:40,590
may happen that the first part of the


650
00:45:40,590 --> 00:45:44,640
first set has used in our I plus 1 and


651
00:45:44,640 --> 00:45:47,730
the second part uses I plus 2 but he or


652
00:45:47,730 --> 00:45:49,830
he assumed that nobody had changed this


653
00:45:49,830 --> 00:45:53,430
variable so there are some basic rules


654
00:45:53,430 --> 00:45:56,430
how you can avoid this but before we can


655
00:45:56,430 --> 00:45:58,290
discuss this I would like to actually


656
00:45:58,290 --> 00:46:01,740
show you what has happened here so you


657
00:46:01,740 --> 00:46:03,700
see there's this index out of town


658
00:46:03,700 --> 00:46:06,520
exception here in the implementation of


659
00:46:06,520 --> 00:46:10,119
the Apache common math math and Twista


660
00:46:10,119 --> 00:46:12,730
and he tells us that this is in unison


661
00:46:12,730 --> 00:46:17,740
twister in line 252 if I click this he


662
00:46:17,740 --> 00:46:19,210
will jump to the court where this


663
00:46:19,210 --> 00:46:23,200
happens okay so this is ugly code that


664
00:46:23,200 --> 00:46:26,369
performs the messin twister calculation


665
00:46:26,369 --> 00:46:30,790
okay and you see that there is some kind


666
00:46:30,790 --> 00:46:34,630
of array this array empty here which


667
00:46:34,630 --> 00:46:37,839
generates the next value and actually


668
00:46:37,839 --> 00:46:39,970
Mason twister works in the following way


669
00:46:39,970 --> 00:46:46,660
that he will generate 624 values in a


670
00:46:46,660 --> 00:46:49,869
single block so he's not generating one


671
00:46:49,869 --> 00:46:52,240
random number from the previous one he's


672
00:46:52,240 --> 00:46:55,300
generating 624 random numbers from the


673
00:46:55,300 --> 00:46:58,510
previous 624 random numbers so actually


674
00:46:58,510 --> 00:47:00,790
it's like linear congruential random


675
00:47:00,790 --> 00:47:04,500
number generator with a very big number


676
00:47:04,500 --> 00:47:10,000
okay so he's storing these 624 numbers


677
00:47:10,000 --> 00:47:13,180
in this array so whenever you ask him


678
00:47:13,180 --> 00:47:16,540
he's checking is your current index


679
00:47:16,540 --> 00:47:19,690
larger than this number so if you over


680
00:47:19,690 --> 00:47:21,579
here over this number you see that this


681
00:47:21,579 --> 00:47:25,869
is 624 yeah so if this number is


682
00:47:25,869 --> 00:47:28,720
actually larger or equal so the he's


683
00:47:28,720 --> 00:47:33,030
beyond the 624 numbers


684
00:47:33,030 --> 00:47:36,300
yes then he will generate the new


685
00:47:36,300 --> 00:47:40,590
numbers and at the end he sets the index


686
00:47:40,590 --> 00:47:43,350
to zero and you can ask for the next


687
00:47:43,350 --> 00:47:46,650
numbers so if you are below this number


688
00:47:46,650 --> 00:47:49,470
you will just get the next number okay


689
00:47:49,470 --> 00:47:51,420
and now you immediately see maybe what


690
00:47:51,420 --> 00:47:54,710
happened here we have parallel threads


691
00:47:54,710 --> 00:47:59,300
in parallel asking for the next number


692
00:47:59,300 --> 00:48:06,210
okay so the first set was here and the


693
00:48:06,210 --> 00:48:13,590
number was may be smaller than the end


694
00:48:13,590 --> 00:48:17,070
now so he was not asking for the next


695
00:48:17,070 --> 00:48:22,140
one so the next thread was here and the


696
00:48:22,140 --> 00:48:25,290
number was also smaller than the end so


697
00:48:25,290 --> 00:48:28,290
he does not generate a new one and he


698
00:48:28,290 --> 00:48:30,390
would like to ask for the next one so


699
00:48:30,390 --> 00:48:33,390
now assume that your index is 606


700
00:48:33,390 --> 00:48:36,930
hundred twenty three and two thread walk


701
00:48:36,930 --> 00:48:40,230
along this in parallel so they will skip


702
00:48:40,230 --> 00:48:43,050
this part here and there are two threads


703
00:48:43,050 --> 00:48:46,530
asking for this number but there's only


704
00:48:46,530 --> 00:48:50,730
one number left now so the next set is


705
00:48:50,730 --> 00:48:53,940
actually seeing here the increment from


706
00:48:53,940 --> 00:48:56,370
the previous thread and he is requesting


707
00:48:56,370 --> 00:49:00,990
a number which did not exist so to avoid


708
00:49:00,990 --> 00:49:04,830
this problem you have to actually allow


709
00:49:04,830 --> 00:49:09,390
only one threat to enter this piece of


710
00:49:09,390 --> 00:49:16,290
code here okay so this can be done with


711
00:49:16,290 --> 00:49:19,470
a verge called synchronize so this is


712
00:49:19,470 --> 00:49:21,780
maybe in a most potent way of fixing


713
00:49:21,780 --> 00:49:28,740
this issue so you can


714
00:49:28,740 --> 00:49:35,400
denies the excess to a threat then the


715
00:49:35,400 --> 00:49:39,810
exit access to to available by using the


716
00:49:39,810 --> 00:49:42,840
word synchronized so this is that only


717
00:49:42,840 --> 00:49:47,400
one thread is allowed to actually


718
00:49:47,400 --> 00:49:50,700
perform this modification and then when


719
00:49:50,700 --> 00:49:54,080
it's done the other set is allowed to


720
00:49:54,080 --> 00:49:58,410
enter this code so if the threads need


721
00:49:58,410 --> 00:50:01,410
to modify a common shared field or


722
00:50:01,410 --> 00:50:03,869
object so in our case this is the


723
00:50:03,869 --> 00:50:13,320
counter inside the SN Twista then the


724
00:50:13,320 --> 00:50:17,880
access has to be synchronized there are


725
00:50:17,880 --> 00:50:20,910
other tips how you can avoid such


726
00:50:20,910 --> 00:50:24,240
problems for example the good thing is


727
00:50:24,240 --> 00:50:28,230
that to use only read-only access if


728
00:50:28,230 --> 00:50:33,420
possible then if you do not modify a


729
00:50:33,420 --> 00:50:35,160
variable it should if you just read it


730
00:50:35,160 --> 00:50:38,460
this problem does not occur or if you


731
00:50:38,460 --> 00:50:41,940
have some kind of counter and it is


732
00:50:41,940 --> 00:50:43,800
possible that every thread has its


733
00:50:43,800 --> 00:50:48,180
individual encounter so the variable


734
00:50:48,180 --> 00:50:54,240
exists in every thread on its own so say


735
00:50:54,240 --> 00:50:56,400
this me this is sometimes called that


736
00:50:56,400 --> 00:50:59,310
the variable is thread-local now then


737
00:50:59,310 --> 00:51:03,240
this problem also does not occur because


738
00:51:03,240 --> 00:51:06,390
every set has its own counter and they


739
00:51:06,390 --> 00:51:10,890
do not interfere I will show you the two


740
00:51:10,890 --> 00:51:13,560
solutions of introducing a thread local


741
00:51:13,560 --> 00:51:19,619
and of synchronization let's try it with


742
00:51:19,619 --> 00:51:27,530
synchronization okay so


743
00:51:27,530 --> 00:51:31,160
maybe I'm a bit reporter and I add here


744
00:51:31,160 --> 00:51:40,400
a synchronized around this block so this


745
00:51:40,400 --> 00:51:42,830
means that actually only one thread is


746
00:51:42,830 --> 00:51:46,490
allowed to enter this block here this


747
00:51:46,490 --> 00:51:49,010
solution is actually a bit stupid but I


748
00:51:49,010 --> 00:51:51,920
just want to show you then it works so


749
00:51:51,920 --> 00:51:55,940
we have a parallel execution but I do


750
00:51:55,940 --> 00:51:59,000
not allow that this critical part here


751
00:51:59,000 --> 00:52:04,370
is calculated by two threads


752
00:52:04,370 --> 00:52:07,640
simultaneously because inside the messin


753
00:52:07,640 --> 00:52:11,390
here next double so there is this


754
00:52:11,390 --> 00:52:14,950
function next called and two threads


755
00:52:14,950 --> 00:52:18,770
modify the counter at the same time not


756
00:52:18,770 --> 00:52:21,470
checking that we are very close to the


757
00:52:21,470 --> 00:52:23,570
bound now because we have already passed


758
00:52:23,570 --> 00:52:30,140
this point here and which then results


759
00:52:30,140 --> 00:52:32,150
that one thread is beyond the size of


760
00:52:32,150 --> 00:52:36,400
this array okay so if I now run this


761
00:52:36,400 --> 00:52:38,870
experiment yeah so maybe I can also


762
00:52:38,870 --> 00:52:42,170
enable all the others here so we maybe


763
00:52:42,170 --> 00:52:48,560
not all xxii Horten sequence sequential


764
00:52:48,560 --> 00:52:50,870
can be may be skipped but the other ones


765
00:52:50,870 --> 00:52:52,880
are may be fast enough so we have fought


766
00:52:52,880 --> 00:52:57,110
in parallel with five point second five


767
00:52:57,110 --> 00:52:59,510
point seven seconds we have may ascend


768
00:52:59,510 --> 00:53:02,830
with seven seconds ten to the minus four


769
00:53:02,830 --> 00:53:05,510
using sequential and now comes to


770
00:53:05,510 --> 00:53:08,120
parallel and what you see here that is


771
00:53:08,120 --> 00:53:11,000
the process was a little bit more busy


772
00:53:11,000 --> 00:53:14,210
but actually he is not using up all the


773
00:53:14,210 --> 00:53:16,400
processors and the reason is that


774
00:53:16,400 --> 00:53:20,570
actually this verge here blocks the


775
00:53:20,570 --> 00:53:24,260
parallelism because this plot here can


776
00:53:24,260 --> 00:53:28,730
be only entered by one thread at a time


777
00:53:28,730 --> 00:53:31,970
and you see that now the time is almost


778
00:53:31,970 --> 00:53:37,950
s verse as sequential halt


779
00:53:37,950 --> 00:53:41,569
it's not only that we blocked the


780
00:53:41,569 --> 00:53:45,180
parallelism so we have became sequential


781
00:53:45,180 --> 00:53:47,849
it's that we have now so much overhead


782
00:53:47,849 --> 00:53:50,099
in parallelizing and then we are


783
00:53:50,099 --> 00:53:52,559
removing the parallelism that it is


784
00:53:52,559 --> 00:53:56,640
actually slower so maybe you say that we


785
00:53:56,640 --> 00:54:00,000
only need to block the generation of the


786
00:54:00,000 --> 00:54:02,970
random numbers so let's pluck only the


787
00:54:02,970 --> 00:54:05,880
generation of the random numbers and the


788
00:54:05,880 --> 00:54:08,369
rest of the calculation can be performed


789
00:54:08,369 --> 00:54:11,069
in parallel which would look like this


790
00:54:11,069 --> 00:54:15,750
so you have a random vector ax the


791
00:54:15,750 --> 00:54:17,490
generation of the random vector is not


792
00:54:17,490 --> 00:54:20,839
allowed to be parallel okay


793
00:54:20,839 --> 00:54:27,059
but each butBut the calculation then if


794
00:54:27,059 --> 00:54:30,420
you are inside the unit cube is allowed


795
00:54:30,420 --> 00:54:33,480
to prepare there so in our example this


796
00:54:33,480 --> 00:54:37,079
doesn't cure a lot because actually the


797
00:54:37,079 --> 00:54:39,299
calculation of are we inside the unit


798
00:54:39,299 --> 00:54:42,180
cube or not is so fast so it does not


799
00:54:42,180 --> 00:54:44,970
matter in other problems this is maybe a


800
00:54:44,970 --> 00:54:51,450
good solution to have a synchronized


801
00:54:51,450 --> 00:54:53,970
around generation of the random numbers


802
00:54:53,970 --> 00:54:57,420
but still it is here not a very good


803
00:54:57,420 --> 00:54:59,400
solution because it takes much longer


804
00:54:59,400 --> 00:55:00,630
you know


805
00:55:00,630 --> 00:55:03,799
then actually the sequential version


806
00:55:03,799 --> 00:55:06,510
this the sequential version is five


807
00:55:06,510 --> 00:55:11,040
seconds here it is still 1970 seconds so


808
00:55:11,040 --> 00:55:14,309
maybe next idea is just to synchronize


809
00:55:14,309 --> 00:55:18,510
each individual s XS which would be like


810
00:55:18,510 --> 00:55:24,770
this okay does this help


811
00:55:24,770 --> 00:55:28,470
so I synchronize the access to the


812
00:55:28,470 --> 00:55:33,059
Mersenne twister yeah but okay


813
00:55:33,059 --> 00:55:36,349
I can I can tell you it does not help


814
00:55:36,349 --> 00:55:40,319
okay so you see that actually with this


815
00:55:40,319 --> 00:55:42,829
implementation of Mayerson


816
00:55:42,829 --> 00:55:47,849
using the stream API it's very difficult


817
00:55:47,849 --> 00:55:50,730
to perform a parallelization


818
00:55:50,730 --> 00:55:52,800
I wouldn't say it is impossible with the


819
00:55:52,800 --> 00:55:54,840
same API the following trick can be also


820
00:55:54,840 --> 00:55:57,450
done with the stream API but I would


821
00:55:57,450 --> 00:56:00,030
like to show you now an alternative


822
00:56:00,030 --> 00:56:06,350
where I perform a parallel execution


823
00:56:06,350 --> 00:56:13,160
make sure there should be parallel here


824
00:56:13,160 --> 00:56:18,780
okay so let's let's go to the cleaner


825
00:56:18,780 --> 00:56:20,940
version of the code here where the


826
00:56:20,940 --> 00:56:23,460
synchronize was around this looks like


827
00:56:23,460 --> 00:56:31,020
bit a bit nicer okay so I would like to


828
00:56:31,020 --> 00:56:36,330
show you an alternative framework so


829
00:56:36,330 --> 00:56:40,119
here on our list


830
00:56:40,119 --> 00:56:43,880
there was distress Java stream API so it


831
00:56:43,880 --> 00:56:49,900
is very easy to parent an eyes with a


832
00:56:49,900 --> 00:56:52,369
stream parallelize the stream by just


833
00:56:52,369 --> 00:56:54,710
adding the word parallel but the code


834
00:56:54,710 --> 00:56:58,640
inside has to be independent of each


835
00:56:58,640 --> 00:56:59,269
other


836
00:56:59,269 --> 00:57:05,719
and has to be set safe okay so the next


837
00:57:05,719 --> 00:57:08,210
thing is an execute the execute of


838
00:57:08,210 --> 00:57:13,670
framework and Java futures so let's


839
00:57:13,670 --> 00:57:20,869
write this so I would like to test my


840
00:57:20,869 --> 00:57:23,900
sin with the so called executor


841
00:57:23,900 --> 00:57:29,950
framework for a given number of samples


842
00:57:29,950 --> 00:57:35,900
okay so in the executor framework you


843
00:57:35,900 --> 00:57:38,809
can get something which is called the


844
00:57:38,809 --> 00:57:42,710
executor and you can submit tasks to the


845
00:57:42,710 --> 00:57:45,380
executor and the executor is performing


846
00:57:45,380 --> 00:57:48,589
all the tasks in parallel okay so I


847
00:57:48,589 --> 00:57:51,049
would like to split now the number of


848
00:57:51,049 --> 00:57:53,900
tasks by hand so let's define some


849
00:57:53,900 --> 00:57:59,839
number of tasks so let's say I have 100


850
00:57:59,839 --> 00:58:00,799
tasks


851
00:58:00,799 --> 00:58:06,499
I would like to split my samples in 100


852
00:58:06,499 --> 00:58:09,710
packages so I have some number of


853
00:58:09,710 --> 00:58:12,619
samples per task so the number of


854
00:58:12,619 --> 00:58:15,229
samples per task is just the number of


855
00:58:15,229 --> 00:58:19,589
samples divided by the number of 

856
00:58:19,589 --> 00:58:19,599
samples divided by the number of 

857
00:58:19,599 --> 00:58:22,120
samples divided by the number of actually at this point you have to be a


858
00:58:22,120 --> 00:58:22,130
actually at this point you have to be a


859
00:58:22,130 --> 00:58:24,829
bit careful yeah that this integer


860
00:58:24,829 --> 00:58:26,390
division has no remainder


861
00:58:26,390 --> 00:58:28,460
otherwise you have to increase one


862
00:58:28,460 --> 00:58:31,789
package by this size of the remainder or


863
00:58:31,789 --> 00:58:34,430
have a specific package but in our case


864
00:58:34,430 --> 00:58:37,609
I don't care about this now because I


865
00:58:37,609 --> 00:58:40,430
know the integer division is is this is


866
00:58:40,430 --> 00:58:43,700
fine so there is something called an


867
00:58:43,700 --> 00:58:45,890
executor service


868
00:58:45,890 --> 00:58:49,430
and they are different


869
00:58:49,430 --> 00:58:57,770
such executors sorry executors well I


870
00:58:57,770 --> 00:59:04,690
see not liking my my ass okay III need


871
00:59:04,690 --> 00:59:07,340
executors I don't know maybe I write it


872
00:59:07,340 --> 00:59:09,920
by hand anomaly drugs okay so there are


873
00:59:09,920 --> 00:59:14,150
different such as to execute just and


874
00:59:14,150 --> 00:59:17,060
that's for example here the fixed sled


875
00:59:17,060 --> 00:59:21,230
pool executors yeah


876
00:59:21,230 --> 00:59:23,720
and you can specify how many parallel


877
00:59:23,720 --> 00:59:26,870
because how many parallels lets you use


878
00:59:26,870 --> 00:59:29,270
for this calculation you know so let's


879
00:59:29,270 --> 00:59:33,590
have here some number of threats and how


880
00:59:33,590 --> 00:59:37,370
many threats would I like to use maybe a


881
00:59:37,370 --> 00:59:41,090
good value as guidance it's the number


882
00:59:41,090 --> 00:59:44,660
of processors just use as many parallel


883
00:59:44,660 --> 00:59:47,570
workers as you have processors you can


884
00:59:47,570 --> 00:59:52,700
ask for the number of processors by


885
00:59:52,700 --> 00:59:54,890
using runtime get one time available


886
00:59:54,890 --> 01:00:00,110
processors so this is our value of the


887
01:00:00,110 --> 01:00:03,980
number of threads so now you can submit


888
01:00:03,980 --> 01:00:10,280
a working task to this executors so what


889
01:00:10,280 --> 01:00:13,940
do I like to do as a task I would like


890
01:00:13,940 --> 01:00:23,350
to calculate the approximation of P with


891
01:00:23,350 --> 01:00:28,060
Amazon twister but each melon twister


892
01:00:28,060 --> 01:00:31,060
for the task should use a different seat


893
01:00:31,060 --> 01:00:34,720
so actually on our list I used the first


894
01:00:34,720 --> 01:00:38,150
trick which was on our list use


895
01:00:38,150 --> 01:00:40,370
sequences with different seat wasn't


896
01:00:40,370 --> 01:00:42,920
recommended but it is here may be a way


897
01:00:42,920 --> 01:00:46,730
to paralyze the pseudo-random number


898
01:00:46,730 --> 01:00:49,000
generator


899
01:00:49,000 --> 01:01:00,119
so for this let's write a small function


900
01:01:00,119 --> 01:01:06,510
get approximation of P with methane


901
01:01:06,510 --> 01:01:12,310
which uses a given seat and uses a


902
01:01:12,310 --> 01:01:23,460
number of samples okay


903
01:01:23,460 --> 01:01:27,550
and then I submit this function with


904
01:01:27,550 --> 01:01:30,090
different seats to the parallel skirts


905
01:01:30,090 --> 01:01:33,040
so let's first generate the Mersenne


906
01:01:33,040 --> 01:01:37,050
twister so let's use this non set safe


907
01:01:37,050 --> 01:01:40,000
implementation from cut party common


908
01:01:40,000 --> 01:01:55,119
math and let's use this seat which is


909
01:01:55,119 --> 01:01:57,700
here our argument is the seed of this


910
01:01:57,700 --> 01:02:03,670
random number generator okay so now we


911
01:02:03,670 --> 01:02:07,599
have this random number generator let's


912
01:02:07,599 --> 01:02:13,089
calculate P from this maybe I just


913
01:02:13,089 --> 01:02:15,580
copied the cord which we had here and so


914
01:02:15,580 --> 01:02:25,310
it is just fair yeah


915
01:02:25,310 --> 01:02:29,070
okay I generate an in-stream with number


916
01:02:29,070 --> 01:02:33,500
of samples not parallel maybe to double


917
01:02:33,500 --> 01:02:36,750
and I do not need to synchronize here


918
01:02:36,750 --> 01:02:41,220
because every thread has its own local


919
01:02:41,220 --> 01:02:43,320
version of the lesson so they are


920
01:02:43,320 --> 01:02:47,940
independent okay and I returned this


921
01:02:47,940 --> 01:02:53,880
number okay so now I have here a


922
01:02:53,880 --> 01:02:59,690
sequential calculation of the lesson


923
01:02:59,690 --> 01:03:00,870
okay


924
01:03:00,870 --> 01:03:04,260
maybe also you you you can do the


925
01:03:04,260 --> 01:03:06,900
traditional one without the street if


926
01:03:06,900 --> 01:03:09,450
you like to see the court without the


927
01:03:09,450 --> 01:03:18,090
street you would right here Montecarlo


928
01:03:18,090 --> 01:03:29,270
some then you have an integer loop


929
01:03:29,270 --> 01:03:34,130
okay or instead of some I can just count


930
01:03:34,130 --> 01:03:45,200
the number of samples in unit circle


931
01:03:45,200 --> 01:03:51,349
okay then you have an integer loop which


932
01:03:51,349 --> 01:03:54,660
generates the random number and counts


933
01:03:54,660 --> 01:03:59,790
the number of so distance yet zero sorry


934
01:03:59,790 --> 01:04:03,030
that starts at zero and counts up if we


935
01:04:03,030 --> 01:04:08,630
are inside the unit circle this would be


936
01:04:08,630 --> 01:04:19,680
the version without stream and the value


937
01:04:19,680 --> 01:04:23,790
which should be returned is four times


938
01:04:23,790 --> 01:04:26,869
the number of samples in the unit circle


939
01:04:26,869 --> 01:04:34,609
divided by the number of total centers


940
01:04:34,609 --> 01:04:39,240
okay so either way he works


941
01:04:39,240 --> 01:04:41,760
yeah so this is now the approximation of


942
01:04:41,760 --> 01:04:47,550
P using a melon twister pseudo-random


943
01:04:47,550 --> 01:04:51,000
number generator with a given seat so


944
01:04:51,000 --> 01:04:56,400
now I continue here and I would like to


945
01:04:56,400 --> 01:05:03,869
have different such jobs with different


946
01:05:03,869 --> 01:05:06,060
seats so actually I use a random number


947
01:05:06,060 --> 01:05:14,760
generator to generate the seat this


948
01:05:14,760 --> 01:05:16,970
random number generator needs also some


949
01:05:16,970 --> 01:05:23,210
Montecarlo seat some seat and I use the


950
01:05:23,210 --> 01:05:33,810
Java random for this okay so and now


951
01:05:33,810 --> 01:05:38,480
let's submit to the executor our drop


952
01:05:38,480 --> 01:05:41,300
so you write executors dot submit and


953
01:05:41,300 --> 01:05:46,910
then you can just submit some tasks yeah


954
01:05:46,910 --> 01:05:52,609
so this task takes no argument but


955
01:05:52,609 --> 01:05:59,180
returns a value okay so the value is the


956
01:05:59,180 --> 01:06:05,390
value of P approximated so let's get the


957
01:06:05,390 --> 01:06:11,119
seat here see it is random seed dot next


958
01:06:11,119 --> 01:06:14,690
long okay so now it works and for this


959
01:06:14,690 --> 01:06:17,480
seed I would like to submit now a task


960
01:06:17,480 --> 01:06:21,020
ok the task is just a function with no


961
01:06:21,020 --> 01:06:24,290
argument so you do this break it open


962
01:06:24,290 --> 01:06:27,550
pack it close and it returns a value


963
01:06:27,550 --> 01:06:30,980
namely it returns the approximation of P


964
01:06:30,980 --> 01:06:34,430
with methane using this seat and here it


965
01:06:34,430 --> 01:06:43,670
uses number of samples per task ok this


966
01:06:43,670 --> 01:06:47,869
submits one such task to the executor so


967
01:06:47,869 --> 01:06:51,020
actually we would like to submit many


968
01:06:51,020 --> 01:07:01,460
tasks so how many tasks would we like to


969
01:07:01,460 --> 01:07:05,960
submit number of tasks is the number and


970
01:07:05,960 --> 01:07:12,740
I created loop around this which submits


971
01:07:12,740 --> 01:07:15,500
many different tasks to the executor so


972
01:07:15,500 --> 01:07:18,319
now the executor takes these tasks and


973
01:07:18,319 --> 01:07:21,980
works on parallel ok so you see this


974
01:07:21,980 --> 01:07:24,230
doing this parallelism by hand without


975
01:07:24,230 --> 01:07:26,089
the stream is a little bit more work


976
01:07:26,089 --> 01:07:28,250
yeah but actually we have much more


977
01:07:28,250 --> 01:07:31,599
control because we can explicitly


978
01:07:31,599 --> 01:07:35,000
specify how many tasks he should use and


979
01:07:35,000 --> 01:07:37,310
you can also specify how the tasks


980
01:07:37,310 --> 01:07:39,490
should be split now this is like


981
01:07:39,490 --> 01:07:44,119
advantage ok so where do we get the


982
01:07:44,119 --> 01:07:47,660
result ok the result is actually coming


983
01:07:47,660 --> 01:07:51,599
back here so I need some list


984
01:07:51,599 --> 01:08:05,809
of results where I collect all my result


985
01:08:05,809 --> 01:08:10,349
okay so the result from this function is


986
01:08:10,349 --> 01:08:14,279
a double okay


987
01:08:14,279 --> 01:08:17,639
but actually this cannot work because if


988
01:08:17,639 --> 01:08:20,099
I would like write this line he would


989
01:08:20,099 --> 01:08:22,920
have to wait for the executor to finish


990
01:08:22,920 --> 01:08:26,520
to get the result so I cannot get the


991
01:08:26,520 --> 01:08:28,949
result immediately but I can get


992
01:08:28,949 --> 01:08:31,589
something which gets me the result in


993
01:08:31,589 --> 01:08:36,799
the future so I get a handle to it and


994
01:08:36,799 --> 01:08:40,230
later I can ask for the result and


995
01:08:40,230 --> 01:08:43,230
actually this object which I get is


996
01:08:43,230 --> 01:08:43,920
called


997
01:08:43,920 --> 01:08:49,079
a future so a future is a value which


998
01:08:49,079 --> 01:08:51,690
you will get at a future point in time


999
01:08:51,690 --> 01:08:54,089
now so you get a handle on this value


1000
01:08:54,089 --> 01:08:56,819
and you can specify what kind of future


1001
01:08:56,819 --> 01:09:03,109
is it is a future value being a double


1002
01:09:03,109 --> 01:09:06,000
okay so this is what this executor


1003
01:09:06,000 --> 01:09:09,810
returns and I create here now a list of


1004
01:09:09,810 --> 01:09:13,380
such future values which are in the


1005
01:09:13,380 --> 01:09:17,579
future a double okay


1006
01:09:17,579 --> 01:09:24,540
and let's put this result here in this


1007
01:09:24,540 --> 01:09:31,540
list okay so this is


1008
01:09:31,540 --> 01:09:38,130
the first step distribute the vodka task


1009
01:09:38,130 --> 01:09:44,140
so we distribute all the tasks so now


1010
01:09:44,140 --> 01:09:46,569
all the tasks ran in parallel and we can


1011
01:09:46,569 --> 01:09:50,080
ask for the results so the next step is


1012
01:09:50,080 --> 01:10:00,940
collect the results so we can collect


1013
01:10:00,940 --> 01:10:05,650
the results in some so we do a loop over


1014
01:10:05,650 --> 01:10:12,940
all tasks again know and collect the


1015
01:10:12,940 --> 01:10:19,710
results so this is some is some plus


1016
01:10:19,710 --> 01:10:24,720
result besides I would like to have the


1017
01:10:24,720 --> 01:10:30,160
result corresponding to the first second


1018
01:10:30,160 --> 01:10:34,030
third and so on tasks this object here


1019
01:10:34,030 --> 01:10:37,030
is the so-called future and from this


1020
01:10:37,030 --> 01:10:45,150
future I can now get the double value


1021
01:10:45,150 --> 01:10:50,320
okay and here an exception can happen


1022
01:10:50,320 --> 01:10:53,889
yeah so I have to declare that an


1023
01:10:53,889 --> 01:10:55,960
exception can happen if the skate was


1024
01:10:55,960 --> 01:10:58,269
interrupted okay but let's don't care


1025
01:10:58,269 --> 01:11:02,880
about this so then our approximation is


1026
01:11:02,880 --> 01:11:06,610
a sum of different P approximations and


1027
01:11:06,610 --> 01:11:10,960
we just take the average of this so this


1028
01:11:10,960 --> 01:11:13,750
is sum divided by actually now divided


1029
01:11:13,750 --> 01:11:16,960
by the number of tasks so I take the


1030
01:11:16,960 --> 01:11:22,449
average of say 100 approximations each


1031
01:11:22,449 --> 01:11:27,429
approximations being the average of 2


1032
01:11:27,429 --> 01:11:30,960
million simulations


1033
01:11:30,960 --> 01:11:34,000
okay so that was a little bit lengthy


1034
01:11:34,000 --> 01:11:39,510
but it's now an example of calculating


1035
01:11:39,510 --> 01:11:42,790
this approximation in parallel using the


1036
01:11:42,790 --> 01:11:50,410
executor okay let's also calculate the


1037
01:11:50,410 --> 01:11:55,750
time yeah so the time in seconds is the


1038
01:11:55,750 --> 01:11:58,510
start time the end time minus the start


1039
01:11:58,510 --> 01:12:05,580
time so let's calculate here time end is


1040
01:12:05,580 --> 01:12:09,000
the current time in milliseconds and


1041
01:12:09,000 --> 01:12:12,700
also time start before we do all this


1042
01:12:12,700 --> 01:12:16,319
stuff here is


1043
01:12:16,319 --> 01:12:21,329
the current time in milliseconds No so


1044
01:12:21,329 --> 01:12:25,559
let's do it here so we can measure the


1045
01:12:25,559 --> 01:12:27,089
time how long this takes


1046
01:12:27,089 --> 01:12:31,280
so I hope I wrote everything correctly


1047
01:12:31,280 --> 01:12:36,209
maybe again the code is not so long yeah


1048
01:12:36,209 --> 01:12:38,789
it's just these lines and it has two


1049
01:12:38,789 --> 01:12:41,280
parts first we distribute all the


1050
01:12:41,280 --> 01:12:44,280
calculations second we collect all the


1051
01:12:44,280 --> 01:12:48,419
results these calls here run as in


1052
01:12:48,419 --> 01:12:51,329
Chronos Li in parallel so i can submit


1053
01:12:51,329 --> 01:12:54,299
more tasks and again and he's just


1054
01:12:54,299 --> 01:12:56,419
collecting the tasks and working on it


1055
01:12:56,419 --> 01:13:01,199
this call here is synchronizing so this


1056
01:13:01,199 --> 01:13:03,319
call is waiting for the task to finish


1057
01:13:03,319 --> 01:13:06,389
but at this point we can wait for the


1058
01:13:06,389 --> 01:13:09,089
first task to finish because all the


1059
01:13:09,089 --> 01:13:12,419
other tasks are already running and it


1060
01:13:12,419 --> 01:13:14,189
also does not matter if the second task


1061
01:13:14,189 --> 01:13:18,030
ends before the first task before or if


1062
01:13:18,030 --> 01:13:21,299
because he will then wait for the first


1063
01:13:21,299 --> 01:13:23,849
task and then he immediately jumps to


1064
01:13:23,849 --> 01:13:25,409
the second one and sees the result is


1065
01:13:25,409 --> 01:13:27,719
already there now so this loops here


1066
01:13:27,719 --> 01:13:31,260
they it's as long as the slowest task


1067
01:13:31,260 --> 01:13:34,169
which is what we need because we need


1068
01:13:34,169 --> 01:13:42,239
all the values so let's add our last


1069
01:13:42,239 --> 01:13:48,780
test here test messin with executor to


1070
01:13:48,780 --> 01:13:53,489
our list and let's keep fingers crossed


1071
01:13:53,489 --> 01:13:57,439
and run this program


1072
01:13:57,439 --> 01:14:00,689
so now we do a test of the Horten


1073
01:14:00,689 --> 01:14:05,440
sequence approximation of pea


1074
01:14:05,440 --> 01:14:08,410
sequential in parallel using the star


1075
01:14:08,410 --> 01:14:11,800
chalice stream API we do this


1076
01:14:11,800 --> 01:14:13,900
same with absurdo random number


1077
01:14:13,900 --> 01:14:17,110
generation later with Zen twister


1078
01:14:17,110 --> 01:14:19,719
sequential and parallel and then we use


1079
01:14:19,719 --> 01:14:22,060
the executor framework you see the first


1080
01:14:22,060 --> 01:14:24,040
sequential one did not use all the


1081
01:14:24,040 --> 01:14:26,469
processors now we are going in parallel


1082
01:14:26,469 --> 01:14:28,810
we were faster we using all the


1083
01:14:28,810 --> 01:14:31,210
processors now we are going sequential


1084
01:14:31,210 --> 01:14:33,370
we are not using all the processors


1085
01:14:33,370 --> 01:14:36,610
partners and was quite fast now we have


1086
01:14:36,610 --> 01:14:40,270
this buggy implementation of using the


1087
01:14:40,270 --> 01:14:43,239
screen stream API where we synchronize


1088
01:14:43,239 --> 01:14:46,380
inside and we lose all the performance


1089
01:14:46,380 --> 01:14:49,390
okay and the last one is messing with


1090
01:14:49,390 --> 01:14:53,620
executor so now he should maybe use all


1091
01:14:53,620 --> 01:14:59,199
processors and it is very fast okay it's


1092
01:14:59,199 --> 01:15:02,500
actually the fastest one 1.6 second you


1093
01:15:02,500 --> 01:15:07,770
know okay so this one is even faster


1094
01:15:07,770 --> 01:15:14,739
then the Horten parallelization yeah so


1095
01:15:14,739 --> 01:15:17,739
you see again the factor of 4 or 5


1096
01:15:17,739 --> 01:15:23,890
between Mason and Orton so Mason is


1097
01:15:23,890 --> 01:15:27,219
factor of 3 or 4 faster and now the


1098
01:15:27,219 --> 01:15:29,080
fastest thing we have is the power


1099
01:15:29,080 --> 01:15:33,640
they're messing you see that the result


1100
01:15:33,640 --> 01:15:36,130
here is different from this result here


1101
01:15:36,130 --> 01:15:41,320
why is that okay so maybe I add here on


1102
01:15:41,320 --> 01:15:48,840
two more digits to two more dots to be


1103
01:15:48,840 --> 01:15:55,329
bit nicer


1104
01:15:55,329 --> 01:15:59,110
so why is the result of methane using


1105
01:15:59,110 --> 01:16:02,139
the executor framework different from


1106
01:16:02,139 --> 01:16:08,619
the stream API the reason is that we are


1107
01:16:08,619 --> 01:16:11,440
using completely different sequences so


1108
01:16:11,440 --> 01:16:17,889
here we used one sequence with a single


1109
01:16:17,889 --> 01:16:24,159
seat okay here we are using many


1110
01:16:24,159 --> 01:16:26,290
different sequences with different seeds


1111
01:16:26,290 --> 01:16:30,400
the seeds are generated from another


1112
01:16:30,400 --> 01:16:32,860
sequence but actually the methane


1113
01:16:32,860 --> 01:16:35,050
sequences have different Montecarlo


1114
01:16:35,050 --> 01:16:36,849
seeds so they are completely different


1115
01:16:36,849 --> 01:16:40,119
sequences and you see I believe the


1116
01:16:40,119 --> 01:16:43,719
result was 7 times 10 to the minus 5 so


1117
01:16:43,719 --> 01:16:46,809
actually this sequence was by chance a


1118
01:16:46,809 --> 01:16:48,460
little bit better but you know that


1119
01:16:48,460 --> 01:16:50,550
Monte Carlo is actually just in


1120
01:16:50,550 --> 01:16:52,960
probability oh no it's a little bit


1121
01:16:52,960 --> 01:16:56,409
worse I see it's a little bit worse ok


1122
01:16:56,409 --> 01:16:58,329
so it was by chance a little bit worse


1123
01:16:58,329 --> 01:17:02,500
you can use a different number here and


1124
01:17:02,500 --> 01:17:11,739
maybe you get another you can also use


1125
01:17:11,739 --> 01:17:15,659
the executor framework to parallelize


1126
01:17:15,659 --> 01:17:20,290
the horton sequence and maybe I like to


1127
01:17:20,290 --> 01:17:22,389
do this because it's just copy and paste


1128
01:17:22,389 --> 01:17:25,900
it's not so much work yeah so get


1129
01:17:25,900 --> 01:17:29,679
approximation of P with me then I copy


1130
01:17:29,679 --> 01:17:34,119
this get approximation of P with Horton


1131
01:17:34,119 --> 01:17:39,250
and now I do not want to split using the


1132
01:17:39,250 --> 01:17:42,670
seed I want to split using the start


1133
01:17:42,670 --> 01:17:45,909
index of the secrets of the start index


1134
01:17:45,909 --> 01:17:49,719
of the sequence so this loop here goes


1135
01:17:49,719 --> 01:17:53,139
from start index to start index plus


1136
01:17:53,139 --> 01:17:56,559
number of samples and inside it uses a


1137
01:17:56,559 --> 01:17:59,020
horton sequence so I can get rid of this


1138
01:17:59,020 --> 01:18:01,630
mess in here


1139
01:18:01,630 --> 01:18:04,510
and inside are you is a heart in


1140
01:18:04,510 --> 01:18:09,250
sequence so Halton sequence dot get halt


1141
01:18:09,250 --> 01:18:13,360
a number four given base I and true for


1142
01:18:13,360 --> 01:18:17,110
the first component and I and three for


1143
01:18:17,110 --> 01:18:21,370
the second component okay so now I have


1144
01:18:21,370 --> 01:18:24,370
an approximation of P using the Horton


1145
01:18:24,370 --> 01:18:26,230
sequence with a different start index


1146
01:18:26,230 --> 01:18:30,430
and I would like to know now create as


1147
01:18:30,430 --> 01:18:33,310
we did here wisdom as n different


1148
01:18:33,310 --> 01:18:36,460
batches you know using the Horton


1149
01:18:36,460 --> 01:18:46,320
sequence okay so I copied this here test


1150
01:18:46,320 --> 01:18:50,200
Carlton and this is my last test now


1151
01:18:50,200 --> 01:18:54,250
Horton with executors so I'd like to run


1152
01:18:54,250 --> 01:18:58,690
this test also here test


1153
01:18:58,690 --> 01:19:03,250
Alton all this executors maybe we maybe


1154
01:19:03,250 --> 01:19:06,000
move it here so we have Horton and


1155
01:19:06,000 --> 01:19:12,760
messin tests okay and I need to modify


1156
01:19:12,760 --> 01:19:16,720
this code here so in this code we have


1157
01:19:16,720 --> 01:19:22,630
here 100 different tasks we create the


1158
01:19:22,630 --> 01:19:25,270
executor service this was needed to


1159
01:19:25,270 --> 01:19:28,600
generate random seats now this is not


1160
01:19:28,600 --> 01:19:32,140
needed because we do not use the gate


1161
01:19:32,140 --> 01:19:34,390
approximation business and we used to


1162
01:19:34,390 --> 01:19:37,360
get approximation with Halton for a


1163
01:19:37,360 --> 01:19:40,780
given start index so and what is the


1164
01:19:40,780 --> 01:19:43,650
start index the start index is just


1165
01:19:43,650 --> 01:19:50,260
which task am i working on


1166
01:19:50,260 --> 01:19:53,240
multiplied with number of samples per


1167
01:19:53,240 --> 01:19:55,430
task and also the first task goes from


1168
01:19:55,430 --> 01:20:00,080
zero to two million minus one and the


1169
01:20:00,080 --> 01:20:02,330
next one goes from two million to four


1170
01:20:02,330 --> 01:20:03,880
million minus one and so on


1171
01:20:03,880 --> 01:20:06,710
okay so you see this will be for the


1172
01:20:06,710 --> 01:20:08,930
first one two million but the two


1173
01:20:08,930 --> 01:20:10,580
million is not included in the loop now


1174
01:20:10,580 --> 01:20:12,890
because we start in zero okay so I have


1175
01:20:12,890 --> 01:20:16,130
created now a parallelization using the


1176
01:20:16,130 --> 01:20:20,770
execute of framework based e hot


1177
01:20:20,770 --> 01:20:26,440
sequence and let's scan this experiment


1178
01:20:26,440 --> 01:20:27,620
okay


1179
01:20:27,620 --> 01:20:30,140
so unfortunately running all the guys


1180
01:20:30,140 --> 01:20:32,750
takes so long yeah we have 20 seconds


1181
01:20:32,750 --> 01:20:36,140
for the first one you see processors are


1182
01:20:36,140 --> 01:20:44,030
not used up yeah it's sequential so I


1183
01:20:44,030 --> 01:20:47,690
hope I did everything all right then


1184
01:20:47,690 --> 01:20:50,690
what's the next one the next one is the


1185
01:20:50,690 --> 01:20:54,830
parallel Horton no which gives us the


1186
01:20:54,830 --> 01:20:58,580
same number much faster the next one is


1187
01:20:58,580 --> 01:21:01,210
hot and with executors which gives us


1188
01:21:01,210 --> 01:21:04,820
the same member almost there's a small


1189
01:21:04,820 --> 01:21:07,160
difference maybe you can think about


1190
01:21:07,160 --> 01:21:10,400
where the difference comes from and it


1191
01:21:10,400 --> 01:21:12,710
is faster it's actually one second


1192
01:21:12,710 --> 01:21:17,630
faster which is 20% you have faster


1193
01:21:17,630 --> 01:21:22,280
you're almost 20% then comes me as n in


1194
01:21:22,280 --> 01:21:26,030
sequential order which is similar to the


1195
01:21:26,030 --> 01:21:27,250
parallel yeah


1196
01:21:27,250 --> 01:21:30,410
the parallel Mezen using three was buggy


1197
01:21:30,410 --> 01:21:36,230
was slow no and we have here the very


1198
01:21:36,230 --> 01:21:38,780
fast messin with the executor framework


1199
01:21:38,780 --> 01:21:42,040
okay there is a surprising thing


1200
01:21:42,040 --> 01:21:44,570
parallelization usually the executor is


1201
01:21:44,570 --> 01:21:47,270
faster than using the stream and the


1202
01:21:47,270 --> 01:21:50,120
reason here is that actually very much


1203
01:21:50,120 --> 01:21:51,890
related to the question which we had in


1204
01:21:51,890 --> 01:21:54,260
the chat which we had from you how does


1205
01:21:54,260 --> 01:21:58,070
he know how to split the task so


1206
01:21:58,070 --> 01:22:00,230
actually he doesn't know a lot of our


1207
01:22:00,230 --> 01:22:03,170
problem so he uses some reasonable split


1208
01:22:03,170 --> 01:22:05,900
but the Horton sequence has the


1209
01:22:05,900 --> 01:22:09,440
unpleasant effect that later blocks take


1210
01:22:09,440 --> 01:22:13,970
longer than earlier blocks so actually


1211
01:22:13,970 --> 01:22:17,270
we should split it up into many small


1212
01:22:17,270 --> 01:22:19,970
blocks but I still would like to use


1213
01:22:19,970 --> 01:22:21,470
eights heads because if I use more


1214
01:22:21,470 --> 01:22:24,380
threads he will switch the threads


1215
01:22:24,380 --> 01:22:26,390
between the processors which takes time


1216
01:22:26,390 --> 01:22:28,640
actually I would like to use once that


1217
01:22:28,640 --> 01:22:31,730
pair processor and every thread works on


1218
01:22:31,730 --> 01:22:34,700
some task and the task should be small


1219
01:22:34,700 --> 01:22:37,730
enough such that he can distribute it


1220
01:22:37,730 --> 01:22:41,290
more evenly so if you just have here


1221
01:22:41,290 --> 01:22:45,020
actually the example is here eight


1222
01:22:45,020 --> 01:22:48,260
blocks he has a very large number of


1223
01:22:48,260 --> 01:22:53,270
blocks and one block is much slower than


1224
01:22:53,270 --> 01:22:55,640
the other one and the calculation takes


1225
01:22:55,640 --> 01:23:00,530
as long as the slowest block if you have


1226
01:23:00,530 --> 01:23:03,290
two small blocks it may be that the


1227
01:23:03,290 --> 01:23:07,160
overhead to schedule the task is too


1228
01:23:07,160 --> 01:23:09,770
large so here in this executor framework


1229
01:23:09,770 --> 01:23:12,470
you have much more control about the


1230
01:23:12,470 --> 01:23:15,170
size of this block and you can choose a


1231
01:23:15,170 --> 01:23:17,810
number which gives you then an even


1232
01:23:17,810 --> 01:23:18,580
faster


1233
01:23:18,580 --> 01:23:20,930
calculation now so if I have here an


1234
01:23:20,930 --> 01:23:28,370
eight it's maybe worse so let's let's


1235
01:23:28,370 --> 01:23:31,460
stop the calculation and just remove


1236
01:23:31,460 --> 01:23:41,840
this first one because it takes so long


1237
01:23:41,840 --> 01:23:46,080
okay so Alton parallel using stream so


1238
01:23:46,080 --> 01:23:47,760
now the difference is a little bit


1239
01:23:47,760 --> 01:23:50,790
smaller yeah it's only it's it's it's


1240
01:23:50,790 --> 01:23:52,860
not one second it's a little bit smaller


1241
01:23:52,860 --> 01:23:55,650
because we used a small number of blocks


1242
01:23:55,650 --> 01:24:00,320
to summarize I let it run all together


1243
01:24:00,320 --> 01:24:04,080
and we have seen many aspects in this


1244
01:24:04,080 --> 01:24:05,699
little experiment yeah for example


1245
01:24:05,699 --> 01:24:08,130
you've seen that you cannot paralyze


1246
01:24:08,130 --> 01:24:10,830
every code because it's not sweat safe


1247
01:24:10,830 --> 01:24:13,880
if you have code which is not set safe


1248
01:24:13,880 --> 01:24:18,239
you need to synchronize things but if


1249
01:24:18,239 --> 01:24:20,190
you use the stream API and just


1250
01:24:20,190 --> 01:24:22,290
synchronize the whole block you you you


1251
01:24:22,290 --> 01:24:26,130
you lose all the advantages okay this is


1252
01:24:26,130 --> 01:24:28,710
maybe trivia but maybe you should have


1253
01:24:28,710 --> 01:24:32,760
seen it once and if you'd like to have


1254
01:24:32,760 --> 01:24:38,580
finer control on splitting the worker


1255
01:24:38,580 --> 01:24:41,760
tasks then you can do this with this


1256
01:24:41,760 --> 01:24:45,300
executor framework I will commit this


1257
01:24:45,300 --> 01:24:48,570
code to our repo so you can use it maybe


1258
01:24:48,570 --> 01:24:55,230
as a blueprint for your examples or when


1259
01:24:55,230 --> 01:24:56,790
you read you like to do something in


1260
01:24:56,790 --> 01:24:59,310
parallel either use the stream API or


1261
01:24:59,310 --> 01:25:07,590
just use the executor brush and you see


1262
01:25:07,590 --> 01:25:11,289
in this two dimension Halton is actually


1263
01:25:11,289 --> 01:25:15,610
still better yeah it takes here a little


1264
01:25:15,610 --> 01:25:17,739
bit longer but it is a factor of 100


1265
01:25:17,739 --> 01:25:21,840
better but in higher dimension this


1266
01:25:21,840 --> 01:25:25,840
difference is shrinking and having a


1267
01:25:25,840 --> 01:25:28,530
fast pseudo-random number generator


1268
01:25:28,530 --> 01:25:31,630
parallelized is maybe then still the


1269
01:25:31,630 --> 01:25:35,860
best way to go okay so actually this was


1270
01:25:35,860 --> 01:25:38,699
quite exhaustive code session you know


1271
01:25:38,699 --> 01:25:42,400
and maybe there were many details inside


1272
01:25:42,400 --> 01:25:45,369
yeah that you do not need for the theory


1273
01:25:45,369 --> 01:25:49,690
for the next sections on theoretical


1274
01:25:49,690 --> 01:25:53,380
sections but I believe it's may be nice


1275
01:25:53,380 --> 01:25:57,070
to have seen this at least once and you


1276
01:25:57,070 --> 01:25:59,679
have also seen that the code you need to


1277
01:25:59,679 --> 01:26:02,260
pile and I something you know there's a


1278
01:26:02,260 --> 01:26:07,050
stream API or using the executor API


1279
01:26:07,050 --> 01:26:09,820
it's not so long and also executor is a


1280
01:26:09,820 --> 01:26:11,679
little bit longer you define your


1281
01:26:11,679 --> 01:26:14,499
executor you distribute your tasks you


1282
01:26:14,499 --> 01:26:17,139
collect the result yeah so maybe it's


1283
01:26:17,139 --> 01:26:23,159
bit longer but still fits on one page


1284
01:26:23,159 --> 01:26:25,539
okay so thanks for today


1285
01:26:25,539 --> 01:26:28,900
yeah so you have seen already the script


1286
01:26:28,900 --> 01:26:32,999
we will continue with generation of


1287
01:26:32,999 --> 01:26:38,400
random numbers with other distributions


1288
01:26:38,400 --> 01:26:42,570
so so far we have just looked at uniform


1289
01:26:42,570 --> 01:26:45,849
distributed random numbers so next


1290
01:26:45,849 --> 01:26:49,869
session will be on random number


1291
01:26:49,869 --> 01:26:52,539
sequences which have other distributions


1292
01:26:52,539 --> 01:26:54,309
like normal distribution exponential


1293
01:26:54,309 --> 01:26:57,280
distribution and so on for this we need


1294
01:26:57,280 --> 01:27:00,449
to prove some some small results and


1295
01:27:00,449 --> 01:27:02,979
have their nice applications in


1296
01:27:02,979 --> 01:27:05,729
mathematical finance



