Closed kuanxu closed 8 years ago
Sorry. I just checked out the recent commits and happily found that approx_op
has been removed! Thanks.
Types can be constructed in Julia (at least in 0.4) with some fields undefined. These require an inner constructor. The "Self-Referential" section in the manual discusses this. Accessing an undefined field results in an error.
Cheers,
Mikael
On Jun 21, 2016, at 6:44 PM, Kuan Xu notifications@github.com wrote:
Currently, FrameFun has a field approx_op which is the approximation operators used to construct the FrameFun or, more precisely, the other field expansion. I totally understand that this might be of a historic issue - you folks just wanted to keep the information for a while, as they're not dirt cheap to acquire and it is pretty useful for any debugging work. However, this causes some troubles for the users.
As a user whose work is built on the top of FrameFuns, if I try to construct a FrameFun not from scratch but from another FrameFun directly (e.g FrameFun x 2), I generally don't have a sensible approx_op to supply to the constructor. However, as far as I understand, I can't construct an object with some fields missing in Julia. I'm also unable to supply something like void to the constructor, since Julia does not have a “null” value. This makes personally assembled FrameFuns almost impossible without providing a place holder, i.e. a dummy approx_op.
The field approx_op costs a lot in memory. So I guess it drags the speed in some degree. But I have no benchmark to justify this.
Shall we consider to get rid of approx_op at all? Comments?
— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub, or mute the thread.
Thanks for reporting! Indeed, that approx_op field was annoying more often than not, and that is why we took it out. I thought it was a good idea at first, because the construction of the approximation operator can be expensive.
@MikaelSlevinsky Thanks for reminding the incompletely initialized objects with new()
. But I didn't mean to modify FrameFun
's constructor, but still be able to construct a FrameFun
with field(s) undefined.
Do you know if there is a way to construct a type with undefined fields but without deliberately using new()
?
@daanhb Do we really need to keep the field expansion
, as it is the only field on its own level? It might be more straightforward if we strip off expansion
so that a FrameFun
directly own the fields set
and coef
. But you guys may have other thoughts on it.
Not that I'm aware... maybe someone at julia-users has an answer
@kuanxu You may want to consider just using a SetExpansion directly, if that is possible for your use case. That is exactly a combination of a set and coefficients. All arithmetic is (or should be) defined on expansions. It would also be faster in many cases since a SetExpansion has fully typed fields, intentionally. This means the compiler will optimize away all overhead of these expansions in most cases.
For background, the reason we introduced the FrameFun type was for convenience. It is a shallow, and slow (because it is untyped) layer over SetExpansion. The only thing it adds is that the type expresses that it is a frame, and that makes it a little easier to dispatch e.g. plotting routines. It also removes many layers of interactive output of nested parameters. Functionally, a FrameFun is (or should be) equivalent to a SetExpansion where the set is a DomainFrame.
Having said that, there might well be holes in our implementation! The above is the general idea. Please report whatever is missing...
@daanhb Sorry for not having responded sooner! I've been hectic for the deadline of exam marking.
Why do you say that FrameFun's fields (now field) are untyped? I don't see it.
immutable FrameFun{N,T} <: AbstractFun
expansion :: SetExpansion
FrameFun(e::SetExpansion) = new(e)
end
Can you elaborate a little?
@kuanxu I was being sloppy: the expansion
field of FrameFun
is indeed typed, but not fully. SetExpansion
is not a concrete type, because its parameters are not specified (S,ELT and ID). Hence, the compiler does not know exactly what the concrete type of the expansion
of a FrameFun
is, and that makes manipulations with FrameFun
's slower than manipulations with SetExpansion
's. Saying that expansion
always is a SetExpansion
does allow the compiler to narrow down the possibilities at runtime.
Not that you're suggesting this, but for completeness: we could add the extra parameters to the field expansion::SetExpansion
, but then we also have to add them to the type FrameFun
itself. There is a large compilation overhead in adding parameters everywhere. In the end, this approach makes everything depend on everything else. As soon as one type is changed somewhere, everything has to be recompiled. In addition, there are hard-coded limits in the depth of nested types in Julia. In fact, that kind of over-typing was a real bottleneck at some point in our code. We started removing type parameters whenever the potential runtime cost of dynamic type checking is not in a time-critical path, or when it is just O(1)
in a computation that is O(N)
or more expensive overall. Look at the history of CompositeOperator
for an example. This exercise is not over yet, but we cut down the running time of our test suite by a factor of 2-3 with such kind of changes.
Anyway, back on topic, we will always make sure that manipulations with SetExpansion
's are fast. That's why I suggested to use them instead. It is not a good name, though. Perhaps we ought to call them Fun
's. Or just Expansion
.
@daanhb Thanks for the detailed explanation!! It can't be more elaborated. 👍 From now on, I'll stick to SetExpansion
for my use cases.
It would be cool if that works for you, thanks.
Currently, FrameFun has a field
approx_op
which is the approximation operators used to construct the FrameFun or, more precisely, the other fieldexpansion
. I totally understand that this might be of a historic issue - you folks just wanted to keep the information for a while, as they're not dirt cheap to acquire and it is pretty useful for any debugging work. However, this causes some troubles for the users.approx_op
to supply to the constructor. However, as far as I understand, I can't construct an object with some fields missing in Julia. I'm also unable to supply something likevoid
to the constructor, since Julia does not have a “null” value. This makes personally assembled FrameFuns almost impossible without providing a place holder, i.e. a dummyapprox_op
.approx_op
costs a lot in memory. So I guess it drags the speed in some degree. But I have no benchmark to justify this.Shall we consider to get rid of
approx_op
at all? Comments?