Till
Till

Reputation: 45

Is a macro always faster than a function in julia?

I am interested to pass the value of a easy function (2 in the minimal example below). My minimal example shows that the macro is much faster than the function. Is that right or did I do a mistake?

using BenchmarkTools
macro func!(arg)
    arg = eval(arg)
    for i in 1:length(arg)
        arg[i] = 2
    end
    return nothing
end
function func!(arg)
    for i in 1:length(arg)
        arg[i] = 2
    end
    return nothing
end
x = ones(10^3)
@btime @func!(x) --> 0.001 ns (0 allocations: 0 bytes)
@btime func!(x) --> 332.272 ns (0 allocations: 0 bytes)

EDIT1:

No, it is not faster. It seems that the @btime and @time macro do not work with macros. I checked that with the @time macro in the minimal example below. And I counted the seconds for the macro even if @time told me that it used almost no time.

x = ones(10^7)
@time @func!(x) --> 0.000001 seconds (3 allocations: 144 bytes)
@time func!(x) --> 0.007362 seconds (4 allocations: 160 bytes)

Upvotes: 0

Views: 263

Answers (1)

Bogumił Kamiński
Bogumił Kamiński

Reputation: 69949

Again there are two comments as last time.

The macro is actually slower

Consider this code that evaluates actual time it takes for the macro and the function to finish its work:

julia> x = ones(10^8);

julia> t1 = time_ns()
0x00006937ba4da19e

julia> @func!(x)

julia> t2 = time_ns()
0x00006939ebcb5c41

julia> Int(t2 - t1)
9420257955

julia>

julia> x = ones(10^8);

julia> t1 = time_ns()
0x0000693a0ee9452f

julia> func!(x)

julia> t2 = time_ns()
0x0000693a16ea941e

julia> Int(t2 - t1)
134303471

And you see that the function is significantly faster. The difference is that the time is consumed at different moments (compile time vs run time, and @btime measures run time).

The macro works only if its argument is defined in global scope

For example the following code fails:

julia> function test()
           abc = [1,2,3]
           @func!(abc)
           abc
       end
ERROR: LoadError: UndefVarError: abc not defined

while:

julia> function test()
           abc = [1,2,3]
           func!(abc)
           abc
       end
test (generic function with 1 method)

julia> test()
3-element Array{Int64,1}:
 2
 2
 2

so function and macro actually do different things.

In general I typically recommend not to use macros unless there is a strong reason to do so.

Upvotes: 6

Related Questions