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

xboxeer 2014-10-20 11:01:55
加精
昨天研究了下利用不同容器实现快排算法(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;

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也不过如此嘛。。。。
顺便。。。这种方式肯定是要在多核的机器上才有效果。。不过现在应该没有不是多核的机器了吧。。。。

欢迎拍砖
...全文
3874 56 打赏 收藏 转发到动态 举报
写回复
用AI写文章
56 条回复
切换为时间正序
请发表友善的回复…
发表回复
xiaogui340 2014-11-02
  • 打赏
  • 举报
回复
关注一下
qq_22856789 2014-11-02
  • 打赏
  • 举报
回复
gaoxg17 2014-10-31
  • 打赏
  • 举报
回复
之前研究过Task,本以为这东西很牛,但是测试发现性能没什么提升。。。
比尔咔咔 2014-10-29
  • 打赏
  • 举报
回复
你这测试结果确实如 sp1234 所说,都没结束你就Print了 并行我在一次处理图片时实际使用过,近千张图片图片排版切割画线,性能不错,没用多线程方法居然会内存溢出。。。 使用Task就没溢出这Bug了。
xieyu1995 2014-10-27
  • 打赏
  • 举报
回复
不错不错。说的很好啊
skyw941 2014-10-27
  • 打赏
  • 举报
回复
单核一样可以多线程
ayun00 2014-10-27
  • 打赏
  • 举报
回复
马克一下!
天边的星星 2014-10-26
  • 打赏
  • 举报
回复
马克一下!
足球中国 2014-10-25
  • 打赏
  • 举报
回复
Intel 系列 CPU 流水线技术的发展与展望 流水线技术是指在程序执行时多条指令重叠进行操作的一种准并行处理实 现技术。在计算机中,把一个重复的过程分解为若干子过程,每个子过程由专门 的功能部件来实现。将多个处理过程在时间上错开,依次通过各功能段,这样, 每个子过程就可以与其他子过程并行进行。其中,流水线中的每个子过程及其功 能部件称为流水线的级或段, 段与段相互连接形成流水线。流水线的段数称为流 水线的深度。把流水线技术应用于指令的解释执行过程,就形成了指令流水线。 其中可以把指令的执行过程分为取指令、译码、执行、存结果 4 个子过程。把流 水线技术应用于运算的执行过程,就形成了运算操作流水线,也称为部件级流水 线。 Inter Pentium 系列中采用的流水线技术 流水线技术早在 Intel 的 X86 芯片中均得到了实现。而 Pentium 系列 CPU 产 品更是一个高级的超标量处理器。 奔腾处理器可以在一个时钟周期内完成两条指 令, 一个流水线完成一条指令。 具有 MMX 技术的奔腾处理器为整型流水线增加了 一个额外的处理阶段。在 486 芯片中,一条指令一般被划分为五个标准的部分, 奔腾亦是如此,而在 P6 中,由于采用了近似于 RISC 的技术,一条指令被划分成 了创纪录的十四个阶段,这极大地提高了流水线的速度。P6 系列处理器使用动 态执行结构, 该结构通过硬件寄存器重命名和分支预测的方法,将乱序执行和推 测执行合成在一起。奔腾Ⅲ处理器使用了 P6 中的动态执行技术,增加了超标量 双流水线结构、分支预测技术、通过乱序来优化指令流水线、将指令划分为更细 的阶段。而奔腾Ⅳ新增的技术有使用高级动态执行、执行跟踪缓存、快速执行引 擎、超长管道处理技术、超线程技术。它基本的指令流水线长度达到了 20 级, 更长的流水线可以使处理器运行在更高的主频下,从而提高处理器的性能,但有 可能带来一些指令执行上的延迟。 提高流水线性能的方法及相关技术 从不同的角度和观点,可以把流水线分成多种不同的种类。按照流水线所完 成的功能来分, 可以分为单功能流水线和多功能流水线。按照同一时间段内各段 之间的连接方式来对多功能流水线进一步的分类, 可以分成静态流水线和动态流 水线。若是按照流水的级别来分类,则可以分成部件级、处理机级和处理机间流 水线。 若按照流水线中是否有回馈回路来分,又可以分为线性流水线和非线性流 水线。按照任务流入和流出的顺序是否相同可以分为顺序流水线和乱序流水线。 衡量一个流水线性能的主要指标有吞吐率、加速比和效率
liuxiaogen2008 2014-10-24
  • 打赏
  • 举报
回复
程序非常皮奥利奥。漂亮的好啊
inmyrealm 2014-10-23
  • 打赏
  • 举报
回复
看各种解法吧~
  • 打赏
  • 举报
回复
只代表了开始,并不代表结束 居然说非法字符,继续测试
  • 打赏
  • 举报
回复
代表代表代表,测试代表是否非法字符
  • 打赏
  • 举报
回复
Task.Start并不是真的完成了,就跟delegate.BeginInvoke()一样 开始了,没结束。。。
qq206115678 2014-10-23
  • 打赏
  • 举报
回复
看各种解法吧~
vbfool 2014-10-23
  • 打赏
  • 举报
回复
引用 27 楼 z81434362 的回复:
我测试了一下 话说 “C#自带排序方法” 为什么那么快 和“无并行计算版本”不同,“C#自带排序方法”是真排完了
内置排序使用的就是快速排序算法,而且是直接操作内存的,.NET库在这些基础方法上花了不少心思。
xiaoxujava123 2014-10-22
  • 打赏
  • 举报
回复
不错不错!!!
反过来 2014-10-22
  • 打赏
  • 举报
回复
很好很好很好
五更琉璃 2014-10-22
  • 打赏
  • 举报
回复
我测试了一下 话说 “C#自带排序方法” 为什么那么快 和“无并行计算版本”不同,“C#自带排序方法”是真排完了
醒道 2014-10-22
  • 打赏
  • 举报
回复
写的不错啊~
加载更多回复(26)

13,190

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 分析与设计
社区管理员
  • 分析与设计社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