-
Notifications
You must be signed in to change notification settings - Fork 149
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
make reshaping SizedArrays not turn them into SArrays #719
Conversation
Interesting, but I'm not sure this helps in practice? After this patch, julia> @code_typed vec(SizedMatrix{2,2}([1 2; 3 4]))
CodeInfo(
1 ─ %1 = Base.getfield(a, :data)::Array{Int64,2}
│ %2 = Base.arrayref(false, %1, 1)::Int64
│ %3 = Base.getfield(a, :data)::Array{Int64,2}
│ %4 = Base.arrayref(false, %3, 2)::Int64
│ %5 = Base.getfield(a, :data)::Array{Int64,2}
│ %6 = Base.arrayref(false, %5, 3)::Int64
│ %7 = Base.getfield(a, :data)::Array{Int64,2}
│ %8 = Base.arrayref(false, %7, 4)::Int64
│ %9 = $(Expr(:foreigncall, :(:jl_alloc_array_1d), Array{Int64,1}, svec(Any, Int64), 0, :(:ccall), Array{Int64,1}, 4, 4))::Array{Int64,1}
│ %10 = %new(SizedArray{Tuple{4},Int64,1,1}, %9)::SizedArray{Tuple{4},Int64,1,1}
│ Base.arrayset(false, %9, %2, 1)::Array{Int64,1}
│ Base.arrayset(false, %9, %4, 2)::Array{Int64,1}
│ Base.arrayset(false, %9, %6, 3)::Array{Int64,1}
│ Base.arrayset(false, %9, %8, 4)::Array{Int64,1}
└── return %10
) => SizedArray{Tuple{4},Int64,1,1} So while the output type may be sensible, the amount of code generated even for simple operations like |
hmm, I really want to carry around this information in the type in the code I am writing. Do you think we should (in general) add a bail-out clause to a bunch of generated functions? |
You mean to generate different code for different static array lengths? That's a reasonable workaround for exploding compile times and code size which we've discussed before. But nobody has put in the work to do it systematically across the package. There are some tricky aspects to doing that:
|
Hmm... Regardless of the problems with So maybe that's an argument we should just go ahead with this. It's certainly a more predictable way for the API to behave: just preserve all static array types as much as possible during computations, and let the user be (more) in charge of the data layout by letting them choose which static array type to supply to a function. |
yes, i think so. It will at least fix my small sized trials.
My thoughts when I saw SizedArray was: Clearly I was wrong. |
FWIW, I think this shouldn't be the mental model. It should be "we give LLVM the explicit size of the arrays" and then it is up to LLVM to decide on unrolling vs not. This would be in a similar spirit to #494. The only problem with that right now is that we cannot mutate immutables so we have to unroll everything when we want the result to be a static array. However, in the future, I would say the static matrix multiply should look something like
where the allocation of That would avoid the amount of code scaling unbounded with the size of the arrays and we could then file performance bugs/fixes against LLVM for cases where it doesn't optimize properly. Giving the code with loops to LLVM should likely allow it to do a better job since it is "higher level", more closely matching the intent of the computation. For example, for SIMD stuff, pattern matching on the loops is likely easier (loop vectorizes) over pattern matching on the unrolled code (SLP vectorizer) |
Right, I completely agree unrolling everything isn't ideal in principle. It's not a long term solution, but it is a good way to get fairly-ok performance with the current compiler and a really simple heuristic. See also the parallel discussion in the LoopVectorization thread on discourse (starting about here: https://discourse.julialang.org/t/ann-loopvectorization/32843/63). |
For good or bad that's not what @andyferris @YingboMa @ChrisRackauckas I believe #327 was a success; certainly it addressed a pain point and nobody complained here afterward ;-) Given you were involved in that, I'd value your thoughts on whether preserving My main thought is that it would make the API more predictable so I'm inclined to do it. |
I think this patch makes sense since it only changes the behavior of |
I agree with that assumption. |
Thanks people for weighing in on this one. Hearing no objections, and with several at least seemingly-good reasons to do this, I've gone ahead and merged this. |
I had an array, and I wanted to carry size information about it around in its type..
At first I thought, I can use a
SArray
, but then I remember my matrix might endup being something like 10^3 x 10^6 elements; and creating aSArray
would be really slow.I looked in the docs and I spotted
SizedArray
and I am likle Pefect.So I am happily using that.
Then at some point I needed to call
vec
on mySizedArray
,and after I did that, it had turned into a
SArray
.Which I really did not want, reasons outlined above.
This fixed that.
The code was basically already there, I just uncommented and updated it.