.net 4.0提供的并行计算Task到底有多快的定量分析

文章有bug.....由于Stopwatch只能监视主线程 所以其实Task那部分耗时完全没有计算进去(可以尝试在排序之后马上foreach输出一下数组,会报运行时异常,因为foreach在迭代时候是不允许对容器进行操作的而此时递归产生的Task还在对容器进行排序)


正在尝试弄一个可以监视多线程的Stopwatch


昨天研究了下利用不同容器实现快排算法(list<t>+lambda, list<int>, int[])之间的速度差异,今天在看.net 4.0的时候熟悉了下4.0下提供的牛逼哄哄的Task类尝试进行并行的快速排序算法(快排本质上是分治法,是可以并行计算的 这是理论基础 不能什么情况都套Task),结果可谓相当惊人

同样的 贴上最原始的快排代码 这里用list<t>+lambda实现

 public static void Sort<T>(List<T> arrayForSort, int startIndex, int endIndex, Func<T, T, bool> CompareMethod)
        {
            if (startIndex >= endIndex)
            {
                return;
            }
            int pointer = startIndex;
            int end = endIndex;
            for (int i = pointer + 1; i <= end; i++)
            {
                if (CompareMethod(arrayForSort[pointer], arrayForSort[i]))//把比当前锚点数小的数全部移到锚点数左边
                {
                    var temp = arrayForSort[pointer];
                    arrayForSort[pointer] = arrayForSort[i];
                    arrayForSort[i] = temp;
                    pointer = i;
                }
                else//若当前比较的数比锚点数大 则将其与最后面的数对调
                {
                    var temp = arrayForSort[end];
                    arrayForSort[end] = arrayForSort[i];
                    arrayForSort[i] = temp;
                    --i;
                    --end;
                }
            }
            Sort<T>(arrayForSort, startIndex, pointer, CompareMethod);
            Sort<T>(arrayForSort, pointer + 1, endIndex, CompareMethod);
        }

然后是Task的并行实现 不得不夸一下微软真是太为程序员考虑 代码基本没有大的变动 只在递归调用的地方改成由Task调用就可以了

public static void SortUsingTask<T>(List<T> arrayForSort, int startIndex, int endIndex, Func<T, T, bool> CompareMethod)
        {
            if (startIndex >= endIndex)
            {
                return;
            }
            int pointer = startIndex;
            int end = endIndex;
            for (int i = pointer + 1; i <= end; i++)
            {
                if (CompareMethod(arrayForSort[pointer], arrayForSort[i]))//把比当前锚点数小的数全部移到锚点数左边
                {
                    var temp = arrayForSort[pointer];
                    arrayForSort[pointer] = arrayForSort[i];
                    arrayForSort[i] = temp;
                    pointer = i;
                }
                else//若当前比较的数比锚点数大 则将其与最后面的数对调
                {
                    var temp = arrayForSort[end];
                    arrayForSort[end] = arrayForSort[i];
                    arrayForSort[i] = temp;
                    --i;
                    --end;
                }
            }
            new Task(() => SortUsingTask<T>(arrayForSort, startIndex, pointer, CompareMethod)).Start();
            new Task(() => SortUsingTask<T>(arrayForSort, pointer + 1, endIndex, CompareMethod)).Start();
        }

调用代码相当简单 如下

 class Program
    {
        static void Main(string[] args)
        {
            Random rdm = new Random();
            List<int> testList = new List<int>();
            List<int> testList2 = new List<int>();
            List<int> testList3 = new List<int>();
            for (int i = 0; i < 100000; i++)
            {
                var number = rdm.Next(1000000);
                testList.Insert(i, number);
                testList2.Insert(i, number);
                testList3.Insert(i, number);
            }
            var watch1 = new Stopwatch();
            watch1.Start();
            QuickSortMain.Sort<int>(testList, 0, testList.Count-1, (x, y) => { return x > y; });
            watch1.Stop();
            var customSort = watch1.ElapsedMilliseconds;

            watch1.Reset();
            watch1.Start();
            QuickSortMain.SortUsingTask<int>(testList2, 0, testList2.Count - 1, (x, y) => { return x > y; });
            watch1.Stop();
            var customSort2 = watch1.ElapsedMilliseconds;

            watch1.Reset();
            watch1.Start();
            testList3.Sort();
            watch1.Stop();
            var systemSort = watch1.ElapsedMilliseconds;

            //foreach (var item in testList2)//验证并行计算的快排结果是否正确
            //{
            //    Console.WriteLine(item.ToString());
            //}

            Console.WriteLine("无并行计算版本      Custom1 Sort:" + customSort);//快排,比较方法用了lambda,容器为list<int>
            Console.WriteLine("并行计算版本         Custom2 Sort:" + customSort2);//快排,比较方法用了lambda,容器为list<int>
            Console.WriteLine("C#自带排序方法     System Sort:" + systemSort);//系统自带排序
            Console.ReadLine();
        }
    }
运行结果如下图



可以看到我自己写的快速排序算法在没有使用Task进行并行计算前 速度直接比.net list自带的排序慢了一个数量级,但是用了Task进行并行计算后 自己比list自带排序还要快(窃喜 有种读书时候超越年级第一的感觉)

Task的好处,首先就是Task利用线程池 这点必须和一般的Thread区分开(根本无法想象这边不用线程池而直接用thread开几万个线程会卡到什么程度)

其次这种并行计算必须是在特定条件下才可以使用 这里在这里由于快速排序是分治的思想 所以才可以用Task来进行并行计算

最后。。。.net list自带的sort也不过如此嘛。。。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值