Skip to content

Commit 7c5f4d8

Browse files
committed
Add variants of PrimsNonStrongRef that use a closure access function rather than an accessor to get the underlying value.
I am going to be adding a variant of this that uses Unmanaged._withUnsafeGuaranteedRef(...). To truly make it fair, I am adding variants that also use an access ref entrypoint.
1 parent 561c76d commit 7c5f4d8

File tree

1 file changed

+119
-0
lines changed

1 file changed

+119
-0
lines changed

benchmark/single-source/PrimsNonStrongRef.swift

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,15 @@ public let PrimsNonStrongRef: [BenchmarkInfo] = ({
4343
touchGlobalInfo()
4444
blackHole(weakPrimsState)
4545
}))
46+
// TODO: Stabilize weak benchmark.
47+
benchmarks.append(BenchmarkInfo(
48+
name: "Prims.NonStrongRef.Weak.ClosureAccess",
49+
runFunction: run_PrimsWeakClosureAccess,
50+
tags: [.validation, .algorithm],
51+
setUpFunction: {
52+
touchGlobalInfo()
53+
blackHole(weakPrimsState)
54+
}))
4655
#endif
4756
benchmarks.append(BenchmarkInfo(
4857
name: "Prims.NonStrongRef.UnownedSafe",
@@ -52,6 +61,14 @@ public let PrimsNonStrongRef: [BenchmarkInfo] = ({
5261
touchGlobalInfo()
5362
blackHole(unownedSafePrimsState)
5463
}))
64+
benchmarks.append(BenchmarkInfo(
65+
name: "Prims.NonStrongRef.UnownedSafe.ClosureAccess",
66+
runFunction: run_PrimsUnownedSafeClosureAccess,
67+
tags: [.validation, .algorithm],
68+
setUpFunction: {
69+
touchGlobalInfo()
70+
blackHole(unownedSafePrimsState)
71+
}))
5572
benchmarks.append(BenchmarkInfo(
5673
name: "Prims.NonStrongRef.UnownedUnsafe",
5774
runFunction: run_PrimsUnownedUnsafe,
@@ -60,6 +77,14 @@ public let PrimsNonStrongRef: [BenchmarkInfo] = ({
6077
touchGlobalInfo()
6178
blackHole(unownedUnsafePrimsState)
6279
}))
80+
benchmarks.append(BenchmarkInfo(
81+
name: "Prims.NonStrongRef.UnownedUnsafe.ClosureAccess",
82+
runFunction: run_PrimsUnownedUnsafeClosureAccess,
83+
tags: [.validation, .algorithm],
84+
setUpFunction: {
85+
touchGlobalInfo()
86+
blackHole(unownedUnsafePrimsState)
87+
}))
6388
benchmarks.append(BenchmarkInfo(
6489
name: "Prims.NonStrongRef.Unmanaged",
6590
runFunction: run_PrimsUnmanaged,
@@ -68,6 +93,14 @@ public let PrimsNonStrongRef: [BenchmarkInfo] = ({
6893
touchGlobalInfo()
6994
blackHole(unmanagedPrimsState)
7095
}))
96+
benchmarks.append(BenchmarkInfo(
97+
name: "Prims.NonStrongRef.Unmanaged.ClosureAccess",
98+
runFunction: run_PrimsUnmanagedClosureAccess,
99+
tags: [.validation, .algorithm, .api],
100+
setUpFunction: {
101+
touchGlobalInfo()
102+
blackHole(unmanagedPrimsState)
103+
}))
71104
return benchmarks
72105
})()
73106

@@ -1059,6 +1092,41 @@ where Node.BoxType == Box, Box.ValueType == Node
10591092
return treeEdges
10601093
}
10611094

