2017-02-22 50 views
1

Я хотел бы запустить метод Полигонизм параллельный для ячеек (они независимы). Как создать потоки для ячеек, если они инициализированы в цикле?Темы для переменных, инициализированных в цикле

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

ДОБАВЛЕНО: Я хотел бы передать его в ГПУ, таким образом, Parallel.For и PLINQ не подходят. Проблема в том, что она длится долго, потому что существует множество вычислений в методе Poligonise и есть много строк и столбцов (параметры цикла). Операции в методе работают очень быстро, но цикл для этого занимает много времени. Мне нужна логика многопоточности в этом.

+3

'Parallel.For'? Параллельный Linq (* Plinq *)? –

+0

@DmitryBychenko Я хочу передать его на GPU с Cudafy, таким образом Parallel.For и PLinq не подходят. Проблема состоит в том, чтобы сделать параллельную (возможно) архитектуру для цикла с вычислениями. Он выполняется долго, потому что в методе Poligonise имеется много вычислений. –

+0

Я имею в виду, мне нужна логика многопоточности, подходящая здесь –

ответ

-1

Вы можете использовать коллекцию Заданий. Это лучшая альтернатива нитей.

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

Но вы должны быть осторожны. Захват переменных не всегда работает так, как вы ожидаете. (Literature)

+2

Если вы предлагаете реализацию 'Task', вы, вероятно, имеете в виду' await Task.WhenAll (tasks); 'чтобы не блокировать пользовательский интерфейс (главное преимущество использования' Task') –

+0

Может быть так. Это зависит от реализации. –

+2

'Task.Factory.StartNew' следует избегать,' Task.Run'. см. http://blog.stephencleary.com/2015/03/a-tour-of-task-part-9-delegate-tasks.html для dfetailes –

0

Прямой вперед ответ будет создавать их там, где вы нуждаетесь в них, и начать их там:

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

Отказ от ответственности: Я не знаю, что Triangles и как вы можете изменить его в вашем методе , поэтому было бы неразумно позволять многим Threads изменять одну и ту же переменную неупорядоченным образом.

+0

Это всего лишь один поток для прохода одного цикла, не так ли? ? P.S. Треугольники для ячеек. Они тоже независимы. Все нормально. –

+0

@JuliaGrabovska Да для каждой итерации он создает нить. Это очень много, если у вас большая матрица. Я не могу сказать, действительно ли это улучшение. Вы должны сами измерить производительность.В конце концов у вас будет (RowCount - 1) * (ColumnCount - 1) Threads –

4

Вы можете попробовать либо Parallel 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); 
    } 
}); 

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

В обоих случаях, пожалуйста, подумайте над которым следует распараллеленные Columns или Rows

+0

Неверный пример, потому что вы начинаете параллельную только часть методов «Polygonise». –

+2

@ Иван Кищенко: слишком много потоков (например, поток на ячейку) часто означают большие * накладные расходы *; Поскольку ЦП имеет ограниченное количество ядер ('2-32'), лучшей политикой является создание/получение от вытягивания * ограниченного количества потоков (например, потока на строку или столбца). Не переусердствуйте *. Исключение составляет GPU (например, NVidia 'Cuda') (графические процессоры часто имеют 1000+ ядер) –

+0

Современные процессоры могут эффективно распараллелить задачи. Откройте диспетчер задач и посмотрите, сколько процессов. И сколько потоков содержит какой-либо процесс? –