-
Notifications
You must be signed in to change notification settings - Fork 17
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Domain error when inferring array type in 0-length degenerated case #29
Comments
One thing we should probably support (but don't currently) is this: julia> m = MappedArray{Float64}(f, a)
ERROR: MethodError: no method matching MappedArray{Float64,N,A,F,Finv} where Finv where F where A<:AbstractArray where N(::typeof(f), ::Array{Int64,1})
Stacktrace:
[1] top-level scope at REPL[4]:1 It would just be a matter of adding a couple of methods. Without requiring the user to provide the answer, for cases like yours I am not aware of a solution that works in general that doesn't use |
Thanks for the answer! I also see another possible problem when inferring the eltype, now for non-empty arrays. If the input array has an eltype that is not a concrete one, then inferring the mapped eltype from the first array entry is not save. I am right? |
Yes, that's right. Another reason to rework this. |
Just a final question: is there any way of using an "inplace" funcion, when working with large arrays of arrays? I would like to avoid allocating memory when getting an entry from the lazy array. something like function f!(v::AbstractArray,a::AbstractArray)
# mutate v from the entries in a
end
# Instead of
function f(a::AbstractArray)
# Allocate v and mutate it from the entries in a
# return v
end
a = [rand(10,20) for i in 1:10000]
mappedarray(f,a) Do you think, allocating memory is a problem each time an entry is accessed for large arrays? Thanks for the help! |
The easiest way to do that would be to put the storage and logic into the function you pass in: julia> using MappedArrays
julia> const buf = zeros(5);
julia> f(x) = (buf .= x.^2; return buf)
f (generic function with 1 method)
julia> aa = [rand(5) for i = 1:10];
julia> m = mappedarray(f, aa);
julia> function sumalot(m)
s = zero(first(m))
for i = 1:10000
s .+= m[(i % (length(m)-1)) + 1]
end
return s
end
sumalot (generic function with 1 method)
julia> sumalot(m)
5-element Array{Float64,1}:
4308.145615923303
4008.7673891697395
4891.049206648661
2737.7823120736575
3687.6835874596586
julia> @time sumalot(m)
0.000576 seconds (5 allocations: 288 bytes)
5-element Array{Float64,1}:
4308.145615923303
4008.7673891697395
4891.049206648661
2737.7823120736575
3687.6835874596586 You could also define a type and a corresponding call function, if you'd prefer to be more explicit about "containment" of the buffer. |
For small arrays you can also use StaticArrays. Also note |
The problem with a constant global buffer is that it's not thread-save, but certainly a solution for single-threaded applications. The approach I like more, is to extend the Thanks for the help! This is all what I needed to know. Best! |
It would be great to fix some of the issues noted. If you don't want to submit a PR to fix them yourself, let's at least leave this open. |
Are you thinking in a solution using I find it quite dangerous, i.a., it hides errors: julia> g(x) = foo(x)
g (generic function with 1 method)
julia> g(1)
ERROR: UndefVarError: foo not defined
Stacktrace:
[1] g(::Int64) at ./REPL[1]:1
[2] top-level scope at REPL[2]:1
julia> Base._return_type(g,(Int,))
Any With I think, the best option is that the user provides test values for the function if he/she knows that For instance foo(x) = sqrt(x-1)
# Default test value
testvalue(f::Function,::Type{T}) where T = zero(T)
# User-defined one
testvalue(::typeof(foo),,::Type{T}) where T = zero(T)+one(T)
Then using This solution is minimally invasive. What do you think? |
Sorry for the delay. I like it! |
Hi!
do you plan to support degenerated cases like the one below in the future?
Just for curiosity, how would you fix this in the library? Is it possible to fix it without calling something like
Base._return_type
?Thanks for the help!
The text was updated successfully, but these errors were encountered: