请问如何详细解释C语言编程?

2026-04-27 15:372阅读0评论SEO问题
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计1673个文字,预计阅读时间需要7分钟。

请问如何详细解释C语言编程?

由于时间紧迫,很久没有更新博客了。今天主要想和大家分享一下PLINQ中的分区概念。上一篇文章介绍了并行编程,这篇文章将更详细地介绍并行编程中的分区和自定义分区。

首先,做一个假设:我们有一个包含大量数据的集合,需要对其进行并行处理。为了提高效率,我们可以将数据集合分成多个子集,每个子集由一个或多个线程并行处理。

分区

在PLINQ中,分区是指将数据集合分割成多个子集的过程。这些子集可以由不同的线程并行处理。PLINQ提供了两种分区方式:

1. 默认分区:PLINQ默认使用分区器对数据集合进行分区,将数据均匀地分配到各个线程上。

2.自定义分区:我们可以通过实现一个自定义的分区器来控制数据分区的逻辑。

自定义分区

自定义分区允许我们根据特定的逻辑对数据进行分区。以下是一个简单的自定义分区器的示例:

csharp

请问如何详细解释C语言编程?

public class CustomPartitioner : Partitioner{ public CustomPartitioner(IEnumerable source) : base(source) { }

protected override PartitionerResult GetPartitions() { // 根据特定逻辑进行分区 // ...

return PartitionerResult.Create(partitions); }}

在这个示例中,我们创建了一个`CustomPartitioner`类,它继承自`Partitioner`。在`GetPartitions`方法中,我们可以根据需要实现自定义的分区逻辑。

通过使用自定义分区,我们可以更好地控制数据分区的过程,从而提高并行处理的效率。

  最近因为比较忙,好久没有写博客了,这篇主要给大家分享一下PLINQ中的分区。上一篇介绍了并行编程,这边详细介绍一下并行编程中的分区和自定义分区。

  先做个假设,假设我们有一个200Mb的文本文件需要读取,怎么样才能做到最优的速度呢?对,很显然就是拆分,把文本文件拆分成很多个小文件,充分利用我们计算机中的多核cpu的优势,让每个cpu都充分的利用,达到效率的最大化。然而在PLINQ中也是,我们有一个数据源,如果想进行最大的并行化操作,那么就需要把其拆分为可以多个线程同时访问的多个部分,这就是PLINQ中的分区。当然,微软已经为我们想到了这一点,知道他的用户可能会有这个需求,所以就先说一下微软给我们提供的默认的一个分区程序吧。

  微软提供的默认的分区程序又叫做任务并行库(TPL),其实就是当你用PLINQ的ForEach的时候,默认在其内部就会给我们进行分区。怎么样,是不是很方便。不过有时候,你可能会需要自己来进行拆分,那么就是另外一种跟高级一点的用法了,就是PLINQ的自定义分区。自定义分区有两种,一种是按照范围分区,另一种是按照区块分区。其中按照范围分区在针对链表集合能够提供非常好的性能,比如IList等,不过它也有一点缺点那就是如果一个线程提前完成,它将无法帮助其他线程完成它们的工作。按照区块分区是当我们不知道我们所要操作的集合的大小的时候,可以使用按照区块分区,在按区块分区中,并行循环或查询中的每个线程或任务都使用一个区块中一定数量的源元素,对它们进行处理,然后返回检索其他元素。分区程序可确保分发所有元素,并且没有重复项。区块可为任意大小。

  通常,只有当委托的执行时间为较短到中等程度,源具有大量的元素,并且每个分区的总工作量大致相等时,按范围分区的速度才会较快。因此,按区块分区的速度在大多数情况下较快。对于元素数量很少或委托执行时间较长的源,则按区块分区和按范围分区的性能大致相等。

  那么我们如何实现动态分区呢?下面有一个摘自MSDN的示例。

  每次分区对枚举器调用 MoveNext 时,枚举器都会提供包含一个列表元素的分区。对于 PLINQ 和 ForEach,分区是一个 Task 实例。由于请求同时在多个线程上发生,因此对当前索引的访问是同步的。

// // 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); } }

  这是按区块分区的示例,其中每个区块都由一个元素组成。通过一次提供多个元素,您可以减少锁争用,并在理论上实现更快的性能。但是,有时较大的区块可能需要额外的负载平衡逻辑才能使所有线程在工作完成之前保持忙碌。

以上就是详解c# PLINQ中的分区的详细内容,更多关于c# PLINQ中的分区的资料请关注易盾网络其它相关文章!

