vb.net 并行for循环步骤-1
vb.net parallel for loop step -1
是否可以使用 Parallel.For 循环加速此代码?
我有几百万个整数数组的列表,需要删除所有不符合比较条件的数组。如果我需要从列表中删除一些项目,我如何使用多线程来加速通过列表的循环?
(这是简单的代码示例,实际代码在循环内有更复杂的条件检查)
Function NewList(iList As List(Of Integer())) As List(Of Integer())
Dim i As Integer
Dim j As Integer
Dim compareArray As Integer() = {0, 1, 2, 3, 4}
Dim item As Integer()
For i = iList.Count - 1 To 0 Step -1
item = iList.Item(i)
For j = 0 To UBound(compareArray )
If compareArray(j) > 0 AndAlso Not item.Contains(compareArray(j)) Then
iList.RemoveAt(i)
GoTo nextIteration
End If
Next j
nextIteration:
Next i
Return iList
End Function
我会尝试这样的事情(未经测试):
Public Shared Function GetFilteredList(valueList As List(Of Int32()), mustIncludeList As Int32()) As List(Of Int32())
'Check args
If (valueList Is Nothing) Then Throw New ArgumentNullException(NameOf(valueList))
If (mustIncludeList Is Nothing) OrElse (Not mustIncludeList.Any()) Then Return New List(Of Int32())(valueList) 'A new instance to avoid side effects. Could be optimized if not needed
'Normalize args
mustIncludeList = (From e In mustIncludeList.Distinct() Where e > 0 Order By e).ToArray() 'Normalize it, remove duplicates and values < 1 (don't do it 1 million times inside the loop)
'Initialize the filter
Dim myFilter As Func(Of Int32(), Boolean) = Function(valueArray As Int32())
'As all of the values must be included we can skip all arrays that are shorter
If (valueArray Is Nothing) OrElse (valueArray.Length < mustIncludeList.Length) Then Return False
'Try out if the next line gives a better performance (depends a bit the size of the arrays)
Dim myValues As New HashSet(Of Int32)(valueArray)
For Each myMustInclude As Int32 In mustIncludeList
If (Not myValues.Contains(myMustInclude)) Then Return False
Next
Return True
End Function
'Apply filter and return new list
Return valueList.AsParallel().Where(myFilter).ToList()
End Function
已编辑
感谢大家,尤其是@Christoph 建议将“Nothing”分配给项目而不是删除它们,然后从列表中清除“Nothing”。对 normalize/prepare 在循环外比较数组一次而不检查它数百万次的有用建议 [此建议未在此处实施)]
结果速度从“分钟”提高到“秒”
以下代码 returns 以毫秒为单位的新列表,包含超过 200 万个项目。
Function NewList(iList As List(Of Integer())) As List(Of Integer())
Dim compareArray As Integer() = {12, 15, 24}
'//Note that "j" and "item" should be declared inside enclosed Sub
'Parallel.For(0, iList.Count - 1, Sub(i)
Parallel.For(0, iList.Count, Sub(i)
'//changed upper limit for loop /see comment below code/
Dim j As Integer
Dim item As Integer()
item = iList.Item(i)
For j = 0 To UBound(compareArray)
If compareArray(j) > 0 AndAlso Not item.Contains(compareArray(j)) Then
iList(i) = Nothing
GoTo nextIteration
End If
Next j
nextIteration:
End Sub)
'//parallel.for looped instantly with 2,118,760 items
'//then removing "Nothing" in usual loop have taken more than a minute,
'//so speed-up failed
'Dim k As Integer
'For k = iList.Count - 1 To 0 Step -1
' If iList(k) Is Nothing Then
' iList.RemoveAt(k)
' End If
'Next
'//but using RemoveAll Function cleared List instantly
iList.RemoveAll(Function(itm) IsNothing(itm))
Return iList
End Function
我已经测试了 Parallel.For 方法(比我自己的答案更复杂)但是将要检查的参数传递给主函数。结果并不总是正确的。使用@Christoph 函数(使用 AsParallel)- 结果正常。
With loop until iList.Count - 1:没有检查最后一个列表,我将循环上限更改为 iList.Count -> 结果是正确的。
必须仔细阅读文档...(上循环值是Exclusive)
public static System.Threading.Tasks.ParallelLoopResult For (int
fromInclusive, int toExclusive,
System.Threading.Tasks.ParallelOptions parallelOptions,
Action<int,System.Threading.Tasks.ParallelLoopState> body);
是否可以使用 Parallel.For 循环加速此代码?
我有几百万个整数数组的列表,需要删除所有不符合比较条件的数组。如果我需要从列表中删除一些项目,我如何使用多线程来加速通过列表的循环?
(这是简单的代码示例,实际代码在循环内有更复杂的条件检查)
Function NewList(iList As List(Of Integer())) As List(Of Integer())
Dim i As Integer
Dim j As Integer
Dim compareArray As Integer() = {0, 1, 2, 3, 4}
Dim item As Integer()
For i = iList.Count - 1 To 0 Step -1
item = iList.Item(i)
For j = 0 To UBound(compareArray )
If compareArray(j) > 0 AndAlso Not item.Contains(compareArray(j)) Then
iList.RemoveAt(i)
GoTo nextIteration
End If
Next j
nextIteration:
Next i
Return iList
End Function
我会尝试这样的事情(未经测试):
Public Shared Function GetFilteredList(valueList As List(Of Int32()), mustIncludeList As Int32()) As List(Of Int32())
'Check args
If (valueList Is Nothing) Then Throw New ArgumentNullException(NameOf(valueList))
If (mustIncludeList Is Nothing) OrElse (Not mustIncludeList.Any()) Then Return New List(Of Int32())(valueList) 'A new instance to avoid side effects. Could be optimized if not needed
'Normalize args
mustIncludeList = (From e In mustIncludeList.Distinct() Where e > 0 Order By e).ToArray() 'Normalize it, remove duplicates and values < 1 (don't do it 1 million times inside the loop)
'Initialize the filter
Dim myFilter As Func(Of Int32(), Boolean) = Function(valueArray As Int32())
'As all of the values must be included we can skip all arrays that are shorter
If (valueArray Is Nothing) OrElse (valueArray.Length < mustIncludeList.Length) Then Return False
'Try out if the next line gives a better performance (depends a bit the size of the arrays)
Dim myValues As New HashSet(Of Int32)(valueArray)
For Each myMustInclude As Int32 In mustIncludeList
If (Not myValues.Contains(myMustInclude)) Then Return False
Next
Return True
End Function
'Apply filter and return new list
Return valueList.AsParallel().Where(myFilter).ToList()
End Function
已编辑
感谢大家,尤其是@Christoph 建议将“Nothing”分配给项目而不是删除它们,然后从列表中清除“Nothing”。对 normalize/prepare 在循环外比较数组一次而不检查它数百万次的有用建议 [此建议未在此处实施)]
结果速度从“分钟”提高到“秒” 以下代码 returns 以毫秒为单位的新列表,包含超过 200 万个项目。
Function NewList(iList As List(Of Integer())) As List(Of Integer())
Dim compareArray As Integer() = {12, 15, 24}
'//Note that "j" and "item" should be declared inside enclosed Sub
'Parallel.For(0, iList.Count - 1, Sub(i)
Parallel.For(0, iList.Count, Sub(i)
'//changed upper limit for loop /see comment below code/
Dim j As Integer
Dim item As Integer()
item = iList.Item(i)
For j = 0 To UBound(compareArray)
If compareArray(j) > 0 AndAlso Not item.Contains(compareArray(j)) Then
iList(i) = Nothing
GoTo nextIteration
End If
Next j
nextIteration:
End Sub)
'//parallel.for looped instantly with 2,118,760 items
'//then removing "Nothing" in usual loop have taken more than a minute,
'//so speed-up failed
'Dim k As Integer
'For k = iList.Count - 1 To 0 Step -1
' If iList(k) Is Nothing Then
' iList.RemoveAt(k)
' End If
'Next
'//but using RemoveAll Function cleared List instantly
iList.RemoveAll(Function(itm) IsNothing(itm))
Return iList
End Function
我已经测试了 Parallel.For 方法(比我自己的答案更复杂)但是将要检查的参数传递给主函数。结果并不总是正确的。使用@Christoph 函数(使用 AsParallel)- 结果正常。
With loop until iList.Count - 1:没有检查最后一个列表,我将循环上限更改为 iList.Count -> 结果是正确的。 必须仔细阅读文档...(上循环值是Exclusive)
public static System.Threading.Tasks.ParallelLoopResult For (int
fromInclusive, int toExclusive,
System.Threading.Tasks.ParallelOptions parallelOptions,
Action<int,System.Threading.Tasks.ParallelLoopState> body);