【发布时间】: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 秒)
-
我建议阅读 stackoverflow.com/questions/19388372/… 。 @Oliver 的建议将有助于减少“第一次调用总是较慢”效果的影响,从而进行真正的性能比较。
标签: c# multithreading performance linq plinq