JuliaArrays / UnsafeArrays.jl

Stack-allocated pointer-based array views
Other
42 stars 5 forks source link

Memory allocation associated with reshape if no explicit indexing occurs. #5

Closed cohensbw closed 4 years ago

cohensbw commented 4 years ago

The following piece of code behaves as you may expect, with zero allocations occurring:

function f(r)
    @uviews r begin
        s = reshape(r, (100*100,))
        s[1] = 1
    end
end

r = rand(100, 100)
@btime f(r)

12.357 ns (0 allocations: 0 bytes)

However, if you eliminate the indexing event, then an allocation appears:

function f(r)
    @uviews r begin
        s = reshape(r, (100*100,))
    end
end

r = rand(100, 100)
@btime f(r)

11.363 ns (1 allocation: 32 bytes)

This seems like undesirable behavior. It doesn't make sense that eliminating the line s[1]=1 would introduce a memory allocation when before there was not one.

Let me know what you think! I am confused by this behavior...

oschulz commented 4 years ago

Hm, I wonder if this could be a benchmarking artifact. But in any case, the second version is not only "unsafe", but very dangerous: You're allowing the unsafe array to escape from the @uviews scope (f returns s). This must never happen, since garbage collection or resizing of the original r can invalidate the memory pointer that the unsafe r and s within @uviews hold.

cohensbw commented 4 years ago

Thank you so much for the quick response, and pointing out the danger in my function code. Based on your guidance I believe I resolved the issue.

function f(r)
    @uviews r begin
        s = reshape(r, (100*100,))
    end
    return nothing
end

r = rand(100, 100)
@btime f(r)

11.261 ns (0 allocations: 0 bytes)

Returning nothing explicitly appears to eliminate the extra memory allocation. You would consider this function no longer dangerous, correct? I should always remember to just explicitly return nothing in my code when that is the intent of a function I suppose... Again, thank you for your assistance and pointing out my mistake.

oschulz commented 4 years ago

Happy to help!

@uviews shouldn't return an UnsafeArray or something that contains an UnsafeArray. So in your code above, return nothing should be inside of @uviews begin ... end.