Práctica: Cálculo con Hilos

El área bajo la curva $ y = \frac{1}{1+x^2}$ entre 0 y $ 1$ nos proporciona un método para calcular $ \pi $:

$\displaystyle \int_{0}^{1} \frac{4}{(1+x^2)} dx = 4 \arctan(x) \vert _{0}^{1} = 4 ( \frac{\pi}{4} - 0) = \pi $

Esta integral puede aproximarse por la suma:

$\displaystyle \pi \simeq \sum_{i=0}^{N-1} \frac{4}{N \times \left (1+ (\frac{i+0.5}{N})^2 \right)}$    

Después que una thread ha terminado de hacer su suma parcial deberá actualizar una variable compartida $pi en la cual pretendemos guardar el valor final. Observe que la variable $pi es un recurso compartido por los $p hilos que debe ser accedido en exclusión mutua. Para realizar la práctica es conveniente que, además de consultar los manuales de threads y threads::shared lea el tutorial sobre threads: perldoc perlthrtut.

Rellene el código que falta en el listado que aparece a continuación:

lhp@nereida:~/Lperl/src/threads$ cat -n pilock.pl
 1  #!/usr/bin/perl -w
 2  use strict;
 3  use threads;
 4  use threads::shared;
 5
 6  { # clausura
 7    my $pi : shared = 0;
 8
 9    sub chunk {
10      my $N = shift;
11      my $numthreads = shift;
12
13      my ($i, $x, $sum, $w);
14      my $id = threads->self()->tid();
15      $w = 1/$N;
16      $sum = 0;
17      for ($i = $id; $i < $N; $i += $numthreads) {
18        $x = .............; # abcisa
19        $sum += .................; # suma parcial
20      }
21      {
22        lock $pi;
23        $pi += $sum;
24      }
25      print "thread $id: $pi\n";
26      return  $pi;
27    }
28
29    sub postprocess {
30      my $N = shift;
31      return ......; # Retornar valor final
32    }
33  } # clausura
34
35  sub par {
36    my $nt = shift();
37    my $task = shift;
38    my $post = shift;
39    my @t; # array of tasks
40    my $result;
41
42    for(my $i=1; $i < $nt; $i++) {
43      ................................; # crear threads
44    }
45    $task->(@_);
46    .............................; # sincronizar
47    return $post->(@_);
48  }
49
50  ### main ###
51  my $numthreads = (shift || 2);
52  my $N = (shift || 10000);
53
54  my $result = par($numthreads, \&chunk, \&postprocess, $N, $numthreads);
55  print "$result\n";
lhp@nereida:~/Lperl/src/threads$ ./pilock.pl 8 100000
thread 1: 39270.533168727
thread 3: 78540.566344954
thread 2: 117810.849518681
thread 4: 157080.632694908
thread 7: 196349.665856134
thread 5: 235619.19902986
thread 6: 274888.482198587
thread 0: 314159.265359813
3.14159265359813
lhp@nereida:~/Lperl/src/threads$

Casiano Rodríguez León
2010-03-22