in reply to how to multiply an array of number as fast as posible

What application could you have that needs a precise value of this product? I would be very surprised if you could not get the accuracy you require using the Stirling_approximation. In any case, if your question is optimization, then you need to test. Specifically, you need to use benchmarking (see Benchmark) and profiling (see Devel::NYTProf) to determine where exactly your bottlenecks are.

For this operation, one very simple optimization would be swapping from a for to a while loop since Foreach Loops need to construct the list before beginning iteration. threads is also a fairly simple way to improve performance. Here is a simple benchmark, showing a 38% speedup using a while loop and two threads. Note the speedup is not higher because creating threads involves overhead.

Threading in this case does not make sense - the overhead in starting a thread exceeds the performance boost. For loops with range operators are automatically transformed into efficient C-style loops internally by Perl. But you should really be using the Stirling_approximation and only storing the log of your value to avoid overflow.

#!/usr/bin/perl use strict; use warnings; use Benchmark qw':all :hireswallclock'; use threads; cmpthese(10, { 'while' => sub { my $i = 230000; my $k = 1; while ($i <= 900000) { $k *= $i++; } }, 'for' => sub { my $k = 1; for (230000 .. 900000) { $k *= $_; } }, 'threads' => sub { my $k = 1; my $thr2 = async { my $k = 1; my $i = 565001; while ($i <= 900000) { $k *= $i++; } }; my $i = 230000; while ($i <= 565000) { $k *= $i++; } $k *= $thr2->join(); } });

outputs

Rate threads while for threads 3.09/s -- -29% -38% while 4.33/s 40% -- -13% for 4.96/s 60% 15% --

And if you look at the results from these multiplications, you have likely exceeded the maximum value representable by floating point on your machine.

Update: Need caffeine, read my Benchmark results backwards, fixed above.

Replies are listed 'Best First'.
Re^2: how to multiply an array of number as fast as posible
by BrowserUk (Patriarch) on Sep 02, 2010 at 17:04 UTC

    The problem with your benchmark is the calculation moves into floating point exception handling very early on.

    If you avoid that by adding logs, using threads improve performance by 65%:

    #! perl -slw use strict; use threads; use Time::HiRes qw[ time ]; { my $start = time; my $t = 0; $t += log( $_ ) for 230000..900000; printf "%.15f\n", $t;; printf "Took %.6f\n", time() - $start; } { my $start = time; my $thr = async { my $t = 0; $t += log( $_ ) for 230000..565000; return $t; }; my $t = 0; $t += log( $_ ) for 565001..900000; $t += $thr->join; printf "%.15f\n", $t;; printf "Took %.6f\n", time() - $start; } __END__ C:\test>junk32 8829606.110849546300000 Took 0.132204 8829606.110849652400000 Took 0.080650

    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
      But at the same time, you've just added a transcendental function to every loop iteration, which is a much more expensive operation than a multiplication. As I pointed out in Re^3: how to multiply an array of number as fast as posible. A more fair comparison would be scaling the operations so that we avoid INFs in the first place:

      #!/usr/bin/perl use strict; use warnings; use Benchmark qw':all :hireswallclock'; use threads; cmpthese(10, { 'for' => sub { my $k = 1; for (230000 .. 900000) { $k *= 1 + $_* 0.0000000001; } #print "for: $k\n"; }, 'threads' => sub { my $thr2 = async { my $k = 1; for (565001 .. 900000) { $k *= 1 + $_* 0.0000000001; } return $k; }; my $k = 1; for (230000 .. 565000) { $k *= 1 + $_* 0.0000000001; } $k *= $thr2->join(); #print "threads: $k\n"; } });

      I've replaced one multiplication per iteration with 2 multiplications and an addition (plus the store), which should shift the balance toward threads. And yet, the benchmark comes out in favor of single-threaded operation:

      Rate threads for threads 2.92/s -- -35% for 4.48/s 53% --

        Hm. Benchmarking a different calculation doesn't seem useful to me.

Re^2: how to multiply an array of number as fast as posible
by ikegami (Patriarch) on Sep 02, 2010 at 15:28 UTC

    the overhead in starting a thread exceeds the performance boost.

    What performance boost could you possibly get? The CPU is already working at 100% calculating the number. That's why threads makes no sense in this case.

      The CPU is already working at 100% calculating the number.

      Yes, one core is working at 100% to calculate the product. By splitting the list in half, two cores are working at 100% - the OP cites having a dual core. It just so happens that in this case:

      loop_overhead + n*multiplication < thread_overhead + loop_overhead + (n/2)*multiplication

      as I would expect for this kind of simple operation. But throw in transcendental functions and maybe the balance shifts.

      What performance boost could you possibly get? The CPU is already working at 100% calculating the number. That's why threads makes no sense in this case.

      Ahem! From the OP.

      i have a dual core proc

      If he decided to calculate this in arbitrary precision, using both his CPU's would make a huge difference.

        I am under the impression that Perl threads are bound to one CPU. Is that wrong?