Ok, I will give a minimum working example.
Consider this:
abstract FElement
type LinTrig <: FElement
v1::Int
end
type LinQuad <: FElement
v1::Int
v2::Int
end
type Node
c::Float64
end
type FEMesh
node::Vector{Node}
elements::Vector{FElement}
end
function assembleK(mesh::FEMesh)
for element in mesh.elements
println(element.v1)
end
end
Now, running @code_warntype gives
@code_warntype(assembleK(mesh))
Variables:
mesh::FEMesh
#s2::Int64
element::FElement
Body:
begin # none, line 2:
GenSym(0) = (top(getfield))(mesh::FEMesh,:elements)::Array{FElement,1}
#s2 = 1
GenSym(2) = #s2::Int64
GenSym(4) = (top(arraylen))(GenSym(0))::Int64
unless
(top(box))(Bool,(top(not_int))((top(slt_int))(GenSym(4),GenSym(2))::Bool))
goto 1
2:
GenSym(10) = (top(arrayref))(GenSym(0),#s2::Int64)::FElement
GenSym(11) = (top(box))(Int64,(top(add_int))(#s2::Int64,1))
element = GenSym(10)
#s2 = GenSym(11) # line 3:
println((top(getfield))(element::FElement,:v1)::Any)::Any
3:
GenSym(6) = #s2::Int64
GenSym(8) = (top(arraylen))(GenSym(0))::Int64
unless
(top(box))(Bool,(top(not_int))((top(box))(Bool,(top(not_int))((top(slt_int))(GenSym(8),GenSym(6))::Bool))))
goto 2
1:
0:
return
end::Void
So I have a type instability that will cause a lot of allocations and slow
the code down. If I instead stick to one element type and instead define
mesh to contain a vector of the concrete type like this
type FEMesh
node::Vector{Node}
elements::Vector{LinTrig}
end
then I don't have an instability any more and my code runs much faster.
My questions is basically how I would easiest remove the instability
without "hard coding" the type the elements will have.
On Saturday, March 14, 2015 at 10:35:04 PM UTC+1, Sisyphuss wrote:
>
> Hello Kristoffer, I don't quite understand what you are doing. But by
> judging from the title of your post, I'd like to share with you my opinion,
> and I hope it would be helpful.
>
> The (multiple) dispatch used by Julia is a dynamic one, that is, the
> dispatch is preformed at run time instead of compiling time (or "code write
> time" as you mentioned). So you shouldn't have any worry about that, as
> long as your callee function can handle different concrete types. If it is
> not the case or it can't be achieved in a simple way, it is advised to
> write separate functions (a.k.a. generic function) for different concrete
> types.
>
>
>
> On Saturday, March 14, 2015 at 9:28:48 PM UTC+1, Kristoffer Carlsson wrote:
>>
>> Hello,
>>
>> I am writing some code for Finite Elements in Julia. As usual, I have a
>> mesh with elements and nodes. However, I do not want to restrict myself to
>> only using one type of element per mesh and therefore I have a hierarchy of
>> element types along the lines of:
>>
>> abstract FElement
>>
>> type LinTrig <:FElement end
>>
>> type LinQuad <: FElement end
>>
>> etc
>>
>> My mesh then consists of a Vector of FElements.
>>
>> Since I have a Vector of an abstract type I get a performance hit when I,
>> for example, assemble the global stiffness matrix. The compiler does not
>> know what type of element it will find and have to check it in each
>> iteration. For simple material models the overhead from the type checking
>> is 10 times larger than calculating the elements stiffness matrix
>> contribution.
>>
>> Now, when I am writing the code for the assembler I can't know what
>> elements that the mesh will contain. However, *at the actual call* to
>> the assembly function I know what element types I have in the mesh and that
>> these will never change. I should then be able to give the compiler that
>> information and have it generate efficient code.
>>
>> I mean, I can do this manually. Just check for the element types,
>> generate one vector of elements for each element type and call the assembly
>> function for each separate vector of elements. All of these types will be
>> known.
>>
>> Is this possible to do somehow?
>>
>> I hope I made sense.
>>
>> Best regards,
>> Kristoffer Carlsson
>>
>