在 Parallel.For 中调用子例程(并将变量 ByRef 传递给它)线程安全吗?
Is calling a subroutine inside Parallel.For (and passing a variable ByRef to it) thread safe?
我在嵌套的 Parallel.For 循环 (vb.net) 中调用子程序 MyPartsMatrix。 MyPartsMatrix 需要一个名为 "unfilled" 的变量,该变量通过 ByRef 传递,因为该值在 MyPartsMatrix 子例程中被修改。我需要在子程序 MyPartsMatrix 执行后获取并存储这个值。
当我 运行 此代码的并行版本与使用普通嵌套 For...Next 循环的非并行版本相比时,"unfilled" 变量产生不同的值。我想不通为什么会这样。
从 Parallel.For 循环内部调用另一个子例程是否线程安全?
这个变量"unfilled"线程安全吗?
Dim ConcurrentListofResults As ConcurrentQueue(Of FindBestResults)
ConcurrentListofResults = New ConcurrentQueue(Of FindBestResults)
Dim x = 5, y = 5
Parallel.For(0, x, Sub(oD)
Parallel.For(0, y, Sub(oT)
Dim unfilled As Integer = 0
MyPartsMatrix (oD, oT, unfilled)
'Create a FBS item to add to the concurrent list collection
Dim FBSResultsItem = New FindBestResults
FBSResultsItem.oD = oD
FBSResultsItem.oT = oT
FBSResultsItem.unfilled = unfilled
'Add this item to the Concurent collection
ConcurrentListofResults.Enqueue(FBSResultsItem)
End Sub)
End Sub)
'Get best result.
Dim bestResult As FindBestResults
For Each item As FindBestResults In ConcurrentListofResults
If item.unfilled < bestResult.unfilled Then
bestResult.oD = item.oD
bestResult.oT = item.oT
bestResult.unfilled = item.unfilled
End If
Next
Public Sub MyPartsMatrix (ByVal oD As Integer, ByVal oT As Integer, ByRef unfilled As Integer)
'....do stuff with the unfilled variable....
'unfilled is a counter that is incremented while we run through the PartsMatrix
unfilled = unfilled + 1
End Sub
如果这不是线程安全的,是否有另一种方法来编写它,以便 "unfilled" 变量是线程安全的或使调用另一个子例程线程安全?
没有 MakeSchedule
的定义(你在另一个地方称之为 MyMakePartsMatrix
)就不可能说它是否是线程安全的。
为了线程安全,sub 不需要修改除 unfilled 之外的任何内容。这将确保使用相同的输入多次调用它总是会产生相同的输出。我还建议转换为函数,因为我发现这更容易理解发生了什么。
另一个注意事项:
如果不嵌套并行循环,您的性能会更好。在启动第二个循环之前,您目前正在等待内部循环完成。如果您使用更大的 x + y 值,那么类似于代码的东西会更好。
Dim scenarios = From x2 In Enumerable.Range(0, x)
From y2 In Enumerable.Range(0, y)
Select New With {x2, y2}
Parallel.ForEach(scenarios, Sub(s)
End Sub)
我在嵌套的 Parallel.For 循环 (vb.net) 中调用子程序 MyPartsMatrix。 MyPartsMatrix 需要一个名为 "unfilled" 的变量,该变量通过 ByRef 传递,因为该值在 MyPartsMatrix 子例程中被修改。我需要在子程序 MyPartsMatrix 执行后获取并存储这个值。
当我 运行 此代码的并行版本与使用普通嵌套 For...Next 循环的非并行版本相比时,"unfilled" 变量产生不同的值。我想不通为什么会这样。
从 Parallel.For 循环内部调用另一个子例程是否线程安全?
这个变量"unfilled"线程安全吗?
Dim ConcurrentListofResults As ConcurrentQueue(Of FindBestResults)
ConcurrentListofResults = New ConcurrentQueue(Of FindBestResults)
Dim x = 5, y = 5
Parallel.For(0, x, Sub(oD)
Parallel.For(0, y, Sub(oT)
Dim unfilled As Integer = 0
MyPartsMatrix (oD, oT, unfilled)
'Create a FBS item to add to the concurrent list collection
Dim FBSResultsItem = New FindBestResults
FBSResultsItem.oD = oD
FBSResultsItem.oT = oT
FBSResultsItem.unfilled = unfilled
'Add this item to the Concurent collection
ConcurrentListofResults.Enqueue(FBSResultsItem)
End Sub)
End Sub)
'Get best result.
Dim bestResult As FindBestResults
For Each item As FindBestResults In ConcurrentListofResults
If item.unfilled < bestResult.unfilled Then
bestResult.oD = item.oD
bestResult.oT = item.oT
bestResult.unfilled = item.unfilled
End If
Next
Public Sub MyPartsMatrix (ByVal oD As Integer, ByVal oT As Integer, ByRef unfilled As Integer)
'....do stuff with the unfilled variable....
'unfilled is a counter that is incremented while we run through the PartsMatrix
unfilled = unfilled + 1
End Sub
如果这不是线程安全的,是否有另一种方法来编写它,以便 "unfilled" 变量是线程安全的或使调用另一个子例程线程安全?
没有 MakeSchedule
的定义(你在另一个地方称之为 MyMakePartsMatrix
)就不可能说它是否是线程安全的。
为了线程安全,sub 不需要修改除 unfilled 之外的任何内容。这将确保使用相同的输入多次调用它总是会产生相同的输出。我还建议转换为函数,因为我发现这更容易理解发生了什么。
另一个注意事项:
如果不嵌套并行循环,您的性能会更好。在启动第二个循环之前,您目前正在等待内部循环完成。如果您使用更大的 x + y 值,那么类似于代码的东西会更好。
Dim scenarios = From x2 In Enumerable.Range(0, x)
From y2 In Enumerable.Range(0, y)
Select New With {x2, y2}
Parallel.ForEach(scenarios, Sub(s)
End Sub)