【问题标题】:How to parallelize method for creating a List and track each element position/index in C#如何并行化创建列表的方法并在 C# 中跟踪每个元素的位置/索引
【发布时间】:2021-12-24 20:37:04
【问题描述】:

我有一个方法可以在一个循环中创建 1000 个表面并将它们存储在列表中:

List<Surface> surfaces = new List<Surface>();
for (int i = 0; i < 1000; i++){
    Surface surface = builder.buildSurface(int length, int width, new Position (x, y, z);
    surfaces.Add(surface);
    x +=2; y+= 4, z++;    // each surface is shifted every iteration
}

当所有表面都生成后,我可以按任何特定顺序输出它们,例如以矩阵形式 A[i][j]。

如何并行创建表面和跟踪位置/索引?我认为每个表面创建可以并行执行,但我想知道它是根据表面位置输出的索引。

是否可以创建一个 TheadPool 来并行生成 1000 个表面并将它们存储在 ConcurrentDictionary() 中以便我可以按特定顺序输出它们?

附:我试图用 Parallel.Invoke 将方法分成两半:

 Parallel.Invoke(
                  () => builder.buildLeft(),
                  () => builder.buildRight());

所以执行时间减少了将近 2 倍,但我想利用 CPU 的所有内核来完成这样耗时的任务。

【问题讨论】:

  • 我猜你要找的是Parallel.ForEachParallel.For。但是,您必须以某种方式准备 xyz
  • Parallel.For 会起作用,但它会以随机顺序生成表面,而我会随着每次迭代从 0 到 1000 逐渐改变 Position(x,y,z)。

标签: c# multithreading concurrency parallel-processing task-parallel-library


【解决方案1】:

你可以把 PLINQ(并行 linq)当傻逼

var surfaces = ParallelEnumerable.Range(0,1000)
                    .AsOrdered()
                    .Select(i=>builder.buildSurface(
                            length, width,
                            new Position (i*2, i*4, i)))
                    .ToList();

此示例假定 x, y, z 值与项目索引 i 连接为 x=i*2, y=i*4, z=i。如果您需要一些不同的 x, y, z 计算方法,那么您可能需要在调用 PLINQ 之前单独准备包含此类数据的集合。

请注意上面的AsOrdered() 调用 - 它告诉 PLINQ 在构建输出列表时保留顺序,但这种保留不是免费的。因此,如果您确实不需要确切的项目 List,但任何具有指定索引/键的存储都可以,您可以尝试使用 Dictionary 而不是 List 的无序 PLINQ

 var surfaces = ParallelEnumerable.Range(0,1000)
                    .ToDictionary(i=>i, i=>builder.buildSurface(
                            length, width,
                            new Position (i*2, i*4, i)));

我不知道,哪个变种会更快,但您可以在做出决定之前自己进行测试。

【讨论】:

  • 强调最后一部分。 PLINQ 有时会很慢
猜你喜欢
  • 1970-01-01
  • 2019-12-07
  • 2013-06-28
  • 2012-06-27
  • 1970-01-01
  • 2020-06-22
  • 2011-05-25
  • 2015-06-18
  • 2015-04-16
相关资源
最近更新 更多