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);