-
Notifications
You must be signed in to change notification settings - Fork 0
Description
Some transducers (e.g. Cat
) do internal reductions inside of their next
methods. For example,
upstream Transducers.jl does
struct Cat <: Transducer
end
function next(rf::R_{Cat}, acc, x)
rf0, itr0 = retransform(inner(rf), asfoldable(x))
return __foldl__(skipcomplete(rf), acc, itr0)
end
which basically says that foldl(+, Cat(), [[1.0,2.0,3.0], [4.0, 5.0]]; init=0.0)
should turn into
acc = 0.0
for v in [[1.0,2.0,3.0], [4.0, 5.0]]
for x in v # <------ The inner fold performed by `Cat`
acc += x
end
end
However, I have been wanting to make whether or not SIMD
is enabled an Executor
option, and I wanted to pass Executor
s to __fold__
and dispatch on them. But this creates a problem for things like Cat()
, because it means they might lose things like their SIMD
execution info.
There's three potential fixes I see here:
- Make executors transducers. Upstream
Transducers.jl
actually does this withSIMD
already, but it doesn't do it with things like threads or distributed. I don't think I like this because it's not really a transformation of the inner reducing function, and it's also messy to use / support. - Make
Cat()
hold an Executor. E.g. this would mean you'd writefold(+, Cat(executor = SIMDEx()), vov)
if you wanted SIMD to be applied in the inner loop. There's some times where this would be nice and make sense, but I think most of the time it'd just be kinda annoying because it'd case a lot of passing around executors.- One place this is nice would be that you could write something like
fold(+, Cat(executor=ThreadsEx()), vov)
to do inner parallelism. I'm not sure how I feel about this though.
- One place this is nice would be that you could write something like
- Make
next
take an executor option. So this means that instead of havingnext(rf, acc, x)
you'd havenext(rf, acc, x, executor)
, where theexecutor
argument is normally just ignored, but transducers likeCat
can forward it to their inner reduction steps.
I think I dont like option 1, and I'm a little unsure about options 2/3. They both have upsides and downsides. We could also do both of 2 and 3, since they're compatible, i.e. if Cat
isn't given an executor, then Cat
will use the provided one inside of next
.