julia lang - Efficient-yet-terse way to add all the arrays in a composite type? -
i came 2 ways add arrays in pair of composite types. first way (add_structs_1) takes 4 seconds run , second way (add_structs_2) takes 0.15 seconds. second way requires lot more code...i have explicitly mention each field in composite type. there way efficiency of add_structs_2, without explicitly listing each field?
type samplestruct a::vector{float64} k::matrix{float64} e_axis::vector{float64} e_dev::vector{float64} e_scale::vector{float64} end function add_structs_1(tgt::samplestruct, src::samplestruct) n in names(samplestruct) in 1:length(tgt.(n)) tgt.(n)[i] += src.(n)[i] end end end function add_structs_2(tgt::samplestruct, src::samplestruct) in 1:length(tgt.a) tgt.a[i] += src.a[i] end in 1:length(tgt.k) tgt.k[i] += src.k[i] end in 1:length(tgt.e_axis) tgt.e_axis[i] += src.e_axis[i] end in 1:length(tgt.e_dev) tgt.e_dev[i] += src.e_dev[i] end in 1:length(tgt.e_scale) tgt.e_scale[i] += src.e_scale[i] end end function time_add_structs(f::function) src = samplestruct(ones(3), ones(3,3), [1.], [1.], [1.]) tgt = samplestruct(ones(3), ones(3,3), [1.], [1.], [1.]) @time in 1:1000000 f(tgt, src) end end time_add_structs(add_structs_1) time_add_structs(add_structs_1) time_add_structs(add_structs_2) time_add_structs(add_structs_2) time_add_structs(add_structs_3) time_add_structs(add_structs_3)
a more julian approach add_structs_1 make inner loop separate function, allows compiler specialize function on each type in samplestruct , gives quite speedup.
by profiling code visible time execute names(samplestruct) quite significant, , should done in each iteration of benchmark, making global constant time gained , function looks like:
function add_array(a::abstractarray,b::abstractarray) in 1:length(a) a[i] += b[i] end end const names_in_struct = names(samplestruct) function add_structs_3(tgt::samplestruct, src::samplestruct) n in names_in_struct add_array(tgt.(n),src.(n)) end end the function within factor of 4 of add_structs_2
the metaprogramming approach more complicated gives same performance add_structs_2
ex = any[] n in names(samplestruct) t = expr(:.,:tgt, quotenode(n)) s = expr(:.,:src, quotenode(n)) e=quote in 1:length($t) $t[i] += $s[i] end end push!(ex,e) end eval(quote function add_structs_4(tgt::samplestruct, src::samplestruct) $(expr(:block,ex...)) end end)
Comments
Post a Comment