C# 在循环中初始化变量的线程
我想为细胞运行Polygonise并行方法(它们是独立的)。 如果单元在循环中初始化,如何为其创建线程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
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(例如NVidiaCuda
)是例外(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);
}
});