多核处理器上的多线程奇怪的结果

时间:2014-02-09 00:42:20

标签: c# multithreading

我正在尝试在多核虚拟机上测试多线程程序的线程执行。我为它编写了C#代码:

class Program
{
    public static int fib(int n)
    {
        if (n < 2)
            return n;

        return fib(n-1)+fib(n-2);
    }

    public static void execution(object n)
    {
        int STEP = 40;
        var start = DateTime.Now;
        int value = fib(STEP);
        var end = DateTime.Now;

        Console.WriteLine(string.Format("threads: {0}, time : {1}, start: {2}, end: {3}", n, end.Subtract(start).TotalSeconds,
            start, end));
    }

    static void Main(string[] args)
    {
        int[] threads = {1, 2, 4, 8, 16};

        for(int j=0; j<5; ++j)
        {
            for (int i = 0; i < threads[j]; ++i)
            {
                var thread = new Thread(Program.execution);
                thread.Start(threads[j]);
            }
            Thread.Sleep(60000);
        }
    }

这是我得到的结果

主题:1,时间:4.2177734,开始时间:2/8/2014 7:30:13 PM,结束时间:2/8/2014 7:30:18 PM

主题:2,时间:4.1015625,开始时间:2/8/2014 7:31:13 PM,结束时间:2/8/2014 7:31:17 PM

主题:2,时间:4.2441407,开始时间:2/8/2014 7:31:13 PM,结束时间:2/8/2014 7:31:18 PM

主题:4,时间:2.0351562,开始时间:2/8/2014 7:32:13 PM,结束时间:2/8/2014 7:32:15 PM

主题:4,时间:2.0527343,开始时间:2/8/2014 7:32:13 PM,结束时间:2/8/2014 7:32:15 PM

主题:4,时间:2.0869141,开始时间:2/8/2014 7:32:13 PM,结束时间:2/8/2014 7:32:15 PM

主题:4,时间:2.0898437,开始时间:2/8/2014 7:32:13 PM,结束时间:2/8/2014 7:32:15 PM

主题:8,时间:3.34375,开始时间:2/8/2014 7:33:13 PM,结束时间:2/8/2014 7:33:17 PM

主题:8,时间:3.381836,开始时间:2/8/2014 7:33:13 PM,结束时间:2/8/2014 7:33:17 PM

主题:8,时间:3.3066406,开始时间:2/8/2014 7:33:14 PM,结束时间:2/8/2014 7:33:17 PM

主题:8,时间:3.2451172,开始时间:2/8/2014 7:33:14 PM,结束时间:2/8/2014 7:33:17 PM

主题:8,时间:3.4560547,开始时间:2/8/2014 7:33:13 PM,结束时间:2/8/2014 7:33:17 PM

主题:8,时间:3.5029296,开始时间:2/8/2014 7:33:13 PM,结束时间:2/8/2014 7:33:17 PM

主题:8,时间:3.2841796,开始时间:2/8/2014 7:33:14 PM,结束时间:2/8/2014 7:33:17 PM

主题:8,时间:3.4160157,开始时间:2/8/2014 7:33:14 PM,结束时间:2/8/2014 7:33:17 PM

主题:16,时间:5.9921875,开始时间:2/8/2014 7:34:14 PM,结束时间:2/8/2014 7:34:20 PM

主题:16,时间:6.4404297,开始时间:2/8/2014 7:34:14 PM,结束时间:2/8/2014 7:34:20 PM

主题:16,时间:5.3896484,开始时间:2/8/2014 7:34:15 PM,结束时间:2/8/2014 7:34:20 PM

主题:16,时间:5.9658203,开始时间:2/8/2014 7:34:14 PM,结束时间:2/8/2014 7:34:20 PM

主题:16,时间:5.9873047,开始时间:2/8/2014 7:34:14 PM,结束时间:2/8/2014 7:34:20 PM

主题:16,时间:6.2226563,开始时间:2/8/2014 7:34:14 PM,结束时间:2/8/2014 7:34:20 PM

主题:16,时间:6.1552735,开始时间:2/8/2014 7:34:14 PM,结束时间:2/8/2014 7:34:20 PM

主题:16,时间:6.5576172,开始时间:2/8/2014 7:34:14 PM,结束时间:2/8/2014 7:34:20 PM

主题:16,时间:6.5273437,开始时间:2/8/2014 7:34:14 PM,结束时间:2/8/2014 7:34:20 PM

主题:16,时间:6.2529297,开始时间:2/8/2014 7:34:14 PM,结束时间:2/8/2014 7:34:20 PM

主题:16,时间:6.2958984,开始时间:2/8/2014 7:34:14 PM,结束时间:2/8/2014 7:34:20 PM

主题:16,时间:5.8544922,开始时间:2/8/2014 7:34:15 PM,结束时间:2/8/2014 7:34:20 PM

主题:16,时间:6.3886719,开始时间:2/8/2014 7:34:14 PM,结束时间:2/8/2014 7:34:20 PM

主题:16,时间:5.7089844,开始时间:2/8/2014 7:34:15 PM,结束时间:2/8/2014 7:34:20 PM

主题:16,时间:6.7207031,开始时间:2/8/2014 7:34:14 PM,结束时间:2/8/2014 7:34:20 PM

主题:16,时间:6.0742188,开始时间:2/8/2014 7:34:14 PM,结束时间:2/8/2014 7:34:21 PM

请注意我在4核Windows 7虚拟机上运行该程序。

对我来说没有意义的是,当我有4个线程同时运行时,每个线程的计算时间比我同时运行1或2个线程的时间要短。

有人可以在这里解释一下吗?

3 个答案:

答案 0 :(得分:2)

这可能是因为优化器在你到达那里之前并没有真正达到它的步伐。尝试添加一些调用,首先将其变形到程序的开头,以获得更一致的结果。我只有一个双核,所以我得到的结果与你所展示的结果截然不同,所以我不能更精确。

for (int r = 0; r < 20; r++)
        fib(40);

答案 1 :(得分:1)

操作系统为您的每个线程提供一定量的CPU运行时间。每个线程都必须在队列中等待才能执行,随着线程数量的增加,这个等待时间会变长。另一方面,每个线程将获得更少的量子时间来执行。这在虚拟多核环境中将更加明显,因为没有足够的物理内核可以同时执行您的线程。

此外,您应该考虑线程之间的上下文切换,其成本会随着线程数量的增加而增加。因此,避免在不使用

的情况下在应用程序上运行多个线程

答案 2 :(得分:1)

这是一个复杂的分析。如前所述,CPU为每个处理器提供时间片,并且您需要对JIT进行优化,但更有可能在4个线程上,CPU能够以最佳速率为您的程序平衡时间片和线程上下文切换。我敢肯定,由于您无法控制很多事情,这些结果会因机器而异。