为什么并行多线程代码执行比顺序执行慢?

2006世界杯 2025-05-14 02:11:04 9124

我想执行积分计算使用矩形和梯形方法使用多线程,以获得更快的结果。不幸的是,在我的例子中,执行多线程代码比执行标准顺序代码要慢。使用多线程比使用单线程慢得多-毕竟,它不应该是相反的吗?感觉线程越多,代码的执行速度就越慢。

此外,我注意到线程越多,积分结果的精度就越低。当使用梯形方法计算积分时,这一点尤其值得注意。

下面是我的代码:https://dotnetfiddle.net/jEPURO

代码语言:javascript运行复制using System;

using System.Diagnostics;

using System.Threading;

using System.Threading.Tasks;

namespace ParallelProgramming.ConsoleApp

{

class Program

{

public static string IntegrationMethod { get; set; }

public static double IntervalBegin { get; set; }

public static double IntervalEnd { get; set; }

public static int NPrecisionValue { get; set; }

public static bool IsParallel { get; set; }

public static int ThreadValue { get; set; }

public static Stopwatch Stopwatch { get; set; }

public static double Result { get; set; }

static void Main(string[] args)

{

Console.WriteLine("Function | Elapsed Time | Estimated Integral");

Console.WriteLine("-----------------------------------------------------------------");

IntervalBegin = 5;

IntervalEnd = -2;

NPrecisionValue = 100000000;

//RectangularIntegration – Sequential

NumericalIntegrationMethods integral = new();

Stopwatch = Stopwatch.StartNew();

Result = integral.RectangularIntegration(IntervalBegin, IntervalEnd, NPrecisionValue);

Stopwatch.Stop();

Console.WriteLine($"{nameof(integral.RectangularIntegration)} – Sequential | {Stopwatch.Elapsed} | {Result}");

//RectangularIntegrationParallel - 1 thread

integral = new();

Stopwatch = Stopwatch.StartNew();

Result = integral.RectangularIntegrationParallel(IntervalBegin, IntervalEnd, NPrecisionValue, 1);

Stopwatch.Stop();

Console.WriteLine($"{nameof(integral.RectangularIntegrationParallel)} – 1 Thread | {Stopwatch.Elapsed} | {Result}");

//RectangularIntegrationParallel - 2 threads

integral = new();

Stopwatch = Stopwatch.StartNew();

Result = integral.RectangularIntegrationParallel(IntervalBegin, IntervalEnd, NPrecisionValue, 2);

Stopwatch.Stop();

Console.WriteLine($"{nameof(integral.RectangularIntegrationParallel)} – 2 Threads | {Stopwatch.Elapsed} | {Result}");

//RectangularIntegrationParallel - 3 threads

integral = new();

Stopwatch = Stopwatch.StartNew();

Result = integral.RectangularIntegrationParallel(IntervalBegin, IntervalEnd, NPrecisionValue, 3);

Stopwatch.Stop();

Console.WriteLine($"{nameof(integral.RectangularIntegrationParallel)} – 3 Threads | {Stopwatch.Elapsed} | {Result}");

//RectangularIntegrationParallel - 4 threads

integral = new();

Stopwatch = Stopwatch.StartNew();

Result = integral.RectangularIntegrationParallel(IntervalBegin, IntervalEnd, NPrecisionValue, 4);

Stopwatch.Stop();

Console.WriteLine($"{nameof(integral.RectangularIntegrationParallel)} – 4 Threads | {Stopwatch.Elapsed} | {Result}");

//TrapezoidalIntegration - Sequential

integral = new();

Stopwatch = Stopwatch.StartNew();

Result = integral.TrapezoidalIntegration(IntervalBegin, IntervalEnd, NPrecisionValue);

Stopwatch.Stop();

Console.WriteLine($"{nameof(integral.TrapezoidalIntegration)} – Sequential | {Stopwatch.Elapsed} | {Result}");

//TrapezoidalIntegrationParallel – 1 Thread

integral = new();

Stopwatch = Stopwatch.StartNew();

Result = integral.TrapezoidalIntegrationParallel(IntervalBegin, IntervalEnd, NPrecisionValue, 1);

Stopwatch.Stop();

Console.WriteLine($"{nameof(integral.TrapezoidalIntegrationParallel)} – 1 Thread | {Stopwatch.Elapsed} | {Result}");

//TrapezoidalIntegrationParallel – 2 Threads

integral = new();

Stopwatch = Stopwatch.StartNew();

Result = integral.TrapezoidalIntegrationParallel(IntervalBegin, IntervalEnd, NPrecisionValue, 2);

Stopwatch.Stop();

Console.WriteLine($"{nameof(integral.TrapezoidalIntegrationParallel)} – 2 Threads | {Stopwatch.Elapsed} | {Result}");

//TrapezoidalIntegrationParallel – 3 Threads

integral = new();

Stopwatch = Stopwatch.StartNew();

Result = integral.TrapezoidalIntegrationParallel(IntervalBegin, IntervalEnd, NPrecisionValue, 3);

Stopwatch.Stop();

Console.WriteLine($"{nameof(integral.TrapezoidalIntegrationParallel)} – 3 Threads | {Stopwatch.Elapsed} | {Result}");

//TrapezoidalIntegrationParallel – 4 Threads

integral = new();

Stopwatch = Stopwatch.StartNew();

Result = integral.TrapezoidalIntegrationParallel(IntervalBegin, IntervalEnd, NPrecisionValue, 4);

Stopwatch.Stop();

Console.WriteLine($"{nameof(integral.TrapezoidalIntegrationParallel)} – 4 Threads | {Stopwatch.Elapsed} | {Result}");

Console.WriteLine("Press any key to continue...");

Console.ReadLine();

}

}

public class NumericalIntegrationMethods

{

double Function(double x)

{

return x * x + 2 * x;

}

public double RectangularIntegration(double xp, double xk, int n)

{

double dx, integral = 0;

dx = (xk - xp) / n;

for (int i = 1; i <= n; i++)

{

integral += dx * Function(xp + i * dx);

//Console.WriteLine("Sekwencyjnie - iteracja {0} wątek ID: {1}", i, Thread.CurrentThread.ManagedThreadId);

}

return integral;

}

public double TrapezoidalIntegration(double xp, double xk, int n)

{

double dx, integral = 0;

dx = (xk - xp) / n;

for (int i = 1; i <= n; i++)

{

integral += Function(xp + i * dx);

//Console.WriteLine("Sekwencyjnie - iteracja {0} wątek ID: {1}", i, Thread.CurrentThread.ManagedThreadId);

}

integral += (Function(xp) + Function(xk)) / 2;

integral *= dx;

return integral;

}

public double RectangularIntegrationParallel(double xp, double xk, int n, int maxThreads)

{

double dx, integral = 0;

dx = (xk - xp) / n;

Parallel.For(1, n + 1, new ParallelOptions { MaxDegreeOfParallelism = maxThreads }, i =>

{

integral += dx * Function(xp + i * dx);

//Console.WriteLine("Równolegle - iteracja {0} wątek ID: {1}", i, Thread.CurrentThread.ManagedThreadId);

});

return integral;

}

public double TrapezoidalIntegrationParallel(double xp, double xk, int n, int maxThreads)

{

double dx, integral = 0;

dx = (xk - xp) / n;

Parallel.For(1, n + 1, new ParallelOptions { MaxDegreeOfParallelism = maxThreads }, i =>

{

integral += Function(xp + i * dx);

//Console.WriteLine("Równolegle - iteracja {0} wątek ID: {1}", i, Thread.CurrentThread.ManagedThreadId);

});

integral += (Function(xp) + Function(xk)) / 2;

integral *= dx;

return integral;

}

}

}下面是输出:

