-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
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
cat
overflows on >= 10000 inputs
#50473
Comments
Splatting arbitrarily large collections is bound to overflow at some point. |
Having it stack overflow is a pretty bad error message for something that's essentially a compiler/language limitation. Is there an issue tracking this problem? It's a fairly common newbie problem in Julia, and it requires specialized knowledge of the language internals to understand why it shouldn't just work. |
It's pretty difficult to detect this kind of thing (semi) accurately, as it's not the splatting or slurping that fails here, but the recursion over that and detecting "this will throw before it finishes due to ressource constraints" is a highly irregular and hard to estimate heuristic due to being machine, ressource use AND function specific. If you want to capture the failure mode during dispatch of the method, you're going to run into much the same issue in regards to estimating how much you're going to need - and it can't capture the allocation of that tuple either, because that needs to happen first. |
Yes, but practically speaking, the way Julians handle this is to internalise the rule "never splat a large number of elements", so we might as well make that emit a warning. |
Where do we emit that warning though? Just attach it to any method taking more than N arguments..? I imagine that's not super simple to do, as most slurping functions end up taking |
I imagine it could be inserted at the language level, since it's a language level limitation, and be compiled away for all function calls where the number of arguments is known at compile time |
That's the same as attaching IO effects to any |
For funcitons with unknown number of arguments, recursion should be avoided. Such type of error in By checking the code, there is another possible way to improve. function __cat_offset!(A, shape, catdims, offsets, x, X...)
# splitting the "work" on x from X... may reduce latency (fewer costly specializations)
newoffsets = __cat_offset1!(A, shape, catdims, offsets, x)
return __cat_offset!(A, shape, catdims, newoffsets, X...)
end Is it possible to optimize out tail recursion with for loops using Julia compiler? |
Dup of #30796 |
Shouldn't we at least improve the implementation of |
Why would you not use Cf the doctstring for
|
I have a program that plays with high order tensors. Given a sample set with with 10000 configurations, for each configuration, I need to slice some tensors along certain dimensions (which is not possible to know beforehand). With the obtained 10000 sliced tensors, I need to concatenate them into a large tensor to feed them into the batched matrix multiplication routines. Maybe the following code explains better. This is the current tensor slicing program, which is not needed if # `x` is the tensor,
# `slicedim` is the dimensions to be sliced
# `configs` is a matrix of size `(nsubindices, nsample)`, each column specifies a subindex for slicing.
function get_slice(x::AbstractArray{T}, slicedim, configs::AbstractMatrix) where T
outdim = setdiff(1:ndims(x), slicedim)
res = similar(x, [size(x, d) for d in outdim]..., size(configs, 2))
return get_slice!(res, x, outdim, slicedim, configs)
end
function get_slice!(res, x::AbstractArray{T}, outdim, slicedim, configs::AbstractMatrix) where T
xstrides = strides(x)
@inbounds for ci in CartesianIndices(res)
idx = 1
# the output dimensions
for (dim, k) in zip(outdim, ci.I)
idx += (k-1) * xstrides[dim]
end
# the batch dimension
batchidx = ci.I[end]
for (dim, k) in zip(slicedim, view(configs, :, batchidx))
idx += k * xstrides[dim]
end
res[ci] = x[idx]
end
return res
end |
For a bit now I've been advocating for I really dislike the julia> using BenchmarkTools
julia> x = [zeros(2,2) for _ in 1:100];
julia> @btime reduce(hcat, $x);
929.167 ns (1 allocation: 3.25 KiB)
julia> @btime mapreduce(vec, hcat, $x);
20.900 μs (299 allocations: 177.42 KiB)
julia> @btime reduce(hcat, Iterators.map(vec,$x));
20.400 μs (299 allocations: 177.42 KiB)
julia> t = ntuple(_->zeros(2,2),100);
julia> @btime reduce(hcat, $t);
18.900 μs (100 allocations: 170.41 KiB)
julia> @btime hcat($t...); # now hcat is better
4.300 μs (4 allocations: 5.64 KiB) Predicate specializations only help for the cases we can imagine beforehand. They're performance minefields. |
After checking the implementation of |
How about we just cap the number of function arguments that are allowed at 1k? Anyone calling a function with that many arguments is doing something bad and should be chastised. That would allow us to give a better error message instead of crashing. |
This would cause problems. |
I want to concatenate multiple arrays. The
hcat
function works well when the number of input arguments is large, however forcat
, it errors on 10000 input argument. The error message as well as a MWE is as bellow:The text was updated successfully, but these errors were encountered: