Мультипотоки, мультизадачи и трудности с ними - C#
Формулировка задачи:
Здравствуйте.
Реализовал простой тест для распределенных вычислений больших масивов, забил 3 теста. Обработка в нескольких Thread, в нескольких Task и через Parallel.For
Ресультаты на компьютере примерно следующие:
Вроде бы все здорово. но есть загвоздка. Я попытался запустить точно эту же программу на сервере (там 24 ядра, против моих 8). Сервер по всем прогонам AIDA64 раза в 3 мощнее компа, но получилось вот что:
Все ядра были загружены на 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
Код программы:
Код очень страшный и не претендует на звание хорошего кода для тестов, но факт остается фактом, он работает не совсем верно на разных машинах...
На инициализацию массива в 100кк ушло 6493 мс
На выполнение мультипотока (Thread) с массивом в 100кк ушло 4241 мс
На выполнение мультитаска (Task) с массивом в 100кк ушло 3959 мс
На выполнение Parallel.For с массивом в 100кк ушло 3759 мс
На инициализацию массива в 100кк ушло 26210 мс
На выполнение мультипотока (Thread) с массивом в 100кк ушло 16963 мс
На выполнение мультитаска (Task) с массивом в 100кк ушло 16358 мс
На выполнение Parallel.For в 100кк ушло 14610 мс
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;
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д