测量 .AsParallel() 时的不同结果
Posted
技术标签:
【中文标题】测量 .AsParallel() 时的不同结果【英文标题】:Different results when measuring .AsParallel() 【发布时间】:2019-02-08 03:23:37 【问题描述】:我似乎找不到答案的问题是:为什么如果我更改调用包含.AsParallel()
的方法和不包含或具有不同选项的方法的顺序,结果会不同.
我已将源代码放在 GitHub 上,所以我不会填满整个屏幕 -> https://github.com/moisoiu/asParallel
还有一些关于我到目前为止如何测试它的说明。
我正在使用其他类来生成一些随机数据,从那时起,我将生成的随机数据传递给 ParallelThreading
方法,并通过 StopWatch
类测量时间并将结果存储在字典中在结束时显示响应时间。
起初我假设性能时间的问题,可能是因为我在同一个引用上工作,所以我创建了 4 个新对象 something 这是一个数组,所以它会有新的参考,但结果我们是一样的。
我什至假设也许(只是也许)来自 watch 的变量可能仍会存储前一个变量的值,所以我为每个变量创建了一个新变量
所以有什么想法吗?
只需从 Program.cs 中选择一个方法,然后将其与其他方法交换,就会有几乎相同的响应时间,但持续时间最长的方法将是 TOP 的方法,而较少的方法将在底部.
编辑: 尊重以下 cmets 的建议。我附上了部分源代码,如果需要更多,我会更新并从上面的Git中删除链接。
程序.cs
class Program
static void Main(string[] args)
var parallelThreading = new ParallelThreading();
long elapsedMs = 0;
Dictionary<string, long> results = new Dictionary<string, long>();
var dataResults = parallelThreading.InitializeDataForParallelData(6500);
var something = new PersonModel[6500];
var something1 = new PersonModel[6500];
var something2 = new PersonModel[6500];
var something3 = new PersonModel[6500];
dataResults.CopyTo(something);
dataResults.CopyTo(something1);
dataResults.CopyTo(something2);
dataResults.CopyTo(something3);
var watch2 = System.Diagnostics.Stopwatch.StartNew();
parallelThreading.AsParallelAddingParallelization(something1.ToList());
watch2.Stop();
elapsedMs = watch2.ElapsedMilliseconds;
results.Add(nameof(parallelThreading.AsParallelAddingParallelization), elapsedMs);
var watch = System.Diagnostics.Stopwatch.StartNew();
parallelThreading.AsParallel(something2.ToList());
watch.Stop();
elapsedMs = watch.ElapsedMilliseconds;
results.Add(nameof(parallelThreading.AsParallel), elapsedMs);
var watch1 = System.Diagnostics.Stopwatch.StartNew();
parallelThreading.WithoutAsParallel(something3.ToList());
watch1.Stop();
elapsedMs = watch1.ElapsedMilliseconds;
results.Add(nameof(parallelThreading.WithoutAsParallel), elapsedMs);
var watch3 = System.Diagnostics.Stopwatch.StartNew();
parallelThreading.AsParallelAsOrdered(something.ToList());
watch3.Stop();
elapsedMs = watch3.ElapsedMilliseconds;
results.Add(nameof(parallelThreading.AsParallelAsOrdered), elapsedMs);
foreach (var result in results)
WriteTime(result.Key, result.Value);
Console.ReadLine();
private static void WriteTime(string methodName, long elapsedMiliseconds)
Console.WriteLine($" methodName: Milisecond passed: elapsedMiliseconds");
ParallelThreading.cs
public class ParallelThreading
private List<PersonModel> RandomData(int range)
List<PersonModel> personModels = new List<PersonModel>();
for (int i = 0; i < range; i++)
var person = new PersonModel()
NumberIdentification = i,
Age = Convert.ToInt32(GenerateString.RandomNumbers(2)),
DateOfBirth = GenerateString.GenerateDateTime(),
LastName = GenerateString.RandomString(10),
Name = GenerateString.RandomString(10),
City = GenerateString.RandomString(10)
;
personModels.Add(person);
return personModels;
private List<PersonModel> RandomDataWithSpecificSameData(int range, string city)
List<PersonModel> personModels = new List<PersonModel>();
for (int i = 0; i < range; i++)
var person = new PersonModel();
if (GenerateString.random.Next(range - 1) % 2 == 0)
person = new PersonModel()
NumberIdentification = i,
Age = Convert.ToInt32(GenerateString.RandomNumbers(2)),
DateOfBirth = GenerateString.GenerateDateTime(),
LastName = GenerateString.RandomString(10),
Name = GenerateString.RandomString(10),
City = city
;
else
person = new PersonModel()
NumberIdentification = i,
Age = Convert.ToInt32(GenerateString.RandomNumbers(2)),
DateOfBirth = GenerateString.GenerateDateTime(),
LastName = GenerateString.RandomString(10),
Name = GenerateString.RandomString(10),
City = GenerateString.RandomString(10),
;
personModels.Add(person);
return personModels;
#region AsParallelLINQ
public List<PersonModel> InitializeDataForParallelData(int range)
return RandomDataWithSpecificSameData(range, "Oradea");
public void AsParallel(List<PersonModel> data)
var result = data
.AsParallel()
.Where(c => c.City == "Oradea")
.Select(c => c);
foreach (var person in result)
Console.WriteLine($"person.NumberIdentification + person.Name + person.City");
public void AsParallelAddingParallelization(List<PersonModel> data)
var result = data
.AsParallel()
.WithDegreeOfParallelism(8)
.WithExecutionMode(ParallelExecutionMode.ForceParallelism)
.Where(c => c.City == "Oradea")
.Select(c => c);
foreach (var person in result)
Console.WriteLine($"person.NumberIdentification + person.Name + person.City");
public void AsParallelAsOrdered(List<PersonModel> data)
var result = data
.AsParallel()
.AsOrdered()
.Where(c => c.City == "Oradea")
.Select(c => c);
foreach (var person in result)
Console.WriteLine($"person.NumberIdentification + person.Name + person.City");
public void WithoutAsParallel(List<PersonModel> data)
var result = data.Where(c => c.City == "Oradea").Select(c => c);
foreach (var person in result)
Console.WriteLine($"person.NumberIdentification + person.Name + person.City");
#endregion
【问题讨论】:
原因是我不想用源代码填充屏幕,因为它不会帮助任何人,将代码屏幕或其他屏幕之间的点连接起来。正如我在上面的帖子中提到的预期结果是,为什么如果我交换方法我仍然得到几乎相同的响应时间?我在 Debug 中进行的测试,它的版本是 .Net Core 版本 2.1.402 如果您需要对代码进行基准测试,您可能应该使用github.com/dotnet/BenchmarkDotNet 以避免在尝试测量代码性能时常见的陷阱。 mjwills 我同意,但 Debug 或 Release 之间没有太大区别。 @Magnus 我所期望的是,每当我运行一个方法(例如 AsParallelAddingParallelization() )以获得相同的经过毫秒数时。如果我交换方法(例如,最后一个与第一个),也不会有不同的时间 Oliver 感谢您的建议,我会试一试。 抱歉之前没有看到链接。我将首先回答您在评论中提出的问题-> 为什么后面的方法调用更快“?正确吗?如果您将 docs.microsoft.com/en-us/dotnet/api/... 设置为50?不完全是,我试图解释为什么如果我调用顺序方法(例如:a,b,c,d)它需要从最多到最少的过程。(例如:a = 3 秒,b = 2 秒,c = 1 秒和 d = 0.5 秒),如果我交换方法,时间保持几乎相同(例如:d = 3 秒,b = 2 秒,c = 1 秒a = 0.5 秒) 我建议阅读 ***.com/questions/19388372/… 。 @Oliver 的建议将有助于减少“第一次调用总是较慢”效果的影响,从而进行真正的性能比较。 【参考方案1】:非常感谢 @mjwills 和 @Oliver 提供的帮助和链接。
在略过BenchmarkDotNet 的表面(有很多选项)并对解决方案进行一些调整之后,似乎(至少)就我而言,这些方法之间没有区别(但那是一个不同的问题,关于 AsParallel 应该如何、何时以及使用什么类型的数据来获得性能)。
第一篇文章的评论总结: 我担心的是为什么方法从上到下调用的时间间隔从最长到最短,即使我交换方法(例如,底部的最后一个与顶部的第一个)
所以,幕后是因为第一次有一个“预热”过程,其中涉及不同操作的缓存机制*** link to details
所以作为解决问题的方法:使用 BenchmarkDotNet,不要忘记缓存操作(上面提到的那个)
【讨论】:
以上是关于测量 .AsParallel() 时的不同结果的主要内容,如果未能解决你的问题,请参考以下文章
在 IEnumerable 上使用 AsParallel - 它是不是有任何并行性的好处?