我有这段代码:
noObjs = 0
Dim oName As String
Dim i As Integer
Dim tripleIndex As Integer = 0
Do While sr.Peek() <> -1
readCSV = sr.ReadLine.Split(sepChar(0))
If readCSV.Length >= 3 Then
oName = readCSV(0)
For i = noObjs - 1 To 0 Step -1
If oName = objNames(i) Then
obIndOfTriple(tripleIndex) = i
Exit For
End If
Next i
If i = -1 Then
objNames(noObjs) = oName
obIndOfTriple(tripleIndex) = noObjs
noObjs += 1
End If
End If
tripleIndex += 1
Loop
sr.Close()
我正试图并行化:
noObjs = 0
Dim oName As String
Dim i As Integer
Dim tripleIndex As Integer = 0
Dim allData() As String = File.ReadAllLines(in_file)
Parallel.For(0, allData.Count, Sub(k)
readCSV = allData(k).Split(sepChar(0))
If readCSV.Length >= 3 Then
oName = readCSV(0)
For i = noObjs - 1 To 0 Step -1
If oName = objNames(i) Then
obIndOfTriple(tripleIndex) = i
Exit For
End If
Next i
If i = -1 Then
objNames(noObjs) = oName
obIndOfTriple(tripleIndex) = noObjs
noObjs += 1
End If
End If
tripleIndex += 1
End Sub)
但是,我得到一个“索引超出了数组的范围”:
If oName = objNames(i) Then
我还应该在这里提一下objNames()和obIndOfTriple()是全局声明的(具有固定大小)。 从一些搜索,我知道这与线程安全有关,虽然我仍然是并行的新手。 有人能指出我正确的方向吗? 感谢。
答案 0 :(得分:3)
看来你正在寻找独特的字符串。
而不是蛮力
For i = noObjs - 1 To 0 Step -1
If oName = objNames(i) Then
obIndOfTriple(tripleIndex) = i
Exit For
尝试
Dictionary<String,Int32>
和ContainsKey
字典有快速查找
This page has an example of locking in parallel。但不确定它是你需要的锁类型。
答案 1 :(得分:1)
问题的关键在于您有多个线程访问共享资源而不同步对这些资源的访问,从而引入竞争条件。
例如,考虑与noObjs
相关的objNames
。我怀疑您希望noObjs
始终反映objNames
中实际项目的数量。现在假设你有两个线程同时达到objNames(noObjs) = oName
,那时noObjs
是4。一个线程会将值写入objNames(4)
,然后另一个线程将立即覆盖它。第一个线程尚未到达增量noObjs
的行!此外,当两个线程都执行noObjs += 1
时,noObjs
将为6,但noObjs(5)
中不存储任何内容。这不是您所看到的异常的确切情况,但它是实施脆弱性的另一个症状。
在每个线程执行的代码中,您需要确保每个线程都有自己的可变空间来使用。通过让objNames
和objIndOfTriple
成为二维数组,可以做到这一点。第一个维度是循环迭代,k
,第二个维度是该迭代的数组索引。同样,noObjs
将是一个数组,noObjs(k)
将是与循环索引objNames
关联的k
数组中的元素数。
从技术上讲,这应该可行,但是在执行objNames
之后,你需要将Parallel.For
从一堆小数组合并到一个大数组中 - 基本上完成map-reduce的实现图案。
如果您确实完成了所有实现,那么您可能需要查看性能。您正在并行处理单行输入,并且从代码中看不出您为每一行做了很多工作。换句话说,逐行并行化,实际上可能会比按顺序完成后增加更多的开销。如果你有1000行,你实际上要求同时运行1000个小任务,因此管理任务变得比实际执行更多。现在,TPL可以根据它认为最好的方式决定是否真正并行做某事,这样可以减轻性能损失。