Ross,

Sorry, yes, 'refcounted' was clearly a bad choice for keyword in my 
proposal.  Perhaps something like 'indirect' or 'byreference' would be 
appropriate.  But still, my proposal to separate the two attributes of 
immutable seems like a definite improvement over current Julia.

-- Steve Vavasis



On Tuesday, August 5, 2014 5:38:17 PM UTC-4, [email protected] wrote:
>
> Dear Julia users,
>
> It seems to me that Julia's distinction between a 'type' and an 
> 'immutable' conflates two independent properties; the consequence of this 
> conflation is a needless loss of performance.  In more detail, the 
> differences between a 'type' struct and 'immutable' struct in Julia are:
>
> 1. Assignment of 'type' struct copies a pointer; assignment of an 
> 'immutable' struct copies the data.
>
> 2. An array of type structs is an array of pointers, while an array of 
> immutables is an array of data.
>
> 3. Type structs are refcounted, whereas immutables are not.  (This is not 
> documented; it is my conjecture.)
>
> 4. Fields in type structs can be modified, but fields in immutables cannot.
>
> Clearly #1-#3 are related concepts.  As far as I can see, #4 is completely 
> independent from #1-#3, and there is no obvious reason why it is forbidden 
> to modify fields in immutables.  There is no analogous restriction in C/C++.
>
> This conflation causes a performance hit.  Consider:
>
> type floatbool
>   a::Float64
>   b:Bool
> end
>
> If t is of type Array{floatbool,1} and I want to update the flag b in 
> t[10] to 'true', I say 't[10].b=true' (call this 'fast'update).  But if 
> instead of 'type floatbool' I had said 'immutable floatbool', then to set 
> flag b in t[10] I need the more complex code t[10] = 
> floatbool(t[10].a,true) (call this 'slow' update).
>
> To document the performance hit, I wrote five functions below. The first 
> three use 'type' and either no update, fast update, or slow update; the 
> last two use 'immutable' and either no update or slow update.   You can see 
> a HUGE hit on performance between slow and fast update for `type'; for 
> immutable there would presumably also be a difference, although apparently 
> smaller. (Obviously, I can't test fast update for immutable; this is the 
> point of my message!)
>
> So why does Julia impose this apparently needless restriction on immutable?
>
> -- Steve Vavasis
>
>
> julia> @time testimmut.type_upd_none()
> @time testimmut.type_upd_none()
> elapsed time: 0.141462422 seconds (48445152 bytes allocated)
>
> julia> @time testimmut.type_upd_fast()
> @time testimmut.type_upd_fast()
> elapsed time: 0.618769232 seconds (48247072 bytes allocated)
>
> julia> @time testimmut.type_upd_slow()
> @time testimmut.type_upd_slow()
> elapsed time: 4.511306586 seconds (4048268640 bytes allocated)
>
> julia> @time testimmut.immut_upd_none()
> @time testimmut.immut_upd_none()
> elapsed time: 0.04480173 seconds (32229468 bytes allocated)
>
> julia> @time testimmut.immut_upd_slow()
> @time testimmut.immut_upd_slow()
> elapsed time: 0.351634871 seconds (32000096 bytes allocated)
>
> module testimmut
>
> type xytype
>     x::Int
>     y::Float64
>     z::Float64
>     summed::Bool
> end
>
> immutable xyimmut
>     x::Int
>     y::Float64
>     z::Float64
>     summed::Bool
> end
>
> myfun(x) = x * (x + 1) * (x + 2)
>
> function type_upd_none()
>     n = 1000000
>     a = Array(xytype, n)
>     for i = 1 : n
>         a[i] = xytype(div(i,2), 0.0, 0.0, false)
>     end
>     numtri = 100
>     for tri = 1 : numtri
>         sum = 0
>         for i = 1 : n
>             @inbounds x = a[i].x
>             sum += myfun(x)
>         end
>     end
> end
>
>
> function type_upd_fast()
>     n = 1000000
>     a = Array(xytype, n)
>     for i = 1 : n
>         a[i] = xytype(div(i,2),  0.0, 0.0, false)
>     end
>     numtri = 100
>     for tri = 1 : numtri
>         sum = 0
>         for i = 1 : n
>             @inbounds x = a[i].x
>             sum += myfun(x)
>             @inbounds a[i].summed = true
>         end
>     end
> end
>
> function type_upd_slow()
>     n = 1000000
>     a = Array(xytype, n)
>     for i = 1 : n
>         a[i] = xytype(div(i,2),  0.0, 0.0, false)
>     end
>     numtri = 100
>     for tri = 1 : numtri
>         sum = 0
>         for i = 1 : n
>             @inbounds x = a[i].x
>             sum += myfun(x)
>             @inbounds a[i] = xytype(a[i].x, a[i].y, a[i].z, true)
>         end
>     end
> end
>
>
> function immut_upd_none()
>     n = 1000000
>     a = Array(xyimmut, n)
>     for i = 1 : n
>         a[i] = xyimmut(div(i,2),  0.0, 0.0, false)
>     end
>     numtri = 100
>     for tri = 1 : numtri
>         sum = 0
>         for i = 1 : n
>             @inbounds x = a[i].x
>             sum += myfun(x)
>         end
>     end
> end
>
> function immut_upd_slow()
>     n = 1000000
>     a = Array(xyimmut, n)
>     for i = 1 : n
>         a[i] = xyimmut(div(i,2),  0.0, 0.0, false)
>     end
>     numtri = 100
>     for tri = 1 : numtri
>         sum = 0
>         for i = 1 : n
>             @inbounds x = a[i].x
>             sum += myfun(x)
>             @inbounds a[i] = xyimmut(a[i].x, a[i].y, a[i].z, true)
>         end
>     end
> end
>
> end
>
>
>   
>

Reply via email to