powered by simpleCommunicator - 2.0.56     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Linq.AsParallel()
12 сообщений из 12, страница 1 из 1
Linq.AsParallel()
    #38248274
relief
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Есть такой простой код

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
  private static void Main(string[] args)
        {
            var count = 50000;
            Queue<Country> queue = new Queue<Country>(count);
            for (int i = 0; i < count; i++)
                queue.Enqueue(new Country() {Id = i, Name = i.ToString()});


            Country[] arr = new Country[count];
            for (int i = 0; i < count; i++)
                arr[i] = new Country() {Id = i, Name = i.ToString()};
            
            Stopwatch sw = new Stopwatch();
            sw.Start();
            Int64 sum = arr.AsParallel().Sum(p => p.Id);
            sw.Stop();

            Stopwatch sw2 = new Stopwatch();
            sw2.Start();
            Int64 sum2 = queue.AsParallel().Sum(p => p.Id);
            sw2.Stop();
        }



почему сумма по обычному массиву всегда в несколько раз медленней?

Судя по тому, что пишут тут
Массив должен быть быстрей
...
Рейтинг: 0 / 0
Linq.AsParallel()
    #38248302
beg-in-er
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
relief,

авторпочему сумма по обычному массиву всегда в несколько раз медленней?

а патаму что не правильно замеряете

попробуйте вот такой код

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
class Program
    {
        static StreamWriter str = new StreamWriter("result.txt", true);
        static void Main(string[] args)
        {
            K1(50000);
            K1(50000);
            K1(50000);
            str.Close();
            Console.ReadKey();
        }
        static void K1(int N)
        {
            var count = N;
            Queue<Country> queue = new Queue<Country>(count);
            for (int i = 0; i < count; i++)
                queue.Enqueue(new Country() {Id = i, Name = i.ToString()});


            Country[] arr = new Country[count];
            for (int i = 0; i < count; i++)
                arr[i] = new Country() {Id = i, Name = i.ToString()};

            Stopwatch sw2 = new Stopwatch();
            sw2.Start();
            Int64 sum2 = queue.AsParallel().Sum(p => p.Id);
            sw2.Stop();

            Stopwatch sw = new Stopwatch();
            sw.Start();
            Int64 sum = arr.AsParallel().Sum(p => p.Id);
            sw.Stop();

          
            
            Console.WriteLine("ARRAY "+sw.ElapsedMilliseconds);
            Console.WriteLine("queue "+sw2.ElapsedMilliseconds);

            
            str.WriteLine("ARRAY " + sw.ElapsedMilliseconds);
            str.WriteLine("queue " + sw2.ElapsedMilliseconds);
            
        }
    }
    class Country
    {
        public int Id;
        public string Name;
    }



ARRAY 36
queue 18
ARRAY 1
queue 12
ARRAY 1
queue 9

а вот если поменять последовательность вызова ( массива и последовательности)
то картина вообще станет разгромной
ARRAY 2
queue 51
ARRAY 1
queue 9
ARRAY 1
queue 10
...
Рейтинг: 0 / 0
Linq.AsParallel()
    #38248420
beg-in-er
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
beg-in-er,

чуть покопавшись с кодом получим

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
 class Program
    {
        static StreamWriter str = new StreamWriter("result.txt", true);
        static void Main(string[] args)
        {
            int count = 1000000;
            Country[] arr = new Country[count];
            for (int i = 0; i < count; i++)
                arr[i] = new Country() { Id = 7, Name = i.ToString() };

            Queue<Country> queue = new Queue<Country>(count);
            for (int i = 0; i < count; i++)
                queue.Enqueue(new Country() { Id = i, Name = i.ToString() });

            
            Action AR1 = () => {  Q0 = arr.AsParallel().Sum(p => p.Id);      };
            Action AR2 = () => { Q0 = arr.Sum(P => P.Id); };
            Action QE1 = () => { Q0 = queue.AsParallel().Sum(p => p.Id); };
            Action QE2 = () => { Q0 = queue.Sum(P => P.Id); };
            Action AR0 = () => { long t = 0; for (int Q = 0; Q < count; Q++)  t += arr[Q].Id; Q0 = t; };
            for (int T = 0; T < 2; T++)
            {
                
                ACT(AR1, "ARRAY PLINQ ");
                ACT(AR2, "ARRAY LINQ  ");
                ACT(AR0, "ARRAY PURE ");
                ACT(QE1, "Queue PLINQ ");
                ACT(QE2, "Queue LINQ ");
                Console.WriteLine();
            }
            str.Close();
            Console.ReadKey();

        }
        static Int64 Q0=0;
        static void ACT(Action A,string TXT)
        {
            Stopwatch sw = new Stopwatch();
            sw.Start();
            A.Invoke();
            sw.Stop();
            Console.WriteLine(TXT + sw.ElapsedMilliseconds);
            str.WriteLine(TXT + sw.ElapsedMilliseconds);
        }
        
    }
    class Country
    {
        public long Id;
        public string Name;
    }



