淺談.Net并行計(jì)算之?dāng)?shù)據(jù)并行
從第一臺(tái)計(jì)算機(jī)問(wèn)世到現(xiàn)在計(jì)算機(jī)硬件技術(shù)已經(jīng)有了很大的發(fā)展。不管是現(xiàn)在個(gè)人使用的PC還是公司使用的服務(wù)器。雙核,四核,八核的CPU已經(jīng)非常常見(jiàn)。這樣我們可以將我們程序分?jǐn)偟蕉鄠€(gè)計(jì)算機(jī)CPU中去計(jì)算,在過(guò)去并行化需要線程的低級(jí)操作,難度很大,在.net4.0中的增強(qiáng)了對(duì)并行化的支持,使得這一切變得非常簡(jiǎn)單 。本次我從以下幾個(gè)方面大家講以下.NET 并行
1. 數(shù)據(jù)并行
2. 任務(wù)并行
3. 并行Linq
4. 任務(wù)工廠
5. 注意事項(xiàng)
本次主要給大家講一下數(shù)據(jù)并行 廢話不說(shuō),下面開(kāi)始了
數(shù)據(jù)并行其實(shí)就是指對(duì)原集合或者數(shù)組中的數(shù)據(jù)進(jìn)行劃區(qū)之后分?jǐn)偟蕉鄠€(gè)CPU或者多個(gè)線程執(zhí)行相同的操作 在 .net中的 System.Threading.Tasks 提供了對(duì)數(shù)據(jù)并行的支持類 , Parallel.For,Parallel.ForEach和我們經(jīng)常的使用的for 和foreach 十分的相似,你不用創(chuàng)建線程隊(duì)列,在基本的循環(huán)中你不用使用鎖。這些.net 會(huì)幫你處理,你只需要關(guān)注你自己的業(yè)務(wù) 那下面我們就來(lái)看看 Parallel.For 和 Parallel.ForEach 是如何使用的
• Parallel.For 簡(jiǎn)單使用
Parallel.For(0, 100, i => {
dosameting()
});
上面的例子是不是和我們經(jīng)常使用的for循環(huán)的影子。 說(shuō)一下 Parallel.For 的第三個(gè)參數(shù)Action<int>類型的委托 不管這個(gè)委托的參數(shù)是0個(gè)還是多少個(gè)他的返回植都是void,那么怎么樣才能獲取到Parallel.For 中的的返回值了,下面的例子將演示如何使用線程本地變量來(lái)存儲(chǔ)和檢索由 for 循環(huán)創(chuàng)建的每個(gè)單獨(dú)任務(wù)中的狀態(tài) 通過(guò)使用線程本地?cái)?shù)據(jù),您可以避免將大量的訪問(wèn)同步為共享狀態(tài)的開(kāi)銷。 在任務(wù)的所有迭代完成之前,您將計(jì)算和存儲(chǔ)值,而不是寫入每個(gè)迭代上的共享資源。 然后,您可以將最終結(jié)果一次性寫入共享資源,或?qū)⑵鋫鬟f到另一個(gè)方法
•對(duì)個(gè)list<int> 進(jìn)行求和我們這里假設(shè)List的長(zhǎng)度為listLength
Parallel.For<long>(0, listLength, () => 0, (j, loop, subsum) =>
{
subsum += lista[j];
return subsum;
}, (x) => Interlocked.Add(ref sum, x));
•在現(xiàn)實(shí)中我們也經(jīng)常會(huì)遇到需要取消循環(huán)的情況。比如你在隊(duì)列中查找一個(gè)數(shù)。那么如何退出Parallel.For 循環(huán)了。是不是也是和for 和foreach那樣 使用Break關(guān)鍵字就可以了,答案否定的。這是因?yàn)閎reak 構(gòu)造對(duì)循環(huán)是有效的,而并行循環(huán)其實(shí)是一個(gè)方法,并不是循環(huán) 那么要怎么樣取消了。請(qǐng)看下面的例子
Parallel.For<long>(0, listLength, () => 0, (j, loop, subsum) =>
{
if (subsum > 20000)
{
loop.Break();
}
subsum += lista[j];
return subsum;
}, (x) => Interlocked.Add(ref sum, x));
• 簡(jiǎn)單Parallel.ForEach 循環(huán) Parallel.ForEach循環(huán)的工作方式類似于 Parallel.For 循環(huán) 根據(jù)系統(tǒng)環(huán)境,對(duì)源集合進(jìn)行分區(qū),并在多個(gè)線程上計(jì)劃工作。 系統(tǒng)中的處理器越多,并行方法的運(yùn)行速度越快。 對(duì)于某些源集合,順序循環(huán)可能更快,具體取決于源的大小和正在執(zhí)行的工作類型
Parallel.ForEach(lista, i => { dosameting(); });
不知道大家在這個(gè)地方有沒(méi)有看到foreach的影子。其實(shí)上面的例子中的ForEach方法的最后一個(gè)輸入?yún)?shù)是 Action<int>委托,當(dāng)所有循環(huán)完成時(shí),方法將調(diào)用該委托。這個(gè)地方和前面的Parallel.For 是一樣的。那么我們要如何獲得返回值了和上面的For是非常相似,我依然以上面數(shù)組求和為例
Parallel.ForEach<int, long>(lista, () => 0, (j, loop, subsum) =>
{
if (subsum > 20000)
{
loop.Break();
}
subsum += lista[j];
return subsum;
}, (x) => Interlocked.Add(ref sum, x));
• Parallel.For 和for 性能測(cè)試比較 我們這里產(chǎn)生1千萬(wàn)個(gè)隨機(jī)數(shù)為例子做個(gè)一個(gè)性能比較,在筆者的筆記本上結(jié)果如下 (可能在你的電腦上得到結(jié)果不一定相同)
附上相關(guān)的代碼給大家參考
int listLength = 10000000;
List<int> listTask = new List<int>();
List<int> list = new List<int>();
Stopwatch watch1 = Stopwatch.StartNew();
Parallel.For(0, listLength, i => {
Random r = new Random(100);
listTask.Add(r.Next());
});
Console.WriteLine("并行耗時(shí):" + watch1.ElapsedMilliseconds );
Stopwatch watch2 = Stopwatch.StartNew();
for (int i = 0; i < listLength; i++)
{
Random r = new Random(100);
list.Add(r.Next());
}
Console.WriteLine("非并行耗時(shí):" + watch2.ElapsedMilliseconds );
相關(guān)文章
.Net Core+Angular Cli/Angular4開(kāi)發(fā)環(huán)境搭建教程
這篇文章主要為大家詳細(xì)介紹了.Net Core+Angular Cli/Angular4開(kāi)發(fā)環(huán)境搭建教程,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-06-06Asp.net中Response.Charset與Response.ContentEncoding區(qū)別示例分析
這篇文章主要介紹了Asp.net中Response.Charset與Response.ContentEncoding區(qū)別示例分析,對(duì)于深入理解Asp.net程序設(shè)計(jì)有一定的幫助,需要的朋友可以參考下2014-08-08Asp.net 中mvc 實(shí)現(xiàn)超時(shí)彈窗后跳轉(zhuǎn)功能
這篇文章主要介紹了Asp.net 中mvc 實(shí)現(xiàn)超時(shí)彈窗后跳轉(zhuǎn)功能,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2017-02-02ASP.net 動(dòng)態(tài)加載控件時(shí)一些問(wèn)題的總結(jié)
經(jīng)常見(jiàn)到有人說(shuō)在ASP.net中不要使用動(dòng)態(tài)控件,我想主要的原因在于使用動(dòng)態(tài)控件會(huì)帶來(lái)一些問(wèn)題,在做項(xiàng)目的過(guò)程中,我將由動(dòng)態(tài)加載控件引發(fā)的總是作了一個(gè)小小的總結(jié).2009-04-04asp.net使用jQuery獲取RadioButtonList成員選中內(nèi)容和值示例
這篇文章主要介紹了通過(guò)jQuery來(lái)獲取RadioButtonList成員內(nèi)容的方法,大家參考使用吧2014-01-01ASP.NET實(shí)現(xiàn)單點(diǎn)登陸(SSO)適用于多種情況
這篇文章主要介紹了ASP.NET在不同情況下實(shí)現(xiàn)單點(diǎn)登陸(SSO)的方法,在同主域但不同子域之間實(shí)現(xiàn)單點(diǎn)登陸等等2014-09-09ajaxControlToolkit中CascadingDropDown的用法說(shuō)明
今天頭叫寫一個(gè)類似三級(jí)聯(lián)動(dòng)的控件,最好實(shí)現(xiàn)無(wú)刷新,是石油軟件中的一個(gè)數(shù)據(jù),需要表現(xiàn)出類似 X1-22 這樣的格式,上下標(biāo)的數(shù)據(jù)是固定的 想了很多辦法來(lái)表現(xiàn)這個(gè)數(shù)字,最后決定用3個(gè)DropDownList控件2008-11-11