Speeding up combination of Funs

I’m building up an ApproxFun.Fun by successively multiplying a lot of individual factors along a graph. The individual factors are themselves also Funs. The situation is similar to this fake code

factors = []
for n in nodes
  factor :: Fun = make_factor(parameters(node))
  push!(factors, factor)
end
result::Fun = prod(factors)

I would like to speed this up as much as possible, possibly by reducing allocation.

I found out that make_factor allocates in the MB range and runs tens of ms. The return value factor has a modest number of coefficients below 100, and is just a few KB. make_factor involves arithmetic with Funs, including:

  • exp(make_fun(t2) - make_fun(t1)) where make_fun constructs a Fun from float parameters t1,t2 and
  • Fun(space) / (Fun(space) + make_fun(t3))

Basically, I’m wondering if I can fuse arithmetic operations on Fun to avoid constructing intermediate expansions, or use inplace transformation of expansions to make this faster. Also, is there a clever way to construct the product in the end?

The space in question is a Chebyshev(0..1)

Your “example code” is not very clear but I will say ApproxFun.jl is not ideal for high-performance manipulations.

There was some intention of making the newer package ClassicalOrthogonalPolynomials.jl better equipped for high-performance, allocation free computing but I don’t think it’s there yet.

I suspect you are best off working directly with FastTransforms.jl to do the transforms between Chebyshev points and coefficients manually. (These are exposed in ApproxFun by plan_transform! so that might also help.)

1 Like

Sorry for not being more clear; I just wanted to convey that there are algebraic operations mapped over many Fun objects and then reduced to yield one final Fun.

I will look into FastTransforms.jl; i did notice that most of the time is spent in transform, so that sounds promising.

I have looked at plan_transform and friends in ApproxFunBase/hBlrP/src/Space.jl. There is a trait supportsinplacetransform but I could not wrap my head around the code there. Is there a place I can get started? From the FAQ of ApproxFun.jl I know how to call transform(space, vals) to compute coefficients, but not how to make that allocate less.