Мультипотоки, мультизадачи и трудности с ними - C#

Узнай цену своей работы

Формулировка задачи:

Здравствуйте. Реализовал простой тест для распределенных вычислений больших масивов, забил 3 теста. Обработка в нескольких Thread, в нескольких Task и через Parallel.For Ресультаты на компьютере примерно следующие:
На инициализацию массива в 100кк ушло 6493 мс На выполнение мультипотока (Thread) с массивом в 100кк ушло 4241 мс На выполнение мультитаска (Task) с массивом в 100кк ушло 3959 мс На выполнение Parallel.For с массивом в 100кк ушло 3759 мс
Вроде бы все здорово. но есть загвоздка. Я попытался запустить точно эту же программу на сервере (там 24 ядра, против моих 8). Сервер по всем прогонам AIDA64 раза в 3 мощнее компа, но получилось вот что:
На инициализацию массива в 100кк ушло 26210 мс На выполнение мультипотока (Thread) с массивом в 100кк ушло 16963 мс На выполнение мультитаска (Task) с массивом в 100кк ушло 16358 мс На выполнение Parallel.For в 100кк ушло 14610 мс
Все ядра были загружены на 100%, почему на более мощном сервере код выполнился настолько медленнее? Я даже попробовал скомпилить программу на сервере, результат тот же. Конфигурация компа: Intel Xeon E5620 4 ядра (+4 HT) 3.5GHz, 24GB RAM Конфигурация серва: 2 x Intel Xeon E5-2620 6 ядер (+6 HT) 2.0 GHz, 32 GB RAM Код программы:
private void button1_Click(object sender, EventArgs e)
        {
            Stopwatch sw = new Stopwatch();
            sw.Start();
            int multiplier = int.Parse(textBox2.Text);
            for (int i = 0; i < 5; i++)
            {
                Test(multiplier);
            }
            sw.Stop();
            textBox1.Text += "На 5 итераций теста ушло " + sw.ElapsedMilliseconds + " мс" + Environment.NewLine;
            
        }
 
        public void Test(int multiplier)
        {
            int procMax = Environment.ProcessorCount * multiplier;
            Stopwatch sw = new Stopwatch();
            sw.Reset();
            sw.Start();
            Random rnd = new Random();
            List<int> list = Enumerable.Range(0, 100000000).AsParallel().Select(l => rnd.Next(int.MaxValue)).ToList();
            sw.Stop();
            textBox1.Text += "На инициализацию массива в 100кк ушло " + sw.ElapsedMilliseconds + " мс" + Environment.NewLine;
            Application.DoEvents();
            List<Thread> threads = new List<Thread>();
            sw.Reset();
            sw.Start();
            for (int i = 0; i < procMax; i++)
            {
                Thread tr = new Thread((o) =>
                {
                    int index = (int)o;
                    for (int j = list.Count / procMax * index;
                        j < list.Count / procMax * (index + 1);
                        j++)
                    {
                        list[j] = (int)Math.Sin(rnd.Next(int.MaxValue));
                    }
 
                });
                threads.Add(tr);
                tr.Start(i);
            }
            Application.DoEvents();
            while (true)
            {
                int count = 0;
                foreach (Thread thread in threads)
                {
                    if (thread.ThreadState == ThreadState.Stopped)
                    {
                        count++;
                    }
                }
                if (count == procMax)
                {
                    Thread.Sleep(100);
                    Application.DoEvents();
                    break;
                }
            }
            sw.Stop();
            textBox1.Text += "На выполнение мультипотока в 100кк ушло " + sw.ElapsedMilliseconds + " мс" + Environment.NewLine;
            Application.DoEvents();
            sw.Reset();
            sw.Start();
            bool finished = false;
            TaskFactory tf = new TaskFactory();
            Task[] tasks = new Task[procMax];
            for (int i = 0; i < procMax; i++)
            {
                Task t = new Task((o) =>
                {
                    int index = (int)o;
                    for (int j = list.Count / procMax * index;
                        j < list.Count / procMax * (index + 1);
                        j++)
                    {
                        list[j] = (int)Math.Sin(rnd.Next(int.MaxValue));
                    }
                }, i);
                t.Start();
                tasks[i] = t;
 
            }
            Application.DoEvents();
            tf.ContinueWhenAll(tasks, (ts) =>
            {
                this.Invoke(
                       new Action(
                           () =>
                           {
                               sw.Stop();
                               textBox1.Text += "На выполнение мультитаска в 100кк ушло " + sw.ElapsedMilliseconds + " мс" + Environment.NewLine;
                               Application.DoEvents();
                               sw.Reset();
                               sw.Start();
                               Parallel.For(0, list.Count, (i) =>
                               {
                                   list[i] = (int)Math.Sin(rnd.Next(int.MaxValue));
                               });
                               sw.Stop();
                               textBox1.Text += "На выполнение Parallel.For в 100кк ушло " + sw.ElapsedMilliseconds + " мс" + Environment.NewLine;
                               finished = true;
                           }));
 
            });
            while (!finished)
            {
                Application.DoEvents();
                Thread.Sleep(100);
            }
            GC.WaitForPendingFinalizers();
            GC.Collect();
        }
Код очень страшный и не претендует на звание хорошего кода для тестов, но факт остается фактом, он работает не совсем верно на разных машинах...
Даже на ноуте с процессором i3 (2 ядра + 2HT) и 4гб оперативы код выполняется в 2 раза быстрее чем на серве, как?!

Решение задачи: «Мультипотоки, мультизадачи и трудности с ними»

textual
Листинг программы
ParallelOptions po = new ParallelOptions();
            po.MaxDegreeOfParallelism = 2;

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

9   голосов , оценка 3.778 из 5
Похожие ответы