我正在研究一个将需要Levenshtein算法来计算两个字符串的相似度的应用程序。相同算法的两个实现之间的性能差异
随着前段时间我适应一个C#版本(这可以很容易找到在互联网上四处传播)到VB.NET和它看起来像这样:
Public Function Levenshtein1(s1 As String, s2 As String) As Double
Dim n As Integer = s1.Length
Dim m As Integer = s2.Length
Dim d(n, m) As Integer
Dim cost As Integer
Dim s1c As Char
For i = 1 To n
d(i, 0) = i
Next
For j = 1 To m
d(0, j) = j
Next
For i = 1 To n
s1c = s1(i - 1)
For j = 1 To m
If s1c = s2(j - 1) Then
cost = 0
Else
cost = 1
End If
d(i, j) = Math.Min(Math.Min(d(i - 1, j) + 1, d(i, j - 1) + 1), d(i - 1, j - 1) + cost)
Next
Next
Return (1.0 - (d(n, m)/Math.Max(n, m))) * 100
End Function
然后,试图调整,并改善其性能,I与版本结束:
Public Function Levenshtein2(s1 As String, s2 As String) As Double
Dim n As Integer = s1.Length
Dim m As Integer = s2.Length
Dim d(n, m) As Integer
Dim s1c As Char
Dim cost As Integer
For i = 1 To n
d(i, 0) = i
s1c = s1(i - 1)
For j = 1 To m
d(0, j) = j
If s1c = s2(j - 1) Then
cost = 0
Else
cost = 1
End If
d(i, j) = Math.Min(Math.Min(d(i - 1, j) + 1, d(i, j - 1) + 1), d(i - 1, j - 1) + cost)
Next
Next
Return (1.0 - (d(n, m)/Math.Max(n, m))) * 100
End Function
基本上,我想的,而不是需要两个初始(和附加)循环该距离d()的阵列可以在主要为周期内进行初始化。我真的认为这将是一个巨大的进步......不幸的是,它不仅没有改善原来的效果,反而变慢了!
我已经试着通过查看生成的IL代码来分析两个版本,但我无法理解它。
所以,我希望有人能够解释这个问题,并解释为什么第二个版本(即使它的周期较少)运行速度比原来慢?
注:时间差约为0.15纳秒。这看起来并不多,但是当你必须检查数千万个字符串时......差异变得相当显着。
我怎么错过那!? 非常感谢! – xfx
我刚刚将循环内部的行的初始化移动了一遍,现在第二个版本的算法比原始版本快了40% - 所以再次感谢您! (我生我的气,因为没有看到!) – xfx