我正在编写一个应用程序,我需要快速响应UDP消息以触发摄像机,同时处理来自这些摄像机的先前图像的结果。图像处理是高度并行的,我使用Parallel.ForEach来运行模式比较。我看到的问题是Parallel.ForEach正在减慢触发器代码的响应速度并产生不必要的延迟。我尝试使用自定义任务调度程序添加任务优先级,以将摄像机触发器代码增加到最高,这有助于减少问题,但不会消除它。
我很好奇是否有任何关于如何确保在其他任务非常紧张的情况下及时处理特定任务的提示或建议。我很有可能过度平行我的代码,线程数量很大可能是罪魁祸首。
我正在努力解决这种过度并行化问题,但我应该能够孤立地解决这些问题。我想确保即使存在过度并行化,也不会影响其他关键任务。
我研究了Parallel.ForEach的分区,但是我的数据大小只有200而且每个操作都很重,所以我不相信我会通过对数据进行分组来获得任何显着的收益。
我正在关注处理器亲和力,但我真的想要一些更清洁的东西。
http://blog.rebuildall.net/2010/03/08/Running_NET_threads_on_selected_processor_cores
我的UDP摄像头触发代码:
Public Class UDPCameraTrigger
Implements System.ComponentModel.INotifyPropertyChanged
Protected _Records As Concurrent.ConcurrentDictionary(Of Integer, clsVisionRecord)
Protected _Cameras As IEnumerable(Of Acquisition.AsyncCamera)
Protected HighPriorityTaskScheduler As TaskScheduler
Protected HighPriorityTaskFactory As TaskFactory
Protected groupEP As Net.IPEndPoint
Protected Async Sub StartListener()
Using listener As New Net.Sockets.UdpClient(groupEP)
While True
Try
Dim Result As Net.Sockets.UdpReceiveResult = Await HighPriorityTaskFactory.StartNew(AddressOf listener.ReceiveAsync).Unwrap
Dim packet As New TriggerEventPacket
packet.ParsePacketBytes(Result.Buffer)
Using Markers.EnterSpan("UDPTriggerEvent #" & packet.RecordID.ToString)
Dim VRecord As New clsVisionRecord(packet.RecordID)
Dim TotalDelay As Double = VRecord.StartTime.Subtract(packet.TimeStamp).TotalMilliseconds
If TotalDelay > 5 Then WriteToLog("VRecord created for " & packet.RecordID.ToString & " with delay of " & TotalDelay.ToString & "ms", EventLogEntryType.Information)
If _Records.TryAdd(packet.RecordID, VRecord) Then
For Each Camera As Acquisition.AsyncCamera In _Cameras
HighPriorityTaskFactory.StartNew(Sub() Camera.Trigger(VRecord))
Next
Else
WriteToLog("Duplicate received " & packet.RecordID, EventLogEntryType.Warning)
End If
End Using
Catch ex As Exception
ex.WriteToLog()
End Try
End While
End Using
End Sub
Public Sub New(Records As Concurrent.ConcurrentDictionary(Of Integer, clsVisionRecord), Cameras As IEnumerable(Of Acquisition.AsyncCamera), Port As Integer)
If (Port < 1) Or (Port > 65535) Then Throw New ArgumentOutOfRangeException("Port", "Specified port of " & Port.ToString & " is invalid")
groupEP = New Net.IPEndPoint(Net.IPAddress.Any, Port)
HighPriorityTaskScheduler = New TaskSchedulerPrioritized(12, System.Threading.ApartmentState.MTA, System.Threading.ThreadPriority.Highest)
HighPriorityTaskFactory = New TaskFactory(HighPriorityTaskScheduler)
HighPriorityTaskFactory.StartNew(AddressOf StartListener)
_Records = Records
_Cameras = Cameras
End Sub
' Create the OnPropertyChanged method to raise the event
Protected Sub OnPropertyChanged(ByVal name As String)
RaiseEvent PropertyChanged(Me, New System.ComponentModel.PropertyChangedEventArgs(name))
End Sub
Public Event PropertyChanged(sender As Object, e As System.ComponentModel.PropertyChangedEventArgs) Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged
End Class
如果在触发相机时遇到延迟> 50ms,则会使图像偏离中心而无法使用。 (捕获在传送带上以合适的夹子移动的物品,因此时机至关重要)。我可以选择进行硬件触发,但我想避免这种情况,因为我失去了在各种系统之间进行强大票证的能力。
相机返回图像并更新记录。然后将记录移动到基于TPL Dataflow块的管道中。在这些数据流块中,有多个Parallel.ForEach方法用于在映像上执行一系列分析任务。代码太宽泛,无法在此完整发布,但我很乐意在必要时讨论我的内容或发布细分。