Page 1 of 1

How to time expression

Posted: Mon Feb 01, 2016 9:13 pm
by alexeyv
How to measure the time the interpreter spend on executing expression?
Like in bash I can write time some_command, in Common Lisp I can write (time (my-expression))
I would like to do something like this in APL as well.

Re: How to time expression

Posted: Mon Feb 01, 2016 10:28 pm
by Roger|Dyalog
I recommend using cmpx in the dfns workspace. For example:

Code: Select all

      x←?1e6⍴2e9
      cmpx '(1e9<x)⍳1' '1e9(1 ⍳⍨ <)x'
  (1e9<x)⍳1    → 9.75E¯4 |    0% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕
  1e9(1 ⍳⍨ <)x → 7.81E¯6 | -100%                               

You may be tempted (as I was) to write your own timer, but resist the temptation. A good timer function is more difficult to write than may first appear. In general, timing on modern CPUs is a difficult problem.

Re: How to time expression

Posted: Mon Feb 01, 2016 11:17 pm
by garylogan
It would be very interesting to see an explanation
of the large difference in execution times for these
expressions. Why is the old code slow? Why is the new
code fast?

Re: How to time expression

Posted: Mon Feb 01, 2016 11:50 pm
by Roger|Dyalog
Both expressions, (1e9<x)⍳1 and 1e9(1⍳⍨<)x, find the index of the first place where x exceeds 1e9. The former computes the boolean vector 1e9<x, then finds the index of the first occurrence of 1. The latter goes through x and compares each element to 1e9, and stops when it finds the first element that exceeds 1e9. Since x are 1e6 random integers between 0 and 1e9, chances are pretty good that it'd stop before too long.

Suppose the scan has to go right to the end?

Code: Select all

      cmpx '(2.1e9<x)⍳1' '2.1e9(1 ⍳⍨ <)x'
  (2.1e9<x)⍳1    → 9.92E¯4 |   0% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕
  2.1e9(1 ⍳⍨ <)x → 6.60E¯4 | -34% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕         

FYI: (1⍳⍨<) is a fork and is supported by special code. A list of the special codes extant can be found here.

Re: How to time expression

Posted: Tue Feb 02, 2016 9:23 am
by AndyS|Dyalog
I second Roger's comments about cmpx .. this is the best tool when determining which of several expressions is the best way to code something.

However, if you want to get an idea of where the time is being used in your functions, or in your application, then ⎕MONITOR and/or ]profile and ⎕PROFILE are very useful; both have a performance impact on the interpreter, so you should not rely too heavily on the absolute values returned .. consider the relative values, and concentrate on the larger numbers.

And if all else fails, you can always go back to
      ai←⎕ai ⋄ my_app ⋄ ⎕ai-ai
or use ⎕TS in a similar fashion.

Re: How to time expression

Posted: Tue Feb 02, 2016 12:14 pm
by DanB|Dyalog
Also, if you prefer you can use user command ]runtime
Ex:

Code: Select all

      ]runtime {⍵∧⍳⍵}1e7

* Benchmarking "{⍵∧⍳⍵}1e7"
             Exp
 CPU (avg):  811
 Elapsed:    806

This tells you it took 811ms CPU and 806ms elapsed.
If you want to compare 2 expressions a la cmpx you can use ]runtime again with modifier -compare:

Code: Select all

      ]runtime  '(1e9<x)⍳1' '1e9(1 ⍳⍨ <)x'  -compare
                                                                         
  (1e9<x)⍳1    → 1.6E¯3 |    0% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕
  1e9(1 ⍳⍨ <)x → 0.0E0  | -100%                                         

]runtime uses cmpx under the covers when -compare is used.

Re: How to time expression

Posted: Tue Feb 02, 2016 8:11 pm
by alexeyv
Thanks for replies! I think they cover all my needs.