首页 文章详情

C# 多线程 Parallel.For 和 For 谁的效率高?那么 Parallel.ForEach 和 ...

llovebo | 263 2022-01-31 03:29 0 0 0
UniSMS (合一短信)

今天和大家探讨一个问题:Parallel.For 和 For 谁的效率高呢?

从CPU使用方面而言,Parallel.For 属于多线程范畴,可以开辟多个线程使用CPU内核,也就是说可以并行处理程序。For 循环是单线程的,一个线程执行完所有循环。

因此你会认为:多线程的效率肯定高于单线程。但这样认为是错误的!

例如下面程序:

static void Main(string[] args)        {            Stopwatch sw = new Stopwatch();            sw.Start();
ParallelLoopResult result = Parallel.For(0, 10000, i => { Console.Write("");
}); sw.Stop(); TimeSpan ts2 = sw.Elapsed; Console.WriteLine("Parallel.For总共花费{0}ms.", ts2.TotalMilliseconds);
// Stopwatch sw_Eq = new Stopwatch(); sw_Eq.Start(); for (int i = 0; i < 10000; i++) { Console.Write(""); } sw_Eq.Stop(); TimeSpan tssw_Eq = sw_Eq.Elapsed; Console.WriteLine("for总共花费{0}ms.", tssw_Eq.TotalMilliseconds); Console.ReadKey();        }

f6c96b4ea207044a40e79b8fded496ef.webp

额,为什么For 循环要比Parallel.For 效率要高呢?

这是因为循环体内执行的任务开销太小,仅仅是输出一个空字符串而已。微软的文章已经指出任务的开销大小对并行任务的影响。如果任务很小,那么由于并行管理的附加开销(任务分配,调度,同步等成本),可能并行执行并不是优化方案。这也是上述程序For效率高出的原因。

如果在循环体内执行向数据库插入操作,那么Parallel.For 效率就会高出,在此,我们认为每向数据库插入一条记录花费1毫秒时间,将程序修改如下:


class Program { static void Main(string[] args) { Stopwatch sw = new Stopwatch(); sw.Start();
ParallelLoopResult result = Parallel.For(0, 10, i => { Console.Write(""); Thread.Sleep(1);
}); sw.Stop(); TimeSpan ts2 = sw.Elapsed; Console.WriteLine("Parallel.For总共花费{0}ms.", ts2.TotalMilliseconds);
// Stopwatch sw_Eq = new Stopwatch(); sw_Eq.Start(); for (int i = 0; i < 10; i++) { Console.Write(""); Thread.Sleep(1); } sw_Eq.Stop(); TimeSpan tssw_Eq = sw_Eq.Elapsed; Console.WriteLine("for总共花费{0}ms.", tssw_Eq.TotalMilliseconds); Console.ReadKey(); } }}


执行结果大大改变:

00a9c194fc95003d2a49f340cb051c41.webp

相信到此,大家应该明白了吧!也就说For是同步,Parallel.For 是异步执行。当然,我们也可以使用Thread实现异步编程:

代码如下:

  class Program    {        static void Main(string[] args)        {            Console.WriteLine("主线程测试开始..");            Thread th = new Thread(ThMethod);            th.Start();            Thread.Sleep(1000);            Console.WriteLine("主线程测试结束..");            Console.ReadLine();        }

static void ThMethod() { Console.WriteLine("异步执行开始"); for (int i = 0; i < 5; i++) { Console.WriteLine("异步执行" + i.ToString() + ".."); Thread.Sleep(1000); } Console.WriteLine("异步执行完成"); } }


Parallel.ForEach 和 ForEach  与 Parallel.For 和 For 一样,一个是异步执行,开辟多个线程。一个是同步执行,开辟一个线程。因此,效率方面同上,主要看执行的什么任务,在此不作具体说明。

下面写了一些代码,从下面的代码中我们可以看出Parallel.ForEach具体开辟了几个线程,如下:


class Program { static void Main(string[] args) { int[] intList = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; ParallelLoopResult result = Parallel.ForEach(intList, (s,pls,longs) => { Console.WriteLine(longs + " " + s); pls.Stop(); if (pls.IsStopped) { Parallel.Invoke(Gs,Ks);//异步调用多个方法 } }); Console.ReadKey(); }
public static void Gs() { Console.WriteLine("异步方法1"); }
public static void Ks() { Console.WriteLine("异步方法2"); } }


上述代码中,调用了Stop()方法,我们都知道,如果是同步执行的,调用Stop()后,会立即停止执行,那么程序只会输出索引值为0的结果。而在异步中不是这样的,异步迭代是多线程且没有顺序的。其执行结果如下:

多次执行的结果可能不同。

7ed7105f000a7e92dc683bae827f03f9.webp

cb06f7c235eb7a9b60a492c64023fa8e.webp

如上图所示,第一个图开辟了三个线程,执行顺序为 0 2 1,第二个图开辟了两个线程,执行顺序为:1 0 

下面的Invoke()方法是异步调用其他的方法,在此不作解释,可参考C# Invoke()

设置开启的线程的个数:

  Parallel.ForEach(NameArray,new ParallelOptions{MaxDegreeOfParallelism=3},(item,pls,i)=>            {           });

出处:https://www.cnblogs.com/chenwolong/p/ParallelFor.html


版权申明:本文来源于网友收集或网友投稿,仅供学习交流之用,如果有侵权,请转告版主或者留言,本公众号立即删除。


支持小微:

腾讯云 新年活动!玩服务器的可以搞搞,老客户也可以参加!

轻量服务器  2核4G8M80G 222元/3年  

爆款1核2G云服务器首年38元  

链接:https://curl.qcloud.com/bR8ycXZa


右下角,您点一下在看图片59b2e537fb8b4dafdff75e65d1778068.webp

小微工资涨1毛

商务合作QQ:185601686


359fa136cfe2e803576f8a19d4d6398e.webp


good-icon 0
favorite-icon 0
收藏
回复数量: 0
    暂无评论~~
    Ctrl+Enter