如何并行编程?

时间:2017-01-09 09:24:13

标签: c# plinq

我目前遇到以下代码的性能问题。

private int globalType1 = 1;
private float globalType2 = 0.0342f;
private Dictionary<string, Tuple<int, float>> dt = new Dictionary<string, Tuple<int, float>>();

foreach (string file in Files) //assume 100 distinct files
{
    //GetType1AndType2 is thread safe
    Tuple<int, float> ift = GetType1AndType2(file, 0); //here 0 is the version of the file.

    if (ift.Item1 == globalType1 && ift.Item2 == globalType2)
    {
        dt.Add(file + "_0", fftandFreq); //Key = <FileName_Version> ; Value = Tuple<Type1, Type2>
    }
}

我如何能够并行完成此任务。

2 个答案:

答案 0 :(得分:1)

从技术上讲,它可能是这样的

private Dictionary<string, Tuple<int, float>> dt = Files
  .AsParallel() // PLinq - parallel Linq
  .Select(file => new {
     ift = GetType1AndType2(file, 0),
     file = file})
  .Where(chunk => chunk.ift.Item1 == globalType1 && 
                  // Math.Abs(chunk.ift.Item2 - globalType2) < 0.00001
                  chunk.ift.Item2 == globalType2) 
  .ToDictionary(chunk => chunk.file + "_0",
                chunk => chunk.ift); //TODO: check the value, please

但我怀疑性能问题是否真的存在于此代码片段中。 Files IO 操作通常操作)是性能问题的最可能来源。

PS 浮点值与==操作(Item2 == globalType2)进行比较是不确定的,因为舍入错误float globalType2 = 0.0342f;似乎可能是0.03419999970.3420000002)。如果您必须使用float类型(不是intstring等),请考虑与容差进行比较:将chunk.ift.Item2 == globalType2更改为Math.Abs(chunk.ift.Item2 - globalType2) < 0.00001或类似的。

答案 1 :(得分:0)

您可以使用Parallel.Foreach

Parallel.Foreach(Files, file => 
{
    //GetType1AndType2 is thread safe
    Tuple<int, float> ift = GetType1AndType2(file, 0); //here 0 is the version of the file.

    if (ift.Item1 == globalType1 && ift.Item2 == globalType2)
    {
        lock (dt)
        {
            dt.Add(file + "_0", fftandFreq); //Key = <FileName_Version> ; Value = Tuple<Type1, Type2>
        }
    }
});

确保锁定字典或使用线程安全的字典类型。这是否有助于您的表现取决于内部采取的行动。如果它是基于I / O的,它可能不会那么受益,但你可以测试它。