@@ -35,14 +35,23 @@ public let PrimsNonStrongRef: [BenchmarkInfo] = ({
35
35
var benchmarks : [ BenchmarkInfo ] = [ ]
36
36
#if false
37
37
// TODO: Stabilize weak benchmark.
38
- benchmarks . . append ( BenchmarkInfo (
38
+ benchmarks. append ( BenchmarkInfo (
39
39
name: " Prims.NonStrongRef.Weak " ,
40
40
runFunction: run_PrimsWeak,
41
41
tags: [ . validation, . algorithm] ,
42
42
setUpFunction: {
43
43
touchGlobalInfo ( )
44
44
blackHole ( weakPrimsState)
45
45
} ) )
46
+ // TODO: Stabilize weak benchmark.
47
+ benchmarks. append ( BenchmarkInfo (
48
+ name: " Prims.NonStrongRef.Weak.Closure " ,
49
+ runFunction: run_PrimsWeakClosureAccess,
50
+ tags: [ . validation, . algorithm] ,
51
+ setUpFunction: {
52
+ touchGlobalInfo ( )
53
+ blackHole ( weakPrimsState)
54
+ } ) )
46
55
#endif
47
56
benchmarks. append ( BenchmarkInfo (
48
57
name: " Prims.NonStrongRef.UnownedSafe " ,
@@ -52,6 +61,14 @@ public let PrimsNonStrongRef: [BenchmarkInfo] = ({
52
61
touchGlobalInfo ( )
53
62
blackHole ( unownedSafePrimsState)
54
63
} ) )
64
+ benchmarks. append ( BenchmarkInfo (
65
+ name: " Prims.NonStrongRef.UnownedSafe.Closure " ,
66
+ runFunction: run_PrimsUnownedSafeClosureAccess,
67
+ tags: [ . validation, . algorithm] ,
68
+ setUpFunction: {
69
+ touchGlobalInfo ( )
70
+ blackHole ( unownedSafePrimsState)
71
+ } ) )
55
72
benchmarks. append ( BenchmarkInfo (
56
73
name: " Prims.NonStrongRef.UnownedUnsafe " ,
57
74
runFunction: run_PrimsUnownedUnsafe,
@@ -60,6 +77,14 @@ public let PrimsNonStrongRef: [BenchmarkInfo] = ({
60
77
touchGlobalInfo ( )
61
78
blackHole ( unownedUnsafePrimsState)
62
79
} ) )
80
+ benchmarks. append ( BenchmarkInfo (
81
+ name: " Prims.NonStrongRef.UnownedUnsafe.Closure " ,
82
+ runFunction: run_PrimsUnownedUnsafeClosureAccess,
83
+ tags: [ . validation, . algorithm] ,
84
+ setUpFunction: {
85
+ touchGlobalInfo ( )
86
+ blackHole ( unownedUnsafePrimsState)
87
+ } ) )
63
88
benchmarks. append ( BenchmarkInfo (
64
89
name: " Prims.NonStrongRef.Unmanaged " ,
65
90
runFunction: run_PrimsUnmanaged,
@@ -68,6 +93,30 @@ public let PrimsNonStrongRef: [BenchmarkInfo] = ({
68
93
touchGlobalInfo ( )
69
94
blackHole ( unmanagedPrimsState)
70
95
} ) )
96
+ benchmarks. append ( BenchmarkInfo (
97
+ name: " Prims.NonStrongRef.Unmanaged.Closure " ,
98
+ runFunction: run_PrimsUnmanagedClosureAccess,
99
+ tags: [ . validation, . algorithm, . api] ,
100
+ setUpFunction: {
101
+ touchGlobalInfo ( )
102
+ blackHole ( unmanagedPrimsState)
103
+ } ) )
104
+ benchmarks. append ( BenchmarkInfo (
105
+ name: " Prims.NonStrongRef.UnmanagedUGR " ,
106
+ runFunction: run_PrimsUnmanagedUGR,
107
+ tags: [ . validation, . algorithm, . api] ,
108
+ setUpFunction: {
109
+ touchGlobalInfo ( )
110
+ blackHole ( unmanagedUGRPrimsState)
111
+ } ) )
112
+ benchmarks. append ( BenchmarkInfo (
113
+ name: " Prims.NonStrongRef.UnmanagedUGR.Closure " ,
114
+ runFunction: run_PrimsUnmanagedUGRClosureAccess,
115
+ tags: [ . validation, . algorithm, . api] ,
116
+ setUpFunction: {
117
+ touchGlobalInfo ( )
118
+ blackHole ( unmanagedUGRPrimsState)
119
+ } ) )
71
120
return benchmarks
72
121
} ) ( )
73
122
@@ -617,6 +666,7 @@ let weakPrimsState = PrimsState(WeakGraphNode.self)
617
666
let unownedSafePrimsState = PrimsState ( UnownedSafeGraphNode . self)
618
667
let unownedUnsafePrimsState = PrimsState ( UnownedUnsafeGraphNode . self)
619
668
let unmanagedPrimsState = PrimsState ( UnmanagedGraphNode . self)
669
+ let unmanagedUGRPrimsState = PrimsState ( UnmanagedUGRGraphNode . self)
620
670
621
671
//===----------------------------------------------------------------------===//
622
672
// Protocols
@@ -628,11 +678,16 @@ protocol ValueBox : Hashable {
628
678
init ( _ inputValue: ValueType )
629
679
var value : ValueType { get }
630
680
681
+ func withValue< Result> ( _ f: ( ValueType ) throws -> Result ) rethrows -> Result
631
682
func free( )
632
683
}
633
684
634
685
extension ValueBox {
635
686
func free( ) { }
687
+ @_transparent
688
+ func withValue< Result> ( _ f: ( ValueType ) throws -> Result ) rethrows -> Result {
689
+ return try f ( value)
690
+ }
636
691
}
637
692
638
693
protocol GraphNode {
@@ -727,6 +782,46 @@ extension UnmanagedVarBox : Hashable where T : Hashable {
727
782
}
728
783
}
729
784
785
+ struct UnmanagedUGRVarBox < T : AnyObject & Hashable > {
786
+ var _value : Unmanaged < T >
787
+
788
+ init ( _ inputValue: T ) {
789
+ _value = Unmanaged< T> . passRetained( inputValue)
790
+ }
791
+ }
792
+
793
+ extension UnmanagedUGRVarBox : ValueBox where T : GraphNode {
794
+ typealias ValueType = T
795
+
796
+ func free( ) {
797
+ _value. release ( )
798
+ }
799
+
800
+ var value : T { return _value. _withUnsafeGuaranteedRef { $0 } }
801
+
802
+ func withValue< Result> ( _ f: ( ValueType ) throws -> Result ) rethrows -> Result {
803
+ try _value. _withUnsafeGuaranteedRef { try f ( $0) }
804
+ }
805
+ }
806
+
807
+ extension UnmanagedUGRVarBox : Equatable where T : Equatable {
808
+ }
809
+
810
+ func == < T> ( lhs: UnmanagedUGRVarBox < T > , rhs: UnmanagedUGRVarBox < T > ) -> Bool {
811
+ return lhs. _value. _withUnsafeGuaranteedRef { x in
812
+ return rhs. _value. _withUnsafeGuaranteedRef { y in
813
+ return x == y
814
+ } }
815
+ }
816
+
817
+ extension UnmanagedUGRVarBox : Hashable where T : Hashable {
818
+ func hash( into hasher: inout Hasher ) {
819
+ _value. _withUnsafeGuaranteedRef {
820
+ hasher. combine ( ObjectIdentifier ( $0) )
821
+ }
822
+ }
823
+ }
824
+
730
825
//===----------------------------------------------------------------------===//
731
826
// Graph Node Implementations
732
827
//===----------------------------------------------------------------------===//
@@ -849,6 +944,41 @@ func ==(lhs: UnmanagedGraphNode, rhs: UnmanagedGraphNode) -> Bool {
849
944
return lhs === rhs
850
945
}
851
946
947
+
948
+ final class UnmanagedUGRGraphNode {
949
+ /// This id is only meant for dumping the state of the graph. It is not meant
950
+ /// to be used functionally by the algorithm.
951
+ var id : Int
952
+
953
+ var adjList : Array < UnmanagedUGRVarBox < UnmanagedUGRGraphNode > >
954
+
955
+ init ( id inputId: Int ) {
956
+ id = inputId
957
+ adjList = Array < UnmanagedUGRVarBox < UnmanagedUGRGraphNode > > ( )
958
+ }
959
+
960
+ deinit {
961
+ for x in adjList {
962
+ x. free ( )
963
+ }
964
+ }
965
+ }
966
+
967
+ extension UnmanagedUGRGraphNode : GraphNode {
968
+ typealias BoxType = UnmanagedUGRVarBox < UnmanagedUGRGraphNode >
969
+ }
970
+
971
+ extension UnmanagedUGRGraphNode : Equatable { }
972
+ extension UnmanagedUGRGraphNode : Hashable {
973
+ func hash( into hasher: inout Hasher ) {
974
+ hasher. combine ( ObjectIdentifier ( self ) )
975
+ }
976
+ }
977
+
978
+ func == ( lhs: UnmanagedUGRGraphNode , rhs: UnmanagedUGRGraphNode ) -> Bool {
979
+ return lhs === rhs
980
+ }
981
+
852
982
//===----------------------------------------------------------------------===//
853
983
// Edge Implementation
854
984
//===----------------------------------------------------------------------===//
@@ -1054,6 +1184,41 @@ where Node.BoxType == Box, Box.ValueType == Node
1054
1184
return treeEdges
1055
1185
}
1056
1186
1187
+ func primsMainLoopClosureAccess< Node : GraphNode , Box> (
1188
+ _ graph : Array < Node > ,
1189
+ _ fun : ( Node . BoxType , Node . BoxType ) -> Double ) -> Array < Int ? >
1190
+ where Node. BoxType == Box , Box. ValueType == Node
1191
+ {
1192
+ var treeEdges = Array < Int ? > ( repeating: nil , count: graph. count)
1193
+ let queue = PriorityQueue < Node > ( count: graph. count)
1194
+
1195
+ // Make the minimum spanning tree root its own parent for simplicity.
1196
+ queue. insert ( EdgeCost ( to: graph [ 0 ] , cost: 0.0 , from: graph [ 0 ] ) )
1197
+
1198
+ // Take an element with the smallest cost from the queue and add its
1199
+ // neighbors to the queue if their cost was updated
1200
+ while !queue. isEmpty {
1201
+ // Add an edge with minimum cost to the spanning tree
1202
+ let e = queue. pop ( ) !
1203
+ let newnode : Node . BoxType = e. to
1204
+
1205
+ // Add record about the edge newnode->e.from to treeEdges
1206
+ treeEdges [ newnode. withValue { $0. id } ] = e. from. withValue { $0. id }
1207
+
1208
+ // Check all adjacent nodes and add edges, ending outside the tree, to the
1209
+ // queue. If the queue already contains an edge to an adjacent node, we
1210
+ // replace existing one with the new one in case the new one costs less.
1211
+ for toNode : Box in ( newnode. withValue { $0. adjList } ) {
1212
+ if treeEdges [ toNode. withValue { $0. id } ] != nil {
1213
+ continue
1214
+ }
1215
+ let newcost = fun ( newnode, toNode)
1216
+ queue. insertOrUpdate ( EdgeCost ( to: toNode, cost: newcost, from: newnode) )
1217
+ }
1218
+ }
1219
+ return treeEdges
1220
+ }
1221
+
1057
1222
//===----------------------------------------------------------------------===//
1058
1223
// Top Level Entrypoints
1059
1224
//===----------------------------------------------------------------------===//
@@ -1079,6 +1244,25 @@ func run_PrimsNonStrongRef<Node: GraphNode, Box>(_ state: PrimsState<Node, Box>)
1079
1244
CheckResults ( Int ( cost) == 49324 )
1080
1245
}
1081
1246
1247
+ @inline ( __always)
1248
+ func run_PrimsNonStrongRefClosureAccess< Node: GraphNode , Box> ( _ state: PrimsState < Node , Box > ) where Node. BoxType == Box , Box. ValueType == Node {
1249
+ let graph = state. graph
1250
+ let map = state. edgeToCostMap
1251
+
1252
+ // Find spanning tree
1253
+ let treeEdges = primsMainLoopClosureAccess ( graph, { ( start: Box , end: Box ) in
1254
+ return map [ Edge ( start: start, end: end) ] !
1255
+ } )
1256
+
1257
+ // Compute its cost in order to check results
1258
+ var cost = 0.0
1259
+ for i in 1 ..< treeEdges. count {
1260
+ if let n = treeEdges [ i] {
1261
+ cost += map [ Edge ( start: Box ( graph [ n] ) , end: Box ( graph [ i] ) ) ] !
1262
+ }
1263
+ }
1264
+ CheckResults ( Int ( cost) == 49324 )
1265
+ }
1082
1266
1083
1267
1084
1268
@inline ( never)
@@ -1089,6 +1273,14 @@ public func run_PrimsWeak(_ N: Int) {
1089
1273
}
1090
1274
}
1091
1275
1276
+ @inline ( never)
1277
+ public func run_PrimsWeakClosureAccess( _ N: Int ) {
1278
+ let state = weakPrimsState
1279
+ for _ in 0 ..< N {
1280
+ run_PrimsNonStrongRefClosureAccess ( state)
1281
+ }
1282
+ }
1283
+
1092
1284
@inline ( never)
1093
1285
public func run_PrimsUnownedSafe( _ N: Int ) {
1094
1286
let state = unownedSafePrimsState
@@ -1097,6 +1289,14 @@ public func run_PrimsUnownedSafe(_ N: Int) {
1097
1289
}
1098
1290
}
1099
1291
1292
+ @inline ( never)
1293
+ public func run_PrimsUnownedSafeClosureAccess( _ N: Int ) {
1294
+ let state = unownedSafePrimsState
1295
+ for _ in 0 ..< N {
1296
+ run_PrimsNonStrongRefClosureAccess ( state)
1297
+ }
1298
+ }
1299
+
1100
1300
@inline ( never)
1101
1301
public func run_PrimsUnownedUnsafe( _ N: Int ) {
1102
1302
let state = unownedUnsafePrimsState
@@ -1105,10 +1305,42 @@ public func run_PrimsUnownedUnsafe(_ N: Int) {
1105
1305
}
1106
1306
}
1107
1307
1308
+ @inline ( never)
1309
+ public func run_PrimsUnownedUnsafeClosureAccess( _ N: Int ) {
1310
+ let state = unownedUnsafePrimsState
1311
+ for _ in 0 ..< N {
1312
+ run_PrimsNonStrongRefClosureAccess ( state)
1313
+ }
1314
+ }
1315
+
1108
1316
@inline ( never)
1109
1317
public func run_PrimsUnmanaged( _ N: Int ) {
1110
1318
let state = unmanagedPrimsState
1111
1319
for _ in 0 ..< N {
1112
1320
run_PrimsNonStrongRef ( state)
1113
1321
}
1114
1322
}
1323
+
1324
+ @inline ( never)
1325
+ public func run_PrimsUnmanagedClosureAccess( _ N: Int ) {
1326
+ let state = unmanagedPrimsState
1327
+ for _ in 0 ..< N {
1328
+ run_PrimsNonStrongRefClosureAccess ( state)
1329
+ }
1330
+ }
1331
+
1332
+ @inline ( never)
1333
+ public func run_PrimsUnmanagedUGR( _ N: Int ) {
1334
+ let state = unmanagedUGRPrimsState
1335
+ for _ in 0 ..< N {
1336
+ run_PrimsNonStrongRef ( state)
1337
+ }
1338
+ }
1339
+
1340
+ @inline ( never)
1341
+ public func run_PrimsUnmanagedUGRClosureAccess( _ N: Int ) {
1342
+ let state = unmanagedUGRPrimsState
1343
+ for _ in 0 ..< N {
1344
+ run_PrimsNonStrongRefClosureAccess ( state)
1345
+ }
1346
+ }
0 commit comments