3

抱歉,线程标题含糊不清;很难简洁地描述我的问题。

我有大量对象(几千个)的集合,定义为...

public class Item
{
    public int ID;
    public float A;
    public float B;
    public float C;
    public float D;
    public float E;
    public float F;
    public float G;
}

如果我为这些浮点字段中的每一个都提供了一个乘数,那么在我的大型集合中找到哪个项目的最大总浮点数乘以它们的乘数的最快方法是什么。

例如,我目前有类似...

public Item FindLargest(float aMult, float bMult, float cMult, float dMult, float eMult, float fMult, float gMult)
{
    Item largest = null;
    float largestTotal = 0f;
    foreach(Item item in ItemsCollection)
    {
        float total = item.A * aMult + 
                      item.B * bMult + 
                      item.C * cMult + 
                      item.D * dMult + 
                      item.E * eMult + 
                      item.F * fMult + 
                      item.G * gMult;
        if (total > largestTotal)
        {
            largest = item;
            largestTotal = total;
        }
    }
    return largest;
}

缺乏这种性能,所以我想知道是否有什么办法可以提前以这种方式重组数据,以便 FindLargest 调用快得多。我已经这样做了一段时间,性能很好,ItemsCollection 中有大约 40-50 个项目,但现在我的应用程序的不同部分的设计已经改变,作为副产品,我需要处理更大的数据集(~2000ish 而不是~50ish),所以我有兴趣进一步优化它。感谢任何人都可以提供的任何帮助!

编辑:我应该首先提到这一点:我已经在并行化这个,因为所谓的这个已经被高度并行化了。调用它确实是多次调用它,使用许多不同的参数,非常快速。每次在我的应用程序中打开文档中的值发生变化时,这需要调用大约一百次,并且应该感觉“响应”(已经在多个后台线程上进行了所有计算,所以我不是说 UI 锁定) .

编辑 2:在接受的答案中查看我的评论。

4

4 回答 4

5

一种选择是使用PLINQ来利用多个内核。

        var result = (from item in ItemsCollection
                      let total = item.A * aMult + 
                                  item.B * bMult + 
                                  item.C * cMult + 
                                  item.D * dMult + 
                                  item.E * eMult + 
                                  item.F * fMult + 
                                  item.G * gMult
                      select new {item, total}).AsParallel().Max(i => i.total);
于 2011-03-24T03:03:37.227 回答
5

我认为问题不在于您的功能。我用不到 0.1 秒的时间完成了集合中包含 500,000 个项目的功能。

您可能想找到一种方法来优化调用此函数的代码部分。在该级别使用 PLINQ 应该会产生更好的结果。

于 2011-03-24T03:38:09.917 回答
1

将您的数据集划分为 6 个连续的范围。将每个范围分配给异步启动的不同线程以计算最大值。完成所有线程后,您将拥有 6 个不同的项目 - 每个范围中的一个。遍历 6 以找到整个数据集最大的那个。

你可以做进一步的优化。

您可以使用 Microsoft 的 PLINQ 库简单地进行编码,而不是自己启动 .NET 线程

于 2011-03-24T03:17:14.040 回答
1

在进行上述乘法运算时,请考虑使用Parallel.ForEach 。您还可以考虑将查找表实现为包含 Item.ID 及其总数的 Dictionary。因此,当乘法完成后,您可以使用 LINQ 对总数最大的项目进行排序和提取。就像是:

var sortedItems = from item in ItemsTotalsDictionary orderby item.Value descending select item.Key;

于 2011-03-24T03:38:27.600 回答