а вот и результаты.
по ним видно , что Queue PLINQ наглухо проигрывает даже Queue LINQ.
а уж обычному ARRAY так вообще на порядок. что в общем и ожидаемо

время в миллисекундах
X64
ARRAY PLINQ 29
ARRAY LINQ 86
ARRAY PURE 23
Queue PLINQ 254
Queue LINQ 210

X86
ARRAY PLINQ 23
ARRAY LINQ 47
ARRAY PURE 15
Queue PLINQ 152
Queue LINQ 114

ну и как всегда, платформа x86 разделала под орех x64. что то же вполне ожидаемо.
...
Рейтинг: 0 / 0
Linq.AsParallel()
    #38248634
relief
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
beg-in-er,

а почему играет очередность вызовов?
...
Рейтинг: 0 / 0
Linq.AsParallel()
    #38248717
beg-in-er
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
relief,

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

от этого "недостатка" можно избавится использовав утилиту ngen
...
Рейтинг: 0 / 0
Linq.AsParallel()
    #38248772
relief
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
beg-in-errelief,

вообщето последовательность вызовов не имеет значение. но при т.к. скомпилированный проект это код JIT , то разница во времени объясняется как раз этим.


хочу остановиться на вот этом вашем сравнении

авторARRAY 36
queue 18
ARRAY 1
queue 12
ARRAY 1
queue 9

почему первый раз Array тратит намного больше чем queue?
насколько я понимаю jit компилирует функцию целиком при первом обращении, т.е. array должен работать также быстрей в 2 и 3 попытках. Если нет - пояссните детали такой разницы
...
Рейтинг: 0 / 0
Linq.AsParallel()
    #38248785
beg-in-er
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
relief,

я чесно говоря не знаю , почему так проиходит. на знаю тонкостей реализации JIT->байт кода.
но судя по поведению, либо счётчик глючит, либо среда пытается исполнить без байткода, но когда натыкается на дорогой вызов - компилит...но счётчик уже запущен.
наверно как так
...
Рейтинг: 0 / 0
Linq.AsParallel()
    #38249600
netivan
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
я не понимаю что вы хотели показать? Вот мой пример на коленке. Взял более "тяжелые" операции, чтобы затраты на потоки были не так видны. Результат есть:
Код: c#
1.
2.
3.
4.
listPure: 00:00:01.0334421
lisPlinq: 00:00:00.4030069
listPure: 00:00:01.0293031
lisPlinq: 00:00:00.2451444


код:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
 static void Main(string[] args)
        {
            const int count = 10000000;
            var rnd = new Random();
            var list = new List<int>(count);
            for (var i = 0; i < count; i++)
            {
                list.Add(rnd.Next());
            }
            //
            Action listPure = () => {
                                        for (int i = 0; i < count; i++)
                                        {
                                            MathOperation(list[i]);
                                        }
            };
            //Action lisPlinq = () => Parallel.ForEach(list, MathOperation);
            Action lisPlinq = () =>list.AsParallel().ForAll(MathOperation);
            int iterations = 2;
            do
            {
                RunTest(listPure, "listPure");
                RunTest(lisPlinq, "lisPlinq");
                iterations--;
            } while (iterations!=0);
            Console.Read();
        }
        private static void MathOperation(int a)
        {
            double d = 0;
            d+=Math.Cos(a);
            d+=Math.Sqrt(a);
            Math.Pow(d, 5);
        }
        private static void RunTest(Action a,string name)
        {
            var sw = new Stopwatch();
            sw.Start();
            a();
            sw.Stop();
            Console.WriteLine(name +": " + sw.Elapsed);
        }
...
Рейтинг: 0 / 0
Linq.AsParallel()
    #38249626
beg-in-er
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
netivan,
а ничего не хочу сказать. цифири сами говорят за себя
а вот с List да , там дела стоят именно так. Да PLINQ будет быстрее.

ну добивать , так добивать. чистый массив туда зафигачим
ARRAY PLINQ 35
ARRAY LINQ 82
ARRAY PURE 20

Queue PLINQ 192
Queue LINQ 184
Queue PURE 74

LIST PLINQ 31
LIST LINQ 112
LIST PURE 41

