C# 在循环中初始化变量的线程

C# 在循环中初始化变量的线程,c#,.net,multithreading,parallel-processing,C#,.net,Multithreading,Parallel Processing,我想为细胞运行Polygonise并行方法(它们是独立的)。 如果单元在循环中初始化,如何为其创建线程 for (int j = 0; j < RowCount - 1; j++) { for (int k = 0; k < ColumnCount - 1; k++) { GridCell currentCell = GetCurrentCell (Slice1, Slice2, j, k); Polygonis

我想为细胞运行Polygonise并行方法(它们是独立的)。 如果单元在循环中初始化,如何为其创建线程

  for (int j = 0; j < RowCount - 1; j++)
  {
      for (int k = 0; k < ColumnCount - 1; k++)
      {
          GridCell currentCell = GetCurrentCell (Slice1, Slice2, j, k);
          Polygonise (ref Triangles, int isoLevel, GridCell currentCell);
      }
  }
for(int j=0;j

添加了:我希望将其传递给GPU,因此并行。For和PLinq不合适。问题是:由于Poligonise方法中有许多计算,并且有许多行和列(循环参数),所以执行时间很长。该方法中的操作几乎是快速的,但为此进行的循环非常耗时。在这方面我需要多线程逻辑。

您可以使用任务集合。 这是线程的最佳选择

        List<Task> tasks = new List<Task>();
        for (int j = 0; j < RowCount - 1; j++)
        {
            for (int k = 0; k < ColumnCount - 1; k++)
            {
                GridCell currentCell = GetCurrentCell(Slice1, Slice2, j, k);

                // Start a new Task and add it to collection
                tasks.Add(Task.Factory.StartNew(() => 
                {
                    Polygonise(ref Triangles, isoLevel, currentCell);
                }));
            }
        }

        // Waiting for the completion of all tasks
        Task.WaitAll(tasks.ToArray());
List tasks=newlist();
对于(int j=0;j
{
Polygonise(参考三角形、等值线、currentCell);
}));
}
}
//等待所有任务的完成
Task.WaitAll(tasks.ToArray());

但是你必须小心。变量的捕获并不总是按照您期望的方式工作。()

直截了当的答案是在需要的地方创建它们,然后从那里开始:

for (int j = 0; j < RowCount - 1; j++)
{
    for (int k = 0; k < ColumnCount - 1; k++)
    {
        GridCell currentCell = GetCurrentCell (Slice1, Slice2, j, k);
        System.Threading.Thread t = new System.Threading.Thread(()=>
        Polygonise (ref Triangles, isoLevel, currentCell));
        t.Start();
    }
}
for(int j=0;j
Polygonise(参考三角形、等值线、currentCell));
t、 Start();
}
}

免责声明:我不知道什么是
三角形,也不知道如何在方法中更改它,因此允许多个线程以无序方式更改同一变量可能是不明智的。

您可以尝试
并行
s:

Parallel.For(0, RowCount, (j) => 
{
    for (int k = 0; k < ColumnCount - 1; k++)
    {
        GridCell currentCell = GetCurrentCell (Slice1, Slice2, j, k);
        // Beware! Possible race condition: 
        // "ref Triangles" is shared reference between threads. 
        Polygonise (ref Triangles, int isoLevel, GridCell currentCell);
    }   
});
Parallel.For(0,行计数,(j)=>
{
for(int k=0;k
或PLinq(平行Linq):

可枚举
.范围(0,行计数)
.天冬酰胺()
//.平行度(4)//{
for(int k=0;k

在这两种情况下,请考虑哪一种应该并行化

并行化。对于
?并行Linq(Plinq)?@DmitryBychenko我希望将其与Cudafy一起传递给GPU,因此是并行的。因为和Plinq不合适。问题是要为带有计算的循环建立并行(可能)体系结构。因为Poligonise方法中有很多计算,所以执行时间很长。我的意思是我需要适当的多线程逻辑here@JuliaGrabovska您将使用哪个库/方法将其传递到GPU,以及以何种方式传递?我认为最合适的答案取决于你将如何做到这一点。如果你想使用GPU(比如Cudafy),你必须在GPU上实现
Polygonise
:你将网格(或其中的一部分)传递给GPU,在GPU上执行
Polygonise
,然后读取结果。在GPU上实现
Polygonise
可能是主要的麻烦。坏例子,因为你只启动了部分“Polygonise”方法的并行。@Ivan Kishchenko:太多线程(例如每个单元一个线程)通常意味着巨大的开销;由于CPU的内核数量有限(
2-32
),因此更好的策略是创建/获取有限数量的线程(例如,每行或每列一个线程)。不要过度聚合。GPU(例如NVidia
Cuda
)是例外(GPU通常有1000多个内核),现代处理器能够有效地并行任务。请打开tasks manager并查看有多少个进程。有多少线程包含一个进程?@Ivan Kishchenko:几乎所有这些线程都在等待;为任务启动线程是一种常见做法(任务并行)-拼写检查程序有自己的线程,internet更新检查程序有自己的线程等。但是您提出了太多同时工作的线程,这是一种糟糕的设计。想象一下,我们必须执行100x100个网格-10000个线程?每个线程都有1-8MB的堆栈(x86-IA64),我建议使用“任务”而不是“线程”任务的机制只启动“线程”的有效计数,而其余线程将等待它们的队列。如果您建议
任务
实现,您的意思可能是
等待任务。当所有(任务);
时,为了不阻塞UI(使用
任务
的主要优点)可能是这样的。这取决于实现。
Task.Factory.StartNew
应该避免,
Task.Run
。请参阅dfetaile这只是一个线程用于一个循环的通道,不是吗?P.s.三角形是用于单元格的。它们也是独立的。这没关系。@JuliaGrabovska是的,每次迭代它都会创建一个线程。如果你有一个big矩阵。我不能说这是否真的是一个改进。你必须自己测量性能。最终你会有(RowCount-1)*(ColumnCount-1)个线程
Enumerable
  .Range(0, RowCount)
  .AsParallel()
  // .WithDegreeOfParallelism(4) // <- if you want to tune PLinq
  .ForAll(j => {
       for (int k = 0; k < ColumnCount - 1; k++)
       {
           GridCell currentCell = GetCurrentCell (Slice1, Slice2, j, k);
           // Beware! Possible race condition: 
           // "ref Triangles" is shared reference between threads. 
           Polygonise (ref Triangles, int isoLevel, GridCell currentCell);
       } 
   });