代码语言:javascript运行复制Function | Elapsed Time | Estimated Integral

-----------------------------------------------------------------

RectangularIntegration – Sequential | 00:00:00.9284260 | -65.33333210831276

RectangularIntegrationParallel – 1 Thread | 00:00:01.7040507 | -65.33333210831276

RectangularIntegrationParallel – 2 Threads | 00:00:01.7191484 | -65.33333210831276

RectangularIntegrationParallel – 3 Threads | 00:00:01.6888398 | -57.73164823448317

RectangularIntegrationParallel – 4 Threads | 00:00:01.5530828 | -65.33333210831276

TrapezoidalIntegration – Sequential | 00:00:00.7278303 | -65.33333333332568

TrapezoidalIntegrationParallel – 1 Thread | 00:00:01.4265208 | -65.33333333332568

TrapezoidalIntegrationParallel – 2 Threads | 00:00:02.3009881 | -33.110522448239216

TrapezoidalIntegrationParallel – 3 Threads | 00:00:01.6062253 | -57.02137898750542

TrapezoidalIntegrationParallel – 4 Threads | 00:00:01.9967140 | -18.120285251376426为什么会发生这种情况?我做错了什么?毕竟,使用的线程越多,结果应该越快。4个线程应该比3更快,3个线程应该比2更快,以此类推。如何使用更多的线程来获得更快的结果?

站点统计