github.com/coyove/nj@v0.0.0-20221110084952-c7f8db1065c3/tests/bench/spec.pl (about)

     1  # The Computer Language Benchmarks Game
     2  # https://salsa.debian.org/benchmarksgame-team/benchmarksgame/
     3  #
     4  # Contributed by Andrew Rodland
     5  # modified by R. Jelinek
     6  # multicore by Mykola Zubach
     7  
     8  use strict;
     9  use threads;
    10  
    11  my $cpus = num_cpus();
    12  
    13  my $n = shift || 500;
    14  my @v = multiplyAtAv(
    15      multiplyAtAv(
    16          multiplyAtAv((1) x $n)
    17      )
    18  );
    19  
    20  my @u = multiplyAtAv(@v);
    21  
    22  my ($vBv, $vv);
    23  my $i = 0;
    24  for my $v (@v) {
    25      $vBv += $u[$i++] * $v;
    26      $vv += $v ** 2;
    27  }
    28  
    29  printf "%0.9f\n", sqrt($vBv / $vv);
    30  
    31  sub multiplyAtAv {
    32      return multiplyAtv(multiplyAv(@_));
    33  }
    34  
    35  sub eval_A {
    36      use integer;
    37      my $div = (($_[0] + $_[1]) * ($_[0] + $_[1] + 1) >> 1) + $_[0] + 1;
    38      no integer;
    39      1 / $div;
    40  }
    41  
    42  sub multiplyAv {
    43      my($begin, $end, @threads);
    44      my $chunk = int($#_ / $cpus) + 1;
    45      
    46      for($begin = 0; $begin < $#_; $begin = $end + 1) {
    47          $end = $begin + $chunk;
    48          $end = $#_ if $end > $#_;
    49          push @threads, threads->create( sub {
    50              my $begin = shift;
    51              my $end = shift;
    52              return map {
    53                  my ($i, $sum) = ($_);
    54                  $sum += eval_A($i, $_) * $_[$_] for (0 .. $#_);
    55                  $sum;
    56              } ($begin .. $end);
    57         }, $begin, $end, @_);
    58      }
    59      return map $_->join, @threads;
    60  }
    61  
    62  sub multiplyAtv {
    63      my($begin, $end, @threads);
    64      my $chunk = int($#_ / $cpus) + 1;
    65      
    66      for($begin = 0; $begin < $#_; $begin = $end + 1) {
    67          $end = $begin + $chunk;
    68          $end = $#_ if $end > $#_;
    69          push @threads, threads->create( sub {
    70              my $begin = shift;
    71              my $end = shift;
    72              return map {
    73                  my ($i, $sum) = ($_);
    74                  $sum += eval_A($_, $i) * $_[$_] for (0 .. $#_);
    75                  $sum;
    76              } ($begin .. $end);
    77         }, $begin, $end, @_);
    78      }
    79      return map $_->join, @threads;
    80  }
    81  
    82  sub num_cpus {
    83      open my $fh, '</proc/cpuinfo' or return 4;
    84      my $cpus;
    85      while (<$fh>) {
    86          $cpus ++ if /^processor\s+:/;
    87      }
    88      return $cpus;
    89  }