Julia Grabovska
Julia Grabovska

Reputation: 161

Threads for variables initialized in loop

I'd like to run method Polygonise parallel for cells (they are independent). How to create threads for cells if it is initialized in loop?

  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);
      }
  }

ADDED: I wish to pass it to GPU thus Parallel.For and PLinq aren't appropriate. The problem is: it performs a long while because there are many computations in Poligonise method and there are many rows and columns (loop params). The operations in the method are nearly fast, but the loop for this is time-consuming. I need logic of multithreading in this.

Upvotes: 1

Views: 199

Answers (3)

Mong Zhu
Mong Zhu

Reputation: 23732

The straight forward answer would be create them where you need them and start them there:

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();
    }
}

Disclaimer: I don't know what Triangles is and how you might change it in your method , so it might be not wise to allow many Threads to change the same variable in an unordered fashion.

Upvotes: 0

Dmitrii Bychenko
Dmitrii Bychenko

Reputation: 186843

You can try either Parallels:

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);
    }   
});

or PLinq (Parallel Linq):

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);
       } 
   });

In both cases, please, think over which should be parallelized Columns or Rows

Upvotes: 4

Ivan Kishchenko
Ivan Kishchenko

Reputation: 815

You can use collection of Tasks. It's best alternative of threads.

        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());

But you have to be careful. Capture of variables does not always work the way you expect it. (Literature)

Upvotes: -1

Related Questions