I see, thank you! (10) 6!:2 '(+) i.10000000' 0.0286243 (10) 6!:2 '(+&:+) i.10000000' NB. process whole array 0.0273438 (10) 6!:2 '(+@:+) i.10000000' 0.0290984 (10) 6!:2 '([:++) i.10000000' 0.0281622
(10) 6!:2 '+ + i.10000000' NB. even this is slower 0.039037 (10) 6!:2 '(+&+) i.10000000' NB. process item by item 1.06261 (10) 6!:2 '(+@+) i.10000000' 1.05878 On Thu, Jun 23, 2016 at 4:04 AM, Ric Sherlock <[email protected]> wrote: > 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 <[email protected]> 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 > ---------------------------------------------------------------------- > For information about J forums see http://www.jsoftware.com/forums.htm ---------------------------------------------------------------------- For information about J forums see http://www.jsoftware.com/forums.htm
