1

有没有办法将 PLINQ 查询的线程“索引”传递给它的一个运算符,比如 Select?

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

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

(threadIndex 是我想要的新变量)

如果我知道线程索引,我可以预先创建 8 个这样的数组(即使可能不使用所有数组)并重用它们。反序列化方法可能会被调用数百万次,所以每一个小的优化都很重要。

4

3 回答 3

1

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

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

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

听起来(评论)的目的是为了获得一个工作缓冲区;在这种情况下,我会(并且确实)在容器中保留一些方便的缓冲区(具有同步访问等),即

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

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

于 2010-11-02T12:27:38.920 回答
0

您可以创建ConcurrentBag整数,然后在取消实现之前从中获取整数用作索引,然后在之后返回。每个线程一次将占用一个数组元素。

考虑使用Parallel 类。当涉及到数组时,它更合适。Select如果您使用的索引版本有限制ParallelEnumerable(不是您的情况,但要小心)

于 2010-11-02T12:38:27.973 回答
0

我建议使用Parallel.ForEach,它提供了一个重载,允许您分配(和清理)将一次传递到循环的一个并行实例中的局部变量。我已经使用这种方法来处理大量图像数据集,其中我需要缓冲区用于处理的各个步骤。

于 2010-11-07T16:07:39.490 回答