詳解c# PLINQ中的分區(qū)
最近因為比較忙,好久沒有寫博客了,這篇主要給大家分享一下PLINQ中的分區(qū)。上一篇介紹了并行編程,這邊詳細(xì)介紹一下并行編程中的分區(qū)和自定義分區(qū)。
先做個假設(shè),假設(shè)我們有一個200Mb的文本文件需要讀取,怎么樣才能做到最優(yōu)的速度呢?對,很顯然就是拆分,把文本文件拆分成很多個小文件,充分利用我們計算機中的多核cpu的優(yōu)勢,讓每個cpu都充分的利用,達(dá)到效率的最大化。然而在PLINQ中也是,我們有一個數(shù)據(jù)源,如果想進(jìn)行最大的并行化操作,那么就需要把其拆分為可以多個線程同時訪問的多個部分,這就是PLINQ中的分區(qū)。當(dāng)然,微軟已經(jīng)為我們想到了這一點,知道他的用戶可能會有這個需求,所以就先說一下微軟給我們提供的默認(rèn)的一個分區(qū)程序吧。
微軟提供的默認(rèn)的分區(qū)程序又叫做任務(wù)并行庫(TPL),其實就是當(dāng)你用PLINQ的ForEach的時候,默認(rèn)在其內(nèi)部就會給我們進(jìn)行分區(qū)。怎么樣,是不是很方便。不過有時候,你可能會需要自己來進(jìn)行拆分,那么就是另外一種跟高級一點的用法了,就是PLINQ的自定義分區(qū)。自定義分區(qū)有兩種,一種是按照范圍分區(qū),另一種是按照區(qū)塊分區(qū)。其中按照范圍分區(qū)在針對鏈表集合能夠提供非常好的性能,比如IList等,不過它也有一點缺點那就是如果一個線程提前完成,它將無法幫助其他線程完成它們的工作。按照區(qū)塊分區(qū)是當(dāng)我們不知道我們所要操作的集合的大小的時候,可以使用按照區(qū)塊分區(qū),在按區(qū)塊分區(qū)中,并行循環(huán)或查詢中的每個線程或任務(wù)都使用一個區(qū)塊中一定數(shù)量的源元素,對它們進(jìn)行處理,然后返回檢索其他元素。分區(qū)程序可確保分發(fā)所有元素,并且沒有重復(fù)項。區(qū)塊可為任意大小。
通常,只有當(dāng)委托的執(zhí)行時間為較短到中等程度,源具有大量的元素,并且每個分區(qū)的總工作量大致相等時,按范圍分區(qū)的速度才會較快。因此,按區(qū)塊分區(qū)的速度在大多數(shù)情況下較快。對于元素數(shù)量很少或委托執(zhí)行時間較長的源,則按區(qū)塊分區(qū)和按范圍分區(qū)的性能大致相等。
那么我們?nèi)绾螌崿F(xiàn)動態(tài)分區(qū)呢?下面有一個摘自MSDN的示例。
每次分區(qū)對枚舉器調(diào)用 MoveNext 時,枚舉器都會提供包含一個列表元素的分區(qū)。對于 PLINQ 和 ForEach,分區(qū)是一個 Task 實例。由于請求同時在多個線程上發(fā)生,因此對當(dāng)前索引的訪問是同步的。
//
// An orderable dynamic partitioner for lists
//
class OrderableListPartitioner<TSource> : OrderablePartitioner<TSource>
{
private readonly IList<TSource> m_input;
public OrderableListPartitioner(IList<TSource> input)
: base(true, false, true)
{
m_input = input;
}
// Must override to return true.
public override bool SupportsDynamicPartitions
{
get
{
return true;
}
}
public override IList<IEnumerator<KeyValuePair<long, TSource>>>
GetOrderablePartitions(int partitionCount)
{
var dynamicPartitions = GetOrderableDynamicPartitions();
var partitions =
new IEnumerator<KeyValuePair<long, TSource>>[partitionCount];
for (int i = 0; i < partitionCount; i++)
{
partitions[i] = dynamicPartitions.GetEnumerator();
}
return partitions;
}
public override IEnumerable<KeyValuePair<long, TSource>>
GetOrderableDynamicPartitions()
{
return new ListDynamicPartitions(m_input);
}
private class ListDynamicPartitions
: IEnumerable<KeyValuePair<long, TSource>>
{
private IList<TSource> m_input;
private int m_pos = 0;
internal ListDynamicPartitions(IList<TSource> input)
{
m_input = input;
}
public IEnumerator<KeyValuePair<long, TSource>> GetEnumerator()
{
while (true)
{
// Each task gets the next item in the list. The index is
// incremented in a thread-safe manner to avoid races.
int elemIndex = Interlocked.Increment(ref m_pos) - 1;
if (elemIndex >= m_input.Count)
{
yield break;
}
yield return new KeyValuePair<long, TSource>(
elemIndex, m_input[elemIndex]);
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return
((IEnumerable<KeyValuePair<long, TSource>>)this)
.GetEnumerator();
}
}
}
class ConsumerClass
{
static void Main()
{
var nums = Enumerable.Range(0, 10000).ToArray();
OrderableListPartitioner<int> partitioner = new OrderableListPartitioner<int>(nums);
// Use with Parallel.ForEach
Parallel.ForEach(partitioner, (i) => Console.WriteLine(i));
// Use with PLINQ
var query = from num in partitioner.AsParallel()
where num % 2 == 0
select num;
foreach (var v in query)
Console.WriteLine(v);
}
}
這是按區(qū)塊分區(qū)的示例,其中每個區(qū)塊都由一個元素組成。通過一次提供多個元素,您可以減少鎖爭用,并在理論上實現(xiàn)更快的性能。但是,有時較大的區(qū)塊可能需要額外的負(fù)載平衡邏輯才能使所有線程在工作完成之前保持忙碌。
以上就是詳解c# PLINQ中的分區(qū)的詳細(xì)內(nèi)容,更多關(guān)于c# PLINQ中的分區(qū)的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
其實/FileShare就是控制文件流的“訪問權(quán)限”,當(dāng)然,這僅僅是入門的文件操作,自己做了筆記,也希望能給大家?guī)韼椭?/div> 2014-01-01
C#實現(xiàn)win10 uwp 右擊浮出窗在點擊位置
本文主要讓MenuFlyout出現(xiàn)在我們右擊位置。我們建一個ListView,然后綁定后臺,在我們ListView要右擊顯示我們的浮出,要求我們的浮出在我們點擊位置2016-10-10
C#字符串與數(shù)值類型、字節(jié)數(shù)組的互相轉(zhuǎn)換實戰(zhàn)案例
最近由于編程的需要,對C#的類型轉(zhuǎn)換做了一些研究,下面這篇文章主要給大家介紹了關(guān)于C#字符串與數(shù)值類型、字節(jié)數(shù)組的互相轉(zhuǎn)換的相關(guān)資料,文中通過實例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-06-06
C#中DataGridView導(dǎo)出Excel的兩種方法
這篇文章主要介紹了C#中DataGridView導(dǎo)出Excel的兩種方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01最新評論

