Reputation: 5134
suppose I have an existing array like
x = rand(4)
and then I want to reset x
to zero. Can I avoid doing x = zeros(4)
. I'm concerened about memory allocation.
Upvotes: 11
Views: 6523
Reputation: 19132
The best way to do it in one line is:
x .= zero(y)
or
fill!(x, zero(y))
where y
is the type of number you want it to be like. The reason why this way is good is that it works in all cases. If x
is any type, using this will work as long as y
matches the type (indeed, you can use y = x[1]
).
When I mean any type, I mean that this also works for odd number types like SIUnits. If you use this command, a package could support SIUnits without ever having to import the package since this will apply the correct units to the x
values (as long as all of its operations are correct in units), while fill!(x, 0.0)
will error due to wrong units (you can also use fill!(x, zeros(y))
. Otherwise, you'd have to check for units and all sorts of things.
Upvotes: 15
Reputation: 22225
It seems to me people have suggested nice alternative ways of doing this but no-one addressed the actual question of "what's the most efficient way (specifically in terms of memory)".
So here it is. Given:
f1(x) = x = zeros(size(x));
f2(x) = x[:] = zero(x[1]);
f3(x) = fill!(x, zero(x[1]));
f4(x) = x = zero(x);
We have:
julia> x=rand(1000,1000); @time (for i in 1_000_000_000; x=f1(x); end;)
0.000715 seconds (3 allocations: 7.629 MB)
julia> x=rand(1000,1000); @time (for i in 1_000_000_000; f2(x); end;)
0.000691 seconds (2 allocations: 32 bytes)
julia> x=rand(1000,1000); @time (for i in 1_000_000_000; f3(x); end;)
0.000702 seconds (2 allocations: 32 bytes)
julia> x=rand(1000,1000); @time (for i in 1_000_000_000; x=f4(x); end;)
0.000704 seconds (2 allocations: 7.629 MB)
f1
or f4
are mutating functions; they are not, they return a reference to a new object in memory; i.e. they are there for completeness to demonstrate the bad alternatives that OP is presumably trying to avoid.
I just felt that a question about "efficiency" deserved some numbers to complement the suggestions offered by my colleagues :)
Upvotes: 2
Reputation: 5325
You can do
fill!(x, 0.0)
This overwrites the contents with zeros.
This should be just as efficient as just doing a for
loop, though:
for i in 1:length(x)
x[i] = 0.0
end
Indeed, if you do @edit fill!(x, 0.0)
, you will see that this is basically what it is doing (except that it uses @inbounds
for more efficiency).
Upvotes: 3