static BigInteger factorial(BigInteger i)
        {          
            if (i == 1)
            {
                return 1;
            }
            else
            {
                return factorial(i - 1) * i;
            }
        }
    static void Main(string[] args)
        {
            Stopwatch sw = new Stopwatch();
            sw.Start();            factorial(10000);
            factorial(10000);
            factorial(10000);
            factorial(10000);
}
计算四次 依次执行 耗时8430毫秒        static void TestTaskFactory()
        {
            Task task = Task.Factory.StartNew(() =>
           {
               Task.Factory.StartNew(() => { factorial(10000); }, TaskCreationOptions.AttachedToParent);
               Task.Factory.StartNew(() => { factorial0(10000); }, TaskCreationOptions.AttachedToParent);
               Task.Factory.StartNew(() => { factorial1(10000); }, TaskCreationOptions.AttachedToParent);
               Task.Factory.StartNew(() => { factorial2(10000); }, TaskCreationOptions.AttachedToParent);
           });
            task.Wait();
        }
耗时25650
         public class Factorial
         {
             private ManualResetEvent doneEvent;
             private BigInteger big = 0;             public Factorial(int n, ManualResetEvent dEvent)
             {
                 big = (BigInteger)n;
                 doneEvent = dEvent;
             }             private BigInteger factorial(BigInteger i)
             {
                 if (i == 1)
                 {
                     return 1;
                 }
                 else
                 {
                     return factorial(i - 1) * i;
                 }
             }             public void CallBack(Object threadContext)
             {
                 Console.WriteLine("thread {0} started...", Thread.CurrentThread);
                 factorial(big);
                 doneEvent.Set();
             }
         }        static void TestThreadPool()
         {
             ManualResetEvent[] doneEvents = new ManualResetEvent[4];
             for (int i = 0; i < 4; i++)
             {
                 doneEvents[i] = new ManualResetEvent(false);
                 Factorial f = new Factorial(10000, doneEvents[i]);         
                 ThreadPool.QueueUserWorkItem(f.CallBack);
             }
             WaitHandle.WaitAll(doneEvents);
         }
耗时 26431
为什么两种并行方式的执行时间都比串行差这么多呢?

解决方案 »

  1.   

    你是单核CPU吧,换个四核的机器试试就不同了
      

  2.   

    CPU :AMD Athlon X3 435
      

  3.   

    parrel.for 这里不适用!能解释上面的现象吗?焦急的等高手
      

  4.   

    你这里有很多问题,简单说两三个:Task是非常慢的,它需要巨大的管理成本。你使用它搞这么简单的功能,除非你不在乎成本(例如在开启一个服务程序时并发启动七八个监听服务,这时候不在乎多花2秒钟管理成本)。这种程序,使用简单的ThreadPool.QueueUserWorkItem,甚至你自己new几个Thread实例就行了,不应该使用Task。另外,当你顺序执行的时候,你肯定只有一个内核工作吗?不能肯定吧。看一下任务性能监视,所有内核都参与处理,顶多是一个内核稍微高出那么百分之三十而已吧!我很少把这种运行在只有2、3个核心(有的甚至是CPU中的线程而不是独立核心)的计算叫做并行计算,我觉得有几十个或者上百个核心的那种计算才叫做并行计算。我只是把这些叫做——一个很平淡地——多线程程序。而之所以以多线程程序执行,是因为考虑到大量的I/O的存在,比如网络通讯的存在。你这种搞个数学计算所能够测试的东西,是歪曲了“很平淡的”多线程编程的目的。
      

  5.   

    这个问题我也在想,我刚写了个demo发现每次输出的顺序都不同
      

  6.   

    就算Task真的这么慢,为什么线程池也这么慢呢?
      

  7.   

            public static void DoWork(object data)
            {
              //  BigInteger big = (BigInteger)data; //强制类型转换还会异常?怎么回事
                factorial(10000);
            }        static void TestThread()
            {
                Thread newThread1 = new Thread(DoWork);
                Thread newThread2 = new Thread(DoWork);
                Thread newThread3 = new Thread(DoWork);
                Thread newThread4 = new Thread(DoWork);
                newThread1.Start();
                newThread2.Start();
                newThread3.Start();
                newThread4.Start();
                newThread1.Join();
                newThread2.Join();
                newThread3.Join();
                newThread4.Join();
                }
    弄了4个线程 耗时25960,和线程池,和task比是相差无几。
    至少我可以证明sp1234所说的Task的管理成本非常的是错误的
      

  8.   

    刚认真观察了下CPU使用量。我上面写的四种方式都是37%
    左右,我是三个核心的CPU,证明这几个写法都是指调用了CPU的一个核心吧,但是既然大家都是只用到了一个核心,那为什么单单连续四次顺序调用的速度最快呢?
    四个线程为什么不能分布到三个核心去执行呢?这些问题挺疑惑的!
    期待高人点拨一二!
    PS:确实没什么分的,哪里有卖分的,本来我想去淘宝买的,没得卖
      

  9.   

    你用了很慢的BigInteger,很慢的递归...Task并行不是做你这种无聊的工作的...
      

  10.   

    这个很假啊,Task就是用线程实现的,你起了4个task应该会轮流跑在3个核心上(如果你没设置线程亲缘性的话),所以时间上缩短为原来的三分之一
    84300(你给的数据少了个零吧)=> 2565084300/3=28100
    实际的数据要比28100小也是有原因的
    这个原因来之指令级的并行(同一个核心可以同时执行存取指令和运算指令)你的数据,我感觉挺合理的
      

  11.   

    我就是用这个递归 用这个BigInteger来拉长时间,写这几个的意思就是为了试试并行到底快在那里,结果让我很纳闷
      

  12.   

    LZ的操作系统不支持CPU并行?就算不支持并行后两种也不应该比前一种慢了几倍啊。
    我的双核E2160前一种方案CPU绝对是50%,后面两种绝对是100%。
    由于递归算50000!会栈溢出,我改成了循环。
    算4个10000!的时候执行时间差不多,都是2300ms左右。
    算4个50000!的时候并行的优势就很明显了,第一种方案23000ms左右,后面两种都是13000ms左右。