本文共计1673个文字,预计阅读时间需要7分钟。

请问如何详细解释C语言编程?

由于时间紧迫,很久没有更新博客了。今天主要想和大家分享一下PLINQ中的分区概念。上一篇文章介绍了并行编程,这篇文章将更详细地介绍并行编程中的分区和自定义分区。

首先,做一个假设:我们有一个包含大量数据的集合,需要对其进行并行处理。为了提高效率,我们可以将数据集合分成多个子集,每个子集由一个或多个线程并行处理。

分区

在PLINQ中,分区是指将数据集合分割成多个子集的过程。这些子集可以由不同的线程并行处理。PLINQ提供了两种分区方式:

1. 默认分区:PLINQ默认使用分区器对数据集合进行分区,将数据均匀地分配到各个线程上。

2.自定义分区:我们可以通过实现一个自定义的分区器来控制数据分区的逻辑。

自定义分区

自定义分区允许我们根据特定的逻辑对数据进行分区。以下是一个简单的自定义分区器的示例:

csharp

请问如何详细解释C语言编程?

public class CustomPartitioner : Partitioner{ public CustomPartitioner(IEnumerable source) : base(source) { }

protected override PartitionerResult GetPartitions() { // 根据特定逻辑进行分区 // ...

return PartitionerResult.Create(partitions); }}

在这个示例中,我们创建了一个`CustomPartitioner`类,它继承自`Partitioner`。在`GetPartitions`方法中,我们可以根据需要实现自定义的分区逻辑。

通过使用自定义分区,我们可以更好地控制数据分区的过程,从而提高并行处理的效率。

  最近因为比较忙,好久没有写博客了,这篇主要给大家分享一下PLINQ中的分区。上一篇介绍了并行编程,这边详细介绍一下并行编程中的分区和自定义分区。

  先做个假设,假设我们有一个200Mb的文本文件需要读取,怎么样才能做到最优的速度呢?对,很显然就是拆分,把文本文件拆分成很多个小文件,充分利用我们计算机中的多核cpu的优势,让每个cpu都充分的利用,达到效率的最大化。然而在PLINQ中也是,我们有一个数据源,如果想进行最大的并行化操作,那么就需要把其拆分为可以多个线程同时访问的多个部分,这就是PLINQ中的分区。当然,微软已经为我们想到了这一点,知道他的用户可能会有这个需求,所以就先说一下微软给我们提供的默认的一个分区程序吧。

  微软提供的默认的分区程序又叫做任务并行库(TPL),其实就是当你用PLINQ的ForEach的时候,默认在其内部就会给我们进行分区。怎么样,是不是很方便。不过有时候,你可能会需要自己来进行拆分,那么就是另外一种跟高级一点的用法了,就是PLINQ的自定义分区。自定义分区有两种,一种是按照范围分区,另一种是按照区块分区。其中按照范围分区在针对链表集合能够提供非常好的性能,比如IList等,不过它也有一点缺点那就是如果一个线程提前完成,它将无法帮助其他线程完成它们的工作。按照区块分区是当我们不知道我们所要操作的集合的大小的时候,可以使用按照区块分区,在按区块分区中,并行循环或查询中的每个线程或任务都使用一个区块中一定数量的源元素,对它们进行处理,然后返回检索其他元素。分区程序可确保分发所有元素,并且没有重复项。区块可为任意大小。

  通常,只有当委托的执行时间为较短到中等程度,源具有大量的元素,并且每个分区的总工作量大致相等时,按范围分区的速度才会较快。因此,按区块分区的速度在大多数情况下较快。对于元素数量很少或委托执行时间较长的源,则按区块分区和按范围分区的性能大致相等。

  那么我们如何实现动态分区呢?下面有一个摘自MSDN的示例。

  每次分区对枚举器调用 MoveNext 时,枚举器都会提供包含一个列表元素的分区。对于 PLINQ 和 ForEach,分区是一个 Task 实例。由于请求同时在多个线程上发生,因此对当前索引的访问是同步的。

// // 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); } }

  这是按区块分区的示例,其中每个区块都由一个元素组成。通过一次提供多个元素,您可以减少锁争用,并在理论上实现更快的性能。但是,有时较大的区块可能需要额外的负载平衡逻辑才能使所有线程在工作完成之前保持忙碌。

以上就是详解c# PLINQ中的分区的详细内容,更多关于c# PLINQ中的分区的资料请关注易盾网络其它相关文章!