2015-11-05 21 views
8

Próbuję utworzyć metodę WebApi, która wykonuje serię obliczeń pętli, które trudno byłoby dalej optymalizować.Wiele rdzeni dla pojedynczego żądania ASP.net

x.Items.AsParallel().ForAll(item => 
{ 
    item.RunCalcs(); 
}); 

Po wykonaniu tego kodu, patrząc na menedżera zadań serwera, wydaje się, że to tylko maxes się jeden rdzeń procesora, pozostawiając pozostałe rdzenie nietknięte.

Z tego, co przeczytałem, asp.net ogranicza pojedyncze żądanie do jednego rdzenia procesora. Ponieważ jest to serwer intranetowy z niewielką liczbą ogólnych żądań, nie jestem zainteresowany zarządzaniem zasobami serwera.

Czy istnieje sposób na obejście lub obejście tego zachowania, aby moja pętla działała szybciej?

+2

Czy próbowałeś ustawić MaxDegreeOfParallelism opcja? Równolegle.ForEach (Items, new ParallelOptions() {MaxDegreeOfParallelism = Environment.ProcessorCount}, item => {...}); –

+0

Czy istnieje możliwość zaprojektowania pętli i uruchomienia różnych wątków w celu rozłożenia obciążenia. Więc jeśli masz kolekcję 1000 przedmiotów odpalić wątek dla pierwszych 500 i inny wątek dla pozostałych 500? – WooHoo

+0

@SK, który wydaje się rozwiązać problem, ale nie jestem pewien, dlaczego, ponieważ myślałem, że PLinq ForAll miał korzystać z maksymalnych dostępnych zasobów. Być może jest inaczej w asp.net. – phosplait

Odpowiedz

1

Program ASP.Net może bardzo ograniczyć liczbę wątków używanych nawet w przypadku licencji TPL. Wystarczy utworzyć TaskScheduler, który jest ograniczony do jednego wątku i uruchomienie żądania ASP.Net na danym TaskScheduler. Założę się, że mieliby pulę tych ograniczonych zadań TaskScheuler, to miałoby sens ...

Co się stanie podczas przetwarzania zadania ASP.Net, kiedy zadzwonisz do TPL lub PLINQ?

Jest to planowanie zadań za pomocą połączeń do Task.Start lub jeszcze lepiej, a przez zespół TPL bardziej preferowany sposób, Task.Factory.StartNew.

Ale, ale, tyłek :), są one harmonogramowanie zadań na górze TaskScheduler.Current i to jest nasz ograniczony TaskScheduler jesteśmy już działa na! Tak więc wszystkie zaplanowane zadania zostaną spalone na ograniczonej liście TaskScheduler, bez względu na to, ile rdzeni ma twoja maszyna.

Z drugiej strony wygląda na to, że operacje asynchroniczne/oczekujące używają nowej funkcji Task.Run() wprowadzonej w .Net 4.5+ i zasugerowano, że jest to planowanie zadań w TashScheduler.Default, czym jest sam ThreadPool , więc nie ma tam żadnych ograniczeń, poza liczbą rdzeni. Nie mam dowodu, ale poza tym: Regarding usage of Task.Start() , Task.Run() and Task.Factory.StartNew() TPL

Niestety AsParallel() nie ma przeciążenia biorąc TaskScheduler.

Zatem rozwiązaniem byłoby:

  1. Pierwszy z nich już sugerowane przez @S K, aby użyć klasy równoległe i określić stopień równoległości. Klasa poprzedza PLINQ i używa ThreadPool, jak się wydaje pasuje.
  2. Drugi pomysł polegałby na samodzielnym planowaniu w ThreadPool.
  3. Lub zaplanuj zadania w TaskScheduler.Default, celując w ThreadPool.
  4. Lub odrodzenie własnych wątków (najgorszy pomysł) dla ASP.Net.
  5. Lub użyj async/await, aby uruchomić pracę w TaskScheduler.Default, ThreadPool i w asynchronicznej metodzie użyj AsParalel(), ponieważ tam TaskScheduler.Current będzie taki sam jak TaskScheduler.Default, po prostu ThreadPool.

UWAGA uwaga: Należy pamiętać, że planowanie ciężkich rzeczy na puli wątków w ASP.NET może prowadzić do malejącej wydajności przetwarzania żądań ASP.Net ...

Powiązane problemy