这是两个非常相似的地方Levenshtein Distance algorithms。
Levenshtein Distance algorithms
Swift实施:https : //gist.github.com/bgreenlee/52d93a1d8fa1b8c1f38b
Swift
和Objective-C实现:https : //gist.github.com/boratlibre/1593632
Objective-C
在swift一个是慢得多然后ObjC实现我送给几个小时,使其速度更快,但......好像Swift阵列和Strings操作是不一样快objC。
swift
ObjC
Strings
objC
在2000年的random Strings计算中,Swift执行速度比慢约100(!!!)倍ObjC。
random Strings
老实说,我不知道可能出什么问题了,因为这很快
func levenshtein(aStr: String, bStr: String) -> Int { // create character arrays let a = Array(aStr) let b = Array(bStr) ...
比整个算法慢几倍 Objective C
Objective C
有谁知道如何加快swift计算速度?
先感谢您!
附加
毕竟,建议的改进是快速代码,如下所示。在发行版配置中,它 比ObjC慢4倍 。
import Foundation class Array2D { var cols:Int, rows:Int var matrix:UnsafeMutablePointer<Int> init(cols:Int, rows:Int) { self.cols = cols self.rows = rows matrix = UnsafeMutablePointer<Int>(malloc(UInt(cols * rows) * UInt(sizeof(Int)))) for i in 0...cols*rows { matrix[i] = 0 } } subscript(col:Int, row:Int) -> Int { get { return matrix[cols * row + col] as Int } set { matrix[cols*row+col] = newValue } } func colCount() -> Int { return self.cols } func rowCount() -> Int { return self.rows } } extension String { func levenshteinDistanceFromStringSwift(comparingString: NSString) -> Int { let aStr = self let bStr = comparingString // let a = Array(aStr.unicodeScalars) // let b = Array(bStr.unicodeScalars) let a:NSString = aStr let b:NSString = bStr var dist = Array2D(cols: a.length + 1, rows: b.length + 1) for i in 1...a.length { dist[i, 0] = i } for j in 1...b.length { dist[0, j] = j } for i in 1...a.length { for j in 1...b.length { if a.characterAtIndex(i-1) == b.characterAtIndex(j-1) { dist[i, j] = dist[i-1, j-1] // noop } else { dist[i, j] = min( dist[i-1, j] + 1, // deletion dist[i, j-1] + 1, // insertion dist[i-1, j-1] + 1 // substitution ) } } } return dist[a.length, b.length] } func levenshteinDistanceFromStringObjC(comparingString: String) -> Int { let aStr = self let bStr = comparingString //It is really strange, but I should link Objective-C coz dramatic slow swift performance return aStr.compareWithWord(bStr, matchGain: 0, missingCost: 1) } }
malloc ?? NSString ?? 并在最后四倍速度下降?有人需要迅速了吗?
Swift代码比Objective-C代码慢的原因有很多。通过比较两个固定字符串100次,我制作了一个非常简单的测试用例。
第一个原因是Swift Character代表一个“扩展的字素簇”,其中可以包含多个Unicode代码点(例如“标志”)。这会使字符串分解为字符变慢。另一方面,Objective-C NSString将字符串存储为一系列UTF-16代码点。
Character
NSString
如果您更换
let a = Array(aStr) let b = Array(bStr)
通过
let a = Array(aStr.utf16) let b = Array(bStr.utf16)
这样Swift代码也可以在UTF-16序列上运行,那么时间就减少到1.88秒。
二维数组的分配也很慢。分配单个一维数组更快。我在Array2D这里找到了一个简单的类:http : //blog.trolieb.com/trouble-multiDimension- arrays-swift/
Array2D
class Array2D { var cols:Int, rows:Int var matrix: [Int] init(cols:Int, rows:Int) { self.cols = cols self.rows = rows matrix = Array(count:cols*rows, repeatedValue:0) } subscript(col:Int, row:Int) -> Int { get { return matrix[cols * row + col] } set { matrix[cols*row+col] = newValue } } func colCount() -> Int { return self.cols } func rowCount() -> Int { return self.rows } }
在代码中使用该类
func levenshtein(aStr: String, bStr: String) -> Int { let a = Array(aStr.utf16) let b = Array(bStr.utf16) var dist = Array2D(cols: a.count + 1, rows: b.count + 1) for i in 1...a.count { dist[i, 0] = i } for j in 1...b.count { dist[0, j] = j } for i in 1...a.count { for j in 1...b.count { if a[i-1] == b[j-1] { dist[i, j] = dist[i-1, j-1] // noop } else { dist[i, j] = min( dist[i-1, j] + 1, // deletion dist[i, j-1] + 1, // insertion dist[i-1, j-1] + 1 // substitution ) } } } return dist[a.count, b.count] }
测试用例中的时间减少到0.84秒。
我在Swift代码中发现的最后一个瓶颈是min()函数。Swift库具有一个min()更快的内置函数。因此,只需从Swift代码中删除自定义函数,就可以将测试用例的时间减少到0.04秒,几乎与Objective- C版本一样。
min()
附录: 使用Unicode标量似乎更快一些:
let a = Array(aStr.unicodeScalars) let b = Array(bStr.unicodeScalars)
并具有可以与代理对(例如表情符号)一起正常使用的优点。