Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister
 
PerlMonks  

Sheer idle curiousity . . .

by TheMonkWithoutVows (Novice)
on Oct 23, 2013 at 21:32 UTC ( #1059354=perlquestion: print w/ replies, xml ) Need Help??
TheMonkWithoutVows has asked for the wisdom of the Perl Monks concerning the following question:

Hi all,

I have a very simple bit of code where I basically want to set a var $wait value to 0 if it is a negative number and stay as is if not. This resulted in a debate with a work colleague as to which of the following lines would be faster.

so we tested . . .

use Benchmark qw( cmpthese ) ; my $wait = -34; cmpthese( -2, { a=>sub{ $wait = $wait < 0 ? 0 : $wait ; $wait = -34; }, b=>sub{ if ($wait < 0 ){ $wait = 0}; $wait = -34; }, c=>sub{ $wait = 0 unless $wait > 0; $wait = -34; }, d=>sub{ $wait = 0 unless abs($wait); $wait = -34; },

and we were amazed by the results . . .. with a negative number:

Rate a b c d a 4216652/s -- -16% -17% -36% b 5010637/s 19% -- -2% -24% c 5094673/s 21% 2% -- -23% d 6616606/s 57% 32% 30% --

with a positive number:

Rate a b c d a 3542992/s -- -5% -6% -50% b 3742730/s 6% -- -1% -47% c 3766874/s 6% 1% -- -47% d 7084993/s 100% 89% 88% --

Two questions -

  • why would using abs be so much faster - (intuitively I felt using a function would add to the cost)?
  • has anyone got a faster way?

Comment on Sheer idle curiousity . . .
Select or Download Code
Re: Sheer idle curiousity . . .
by davido (Archbishop) on Oct 23, 2013 at 21:45 UTC

    What does your intuition tell you this code does?

    d=>sub{ $wait = 0 unless abs($wait); $wait = -34; },

    In particular, abs returns the absolute value. The absolute value of -34 is 34, which is "true". Since your condition is never false, you never fall through to the action of the "unless" clause.


    Dave

      Besides what David just said, it seems to me that the operation of simply setting a sign bit and then testing for 0 would inherently faster than any of the other comparisons if the resulting code is optimized. I know that would be the case if I were coding that in assembly.

      The answer to the question "Can we do this?" is always an emphatic "Yes!" Just give me enough time and money.
        if the resulting code is optimized.

        Its not. It just results in less opcodes.


        With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
        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.

      My intuition tells me it's been a long day and typos are creeping in :-)

      The last test should have read:

      d=>sub{ $wait = 0 unless ($wait == abs($wait)); $wait = -34; },
      I thought the results had shot up on my home pc.
      Rate d c b a d 3468819/s -- -8% -10% -13% c 3780923/s 9% -- -1% -5% b 3834916/s 11% 1% -- -4% a 3997317/s 15% 6% 4% -- and Rate d c b a d 3246175/s -- -8% -15% -17% c 3526456/s 9% -- -7% -9% b 3799184/s 17% 8% -- -2% a 3890565/s 20% 10% 2% --

      It's still the outright winner - so the questions still stand.

Re: Sheer idle curiousity . . .
by BrowserUk (Pope) on Oct 23, 2013 at 22:14 UTC
    why would using abs be so much faster

    Because it requires less opcodes.

    • With the ternary, it has to:
      1. load the value;
      2. load the constant;
      3. perform the compare;
      4. perform an assignment in both branches.
    • With the unless $x >= 0 (your condition is wrong), it has to
      1. load the value;
      2. load the constant;
      3. perform the compare;
      4. perform an assignment in one branch.
    • With the unless abs $x the is no constant to load; and abs is just an opcode the same as greater than or less than:
      1. load the abs value;
      2. perform the compare;
      3. perform an assignment in one branch.

    Best shown by the difference in the Concise output, where each successively faster option requires one less opcode than the precedent:

    C:\test>perl -MO=Concise -E"my$x=-1; $x = $x<0?0:$x;" e <@> leave[1 ref] vKP/REFC ->(end) 1 <0> enter ->2 2 <;> nextstate(main 46 -e:1) v:%,{ ->3 5 <2> sassign vKS/2 ->6 3 <$> const[IV -1] s ->4 4 <0> padsv[$x:46,47] sRM*/LVINTRO ->5 6 <;> nextstate(main 47 -e:1) v:%,{ ->7 d <2> sassign vKS/2 ->e - <1> null sK/1 ->c a <|> cond_expr(other->b) sK/1 ->f 9 <2> lt sK/2 ->a 7 <0> padsv[$x:46,47] s ->8 8 <$> const[IV 0] s ->9 b <$> const[IV 0] s ->c f <0> padsv[$x:46,47] s ->c c <0> padsv[$x:46,47] sRM* ->d -e syntax OK C:\test>perl -MO=Concise -E"my$x=-1; $x = 0 unless $x >=0;" e <@> leave[1 ref] vKP/REFC ->(end) 1 <0> enter ->2 2 <;> nextstate(main 46 -e:1) v:%,{ ->3 5 <2> sassign vKS/2 ->6 3 <$> const[IV -1] s ->4 4 <0> padsv[$x:46,47] sRM*/LVINTRO ->5 6 <;> nextstate(main 47 -e:1) v:%,{ ->7 - <1> null vK/1 ->e a <|> or(other->b) vK/1 ->e 9 <2> ge sK/2 ->a 7 <0> padsv[$x:46,47] s ->8 8 <$> const[IV 0] s ->9 d <2> sassign vKS/2 ->e b <$> const[IV 0] s ->c c <0> padsv[$x:46,47] sRM* ->d -e syntax OK C:\test>perl -MO=Concise -E"my$x=-1; $x = 0 unless abs($x);" d <@> leave[1 ref] vKP/REFC ->(end) 1 <0> enter ->2 2 <;> nextstate(main 46 -e:1) v:%,{ ->3 5 <2> sassign vKS/2 ->6 3 <$> const[IV -1] s ->4 4 <0> padsv[$x:46,47] sRM*/LVINTRO ->5 6 <;> nextstate(main 47 -e:1) v:%,{ ->7 - <1> null vK/1 ->d 9 <|> or(other->a) vK/1 ->d 8 <1> abs[t3] sK/1 ->9 7 <0> padsv[$x:46,47] s ->8 c <2> sassign vKS/2 ->d a <$> const[IV 0] s ->b b <0> padsv[$x:46,47] sRM* ->c -e syntax OK

    Of course, speed is no good to you if it doesn't perform the required function ... (davido++)


    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    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.
      Thanks that really is clear - appreciated.
Re: Sheer idle curiousity . . .
by vsespb (Hermit) on Oct 23, 2013 at 23:01 UTC
    As @TheMonkWithoutVows pointed out in Re^2: Sheer idle curiousity . . ., the code
    $wait = 0 unless abs($wait);
    unlike other examples, never assigns anything to $wait if $wait is -34.

    Proof:
    my $wait = -34; $wait = 0 unless abs($wait); print $wait;
    prints -34

    So if you change your benchmark to
    $wait = 0 if abs($wait);
    you'll see, difference is small (I got 4%). (even through abs() is still used).

    UPD:Oh, @TheMonkWithoutVows and you(OP) are same persons :)
Re: Sheer idle curiousity . . .
by Anonymous Monk on Oct 24, 2013 at 02:48 UTC

    This may be faster:

    e=>sub{ $wait *= $wait > 0; $wait = -34; },

    For negative numbers:

    Rate d b a c e d 7216838/s -- -7% -13% -16% -35% b 7785170/s 8% -- -6% -10% -30% a 8270205/s 15% 6% -- -4% -26% c 8609980/s 19% 11% 4% -- -23% e 11128061/s 54% 43% 35% 29% --

    For positive numbers:

    Rate a d e c b a 9665991/s -- -10% -14% -24% -26% d 10777285/s 11% -- -4% -15% -17% e 11190507/s 16% 4% -- -12% -14% c 12748698/s 32% 18% 14% -- -2% b 13022958/s 35% 21% 16% 2% --

      Now that is just dandy

       %wait *= $wait < 0

      . . . . is the clear winner

      Take a bow Anonymous Monk

Re: Sheer idle curiousity . . .
by AnomalousMonk (Monsignor) on Oct 24, 2013 at 03:50 UTC

    And you and your cow-orkers spent how much time on this today?!? I wish I worked where you work. (Actually, I foresee there may be a couple of openings RSN...:)

      It's called "professional development time" at the end of the sprint where I work. :)

      The answer to the question "Can we do this?" is always an emphatic "Yes!" Just give me enough time and money.
      I work at The Unemployment Line. You don't want to work here. There are plenty of openings.
Re: Sheer idle curiousity . . .
by hdb (Parson) on Oct 24, 2013 at 07:27 UTC

    Running a comparison of a, c and e several times on Win 7, Strawberry 5.16 shows the following results:

    Rate e a c e 7079226/s -- -1% -3% a 7185758/s 2% -- -1% c 7269278/s 3% 1% -- Rate e c a e 7072032/s -- -1% -3% c 7143388/s 1% -- -2% a 7316126/s 3% 2% -- Rate c e a c 7161561/s -- -1% -4% e 7257544/s 1% -- -2% a 7427981/s 4% 2% --

    so my conclusion would be that the difference between the three is negligible. This is with -34 as the test number. For +34 the picture is quite different:

    Rate e a c e 6807195/s -- -26% -37% a 9201425/s 35% -- -15% c 10867659/s 60% 18% --

    where c is a clear and consistent winner.

    What shall I make of this in the light of the thread above?

      What shall I make of this in the light of the thread above?

      That CPUs have differences in performance, and so do Perl versions?

      # This is perl, v5.10.1 (*) built for i486-linux-gnu-thread-multi # negative Rate d c e a b d 1219274/s -- -7% -15% -20% -31% c 1315339/s 8% -- -9% -13% -26% e 1441482/s 18% 10% -- -5% -19% a 1519028/s 25% 15% 5% -- -15% b 1778883/s 46% 35% 23% 17% -- # positive Rate d e c a b d 1300194/s -- -3% -6% -13% -13% e 1336169/s 3% -- -3% -10% -10% c 1375954/s 6% 3% -- -7% -8% a 1486080/s 14% 11% 8% -- -0% b 1492276/s 15% 12% 8% 0% --

      The winner here is, quite unexpectedly, B.

      Another cpu, also on Perl 5.10.1 but amd64, says B is 80% faster than the worst contender (E) when negative; and A is 51% faster than E (B having the second place at 42% faster) when positive.

      Third cpu with Perl 5.14.4 gives a negligible win for E -- D being the low anchor. So I think we can conclude that the Perl version matters the most?

Re: Sheer idle curiousity . . .
by ikegami (Pope) on Oct 25, 2013 at 14:50 UTC

    To put it into perspective, the slowest one of the above takes 180 billionths of a second, while a subroutine call with a single ten-character string argument takes 650 billionths of a second.

    If your tenth of millionths of seconds are that precious, you should probably inline your subs.


    '$wait = 0 unless ($wait == abs($wait)); $wait = 34;' 'sub { my ($x) = @_; }->(q{abcdefghij})'

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1059354]
Approved by keszler
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others exploiting the Monastery: (11)
As of 2014-08-28 07:39 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The best computer themed movie is:











    Results (257 votes), past polls