Can't find the method for conv(x, w, dims) in NNLib.jl src

I have done searches on the repo and looked through all of conv.jl within NNLib.jl. I can only find a method that takes 2 positional arguments and the rest named arguments. If you except the defaults for all of the named arguments you can call this as conv(x, w). But, the one and only function called conv returns conv(x, w, cdims) where cdims is calculated based on the named arguments to conv().

Somewhere the 3 argument method has to exist. Searches on both the Flux.jl repo and NNLib.jl repo did not reveal it. It has to exist somewhere.

I am trying to learn from the Flux implementation as I have had considerable difficulty writing my own code for convolutional layers using unrolling.

That method definition is generated by meta-programming, which is probably why you didn’t spot it:

Thanks.

I hate code like that. Layers of layers of indirection. Impossible to see the names of the functions. Impossible even to see the body of the function, although this one just supplies some parameters to the primary conv function.

Is it really necessary to have this macro generated code? Would it be so hard to explicitly code the required methods? Text editors are efficient. Then, others could interpret what the code does.

Why is this so Julian? It’s worse than the c++ standard template library.

Just trying to see how the convolutions are implemented. Where is something the provides the “template” for all of the various methods…

Sorry, I am using email to reply rather than the discourse thread, so too many separate messages.

Step 4 selects the implementation, but where is any instance of a realized implementation?

I’m not familiar with the source file, either, and only had a quick look for this thread. But maybe you can try a debugger to step into various function definitions to locate the source lines.

The code for the implementations lives in NNlib.jl/src/impl at master · FluxML/NNlib.jl · GitHub, which makes sense since it is segregated from the generated code in the post you’re replying to.

When this code was originally written, Julia was a less mature language and NNlib had more, idiosyncratic backends. My understanding is that the code generation and multiple levels of indirection was a way around both of those challenges.

These days, overuse of @eval is not Julian and there are only two CPU implementations left for conv (direct and im2col). Ideally someone could help simplify the template routines in conv.jl. It’s unlikely to happen without a volunteer, unfortunately.

1 Like

Very fair.

I think the goal of the macro was to avoid dynamic dispatch by instantiating all the needed methods. Sometimes concision collides with clarity and maintainability.

An alternative would have been to create functions that provided the appropriate signature for each method and in each function body prepare the input parameters needed and call the generic code.