I'm relatively new to Swift so I have probably done something dumb.
I've implemented code very similar to this in Java and the algorithm executes in under 1 second on a graph with 800 vertices. However the Swift 3 version takes over 5 minutes on the same graph!
What have I done wrong?
var myMatrix = myGraph.getAdjMatr() // Returns adjacency matrix as 2d array.
let n = myGraph.vertexCount!
for i in 0..<n
{
for j in 0..<n
{
if (myMatrix[i][j] == 0)
{
myMatrix[i][j] = Int.max/2
}
}
}
for i in 0..<n
{
myMatrix[i][i] = 0;
}
for i in 0..<n
{
for j in 0..<n
{
for k in 0..<n
{
myMatrix[j][k] = min(myMatrix[j][k], (myMatrix[i][k] + myMatrix[j][i]))
}
}
}
Thanks.
I'm relatively new to Swift so I have probably done something dumb.
You've done nothing dumb, but performance of Swift can be "interesting". Let's have a play and see what we find, none of this is "definitive", but hopefully it will help. All tests done with Xcode 8/Swift 3, and an 800 node graph forming a single directional circle, YMMV.
Instead of comparing against Java I coded your algorithm in C wrapped as Objective-C i.e. using standard C value arrays. This can be directly called from Swift and provides a baseline for best speed.
Next I compared your Swift code above using a Swift 2-dimensional array of Int
. The performance was about 80 times slower than the (Objective-)C version. Ouch.
Finally I replaced the 2-dimensional array with a single-dimensional one and did the index calculation direct in the code, i.e. replacing:
myMatrix[i][j]
with:
myMatrix[i*n + j]
This version is about 15 times slower than the baseline. Better (relatively!). This improvement will be down to a 2-dimensional array in Swift actually being a 1-dimensional array of 1-dimensional arrays.
The above tests were done in normal debug mode, i.e. without optimisation. With fast optimisation the C baseline was roughly 4 times faster but the Swift versions changed only slightly. So with optimisation on the Swift 1-dimensional version was about 60 times slower than the C baseline version.
Your reported ratio of Swift to Java is about 300:1, far worse than any of my results. Where they run on the same machine? Also if your array is actually an NSArray
that may account for the difference, but I haven't run tests to check this hypothesis (an NSArray
is object-based and somewhat slower (but more flexible) than a C array).
Results (YMMV):
HTH