如何以缓慢的产出并行化 IEnumerable(这使得 PLINQ 无用)?

How to parallelize an IEnumerable with a slow yield (which renders PLINQ useless)?

我在寻找一种正确并行处理 IEnumerable 的方法时遇到了一些麻烦,其中每个项目的实际生成都需要相当长的时间,因此每次调用都会有效地锁定一点reader 一侧的 MoveNext

这是我的场景:

I have a method that takes an IEnumerable<(float[], float[])> (the specific type doesn't actually matter here), and I need to compute those items, split them into batches of a fixed side, then process every batch.

假设我已经准备好分区代码(参见 this answer here)以及处理每个单独分区的代码。

问题是,正如我所说,从初始列表中生成每个值都涉及一些 IO/CPU 操作(通常会读取图像,处理它并 return 这两个矩阵有),所以即使有:

var items = dataset.AsParallel().Partition(size).ToArray().AsParallel().Select(partition =>
{
    // Process the partitions here..
    return partition;
}).ToArray(); // Two AsParallel calls because I'm doing two selections one after the other

我使用了大约 25% CPU(我有一个 8 核 AMD FX-8350),因为我猜这是第一个列表中项目的实际生成导致枚举变慢,甚至在开始第一个 AsParallel 电话之前。

我在想一个可能的解决方案是要求此方法的用户提供一个 IEnumerable<Func<(float[], float[])>>,因为这将使我的方法能够轻松地并行处理这些元素。

我的问题是:这是唯一可能的解决方案,还是有另一种方法可以并行枚举 "locking" IEnumerable,而不会导致每个项目的产生不是并行的?

谢谢!

编辑:澄清一下,我不是在第一个 IEnumerable 中编写实际代码,这取决于相关图书馆的用户,它将输入自己的 IEnumerable 以便图书馆分成批次并继续工作。 我希望有替代 Func 委托的原因之一是,在用户方面,仅 returning 一个元组比必须显式 return 更容易和更直观 return 一个懒惰地计算整个事情的函数。

恐怕你不能。如果最初的 IEnumerable 很慢,那么无论您在并行化和处理能力方面使用多少资源,都无法作为第二步来使其更快。最好的情况是您添加的越少越好。但是还是很慢。

解决方案是看看是否可以通过任何方式加快原始的初始序列。