1095+
func primsMainLoopClosureAccess<Node : GraphNode, Box>(
1096+
_ graph : Array<Node>,
1097+
_ fun : (Node.BoxType, Node.BoxType) -> Double) -> Array<Int?>
1098+
where Node.BoxType == Box, Box.ValueType == Node
1099+
{
1100+
var treeEdges = Array<Int?>(repeating:nil, count:graph.count)
1101+
let queue = PriorityQueue<Node>(count: graph.count)
1102+
1103+
// Make the minimum spanning tree root its own parent for simplicity.
1104+
queue.insert(EdgeCost(to: graph[0], cost: 0.0, from: graph[0]))
1105+
1106+
// Take an element with the smallest cost from the queue and add its
1107+
// neighbors to the queue if their cost was updated
1108+
while !queue.isEmpty {
1109+
// Add an edge with minimum cost to the spanning tree
1110+
let e = queue.pop()!
1111+
let newnode: Node.BoxType = e.to
1112+
1113+
// Add record about the edge newnode->e.from to treeEdges
1114+
treeEdges[newnode.withValue { $0.id }] = e.from.withValue { $0.id }
1115+
1116+
// Check all adjacent nodes and add edges, ending outside the tree, to the
1117+
// queue. If the queue already contains an edge to an adjacent node, we
1118+
// replace existing one with the new one in case the new one costs less.
1119+
for toNode: Box in (newnode.withValue { $0.adjList }) {
1120+
if treeEdges[toNode.withValue { $0.id }] != nil {
1121+
continue
1122+
}
1123+
let newcost = fun(newnode, toNode)
1124+
queue.insertOrUpdate(EdgeCost(to: toNode, cost: newcost, from: newnode))
1125+
}
1126+
}
1127+
return treeEdges
1128+
}
1129+
10621130
//===----------------------------------------------------------------------===//
10631131
// Top Level Entrypoints
10641132
//===----------------------------------------------------------------------===//
@@ -1084,6 +1152,25 @@ func run_PrimsNonStrongRef<Node: GraphNode, Box>(_ state: PrimsState<Node, Box>)
10841152
CheckResults(Int(cost) == 49324)
10851153
}
10861154

1155+
@inline(__always)
1156+
func run_PrimsNonStrongRefClosureAccess<Node: GraphNode, Box>(_ state: PrimsState<Node, Box>) where Node.BoxType == Box, Box.ValueType == Node {
1157+
let graph = state.graph
1158+
let map = state.edgeToCostMap
1159+
1160+
// Find spanning tree
1161+
let treeEdges = primsMainLoopClosureAccess(graph, { (start: Box, end: Box) in
1162+
return map[Edge(start: start, end: end)]!
1163+
})
1164+
1165+
// Compute its cost in order to check results
1166+
var cost = 0.0
1167+
for i in 1..<treeEdges.count {
1168+
if let n = treeEdges[i] {
1169+
cost += map[Edge(start: Box(graph[n]), end: Box(graph[i]))]!
1170+
}
1171+
}
1172+
CheckResults(Int(cost) == 49324)
1173+
}
10871174

10881175

10891176
@inline(never)
@@ -1094,6 +1181,14 @@ public func run_PrimsWeak(_ N: Int) {
10941181
}
10951182
}
10961183

1184+
@inline(never)
1185+
public func run_PrimsWeakClosureAccess(_ N: Int) {
1186+
let state = weakPrimsState
1187+
for _ in 0..<N {
1188+
run_PrimsNonStrongRefClosureAccess(state)
1189+
}
1190+
}
1191+
10971192
@inline(never)
10981193
public func run_PrimsUnownedSafe(_ N: Int) {
10991194
let state = unownedSafePrimsState
@@ -1102,6 +1197,14 @@ public func run_PrimsUnownedSafe(_ N: Int) {
11021197
}
11031198
}
11041199

1200+
@inline(never)
1201+
public func run_PrimsUnownedSafeClosureAccess(_ N: Int) {
1202+
let state = unownedSafePrimsState
1203+
for _ in 0..<N {
1204+
run_PrimsNonStrongRefClosureAccess(state)
1205+
}
1206+
}
1207+
11051208
@inline(never)
11061209
public func run_PrimsUnownedUnsafe(_ N: Int) {
11071210
let state = unownedUnsafePrimsState
@@ -1110,10 +1213,26 @@ public func run_PrimsUnownedUnsafe(_ N: Int) {
11101213
}
11111214
}
11121215

1216+
@inline(never)
1217+
public func run_PrimsUnownedUnsafeClosureAccess(_ N: Int) {
1218+
let state = unownedUnsafePrimsState
1219+
for _ in 0..<N {
1220+
run_PrimsNonStrongRefClosureAccess(state)
1221+
}
1222+
}
1223+
11131224
@inline(never)
11141225
public func run_PrimsUnmanaged(_ N: Int) {
11151226
let state = unmanagedPrimsState
11161227
for _ in 0..<N {
11171228
run_PrimsNonStrongRef(state)
11181229
}
11191230
}
1231+
1232+
@inline(never)
1233+
public func run_PrimsUnmanagedClosureAccess(_ N: Int) {
1234+
let state = unmanagedPrimsState
1235+
for _ in 0..<N {
1236+
run_PrimsNonStrongRefClosureAccess(state)
1237+
}
1238+
}

0 commit comments

Comments
 (0)