Sorry, didn’t realize the conversation had wandered off-list. Thanks for correcting that. I’ll check the type-stability and return with some benchmarks. I’ve got a julia build as of yesterday showing about a 5x decrease over native memory access which surprised me a little bit.
julia> const a = rand(10_000, 10_000); (after a few repetitions…) julia> @time mean(a) elapsed time: 0.050039199 seconds (184 bytes allocated) 0.5000072164856915 julia> @time mean(sub(a, 1:10_000, 1:10_000)); elapsed time: 2.349825138 seconds (584 bytes allocated) Here we’re about 5x slower. In my larger case we’re about 50x slower, but I will check there for type instability. On March 26, 2015 at 5:13:21 PM, Tim Holy ([email protected]) wrote: It's better to keep these conversations on the list (CCed). I can't tell from what you've shown whether you're talking about creation performance or usage performance. For most cases, usage (indexing) performance should be nearly at the level of Arrays, if you believe the benchmarks (https://github.com/JuliaLang/julia/pull/8501#issuecomment-63232821, https://github.com/JuliaLang/julia/pull/9329, https://github.com/JuliaLang/julia/pull/10507). Are you sure you're using a recent 0.4 checkout? You don't have a type-stability problem, do you? --Tim On Thursday, March 26, 2015 03:44:13 PM you wrote: > Now that I’ve used a few in anger, they also seem slow in v0.4, like 50x > slower than regular arrays. Is this down to bounds checking? > > My case is simple, I have data that looks like > > ..header..|..data[n]..|..header..|..data[n]..|... > > So all I have to do to expose the data as a 2D array is > sub(header_len+1:header_len+n, 1:num_records) I’d think it would specialize > very fast since there is still contiguous access in the first dimension, > and a contiguous stride. > > And it’s good enough to get working, but I was a bit surprised. Any > suggestions? > > On March 25, 2015 at 4:48:41 PM, Sebastian Good > ([email protected]) wrote: > > I think I’d have to know a lot more about Julia to have a reasonable > contribution in those murky waters! > > On March 25, 2015 at 4:07:19 PM, Tim Holy ([email protected]) wrote: > > On Wednesday, March 25, 2015 03:47:55 PM you wrote: > > I guess it’s at that point that getindex > > with ranges will return SubArrays, i.e. mutable views, instead of copies? > > Is that still targeted for v0.4? > > In my opinion, that depends mostly on whether we settle on a solution to > https://github.com/JuliaLang/julia/pull/8227 in time. Help wanted :-). > > --Tim > > > On March 25, 2015 at 3:30:03 PM, Tim Holy ([email protected]) wrote: > > > > SubArrays are immutable on 0.4. But tuples aren't inlined, which is going > > to force allocation. > > > > Assuming you're using 0.3, there's a second problem: the code in the > > constructor is not type-stable, and that makes construction slow and > > memory- hungry. Compare the following on 0.3 and 0.4: > > > > julia> A = rand(2,10^4); > > > > julia> function myfun(A) > > s = 0.0 > > for j = 1:size(A,2) > > S = slice(A, :, j) > > s += sum(S) > > end > > s > > end > > myfun (generic function with 1 method) > > > > > > On 0.3: > > # warmup call > > julia> @time myfun(A) > > elapsed time: 0.145141435 seconds (11277536 bytes allocated) > > > > # the real call > > julia> @time myfun(A) > > elapsed time: 0.034556106 seconds (7866896 bytes allocated) > > > > > > On 0.4: > > julia> @time myfun(A) > > elapsed time: 0.190744146 seconds (7 MB allocated) > > > > julia> @time myfun(A) > > elapsed time: 0.000697173 seconds (1 MB allocated) > > > > > > > > So you can see it's about 50x faster and about 8-fold more memory > > efficient > > on 0.4. Once Jeff finishes his tuple overhaul, the allocation on 0.4 could > > potentially drop to 0. > > > > --Tim > > > > On Wednesday, March 25, 2015 11:18:08 AM Sebastian Good wrote: > > > I was surprised by two things in the SubArray implementation > > > > > > 1) They are big! About 175 bytes for a simple subset from a 1D array > > > from > > > my naive measurement.[*] > > > 2) They are not flat. That is, they seem to get heap allocated and have > > > indirections in them. > > > > > > I'm guessing this is because SubArrays aren't immutable, and tuples > > > aren't > > > always inlined into an immutable either, but I am really grasping at > > > straws. > > > > > > I'm walking through a very large memory mapped structure and generating > > > hundreds of thousands of subarrays to look at various windows of it. I > > > was > > > hoping that by using views I would reduce memory usage as compared with > > > creating copies of those windows. Indeed I am, but by a lot less than I > > > thought I would be. > > > > > > In other words: SubArrays are surprisingly expensive because they > > > necessitate several memory allocations apiece. > > > > > > From the work that's gone into SubArrays I'm guessing that isn't meant > > > to > > > be. They are so carefully specialized that I would expect them to behave > > > roughly like a (largish) struct in common use. > > > > > > Is this a misconception? Do I need to take more care about how I > > > parameterize the container I put them in to take advantage? > > > > > > [*] > > > > > > > const b = [1:5;] > > > > function f() > > > > > > for i in 1:1_000_000 sub(b, 1:2) end > > > end > > > > > > > @time f() > > > > > > elapsed time: 0.071933306 seconds (175 MB allocated, 9.21% gc time in 8 > > > pauses with 0 full sweep)
