Skip to content

Commit 6d5edc2

Browse files
KristofferCKristofferC
authored andcommitted
use ArrayOfArrays for return value to reduce the number of allocated arrays
A long standing gripe for me has been that indices and distances are returned as standard nested `Array`s. Typically, each inner array hold quite a small number of neighbors so it means that we allocate a large number of small arrays. Using ArrayOfArrays, these are stored contigously in one large flat array instead. The difference in allocations can be readily seen: ```julia julia> input = rand(3, 10^6); julia> tree = KDTree(rand(3, 10^6)); julia> @time knn(tree, input, 5); 1.538003 seconds (2.00 M allocations: 221.253 MiB, 10.03% gc time) julia> @time knn(tree, input, 5); 1.489310 seconds (98 allocations: 189.884 MiB, 0.29% gc time) ```
1 parent bc645d1 commit 6d5edc2

File tree

4 files changed

+16
-5
lines changed

4 files changed

+16
-5
lines changed

Project.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,15 @@ uuid = "b8a86587-4115-5ab1-83bc-aa920d37bbce"
33
version = "0.4.17"
44

55
[deps]
6+
ArraysOfArrays = "65a8f2f4-9b39-5baf-92e2-a9cc46fdf018"
67
Distances = "b4f34e82-e78d-54a5-968a-f98e89d6e8f7"
78
StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
89

910
[compat]
1011
Distances = "0.9, 0.10"
1112
StaticArrays = "0.9, 0.10, 0.11, 0.12, 1.0"
1213
julia = "1.6"
14+
ArraysOfArrays = "0.6"
1315

1416
[extras]
1517
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"

src/NearestNeighbors.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ using Distances
44
import Distances: PreMetric, Metric, result_type, eval_reduce, eval_end, eval_op, eval_start, evaluate, parameters
55

66
using StaticArrays
7+
using ArraysOfArrays
78
import Base.show
89

910
export NNTree, BruteTree, KDTree, BallTree, DataFreeTree

src/inrange.jl

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,13 @@ function inrange(tree::NNTree,
1313
check_input(tree, points)
1414
check_radius(radius)
1515

16-
idxs = [Vector{Int}() for _ in 1:length(points)]
16+
idxs = VectorOfArrays{Int, 1}()
17+
idx = Int[]
1718

1819
for i in 1:length(points)
19-
inrange_point!(tree, points[i], radius, sortres, idxs[i])
20+
inrange_point!(tree, points[i], radius, sortres, idx)
21+
push!(idxs, idx)
22+
resize!(idx, 0)
2023
end
2124
return idxs
2225
end

src/knn.jl

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,15 @@ function knn(tree::NNTree{V}, points::Vector{T}, k::Int, sortres=false, skip::F=
1818
check_input(tree, points)
1919
check_k(tree, k)
2020
n_points = length(points)
21-
dists = [Vector{get_T(eltype(V))}(undef, k) for _ in 1:n_points]
22-
idxs = [Vector{Int}(undef, k) for _ in 1:n_points]
21+
dists = VectorOfArrays{Float64, 1}()
22+
idxs = VectorOfArrays{Int, 1}()
23+
dist = zeros(Float64, k)
24+
idx = zeros(Int, k)
25+
2326
for i in 1:n_points
24-
knn_point!(tree, points[i], sortres, dists[i], idxs[i], skip)
27+
knn_point!(tree, points[i], sortres, dist, idx, skip)
28+
push!(dists, dist)
29+
push!(idxs, idx)
2530
end
2631
return idxs, dists
2732
end

0 commit comments

Comments
 (0)