Performance when chaining multiple macros

I’m aware that macros such as @muladd from MuladdMacro.jl, @views, and @inbounds are occasionally very useful for performance. Might there be any problems with combining them in general? For example, is the following chaining of macros valid?

using MuladdMacro
A = rand(100, 100)
B = rand(100, 100)
C = rand(100, 1)
@muladd @views @inbounds @. for j = 1:100
    A[:, j] = C * C + B[:, j] * A[:, j] # Write C^2 = C * C so that @muladd works 
end 

Or are there limitations on how far we can chain these individual macros for performance without seeing negative effects?

Macros transform code, and there’s no way to guarantee that a series of transformations will be useful (or even valid). You can check with @macroexpand, though:

julia> @macroexpand @muladd @views @inbounds @. for j = 1:100
           A[:, j] = C * C + B[:, j] * A[:, j] # Write C^2 = C * C so that @muladd works
       end
quote
    $(Expr(:inbounds, true))
    local var"#2016#val" = for j = 1:100
                #= REPL[106]:2 =#
                A[:, j] .= (muladd).((Base.maybeview)(B, :, j), (Base.maybeview)(A, :, j), (*).(C, C))
            end
    $(Expr(:inbounds, :pop))
    var"#2016#val"
end
2 Likes

On the other hand, they only impose a performance loss at compilation time. So, if they are used in the body of a function called often with the same parameter types, especially to speed-up loops, then the performance loss should be minimal in comparison to their gains.

1 Like