2013-01-04 16 views
5

Dlaczego poniższy kod jest wykonywany sekwencyjnie?Dlaczego te zadania są uruchamiane sekwencyjnie?

List<Task> tasks = new List<Task>(); 

for (int i = 0; i <= max; i += block) 
{ 
    if (i + block >= max) 
     tasks.Add(Task.Factory.StartNew(() => Count(ref counter, block))); 
    else 
     block = max - i; 
} 

Task.WaitAll(tasks.ToArray()); 

Przetestowałem również wersję tego przy użyciu Parallel.Invoke; ono również nie działa równolegle. Musi być coś, czego nie rozumiem, ale kiedy próbuję tego używać, najczęściej otrzymuję instrukcje, jak wymusić sekwencyjne wykonanie.

W odpowiedzi na jedno z zastrzeżeniami podanymi w poniższej odpowiedzi, mam włączone następujące metody dla odniesienia:

static void Count(ref int counter, int num) 
{ 
    int localCounter = 0; 
    for (int i = 0; i < num; i++) 
     if (Coin()) localCounter++; 
    System.Threading.Interlocked.Add(ref counter, localCounter); 
} 

redakcją ponownie: Dziękuję wszystkim!

+0

Ile masz procesorów/rdzeni? –

+3

Jak szybkie jest 'Count'? –

+0

Jaki masz dowód na to, że nie jest on porównywany? Problemem może być obserwacja tego, co się dzieje, a nie to, co się dzieje. – Servy

Odpowiedz

1

dlaczego poniższy kod jest wykonywany sekwencyjnie?

Nie ma, chyba że masz coś w metodzie Count synchronizującej dostęp do pojedynczego zasobu. Jeśli można go zrównoleglić, to będzie działać równolegle.

Jeśli bardzo szybko wykonasz Count, zadania zakończą się szybciej, niż zaplanowano nowe zadania, dlatego wszystkie mogą być wykonywane w kolejności.

+0

Gdyby tak było! Spodziewałbym się 100% wykorzystania rdzenia do równoległego wykonania czegoś podobnego, ale to, co otrzymałem, to 12,5%, czyli dokładnie jeden wątek. Niestety nie mam wizualizatora współbieżności dostępnego dla mnie w moim IDE, więc to jest najlepszy dowód jaki mam. Zmienię moje pytanie, aby uwzględnić metodę liczenia. –

+1

@ user1949917 Jeśli zadania są wykonywane bardzo szybko, spodziewam się 12,5% wykorzystania. Jeśli czas potrzebny do przetworzenia jednej iteracji jest niewielki, ale liczba iteracji jest duża, powinieneś mieć każde zadanie obsługiwać wielokrotne iteracje, a nie tylko jedną. – Servy

4

Wystarczy wymienić tasks.Add(Task.Factory.StartNew(() => Count(ref counter, block))); na Console.WriteLine i zdebugować swój kod.

Nigdy nie tworzy się więcej niż jedno zadanie.

for (int i = 0; i <= max; i += block) 
{ 
    if (i + block >= max) 
     Console.WriteLine(i); 
    else 
     block = max - i; 

} 
+1

Masz rację. –

1

Wydaje mi się, że jest coś nie tak z pętli/if:

for (int i = 0; i <= max; i += block) 
{ 
    if (i + block >= max) 
     tasks.Add(Task.Factory.StartNew(() => Count(ref counter, block))); 
    else 
     block = max - i; 
} 

Jeśli czytam to prawo, będzie dodać zadanie tylko jeśli i + block >= max i będziesz pętla tylko wtedy, gdy i + block <= max (pokazujący zarówno wzrost licznika, jak i sprawdzenie stanu). W związku z tym dodasz zadanie tylko raz.

Ponadto zmieniasz blok, gdy nie dodajesz zadania. Oczekuję, że chcesz czegoś bardziej podobnego do poniższego, ale nie mogę być pewny, że nie ma więcej kodu:

for (int i = 0; i <= max; i += block) 
{ 
    tasks.Add(Task.Factory.StartNew(() => Count(ref counter, block))); 
    if (i + block >= max) { block = max - i; } 
} 
Powiązane problemy