C#中的高性能乘法/评估

时间:2011-03-24 02:59:51

标签: c# performance matrix transform multiplication

对于模糊的主题标题感到抱歉;很难简洁地描述我的问题。

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

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 个答案:

答案 0 :(得分: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);

答案 1 :(得分:5)

我认为问题不在于你的功能。我花了不到0.1秒的时间完成了该系列中500,000件物品的功能。

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

答案 2 :(得分:1)

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

您可以进行进一步的优化。

不是自己启动.NET线程,而是使用Microsoft的PLINQ库进行编码

答案 3 :(得分:1)

在进行上面的乘法时,请考虑使用Parallel.ForEach。您还可以考虑将查找表实现为包含Item.ID的Dictionary,并将其作为总计。因此,当乘法完成后,您可以使用LINQ对具有最大总数的项进行排序和提取。类似的东西:

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