Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 34 additions & 1 deletion benchmark/autofill.jl
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,37 @@ function coarse_and_fine_autofill()
return
end

SUITE["autofill"] = @benchmarkable coarse_and_fine_autofill()
SUITE["autofill"] = BenchmarkGroup()
SUITE["autofill"]["coarse_and_fine"] = @benchmarkable coarse_and_fine_autofill()

# gridpoints_in_polygon microbenchmarks at varying grid densities
using DeviceLayout.Polygons: difference2d

# Polygon with a cutout (exercises both horizontal edge and winding number paths)
const _gip_r1 = Rectangle(200μm, 200μm)
const _gip_r2 = Rectangle(100μm, 100μm) + Point(50μm, 50μm)
const _gip_poly = [difference2d(_gip_r1, _gip_r2)]

const _gip_grids = [
(
"33x25",
collect(range(-10μm, 210μm, length=33)),
collect(range(-10μm, 210μm, length=25))
),
(
"321x241",
collect(range(-10μm, 210μm, length=321)),
collect(range(-10μm, 210μm, length=241))
),
(
"3201x2401",
collect(range(-10μm, 210μm, length=3201)),
collect(range(-10μm, 210μm, length=2401))
)
]

SUITE["autofill"]["gridpoints_in_polygon"] = BenchmarkGroup()
for (label, gx, gy) in _gip_grids
SUITE["autofill"]["gridpoints_in_polygon"][label] =
@benchmarkable gridpoints_in_polygon($_gip_poly, $gx, $gy)
end
2 changes: 1 addition & 1 deletion benchmark/tune.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
[{"Julia":"1.12.0","BenchmarkTools":{"major":1,"minor":6,"patch":2,"prerelease":[],"build":[]}},[["BenchmarkGroup",{"data":{"schematic":["BenchmarkGroup",{"data":{"plan":["Parameters",{"gctrial":true,"time_tolerance":0.05,"evals_set":false,"samples":10000,"evals":1,"gcsample":false,"seconds":5.0,"overhead":0.0,"memory_tolerance":0.01}]},"tags":[]}],"curves":["BenchmarkGroup",{"data":{"turns_render":["Parameters",{"gctrial":true,"time_tolerance":0.05,"evals_set":false,"samples":10000,"evals":1,"gcsample":false,"seconds":5.0,"overhead":0.0,"memory_tolerance":0.01}],"bsplines_render":["Parameters",{"gctrial":true,"time_tolerance":0.05,"evals_set":false,"samples":10000,"evals":1,"gcsample":false,"seconds":5.0,"overhead":0.0,"memory_tolerance":0.01}],"offset_bspline_approximation":["Parameters",{"gctrial":true,"time_tolerance":0.05,"evals_set":false,"samples":10000,"evals":1,"gcsample":false,"seconds":5.0,"overhead":0.0,"memory_tolerance":0.01}]},"tags":[]}],"polygons":["BenchmarkGroup",{"data":{"rectangles":["BenchmarkGroup",{"data":{"render_units":["Parameters",{"gctrial":true,"time_tolerance":0.05,"evals_set":false,"samples":10000,"evals":1,"gcsample":false,"seconds":5.0,"overhead":0.0,"memory_tolerance":0.01}],"render":["Parameters",{"gctrial":true,"time_tolerance":0.05,"evals_set":false,"samples":10000,"evals":1,"gcsample":false,"seconds":5.0,"overhead":0.0,"memory_tolerance":0.01}],"render_units_gds":["Parameters",{"gctrial":true,"time_tolerance":0.05,"evals_set":false,"samples":10000,"evals":1,"gcsample":false,"seconds":5.0,"overhead":0.0,"memory_tolerance":0.01}],"render_convertunits":["Parameters",{"gctrial":true,"time_tolerance":0.05,"evals_set":false,"samples":10000,"evals":1,"gcsample":false,"seconds":5.0,"overhead":0.0,"memory_tolerance":0.01}],"render_gds":["Parameters",{"gctrial":true,"time_tolerance":0.05,"evals_set":false,"samples":10000,"evals":1,"gcsample":false,"seconds":5.0,"overhead":0.0,"memory_tolerance":0.01}]},"tags":[]}],"circles":["BenchmarkGroup",{"data":{"direct":["Parameters",{"gctrial":true,"time_tolerance":0.05,"evals_set":false,"samples":10000,"evals":1,"gcsample":false,"seconds":5.0,"overhead":0.0,"memory_tolerance":0.01}],"entity_delta":["Parameters",{"gctrial":true,"time_tolerance":0.05,"evals_set":false,"samples":10000,"evals":1,"gcsample":false,"seconds":5.0,"overhead":0.0,"memory_tolerance":0.01}],"direct_units_gds":["Parameters",{"gctrial":true,"time_tolerance":0.05,"evals_set":false,"samples":10000,"evals":1,"gcsample":false,"seconds":5.0,"overhead":0.0,"memory_tolerance":0.01}],"direct_units":["Parameters",{"gctrial":true,"time_tolerance":0.05,"evals_set":false,"samples":10000,"evals":1,"gcsample":false,"seconds":5.0,"overhead":0.0,"memory_tolerance":0.01}],"entity_atol":["Parameters",{"gctrial":true,"time_tolerance":0.05,"evals_set":false,"samples":10000,"evals":1,"gcsample":false,"seconds":5.0,"overhead":0.0,"memory_tolerance":0.01}],"direct_gds":["Parameters",{"gctrial":true,"time_tolerance":0.05,"evals_set":false,"samples":10000,"evals":1,"gcsample":false,"seconds":5.0,"overhead":0.0,"memory_tolerance":0.01}]},"tags":[]}]},"tags":[]}],"flatten":["BenchmarkGroup",{"data":{"shallow_references":["Parameters",{"gctrial":true,"time_tolerance":0.05,"evals_set":false,"samples":10000,"evals":1,"gcsample":false,"seconds":5.0,"overhead":0.0,"memory_tolerance":0.01}],"array_reference":["Parameters",{"gctrial":true,"time_tolerance":0.05,"evals_set":false,"samples":10000,"evals":1,"gcsample":false,"seconds":5.0,"overhead":0.0,"memory_tolerance":0.01}],"nested_references":["Parameters",{"gctrial":true,"time_tolerance":0.05,"evals_set":false,"samples":10000,"evals":1,"gcsample":false,"seconds":5.0,"overhead":0.0,"memory_tolerance":0.01}]},"tags":[]}],"clipping":["BenchmarkGroup",{"data":{"difference2d_offset":["Parameters",{"gctrial":true,"time_tolerance":0.05,"evals_set":false,"samples":10000,"evals":1,"gcsample":false,"seconds":5.0,"overhead":0.0,"memory_tolerance":0.01}],"difference2d":["BenchmarkGroup",{"data":{"100_square":["Parameters",{"gctrial":true,"time_tolerance":0.05,"evals_set":false,"samples":10000,"evals":1,"gcsample":false,"seconds":5.0,"overhead":0.0,"memory_tolerance":0.01}],"3600_square":["Parameters",{"gctrial":true,"time_tolerance":0.05,"evals_set":false,"samples":10000,"evals":1,"gcsample":false,"seconds":5.0,"overhead":0.0,"memory_tolerance":0.01}],"961_square":["Parameters",{"gctrial":true,"time_tolerance":0.05,"evals_set":false,"samples":10000,"evals":1,"gcsample":false,"seconds":5.0,"overhead":0.0,"memory_tolerance":0.01}],"19881_square":["Parameters",{"gctrial":true,"time_tolerance":0.05,"evals_set":false,"samples":10000,"evals":1,"gcsample":false,"seconds":5.0,"overhead":0.0,"memory_tolerance":0.01}],"8000_skew":["Parameters",{"gctrial":true,"time_tolerance":0.05,"evals_set":false,"samples":10000,"evals":1,"gcsample":false,"seconds":5.0,"overhead":0.0,"memory_tolerance":0.01}],"10000_square":["Parameters",{"gctrial":true,"time_tolerance":0.05,"evals_set":false,"samples":10000,"evals":1,"gcsample":false,"seconds":5.0,"overhead":0.0,"memory_tolerance":0.01}]},"tags":[]}]},"tags":[]}],"bounds":["BenchmarkGroup",{"data":{"random_rectangles":["Parameters",{"gctrial":true,"time_tolerance":0.05,"evals_set":false,"samples":10000,"evals":1,"gcsample":false,"seconds":5.0,"overhead":0.0,"memory_tolerance":0.01}],"shallow_references":["Parameters",{"gctrial":true,"time_tolerance":0.05,"evals_set":false,"samples":10000,"evals":1,"gcsample":false,"seconds":5.0,"overhead":0.0,"memory_tolerance":0.01}],"random_circles":["Parameters",{"gctrial":true,"time_tolerance":0.05,"evals_set":false,"samples":10000,"evals":1,"gcsample":false,"seconds":5.0,"overhead":0.0,"memory_tolerance":0.01}],"nested_references":["Parameters",{"gctrial":true,"time_tolerance":0.05,"evals_set":false,"samples":10000,"evals":1,"gcsample":false,"seconds":5.0,"overhead":0.0,"memory_tolerance":0.01}]},"tags":[]}],"intersection":["BenchmarkGroup",{"data":{"straight_lines":["Parameters",{"gctrial":true,"time_tolerance":0.05,"evals_set":false,"samples":10000,"evals":1,"gcsample":false,"seconds":5.0,"overhead":0.0,"memory_tolerance":0.01}]},"tags":[]}],"autofill":["Parameters",{"gctrial":true,"time_tolerance":0.05,"evals_set":false,"samples":10000,"evals":1,"gcsample":false,"seconds":5.0,"overhead":0.0,"memory_tolerance":0.01}]},"tags":[]}]]]
[{"Julia":"1.12.0","BenchmarkTools":{"major":1,"minor":6,"patch":2,"prerelease":[],"build":[]}},[["BenchmarkGroup",{"data":{"schematic":["BenchmarkGroup",{"data":{"plan":["Parameters",{"gctrial":true,"time_tolerance":0.05,"evals_set":false,"samples":10000,"evals":1,"gcsample":false,"seconds":5.0,"overhead":0.0,"memory_tolerance":0.01}]},"tags":[]}],"curves":["BenchmarkGroup",{"data":{"turns_render":["Parameters",{"gctrial":true,"time_tolerance":0.05,"evals_set":false,"samples":10000,"evals":1,"gcsample":false,"seconds":5.0,"overhead":0.0,"memory_tolerance":0.01}],"bsplines_render":["Parameters",{"gctrial":true,"time_tolerance":0.05,"evals_set":false,"samples":10000,"evals":1,"gcsample":false,"seconds":5.0,"overhead":0.0,"memory_tolerance":0.01}],"offset_bspline_approximation":["Parameters",{"gctrial":true,"time_tolerance":0.05,"evals_set":false,"samples":10000,"evals":1,"gcsample":false,"seconds":5.0,"overhead":0.0,"memory_tolerance":0.01}]},"tags":[]}],"polygons":["BenchmarkGroup",{"data":{"rectangles":["BenchmarkGroup",{"data":{"render_units":["Parameters",{"gctrial":true,"time_tolerance":0.05,"evals_set":false,"samples":10000,"evals":1,"gcsample":false,"seconds":5.0,"overhead":0.0,"memory_tolerance":0.01}],"render":["Parameters",{"gctrial":true,"time_tolerance":0.05,"evals_set":false,"samples":10000,"evals":1,"gcsample":false,"seconds":5.0,"overhead":0.0,"memory_tolerance":0.01}],"render_units_gds":["Parameters",{"gctrial":true,"time_tolerance":0.05,"evals_set":false,"samples":10000,"evals":1,"gcsample":false,"seconds":5.0,"overhead":0.0,"memory_tolerance":0.01}],"render_convertunits":["Parameters",{"gctrial":true,"time_tolerance":0.05,"evals_set":false,"samples":10000,"evals":1,"gcsample":false,"seconds":5.0,"overhead":0.0,"memory_tolerance":0.01}],"render_gds":["Parameters",{"gctrial":true,"time_tolerance":0.05,"evals_set":false,"samples":10000,"evals":1,"gcsample":false,"seconds":5.0,"overhead":0.0,"memory_tolerance":0.01}]},"tags":[]}],"circles":["BenchmarkGroup",{"data":{"direct":["Parameters",{"gctrial":true,"time_tolerance":0.05,"evals_set":false,"samples":10000,"evals":1,"gcsample":false,"seconds":5.0,"overhead":0.0,"memory_tolerance":0.01}],"entity_delta":["Parameters",{"gctrial":true,"time_tolerance":0.05,"evals_set":false,"samples":10000,"evals":1,"gcsample":false,"seconds":5.0,"overhead":0.0,"memory_tolerance":0.01}],"direct_units_gds":["Parameters",{"gctrial":true,"time_tolerance":0.05,"evals_set":false,"samples":10000,"evals":1,"gcsample":false,"seconds":5.0,"overhead":0.0,"memory_tolerance":0.01}],"direct_units":["Parameters",{"gctrial":true,"time_tolerance":0.05,"evals_set":false,"samples":10000,"evals":1,"gcsample":false,"seconds":5.0,"overhead":0.0,"memory_tolerance":0.01}],"entity_atol":["Parameters",{"gctrial":true,"time_tolerance":0.05,"evals_set":false,"samples":10000,"evals":1,"gcsample":false,"seconds":5.0,"overhead":0.0,"memory_tolerance":0.01}],"direct_gds":["Parameters",{"gctrial":true,"time_tolerance":0.05,"evals_set":false,"samples":10000,"evals":1,"gcsample":false,"seconds":5.0,"overhead":0.0,"memory_tolerance":0.01}]},"tags":[]}]},"tags":[]}],"flatten":["BenchmarkGroup",{"data":{"shallow_references":["Parameters",{"gctrial":true,"time_tolerance":0.05,"evals_set":false,"samples":10000,"evals":1,"gcsample":false,"seconds":5.0,"overhead":0.0,"memory_tolerance":0.01}],"array_reference":["Parameters",{"gctrial":true,"time_tolerance":0.05,"evals_set":false,"samples":10000,"evals":1,"gcsample":false,"seconds":5.0,"overhead":0.0,"memory_tolerance":0.01}],"nested_references":["Parameters",{"gctrial":true,"time_tolerance":0.05,"evals_set":false,"samples":10000,"evals":1,"gcsample":false,"seconds":5.0,"overhead":0.0,"memory_tolerance":0.01}]},"tags":[]}],"clipping":["BenchmarkGroup",{"data":{"difference2d_offset":["Parameters",{"gctrial":true,"time_tolerance":0.05,"evals_set":false,"samples":10000,"evals":1,"gcsample":false,"seconds":5.0,"overhead":0.0,"memory_tolerance":0.01}],"difference2d":["BenchmarkGroup",{"data":{"100_square":["Parameters",{"gctrial":true,"time_tolerance":0.05,"evals_set":false,"samples":10000,"evals":1,"gcsample":false,"seconds":5.0,"overhead":0.0,"memory_tolerance":0.01}],"3600_square":["Parameters",{"gctrial":true,"time_tolerance":0.05,"evals_set":false,"samples":10000,"evals":1,"gcsample":false,"seconds":5.0,"overhead":0.0,"memory_tolerance":0.01}],"961_square":["Parameters",{"gctrial":true,"time_tolerance":0.05,"evals_set":false,"samples":10000,"evals":1,"gcsample":false,"seconds":5.0,"overhead":0.0,"memory_tolerance":0.01}],"19881_square":["Parameters",{"gctrial":true,"time_tolerance":0.05,"evals_set":false,"samples":10000,"evals":1,"gcsample":false,"seconds":5.0,"overhead":0.0,"memory_tolerance":0.01}],"8000_skew":["Parameters",{"gctrial":true,"time_tolerance":0.05,"evals_set":false,"samples":10000,"evals":1,"gcsample":false,"seconds":5.0,"overhead":0.0,"memory_tolerance":0.01}],"10000_square":["Parameters",{"gctrial":true,"time_tolerance":0.05,"evals_set":false,"samples":10000,"evals":1,"gcsample":false,"seconds":5.0,"overhead":0.0,"memory_tolerance":0.01}]},"tags":[]}]},"tags":[]}],"bounds":["BenchmarkGroup",{"data":{"random_rectangles":["Parameters",{"gctrial":true,"time_tolerance":0.05,"evals_set":false,"samples":10000,"evals":1,"gcsample":false,"seconds":5.0,"overhead":0.0,"memory_tolerance":0.01}],"shallow_references":["Parameters",{"gctrial":true,"time_tolerance":0.05,"evals_set":false,"samples":10000,"evals":1,"gcsample":false,"seconds":5.0,"overhead":0.0,"memory_tolerance":0.01}],"random_circles":["Parameters",{"gctrial":true,"time_tolerance":0.05,"evals_set":false,"samples":10000,"evals":1,"gcsample":false,"seconds":5.0,"overhead":0.0,"memory_tolerance":0.01}],"nested_references":["Parameters",{"gctrial":true,"time_tolerance":0.05,"evals_set":false,"samples":10000,"evals":1,"gcsample":false,"seconds":5.0,"overhead":0.0,"memory_tolerance":0.01}]},"tags":[]}],"intersection":["BenchmarkGroup",{"data":{"straight_lines":["Parameters",{"gctrial":true,"time_tolerance":0.05,"evals_set":false,"samples":10000,"evals":1,"gcsample":false,"seconds":5.0,"overhead":0.0,"memory_tolerance":0.01}]},"tags":[]}],"autofill":["BenchmarkGroup",{"data":{"coarse_and_fine":["Parameters",{"gctrial":true,"time_tolerance":0.05,"evals_set":false,"samples":10000,"evals":1,"gcsample":false,"seconds":5.0,"overhead":0.0,"memory_tolerance":0.01}],"gridpoints_in_polygon":["BenchmarkGroup",{"data":{"33x25":["Parameters",{"gctrial":true,"time_tolerance":0.05,"evals_set":false,"samples":10000,"evals":1,"gcsample":false,"seconds":5.0,"overhead":0.0,"memory_tolerance":0.01}],"3201x2401":["Parameters",{"gctrial":true,"time_tolerance":0.05,"evals_set":false,"samples":10000,"evals":1,"gcsample":false,"seconds":5.0,"overhead":0.0,"memory_tolerance":0.01}],"321x241":["Parameters",{"gctrial":true,"time_tolerance":0.05,"evals_set":false,"samples":10000,"evals":1,"gcsample":false,"seconds":5.0,"overhead":0.0,"memory_tolerance":0.01}]},"tags":[]}]},"tags":[]}]},"tags":[]}]]]
45 changes: 27 additions & 18 deletions src/polygons.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2100,6 +2100,10 @@ function gridpoints_in_polygon(
fT = float(T)
grid_x = convert.(fT, sort(grid_x))
grid_y = convert.(fT, sort(grid_y))
nx = length(grid_x)

# Pre-strip units once for horizontal edge lookups (avoids per-edge allocation)
grid_x_stripped = ustrip.(grid_x)

# Segment endpoints
p0s = points.(poly)
Expand All @@ -2120,24 +2124,22 @@ function gridpoints_in_polygon(
)
edge_tree = IntervalTrees.IntervalMap{fT, Tuple{Point{T}, Point{T}}}(edge_iv)

# Difference array for winding number accumulation (extra element as sentinel)
delta = zeros(Int32, nx + 1)
# For each grid y value, look at the edges containing that value
grid_count = zeros(Int32, length(grid_x))
for (iy, y) in enumerate(grid_y)
for i2 in intersect(edge_tree, (y, y))
edge = i2.value
# Count horizontal edges only if grid point lies on them
if last(edge).y == first(edge).y
if first(edge).y == y
in_poly[
findall(
in(
ustrip(min(first(edge).x, last(edge).x)) ..
ustrip(max(first(edge).x, last(edge).x))
),
ustrip.(grid_x)
),
iy
] .= true
x_lo = ustrip(min(first(edge).x, last(edge).x))
x_hi = ustrip(max(first(edge).x, last(edge).x))
i_lo = searchsortedfirst(grid_x_stripped, x_lo)
i_hi = searchsortedlast(grid_x_stripped, x_hi)
for i = i_lo:i_hi
in_poly[i, iy] = true
end
end
continue
end
Expand All @@ -2150,18 +2152,25 @@ function gridpoints_in_polygon(
first(edge).x +
(last(edge).x - first(edge).x) * (y - first(edge).y) /
(last(edge).y - first(edge).y)
ix = findfirst(grid_x .>= x) # The first index to the right of x
x_right_minidx = isnothing(ix) ? length(grid_x) + 1 : ix
x_right_minidx = searchsortedfirst(grid_x, x) # Can be nx + 1 if x > last(grid_x)
# If the grid point lies on the edge, it's in the polygon
x_right_minidx <= length(grid_x) &&
x_right_minidx <= nx &&
x == grid_x[x_right_minidx] &&
(in_poly[x_right_minidx, iy] = true)
# Add edge count to all grid points to the left (sign depending on direction)
# Record edge crossing in difference array (O(1) instead of O(grid_x))
s = sign(last(edge).y - first(edge).y)
@. grid_count[1:(x_right_minidx - 1)] = grid_count[1:(x_right_minidx - 1)] + s
delta[1] += s
delta[x_right_minidx] -= s # In bounds thanks to sentinel
end
# Prefix sum over delta to recover winding counts, then mark in_poly
acc = zero(Int32)
for ix = 1:nx
acc += delta[ix]
if acc != 0
in_poly[ix, iy] = true
end
end
@. in_poly[:, iy] = (grid_count != 0) || in_poly[:, iy]
grid_count .= 0
delta .= 0
end

return in_poly
Expand Down
Loading