Just a word of caution to anyone seduced by the power of Quantum::Superpositioning (as I was around 10 months ago:) : Quick, it ain't; Memory hungry it is.
It's a fun, and very powerful demonstraton of some powerful concepts, but using it in workaday code is costly.
To demonstrate that, I reimplemented the brute force algorithms shown in the Q::S pod for is_prime(), factors() and GCD() using fairly standard perl, and the result show that this is not permature micro-optimisation I am talking about:
The benchmark
#! perl -slw use strict; use List::Util qw[max]; use Quantum::Superpositions UNARY => ['CORE::int']; use Benchmark qw[cmpthese]; sub pl_all{ $_ || return 0 for @_; 1 } sub PL_is_prime{ $_[0]==2 || pl_all map{ $_[0] % $_ } 2..sqrt($_[0])+1 + } sub QS_is_prime{ $_[0]==2 || $_[0] % all(2..sqrt($_[0])+1) != 0 } our ($QS_count, $PL_count); cmpthese( -1, { 'Q::S' => q[ $QS_count = 0; $QS_count += QS_is_prime($_) ? 1 : 0 f +or 2..10000; ], 'perl' => q[ $PL_count = 0; $PL_count += PL_is_prime($_) for 2..10 +0000; ], }); print "Primes found: Q::S:$QS_count; Perl:$PL_count\n\n"; sub QS_factors { eigenstates (int($_[0] / any(2..$_[0]-1)) == ($_[0] / + any(2..$_[0]-1))); } sub PL_factors{ grep{ $a = $_[0]/$_; int($a) == $a } 2 .. $_[0] - 1; } our (@QS_factors, @PL_factors); cmpthese( -1, { QS_factors => q[ $a=1; @QS_factors = QS_factors($_) for map{$a *= +$_} 2 .. 6; ], PL_factors => q[ $a=1; @PL_factors = PL_factors($_) for map{$a *= +$_} 2 .. 9; ], }); print "qs:\n@QS_factors\npl:\n@PL_factors\n"; sub QS_GCD{ my ($x, $y) = @_; my $common = all(any(QS_factors($x)), any(QS_factors($y))); any(eigenstates $common) >= all(eigenstates $common); } sub PL_GCD{ my ($x, $y) = @_; my %any; max grep{ ++$any{$_} > 1 } PL_factors($x), PL_factors($y); } our ($QS_GCD, $PL_GCD); cmpthese( -20, { QS_GCD => q[ $a=$b=1; $QS_GCD = QS_GCD($a=$b, $b *= $_) for 2 .. 6 +; ], PL_GCD => q[ $a=$b=1; $PL_GCD = PL_GCD($a=$b, $b *= $_) for 2 .. 9 +; ], }); print "QS:$QS_GCD - PL:$PL_GCD"
The results
D:\Perl\test>qs-test s/iter Q::S perl Q::S 282 -- -98% perl 4.87 5702% -- Primes found: Q::S:1229; Perl:1229 s/iter QS_factors PL_factors QS_factors 322 -- -100% PL_factors 0.120 267905% -- qs:90 80 2 48 180 360 18 72 30 144 16 6 240 120 3 36 40 9 12 15 20 8 4 + 60 24 45 10 5 pl:2 3 4 5 6 8 9 10 12 15 16 18 20 24 30 36 40 45 48 60 72 80 90 120 1 +44 180 240 360 s/iter QS_GCD PL_GCD QS_GCD 336 -- -100% PL_GCD 0.148 226174% -- QS:60 - PL:60
To put that into perspective, the non-Q::S version of is_prime() will find the 9592 prime < 100,000 in approximately half the time the Q::S version finds the 1229 < 10,000.
The non Q::S version of factors() will find the approx: 400,000 factors of 2!..9! in around a 5th of the time required by the Q::S version to find the approx 6000 factors of 2! .. 6!.
And The non-Q::S version will perform the approx: 400,000 divisions and int's and the approx: 800,000 comparisons involved in finding the GCD() (using this algorithm) between each succesive pair of factorial 2! thru 9! in about 1/5th the time taken for the Q::S version to do the (approx) 12,000 divisions, 6,000 int's and 12,000 comparisons.
Even when used for simple testing of arrays against constants Eg.if (all(@array) != 1) {...) the overheads are quite heavy and can quite quickly invoke swapping if your arrays are of any size.
Hopefully, once the functionality is moved into the core as C or XS, this caveat will disappear.
In reply to Re: Re: Favourite modules April 2003
by BrowserUk
in thread Favourite modules April 2003
by Juerd
For: | Use: | ||
& | & | ||
< | < | ||
> | > | ||
[ | [ | ||
] | ] |