测量.AsParallel()

时间:2018-09-03 05:14:58

标签: c# multithreading performance linq plinq

我的问题似乎无法找到答案:为什么如果我更改了调用包含.AsParallel()和不包含或具有不同选项的方法的顺序,为什么呢?不一样。

我已将源代码放置在GitHub上,因此我无法覆盖所有屏幕-> https://github.com/moisoiu/asParallel

以及到目前为止我如何测试的一些说明。

我正在使用其他类生成一些随机数据,从那时起,我将生成的和随机化的数据传递给ParallelThreading方法,并通过StopWatch类测量时间并存储结果在字典中显示响应时间。

起初,我认为性能时间问题可能是因为我在同一个引用上工作,所以我创建了4个新对象 something ,它是一个数组,因此将有一个新的参考,但结果相同。

在某个时候,我什至甚至假设 watch 中的变量仍然可以存储上一个变量的值,所以我为每个变量都创建了一个新变量

有什么想法吗?

只需从Program.cs中选择一种方法,然后将其与其他方法交换,响应时间将几乎相同,但是使用时间最长的方法将是TOP上的方法,而使用时间最少的方法将是底部的方法。 。

编辑: 为了尊重来自以下评论的建议。我已经附加了部分源代码,以防万一,如果需要更多,我将更新并从上面的Git中删除链接。

Program.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

}

Example of result with name and time elapsed

Example of result when the method name is swapped

1 个答案:

答案 0 :(得分:1)

首先感谢@mjwills@Oliver所提供的帮助和链接。

在刮擦BenchmarkDotNet的表面(有大量选项)并对该解决方案进行了一些调整之后,看来(至少)就我而言,这两种方法之间没有区别(但是那是一个不同的问题,关于如何,何时以及以何种类型的数据使用AsParallel来获得性能。

第一篇文章的评论摘要: 我担心的是,即使我交换了这些方法(例如,从底部开始的最后一个与从顶部开始的第一个),为什么这些方法从上到下调用​​的时间也是从最长到最短?

因此,在幕后的原因是,因为首先有一个“热身”过程,其中涉及针对不同操作Stackoverflow link to details

的缓存机制

作为解决方案的解决方案:使用BenchmarkDotNet,不要忘记缓存操作(上述操作)