假设执行一个方法CountString,给定一个字符串数组和一个int值,该方法返回长度大于该int的字符串数。
如果我必须尽可能多地利用多核硬件,那么这样做是否足够:

public int CountString(string[] s, int i)
{
  return s.AsParallel().Count( res => res.length > i);
}


还是我必须以某种方式使用Tasks甚至混合Task和PLinq?

它仅是一个简单的示例,我知道此方法不会对硬件性能产生太大影响。

我想知道使用AsParallel()这样做是否更好,或者声明方法async并在方法主体中使用await(即使我不知道如何)也更好。

最佳答案

编辑:

当我看到您的实际问题有点误导时,我将尝试回答故意的问题。特别是在这里,与AsParallel一起使用将是一种很好的方法,因为实际上await不需要任何内容​​。由于您正在处理集合,因此PLINQ或Paralle.ForEach是一个不错的选择。当您具有自然的异步I / O绑定操作时,请考虑使用async-await。建议不要wrap synchronous methods with async wrappers.



如果您实际测试代码,您甚至会惊讶地发现,并行执行这段代码实际上会对方法执行产生负面的性能影响,具体取决于要迭代的数组的大小。

很多人忘记了使用线程实际上会产生开销,即使在线程池之外使用线程也是如此。您必须进行最少的CPU密集型工作,才能使并行化对性能产生负面影响。

如果您的数组足够长,则使用AsParallel就足够了。没有必要添加Task,因为PLINQ可以很好地处理并行化。

好的,让我们实际测试该代码。我将在一个充满GUID的string[]上进行迭代。这是代码:

主要方法:

void Main()
{
    //JIT
    Test(0);

    Test(100);
    Test(1000);
    Test(10000);
    Test(1000000);
    Test(10000000);
}

public void Test(int itemAmount)
{
    string[] strings = Enumerable.Range(0, itemAmount).Select(i => Guid.NewGuid()
                                                      .ToString()).ToArray();

    var stopWatch = Stopwatch.StartNew();
    CountStringInParallel(strings, itemAmount);
    stopWatch.Stop();
    Console.WriteLine("Parallel Call: String amount: {0}, Time: {1}",
                                                        itemAmount, stopWatch.Elapsed);

    stopWatch.Restart();
    CountStringSync(strings, itemAmount);
    stopWatch.Stop();
    Console.WriteLine("Synchronous Call: String amount: {0}, Time: {1}",
                                                        itemAmount, stopWatch.Elapsed);
}


并行和同步:

public int CountStringInParallel(string[] s, int i)
{
    return s.AsParallel().Count( res => res.Length > i);
}

public int CountStringSync(string[] s, int i)
{
    return s.Count(res => res.Length > i);
}


结果:


  并行呼叫:字符串数量:100,时间:00:00:00.0000197
  
  同步通话:字串数量:100,时间:00:00:00.0000026





  并行呼叫:字符串数量:1000,时间:00:00:00.0000266
  
  同步通话:字串数量:1000,时间:00:00:00.0000201





  并行呼叫:字符串数量:10000,时间:00:00:00.0002060
  
  同步通话:字符串数量:10000,时间:00:00:00.0002003





  平行通话:字串金额:1000000,时间:00:00:00.0080492
  
  同步通话:字符串数量:1000000,时间:00:00:00.0135279





  平行通话:字串金额:10000000,时间:00:00:00.0744104
  
  同步通话:字串金额:10000000,时间:00:00:00.1402474


您可以看到多达10,000个字符串,同步方法实际上比并行方法要快。

10-01 07:49