Различные результаты при измерении .AsParallel () - PullRequest
0 голосов
/ 03 сентября 2018

Моя проблема, на которую, похоже, я не смог найти ответ, заключается в следующем: почему, если я меняю порядок вызова метода, который содержит .AsParallel(), и метода, который не содержит или имеет другие параметры, результат будет другим .

Я поместил исходный код на GitHub, поэтому я не заполняю весь экран -> https://github.com/moisoiu/asParallel

И некоторые объяснения относительно того, как я до сих пор проверял это.

Я использую другие классы для генерации некоторых случайных данных, и с этого момента я передаю сгенерированные и рандомизированные данные в методы ParallelThreading, измеряю время с помощью класса StopWatch и сохраняю результаты в словаре для показать в конце время отклика.

Сначала я предположил, что проблема со временем исполнения может быть из-за того, что я работаю над одной и той же ссылкой, поэтому я создал 4 новых объекта что-то , которое является массивом, поэтому есть новая ссылка, но результаты у нас одинаковые.

В какой-то момент я даже предположил, что, возможно (просто может быть) переменная из watch все еще может хранить значение из предыдущего, поэтому я создал новую переменную для каждой

Так есть идеи?

Просто выберите метод из Program.cs и поменяйте его местами с другим методом, и время отклика будет почти таким же, но метод, который длится больше всего, будет одним из TOP, а гораздо меньший - снизу. ,

Edit: Уважать рекомендации из комментариев ниже. Я приложил часть исходного кода, на случай, если потребуется больше, я обновлю и удалю ссылку из 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 голосов
/ 03 сентября 2018

Хочу начать с огромной благодарности @ mjwills и @ Oliver за предоставленную помощь и предоставленные ссылки.

Немного поцарапав поверхность BenchmarkDotNet (имеет массу опций) и некоторые изменения в решении, кажется, что (по крайней мере) для моего случая нет разницы между методами (но это другая проблема, касающаяся того, как, когда и какой тип данных должен использоваться AsParallel для получения производительности).

Резюме из комментария к первому сообщению: Меня беспокоило, почему методы, вызываемые сверху вниз, по прошествии времени становятся самыми длинными и самыми короткими, даже если я поменяю местами методы (например, последний снизу с первым сверху)

Таким образом, за кулисами было потому, что вначале был процесс «разогрева», включающий механизм кэширования для различных операций Ссылка Stackoverflow на подробности

Итак, в качестве решения проблемы: используйте BenchmarkDotNet и не забывайте об операциях кэширования (упомянутых выше)

...