System.Threading.Tasks.Parallel — параллельность для ленивых

3 Май
2012

Привет, блоговцы!
В этой статье я протестирую, насколько быстро работает метод
Parallel.For
, позволяющий практически без увеличения
объема кода «распараллелить» выполнение стандартного цикла.

В качестве тестовой задачи будет выступать возведение в степень 5 чисел от 0 до 10000000 (чтобы удобнее сравнивать было).

Замеры проводились отдельными запусками программ (10 испытаний для каждой реализации), на двухъядерном Athlon 64X2.

Итак, начнем с решения в одном-единственном потоке, а точнее, вообще без
потоков. Здесь никакой параллельности нет, а потому среднее время выполнения — 1.056 сек.

static void Main (string[] args)
{
Int64 n = 0;
Stopwatch sw = new Stopwatch(); //часы для замера времени
sw.Start();
for (Int32 i = 0; i < 10000000; i++)
n = (Int64)Math.Pow(i, 5);
Console.WriteLine(sw.Elapsed);
}


Следующая программа использует Parallel.For, и работает быстрее… 0.817 сек.

static void Main(string[] args)
{
Int64 n = 0;
Stopwatch sw = new Stopwatch();
sw.Start();
Parallel.For(0, 10000000, j => { n = (Int64)Math.Pow(j, 5); });
Console.WriteLine(sw.Elapsed);
}


Следующие примеры служат, хм… для демонстрации того, насколько ужасающе медленно работает Parallel.For по сравнению с явным использованием потоков и даже по сравнению с Tasks:



потоки, среднее время работы — 0.5246
static void Main(string[] args)
{
Stopwatch sw = new Stopwatch();
Thread m = new Thread(FirstHalf);
Int64 n = 0;
sw.Start();
m.Start();
for (Int32 i = 5000000; i < 10000000; i++)
n = (Int64)Math.Pow(n, 5);
while (m.IsAlive)
Thread.Sleep(5);
Console.WriteLine(sw.Elapsed);
}

static void FirstHalf()
{
Int64 n = 0;
for (Int32 i = 0; i < 5000000; i++)
n = (Int64) Math.Pow(i, 5);
}


Tasks, среднее время работы — 0.5789
static void Main(string[] args)
{
Int64 n = 0;
Task t = new Task(SomeOperation);
Stopwatch sw = new Stopwatch();
sw.Start();
t.Start();
for (Int32 i = 5000000; i < 10000000; i++)
n = (Int64)Math.Pow(i, 5);
while (!t.IsCompleted) { }
Console.WriteLine(sw.Elapsed);
}

static void SomeOperation()
{
Int64 n = 0;
for (Int32 i = 0; i < 5000000; i++)
n = (Int64) Math.Pow(i, 5);
}


Подводя небольшой итог:
Parallel.For, конечно, легкий и простой способ, но стоит ли реализовывать такую «недопараллельность»?
По материалам Хабрахабр.



загрузка...

Комментарии:

Наверх