Parallel calculations: Difference between revisions

→‎{{header|Perl 6}}: Expand on parallelization parameters
(→‎{{header|Perl 6}}: Expand on parallelization parameters)
Line 1,491:
Takes the list of numbers and converts them to a <tt>HyperSeq</tt> that is stored in a raw variable. Any <tt>HyperSeq</tt> overloads <tt>map</tt> and <tt>grep</tt> to convert and pick values in worker threads. The runtime will pick the number of OS-level threads and assign worker threads to them while avoiding stalling in any part of the program. A <tt>HyperSeq</tt> is lazy, so the computation of values will happen in chunks as they are requested.
 
The hyper (and race) method can take two parameters that will tweak how the parallelization occurs: :degree and :batch. :degree is the number of worker threads to allocate to the job. By default it is set to the number of physical cores available. If you have a hyper threading processor, and the tasks are not cpu bound, it may be useful to raise that number but it is a reasonable default. :degree is how many sub-tasks are parcelled out at a time to each worker thread. Default is 64. For small numbers of cpu intensive tasks a lower number will likely be better, but too low may make the dispatch overhead cancel out the benefit of threading. Conversely, too high will over-burden some threads and starve others. Over long running processes of multi hundreds/thousands of sub-tasks, the scheduler will automatically adjust the batch size up or down to try to keep the pipeline filled. For small batch sizes of cpu intensive tasks (such as this one) it is useful to give it a smaller starting batch size.
Note that in this specific example (prime decomposition of these 15 numbers), the overhead from setting up threading eats up any gain from doing it in parallel. Probably wouldn't see any real speed up until there are 50 or more numbers to decompose, but this example is deterministic, compact and verifiable.
 
On my system, under the load I was running, I found a batch size of 3 to be optimal for this task. May be different for different systems and different loads.
 
Using the <tt>prime-factors</tt> routine as defined in the [[Prime_decomposition#Perl_6 |prime decomposition]] task:
Line 1,500 ⟶ 1,502:
278352769033314050117, 281398154745309057242, 292057004737291582187;
 
my \factories = @nums.hyper(:batch(3)).map: *.&prime-factors.cache;
say my $gmf = {}.append(factories»[0] »=>« @nums).max: {+.key};
say 'Run time: ', now - INIT now;
 
sub prime-factors ( Int $n where * > 0 ) {
Line 1,526 ⟶ 1,529:
$factor;
}</lang>
{{out|Typical output}}
<pre>736717 => [64921987050997300559 71774104902986066597 83448083465633593921 87001033462961102237 89538854889623608177 98421229882942378967]</pre>
Run time: 0.2893774</pre>
 
Beside <tt>HyperSeq</tt> and its (allowed to be) out-of-order equivalent <tt>RaceSeq</tt>, [[Rakudo]] supports primitive threads, locks and highlevel promises. Using channels and supplies values can be move thread-safely from one thread to another. A react-block can be used as a central hub for message passing.
 
In [[Perl 6]] most errors are bottled up <tt>Exceptions</tt> inside <tt>Failure</tt> objects that remember where they are created and thrown when used. This is useful to pass errors from one thread to another without losing file and linennumberline number of the source file that caused the error.
 
In the future hyper operators, junctions and feeds will be candidates for autothreading.
10,327

edits