The fork I proffered should never be slower.
f t.'' g&:> h t.'' will make a new task for h, make a new task for f (which
run in parallel with each other), suspend the current task until both are
done, and finally invoke g.
f (g >) h t.'' will make a new task for h, run f on the current task, wait for
h to finish, and then invoke g.
In both cases, f and h run in parallel with each other, and in both cases both
must complete before g can run. But the latter fork avoids the bookkeeping
and overhead associated with creating and scheduling a task for f, which can
be significant. There are also second-order cache effects. FWIW this is also
what java's 'fork-join' does.
-E
On Mon, 23 May 2022, Raul Miller wrote:
I imagine that speedups and/or slowdowns somewhat depends on the
definitions of f, g and h... (not to mention x and/or y).
Hints here would be welcome.
Thanks,
--
Raul
--
Raul
On Mon, May 23, 2022 at 9:48 PM Elijah Stone <[email protected]> wrote:
I suggest using f (g >) h t.'' instead of f t.'' g&:> h t.'', as it is
somewhat faster.
On Sun, 22 May 2022, Jan-Pieter Jacobs wrote:
> I've had some fun with parallel primitives and forks, and came up with two
> approaches that result in the exact same result, but have different sytax.
>
> The first converts to AR and replaces the verbs by applying (t.'') and (&>)
> to the outer and inner tines of the fork, respectively:
>
> NB. parallel single fork
> psf =: {{
> 'cod dat' =. > u toar
> if. '3'=cod do. NB. if fork
> dat =. pf dat
> end.
> (< cod ,&< dat) 5!:0
> }}
>
> pf =: {{
> NB. Parallelise outer tines
> y =. ((0 { y) 5!:0 t.'' toar) 0 } y
> y =. ((2 { y) 5!:0 t.'' toar) 2 } y
> NB. Open to wait for tines to finish
> y =. ((1 { y) 5!:0 &> toar) 1 } y
> }}
>
> NB. adverb: convert u to atomic representation
> toar =: {{
> vb =. u f.
> ar =. 5!:1<'vb' }}
>
> (+/%#) psf
> +/t.'' %&:> #t.''
>
> Of course, in this simplistic example, the parallel version is slower,
> because the outer tines are so simple, but on more complicated verbs, I can
> imagine it gains some speed. Note that any side-effects the outer tines
> would have would become evidently unreliable as to their execution order.
>
> The second approach uses a tie and `:6 to create a conjunction to be
> applied between middle and last tine, that returns an adverb that will take
> the left tine, and combine it into a fork. Likely it can be written
> tacitly, but I did not yet spend enough time learning tacit modifiers
> trains.
>
> NB. parallel fork, conjunction.
> pfr=: {{ (t.'')(`(u&:>))(`(v t.''))(`:6)}}
>
> +/ % pfr #
> +/t.'' %&:> #t.''
>
> This luckily works fine for combinations in other verbs and even nested
> application, e. g. the hypothetical (sorry, couldn't come up with an
> example that made sense)
>
> $ +/ % prf # ?
> $ (+/t.'' %&> #t.'') ?
>
> $ +/ % prf # prf ?
> $t.'' (+/t.'' %&> #t.'')&> ?t.''
>
> I guess there's something to say for both approaches. The first is certaily
> more wordy, but I think it could be extended to recursing through an AR and
> parallelising where it makes sense (based on some yet-to-be-defined metric).
> The second one requires the user to be aware of parallelisation (also
> allowing more targeted application), and adapt their code to make use of
> it. It also has a lot less moving parts.
>
> I hope someone finds this useful.
>
> Jan-Pieter
> ----------------------------------------------------------------------
> 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
----------------------------------------------------------------------
For information about J forums see http://www.jsoftware.com/forums.htm