[Jprogramming] Performance of fork vs train
Ric Sherlock
tikkanz at gmail.com
Thu Jun 23 01:04:21 UTC 2016
This isn't to do with forks vs trains per se. It is about J working better
on (big) chunks rather than small ones. Using & or @ rather than &: or @:
causes the verb to the left to operate on chunks that are a size determined
by the rank of the verb to the right. Using @: or &: causes the verb to the
right to finish processing and provide the entire array to the verb on the
left.
([: *: >:) is equivalent to *:@:>:
In this case the answer is the same as for *:@>: but the processing path is
different.
Both >: and *: are rank 0
>: b. 0
0 0 0
*: b. 0
0 0 0
So *:@>: will process each atom of the argument separately whereas *:@:>:
will finish incrementing all the atoms in the argument and then give the
entire result to square (*:) to process. This might help visualise what is
going on:
<@:*:@>: 0 1 2 3 4 5
+-+-+-+--+--+
|1|4|9|16|25|
+-+-+-+--+--+
<@:*:@:>: 0 1 2 3 4 5
+-----------+
|1 4 9 16 25|
+-----------+
Looking at the timing differences in sentences below you can see that they
key is that *: is operating on the entire array.
6!:2 '(+/@:(*:&>:&i.))"0 (i.9999)'
13.55
6!:2 '(+/@:(*:&:>:&:i.))"0 (i.9999)'
0.162699
6!:2 '(+/@:(*:@:>:@:i.))"0 (i.9999)'
0.169901
6!:2 '(+/@:(*:@>:@i.))"0 (i.9999)'
13.4185
6!:2 '(+/@:(*:@:>:@i.))"0 (i.9999)'
0.156401
6!:2 '(+/@:(*:@>:@:i.))"0 (i.9999)'
13.49
Note that there appears to be no performance benefit between >:@i. and
>:@:i. because the monadic rank of i. is 1
i. b. 0
1 _ _
The rank of the argument given to i. is already 1 or less, so >: is being
given the whole result from i. already.
Hope that helps
On Thu, Jun 23, 2016 at 12:10 PM, Moon S <moon.aka.sun at gmail.com> wrote:
> I was searching integer solutions (k,m) for
> 1^2 + 2^2 + ... + k^2 = m^2
> and I found that one expression runs much faster than the other:
>
> (#~(0=1|[:%:+/@:([:*:1+i.))"0) 2+i.9999
> 24
> (#~(0=1|[:%:+/@:(*:&>:&i.))"0) 2+i.9999
> 24
>
> The first one is ~100 times faster, and moreover, the expression with '+/'
> is faster, then without it!
>
> (3) 6!:2 '(+/@:([:*:1+i.))"0 (i.9999)' NB. with +/ and fork
> 0.143744
> (3) 6!:2 '(+/@:(*:&>:&i.))"0 (i.9999)' NB. with +/ and train
> 13.4614
>
> (3) 6!:2 '([:*:1+i.)"0 (i.9999)' NB. without +/
> 0.608895
> (3) 6!:2 '(*:&>:&i.)"0 (i.9999)'
> 14.0192
>
> As for '+/' I think the explanation is that no additional arrays are
> created, the sums are just computed on the fly.
> But the question remains, why the (equivalent) fork is so much faster than
> the train?
>
> Hm, changing the long train to a shorter one with a fork helps:
> (3) 6!:2 '(*:&(1+i.))"0 (i.9999)'
> 0.62027
> So, what's the rule?
>
> ---
> Georgiy Pruss
> ----------------------------------------------------------------------
> For information about J forums see http://www.jsoftware.com/forums.htm
More information about the Programming
mailing list