I32 PLINQ 28
I32 LINQ 40
I32 foreach 4
I32 for 9


Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
   static StreamWriter str = new StreamWriter("result.txt", true);
        static void Main(string[] args)
        {
            k1();
            str.Close();
            Console.ReadKey();
        }
        
        static void k1()
        {
            int count = 1000000;

            int[] arr32 = new int[count];
            Country[] arr = new Country[count];
            for (int i = 0; i < count; i++) arr32[i] = 7;

            for (int i = 0; i < count; i++)
                arr[i] = new Country() { Id = 7, Name = i.ToString() };

            Queue<Country> queue = new Queue<Country>(count);
            for (int i = 0; i < count; i++)
                queue.Enqueue(new Country() { Id = i, Name = i.ToString() });

            List<Country> LIST = new List<Country>(count);
            for (int i = 0; i < count; i++)
                LIST.Add(new Country() { Id = i, Name = i.ToString() });
            
            
            Action AR1 = () => { Q0 = arr.AsParallel().Sum(p => p.Id);      };
            Action AR2 = () => { Q0 = arr.Sum(P => P.Id); };
            Action QE1 = () => { Q0 = queue.AsParallel().Sum(p => p.Id); };
            Action QE2 = () => { Q0 = queue.Sum(P => P.Id); };
            Action AR0 = () => { long t = 0; for (int Q = 0; Q < count; Q++)  t += arr[Q].Id; Q0 = t; };
            Action QE0 = () => { long t = 0; foreach (var T in queue) t += T.Id;};

            Action L1 = () => { Q0 = LIST.AsParallel().Sum(p => p.Id); };
            Action L2 = () => { Q0 = LIST.Sum(P => P.Id); };
            Action L0 = () => { long t = 0; foreach (var T in LIST) t += T.Id; Q0 = t; };

            Action Z1 = () => { Q000 = arr32.AsParallel().Sum(p => p); };
            Action Z2 = () => { Q000 = arr32.Sum(P => P); };
            Action Z0 = () => { long t = 0; foreach (var T in arr32) t += T; Q000 = t; };
            Action Z00 = () => { long t = 0; for (int Q=0;Q<count;Q++) t += arr32[Q]; Q000 = t; };
           
            for (int Z=0;Z<100;Z++)
            {
                SS = queue.Peek().Name;
            }
            
            for (int T = 0; T < 2; T++)
            {
                
                ACT(AR1, "ARRAY PLINQ ");
                ACT(AR2, "ARRAY LINQ  ");
                ACT(AR0, "ARRAY PURE ");
                ACT(QE1, "Queue PLINQ ");
                ACT(QE2, "Queue LINQ ");
                ACT(QE0, "Queue PURE ");

                ACT(L1, "LIST PLINQ ");
                ACT(L2, "LIST LINQ ");
                ACT(L0, "LIST PURE ");
                Q0 = 0;
                ACT(Z1, "I32 PLINQ ");
                ACT(Z2, "I32 LINQ ");
                ACT(Z0, "I32 foreach ");
                ACT(Z00, "I32 for ");



                Console.WriteLine();
            }
           

        }
        static string SS = "";
        static Int64 Q0=0;
        static Int64 Q000 = 0;
        static void ACT(Action A,string TXT)
        {
            Stopwatch sw = new Stopwatch();
            sw.Start();
            A.Invoke();
            sw.Stop();
            Console.WriteLine(TXT + sw.ElapsedMilliseconds);
            str.WriteLine(TXT + sw.ElapsedMilliseconds);
        }




ПС. многое зависит от проца. у меня какой то щас на ноуте мутный проц AMDx64 . ноут , который был на 30% дешевле , но Core i3, работает в 2 раза быстрее.

ПС2.
в толк не могу взять , почему на х86 оператор foreach в 2 раза быстрее оператора for. foreach 4 миллисекунды , супротив 9 для for.
при том , что на х64 разницы нет никакой . парадоксЪ. я то думал , что быстрее for трудно сделать. ан нет.
...
Рейтинг: 0 / 0
Linq.AsParallel()
    #38249631
beg-in-er
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
beg-in-er,

но само по себе , что разница в обработке для простого массива интов в разы быстрее чем сложных типов очень показательна.

меня это наводит только на одну мысль , что все эти PLINQ какой-то паллиатив.
...
Рейтинг: 0 / 0
Linq.AsParallel()
    #38249641
Фотография МСУ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
beg-in-erв толк не могу взять , почему на х86 оператор foreach в 2 раза быстрее оператора for. foreach 4 миллисекунды , супротив 9 для for.
Слишком велика погрешность на IO и т.п., не заморачивайся.
...
Рейтинг: 0 / 0
Linq.AsParallel()
    #38249955
netivan
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
beg-in-er,

почему ты не берешь в расчет, что просто сумма массива слишком простая операция и поэтому затраты на весь этот пул будут выше? List тут не причем, он все равно в данном случае как массив.
...
Рейтинг: 0 / 0
12 сообщений из 12, страница 1 из 1
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Linq.AsParallel()
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]