需要有关线程优化的帮助 [英] Need help with threading optimization

查看:88
本文介绍了需要有关线程优化的帮助的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个程序,它以特定类的对象列表开头。第一个对象分配给局部变量,然后从列表中删除。对此局部变量执行工作,这可能导致同一类的对象的新列表。如果返回一个列表,则将对象插回到基于类的属性排序的原始列表中。重复该过程,直到列表中没有其他对象。



代码基于分支定界方法来寻找问题的最佳解决方案。每个答案都会收到一个分数,即结果属性。得分越低越好。选择具有最佳分数的答案以在产生新答案时迭代,每个答案具有其自己的分数,其被放回到列表中。一旦满足某些标准,答案将被视为最终答案,不再适用。一旦答案是最终答案,就会根据当前的最佳答案(如果有的话)进行检查,如果答案得分更高,则成为最佳答案。评分算法的工作方式使得答案无法产生较低分数的答案,因此一旦找到最佳答案,列表中具有较高分数的任何答案都不能产生更好的答案并且可以从列表中删除。



I have a program that starts with a list of objects of a specific class. The first object is assigned to a local variable and then removed from the list. Work is performed on this local variable which may result in a new list of objects of the same class. if a list is returned then the objects are inserted back into the original list sorted based on a property of the class. The process is repeated until there are no more objects in the list.

The code is based on a branch and bound approach to finding the optimal solution to a problem. Each answer receives a score which is the Result property. The lower the score the better. The answers with the best score are chosen to be iterated on producing new answers, each with their own score, which are placed back into the list. Once certain criteria are met, an answer is considered final and is no longer worked on. Once an answer is final it is checked against the current best answer (if any) and becomes the best answer if it has a better score. The way the scoring algorithm work makes it impossible for an answer to produce an answer with a lower score, thus once a best answer is found any answers in the list with a higher score cannot produce a better answer and can be removed from the list.

Dim MainList as new List(of B)
Populate(MainList ) ' Populates MainList 
Dim Best as B = Nothing

Do
  Dim Current as B = MainList(0)
  MainList.RemoveAt(0)
  Dim SubList as list(of B)=PerformWork(Current) ' Function that preforms the work
  if Sublist.Count > 0 then
    If Sublist(0).IsFinal then ' Note that only 1 item will be returned if IsFinal is true
      If Best Is Nothing OrElse Best.Result > SubList(0).Result then
        Best=Sublist(0)
        Remove(Best.Result) ' Removes all items in MainList that have a Result > Best.Result
      End if
    Else
      Insert(SubList) ' Sub that inserts all the items in SubList into MainList
    End if
  end if
Loop While MainList.Count > 0





我的目标是通过取第一个n来并行化这个过程对象数量和每个将返回对象列表的线程。当每个线程返回时,返回的对象列表将被插入到列表中,并且当前的第一个对象将被传递给新线程。



我见过的每个例子将只循环遍历整个列表并为每个对象创建一个新线程。因为我只想关注最好的对象,这会随着程序的运行而改变,我认为这不是最好的方法。我可以直接浏览前4个项目,并保持这种状态,但我计划使用多台计算机,每个计算机必须专门针对它进行调整。有没有办法让框架确定最佳线程数?



我尝试过:



到目前为止还没有任何代码明智,只看了很多文章都没什么帮助。



My goal is to parallelize this process by taking the first n number of objects and starting a thread for each which will return the list of objects. As each thread returns, the returned list of objects will be inserted into the list and the current first object will be passed to a new thread.

Every example I have seen will just loop through the entire list and create a new thread for each object. Since I only want to focus on the best objects and this will change as the program runs, I do not think this is the best approach. I could just loop through the first 4 items, and keep that going, but I plan on using multiple computers and each would have to have the software tuned specifically for it. Is there any way to have the framework determine the best number of threads?

What I have tried:

Nothing code wise so far, just looked at a lot of articles that are not much help.

推荐答案

我不认为排序是有道理的。如果您正在并行处理列表,则可以按任何顺序处理这些项目。



列表(Of T)上课不是一个好选择。它不是线程安全的,从列表的开头删除项目是一项昂贵的操作。我建议使用 ConcurrentQueue(Of T) ) [ ^ ]类。



你需要一个扩展方法来获取一个消费枚举器,它会删除项目处理时从队列中:

I don't think the sorting makes any sense. If you're processing the list in parallel, the items can be processed in any order.

The List(Of T) class is not a good choice. It's not thread-safe, and removing items from the start of the list is an expensive operation. I'd suggest using the ConcurrentQueue(Of T)[^] class instead.

You'll need an extension method to get a "consuming" enumerator, that removes items from the queue as they're processed:
Module CollectionExtensions
    <Extension()> 
    Public Iterator Function GetConsumingEnumerator(Of T)(ByVal source As IProducerConsumerCollection(Of T)) As IEnumerable(Of T)
        Dim item As T
        While source.TryTake(item)
            Yield item
        End While
    End Function
End Module



然后您可以使用 AsParallel [ ^ ]并行使用列表的扩展方法:


You can then use the AsParallel[^] extension method to consume the list in parallel:

Dim best As B = Nothing
Dim initialList As New List(Of B)
Populate(initialList)

Dim mainList As New ConcurrentQueue(Of B)(initialList)
While Not mainList.IsEmpty
    Dim newItems As IEnumerable(Of List(Of B)) = mainList _
        .GetConsumingEnumerator() _
        .AsParallel() _
        .Where(Function (current) best Is Nothing OrElse current.Result <= best.Result) _
        .Select(Function (current) PerformWork(current)) _
        .Where(Function (newList) newList.Count > 0)
        
    For Each newList As List(Of B) In newItems
        If newList(0).IsFinal Then
            If best Is Nothing OrElse best.Result > newList(0).Result Then
                best = newList(0)
            End If
        Else
            For Each item As B In newList
                mainList.Enqueue(item)
            Next
        End If
    Next
End While



注意:您当前的代码中有错误:


NB: You have a mistake in your current code:

If Best IsNot Nothing OrElse Best.Result > SubList(0).Result then

如果 Best Nothing ,你会得到一个该行 NullReferenceException

If Best is Nothing, you'll get a NullReferenceException on that line.


这篇关于需要有关线程优化的帮助的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