PLINQ查询中的线程索引?

时间:2010-11-02 12:25:01

标签: c# .net plinq

是否可以将PLINQ查询的线程“索引”传递给其中一个运算符,如Select?

背景是我有一个PLINQ查询进行一些反序列化,反序列化方法使用一个结构(可能是一个数组)将数据传递给另一个方法:

      ParallelEnumerable.Range(0, nrObjects)
        .WithDegreeOfParallelism(8)
        .Select(i => this.Deserialize(serializer, i, arrays[threadIndex]))
        .ToList();

(threadIndex是我想要的新变量)

如果我知道线程索引,我可以预先创建8个这些数组(即使所有数组都可能没有使用)并重用它们。反序列化方法可能会被调用数百万次,因此每个小优化都会计算在内。

3 个答案:

答案 0 :(得分:1)

重新线程索引;请注意,并行度是(IIRC)仅使用最大线程数;它不 使用该号码。以您描述的方式依赖threadIndex似乎意味着您实际只能访问arrays[0]。所以简而言之,不:我不这么认为。

可以获取索引;所以,如果这就是你的意思,那就简单地说:

.Select((value, itemIndex) => this.Deserialize(
     serializer, i, arrays[itemIndex])).ToList();

听起来像(评论),意图是获得工作缓冲区;在这种情况下,我会(实际上,)在容器中保留一些方便的缓冲区(具有同步访问等),即

  • 尝试从容器中获取现有缓冲区(已同步)
  • 如果找不到,请创建一个新缓冲区
  • (做好工作)
  • 向容器返回/添加缓冲区(已同步)

这通常非常快(比每次迭代的缓冲区分配快得多)

答案 1 :(得分:0)

您可以创建ConcurrentBag个整数,然后在将deserealization用作索引之前取出它,然后返回。每个线程一次占用一个数组元素。

考虑使用Parallel class。在阵列方面更合适。如果您使用Select,则ParallelEnumerable的索引版本存在限制(不是在您的情况下,但要谨慎)

答案 2 :(得分:0)

我建议使用Parallel.ForEach which offers an overload that allows you to allocate (and cleanup) locals,它将一次传递到循环的一个并行实例中。我已经使用这种方法处理大量图像数据,其中我需要缓冲区来处理该过程的各个步骤。