.Net

时间:2015-09-11 16:00:15

标签: c# .net multithreading performance

为什么我会从下面的代码中获得如此糟糕的表现?

以下命令行使用16个线程,负载为60。 在我的机器上,这需要大约31秒才能完成(如果你重新运行会有一些轻微的变化)

testapp.exe 16 60

在Microsoft Windows Server 2008 R2 Enterprise SP1上使用60负载,在16个Intel Xeon E5-2670 @ 2.6 GHz CPU上运行,我获得以下性能:

1 cpu - 305秒

2 cpus - 155秒

4 cpus - 80秒

8 cpus - 45秒

10 cpus - 41秒

12 cpus - 37秒

14 cpus - 34秒

16 cpus - 31秒

18 cpus - 27秒

20 cpus - 24秒

22 cpus - 23秒

24 cpus - 21秒

26 cpus - 20秒

28 cpus - 19秒

在此之后它变得平坦......

使用.Net 3.5,4,4.5或4.5.1获得大致相同的性能。

我理解22 cpu后的性能下降,因为我只有16个盒子。我不明白的是8 cpu后表现不佳。谁能解释一下?这是正常的吗?

private static void Main(string[] args)
{
    int threadCount;
    if (args == null || args.Length < 1 || !int.TryParse(args[0], out threadCount))
        threadCount = Environment.ProcessorCount;

    int load;
    if (args == null || args.Length < 2 || !int.TryParse(args[1], out load))
        load = 1;

    Console.WriteLine("ThreadCount:{0} Load:{1}", threadCount, load);

    List<Thread> threads = new List<Thread>();

    for (int i = 0; i < threadCount; i++)
    {
        int i1 = i;
        threads.Add(new Thread(() => DoWork(i1, threadCount, load)));
    }

    Stopwatch timer = Stopwatch.StartNew();

    foreach (var thread in threads)
    {
        thread.Start();
    }

    foreach (var thread in threads)
    {
        thread.Join();
    }

    timer.Stop();

    Console.WriteLine("Time:{0} seconds", timer.ElapsedMilliseconds/1000.0);
}

static void DoWork(int seed, int threadCount, int load)
{
    double[,] mtx = new double[3,3];

    for (int i = 0; i < ((100000 * load)/threadCount); i++)
    {
        for (int j = 0; j < 100; j++)
        {
            mtx = new double[3,3];

            for (int k = 0; k < 3; k++)
            {
                for (int l = 0; l < 3; l++)
                {
                    mtx[k, l] = Math.Sin(j + (k*3) + l + seed);
                }
            }
        }
    }
}

2 个答案:

答案 0 :(得分:1)

请参阅英特尔ARK了解XEON E5-2670

此特定处理器具有 8个物理内核,它们是超线程的。这就是为什么你看到8个线程后性能下降的原因。调用Environment.ProcessorCount获得16个逻辑核心(每个物理核心2个逻辑核心,因为它们是超线程的)。

在SuperUser上有一个类似的问题answered

您可以尝试设置线程的亲和力,看它是否有所不同,但调度程序通常可以很好地分配资源。

希望这会有所帮助。

答案 1 :(得分:1)

导致性能下降的线程并不是这样。但它是&#34;创造&#34;线程本身。

您需要从OS线程池中借用已创建的线程,而不是创建全新的线程。使用ThreadPool课程而不是new Thread()