2016-02-19 2 views
4

Как я могу проверить, что n методов выполняются параллельно?Как проверить, что n методов выполняются параллельно?

Parallel.For(0, 10, i => DoSomething(i)); 

... 

void DoSomething(int par) 
{ 
    Console.WriteLine($"Test: {par}"); 
} 

Есть ли тест, который может убедить меня, что DoSomething не выполняется последовательно (Если Console.WriteLine не хороший тест, что может быть очень простой функциональный тест?)

+0

Сделать одну из задач более длинной, например 'if (par == 1) Thread.Sleep (1000); Console.Write .... ' –

+2

Вы можете попытаться преднамеренно создать условие гонки и посмотреть, если это произойдет. –

+0

Почему вы не пытаетесь напечатать 'Текущее время'? – Adheep

ответ

5

В вашем примере методы будут определенно последовательными, потому что консоль .NET будет synchronize calls from different threads.

Вы можете, однако, проверить идентификатор потока, на котором выполняется метод с использованием Thread.ManagedThreadID или Environment.CurrentManagedThreadId (для .NET 4,5)

class Program 
{ 
    static void Main(string[] args) 
    { 
     // first run with default number of threads 
     Parallel.For(0, 10, i => DoSomething(i)); 
     Console.ReadLine(); 

     // now run with fewer threads... 
     Parallel.For(0, 10, new ParallelOptions{ 
            MaxDegreeOfParallelism = 2 
           }, i => DoSomething(i)); 
     Console.ReadLine(); 
    } 

    static void DoSomething(int par) 
    { 
     int i = Environment.CurrentManagedThreadId; 
     // int i = Thread.ManagedThreadId; -- .NET 4.0 and under 
     Thread.Sleep(200); 
     Console.WriteLine("Test: "+ par.ToString() + 
          ", Thread :" + i.ToString()); 
    } 
} 

Если вы запустите это без Thread.Sleep вы заметите, что только несколько потоков будет использоваться, поскольку вызов будет завершен достаточно быстро, чтобы поток был возвращен в пул вовремя, чтобы получить следующее задание, которое распределяется по очереди.

Добавление сна будет задерживать поток (имитирующий работу) достаточно долго, чтобы в потоковом потоке было больше источников потоков, чтобы своевременно выработать задание.

При параллельном выполнении любой задачи легко проверить, что задачи, по сути, выполняются в отдельных потоках. Однако, независимо от того, получаете ли вы выгоду от производительности, это будет зависеть от того, насколько эффективно эти потоки могут работать. Как вы видели, некоторые операции вызывают конкуренцию на общем ресурсе (например, запись на консоль) и могут препятствовать одновременной работе многих потоков.

Другими источниками разногласий могут быть, например, выделение памяти - если ваши потоки распределяют и выделяют память, то они могут потратить много времени на ожидание своей очереди с менеджером памяти. Это ограничит реальную степень параллелизма, которую вы достигнете.

0

Не уверен, что я понял, что вы хотите сделать. Вы можете просто посчитать их.

Parallel.For(0, 10, i => DoSomething(i)); 

... 

private static int parallelCounter = 0; 
private static object counterLockObject = new Object(); 
void DoSomething(int par) 
{ 
    int myCounter; 
    lock(counterLockObject) 
    { 
     myCounter = ++parallelCounter; 
    } 
    try 
    { 
     // you probably need something that takes more time to 
     // see anything executing in parallel 
     Console.WriteLine("Current number of parallel threads: {0}", myCounter); 
    } 
    finally 
    { 
     lock(counterLockObject) 
     { 
      parallelCounter--; 
     }   
    } 
} 
+2

Зачем вытаскивать блокировку, когда вы можете «Блокировать. Инкремент» и «Блокировка. Тогда достаточно одного поля 'int'. –

+0

Не имеет значения, не так ли? –

+0

Выбор правильного инструмента для работы не * действительно * имеет значение - пока это не произойдет. В ответ ничего нет, но если есть лучший способ сделать что-то, стоит упомянуть (а здесь «лучше» можно объективно количественно определить количество полей и инструкций). –

1

Вы можете проверить, сколько методы выполнения в Параллели со следующим кодом:

using System; 
using System.Threading; 
using System.Threading.Tasks; 

namespace ParallelMethodsCounter 
{ 
    class Program 
    { 
     public static int _parallelCounter = 0; 
     public static int _maxParallelExecutionsCount = 0; 

     static void Main(string[] args) 
     { 
      Parallel.For(0, 10, i => DoSomething(i)); 
      Console.WriteLine("MAX PARALLEL EXECUTIONS: {0}", _maxParallelExecutionsCount); 
     } 

     public static void DoSomething(int par) 
     { 
      int currentParallelExecutionsCount = Interlocked.Increment(ref _parallelCounter); 
      InterlockedExchangeIfGreaterThan(ref _maxParallelExecutionsCount, currentParallelExecutionsCount, currentParallelExecutionsCount); 
      Console.WriteLine("Current parallel executions: {0}", currentParallelExecutionsCount); 
      try 
      { 
       //Do your work here 
      } 
      finally 
      { 
       Interlocked.Decrement(ref _parallelCounter); 
      } 
     } 

     public static bool InterlockedExchangeIfGreaterThan(ref int location, int comparison, int newValue) 
     { 
      int initialValue; 
      do 
      { 
       initialValue = location; 
       if (initialValue >= comparison) return false; 
      } 
      while (Interlocked.CompareExchange(ref location, newValue, initialValue) != initialValue); 
      return true; 
     } 
    } 
} 

Но голым в виде, что Parallel.For не будет пытаться выполнением слишком много параллельно, так как он использует нить пул и по умолчанию использует количество потоков, равное числу ваших процессорных ядер. На моей четырехъядерной машине я обычно получаю 2-4 параллельных исполнения с максимальным количеством 5 исполнений (но, конечно, здесь нет строгого ограничения).

+3

Эта «блокировка чего-либо» реализации настолько забавно усложняется в попытке остаться свободным от блокировки, я просто должен был дать ей преимущество для чистой развлекательной ценности. Я считаю, что префикс 'Interlocked' на длинном имени метода * слегка вводит в заблуждение, поскольку, в отличие от других,« истинных »взаимосвязанных методов, он не гарантирует забор памяти (не то, что имеет значение в данном конкретном случае), но в остальном это довольно круто , –

+1

.NET имеет счетчики производительности для пула потоков. –

Смежные вопросы