Denna artikel är en spegelartikel om maskinöversättning, klicka här för att hoppa till originalartikeln.

Utsikt: 42759|Svar: 5

[Källa] Varför är .net/c# Task långsammare än Thread?

[Kopiera länk]
Publicerad på 2017-05-03 16:40:28 | | | |
.NET 4 inkluderar ett nytt namnrymd, System.Threading.Tasks, som innehåller klasser som abstraherar ut trådningsfunktionalitet. Använd ThreadPool i bakgrunden. En uppgift representerar arbetet av en enhet som bör slutföras. Arbetet med denna enhet kan köras i en separat tråd eller så kan en uppgift startas synkront, vilket kräver att man väntar på huvudinställningstråden. Att använda uppgifter ger dig inte bara ett abstraktionslager, utan också mycket kontroll över de underliggande trådarna.
Uppgifter erbjuder stor flexibilitet när det gäller att schemalägga det arbete som behöver göras. Till exempel kan du definiera en kontinuerlig uppgift – vilket arbete som ska göras efter att en uppgift är slutförd. Detta kan vara avgörande för att det blir en lyckad uppgift eller inte. Dessutom kan uppgifter ordnas i en hierarki. Till exempel kan en föräldrauppgift skapa en ny barnuppgift. Detta skapar ett beroende så att om du avbryter föräldrauppgiften, kommer även dess barnuppgift att avbrytas.


Nuförtiden är det populärt att använda metoder för uppgiftsutförande, och det är högpresterande, och jag vet inte var uppgiftsprestandan ligger.

Jag testade Task och Thread själv, och jag tycker att Task är väldigt långsam, vilket påverkar prestandan kraftigt, och testkoden är följande:

Vi loopar igenom metoden 1000 gånger, och sedan blockerar metoden i 100 millisekunder, och testresultatet är följande:



Utfall:
Trådexekveringen tar 188 millisekunder
Uppgiftsutförandet tar 14 671 millisekunder


Hastighetsskillnaden mellan de två är 78 gånger!!

Uppgiften är väldigt långsam, jag vet inte varför detta händer, är det något fel på min testkod eller vad? Jag hoppas du kan förklara varför detta händer...




Föregående:Skicka meddelanden med ASP.NET Core
Nästa:C# Parallell beräkning Parallell.For&Parallell.For
 Hyresvärd| Publicerad på 2020-10-13 10:47:17 |
tongli1996218 Publicerad den 2020-10-13 09:34
För att säkerställa samma kod som Thread är min funktion följande kod, och ovanstående är pseudokod
PS: Kalla bara await Task.Delay utan att lägga till ...

Ja, tack

Tid för uppgiftsutförande: 117.0357

Du kan ändra koden enligt följande:

Task.Run ersätter Task.Factory.StartNew eftersom den automatiskt packar upp interna uppgifter.
Task.WaitAll väntar på en extern uppgift istället för en intern. Att använda Task.Run har inga nästlade uppgifter.


Om du tittar i msdn-dokumentationen kan du se att metoden Task.Delay Method skapar en uppgift som slutförs efter ett angivet antal millisekunder. (Faktum är att en ny tråd kommer att skapas, och vänta kommer att läggas till för att vänta på att uppgiften ska köras, jag vet inte om jag förstår rätt)

Inloggningen med hyperlänken är synlig.

Dessutom finns det en skillnad mellan Uppgift och tomrum

Uppgiften returnerar en asynkron metod som kan vänta
Void return asynkrona metoden kan inte vänta, den fungerar asynkront, du kan inte veta när den är klar, du kan inte övervaka statusen för den asynkrona operationen.


Hänvisning:

Inloggningen med hyperlänken är synlig.
Inloggningen med hyperlänken är synlig.

Sammanfattningsvis: det finns ett problem med koden, jag bör inte använda Thread.Sleep i Task-metoden
Publicerad på 2020-07-21 13:09:29 |
Jag hade samma problem idag, använde multitrådning för AES-kryptering, Task är mycket långsammare än Thread!!
Har hyresvärden hittat orsaken?
Publicerad på 2020-10-12 19:24:48 |
Detta inlägg redigerades senast av tongli1996218 den 2020-10-12 19:43

Efter att ha testat ägarens kod, när programmet startas och körs flera gånger, kommer tiden för uppgiften att fortsätta minska, och på min dator kommer den att minskas till mindre än Thread, och Thread är stabil inom denna tid.

Det visade sig senare att metoden Thread.Sleep(100) hade en negativ inverkan på Task, men inte på Thread, och Thread.Sleep(100) kunde ersättas med annan tidskrävande programverifiering såsom numerisk självaddition eller vänta på Task.Delay(100).

PS: Thread.Sleep avslutar den aktuella trådens slicingtid efter anrop, till exempel avslutar Thread.Sleep(0) den aktuella trådens slicingtid och överför den till andra trådar för att köras. Inuti uppgiften finns en trådpool som kan optimera kontextväxling av trådar och minska CPU-förlusttiden (särskilt för multikärnig CPU-optimering), medan Thread.Sleep(100) stör switchningslogiken i den ursprungliga trådpoolen för uppgiften, vilket orsakar mycket CPU-tidsförlust

Om du ersätter Thread.Sleep(100) med await Task.Delay(100), kommer du att upptäcka att uppgiftens tidsåtvinning bara är mer än 100 millisekunder, som visas nedan:
privat void TaskTest()
{
        Thread.Sleep (100);
         ... Utför handlingen
}
Ersatt av
privat asynkron void TaskTest()
{
      vänta på Uppgift.Fördröjning(100);
      ... Exekveringen tar mer än 100 millisekunder för uppgiften, vilket är samma som den ursprungliga Thread.Sleep(100) för Thread
}




 Hyresvärd| Publicerad på 2020-10-12 22:53:05 |
tongli1996218 Publicerad den 2020-10-12 19:24
Efter att ha testat ägarens kod, när programmet startas, kommer tiden för uppgiften att fortsätta minska efter att ha kört flera gånger, och på min dator kommer den att minskas till mindre än Thread...

Jag försökte ändra det till kod så här:
Uppgift.Fördröjning(100000);

Tid för uppgiftsutförande:14,1306 ms, den totala tiden är faktiskt mycket kort, men jag upptäckte att metoden som anropades av Task inte slutförde exekveringen.
Publicerad på 2020-10-13 09:34:33 |
Detta inlägg redigerades senast av tongli1996218 den 2020-10-13 09:40
Publicerad den 2020-10-12 22:53
Jag försökte ändra det till kod så här:
Uppgift.Fördröjning(100000);

För att säkerställa samma kod som Thread är min funktion följande kod, och ovanstående är pseudokod
PS: Anropa bara await Task.Delay, och lägg sedan till ingen kod, tråden som öppnas av uppgiften returneras omedelbart, för att säkerställa simulering av compute-bound, kan du använda för (int a = 0; a< 1000000; ++a){}; Sådana metoder används istället

privat asynkron statisk void TaskTest()
        {
            invänta Uppgift.Fördröjning(100000);
             Interlocked.Increment (ref run);    lås, men taket är mindre
            if(run == j)
             {
                Stoppur. Stop(); Sluta övervaka
                TimeSpan timespan = stoppur. Förflutit;  Får den totala tiden som uppmäts av den aktuella instansen
                Console.WriteLine("Task execution time:" + tidsspann. TotalMillisekunder); Totala millisekunder
              }
        Den tid som tas är också mycket kort


Friskrivning:
All programvara, programmeringsmaterial eller artiklar som publiceras av Code Farmer Network är endast för lärande- och forskningsändamål; Ovanstående innehåll får inte användas för kommersiella eller olagliga ändamål, annars kommer användarna att bära alla konsekvenser. Informationen på denna sida kommer från internet, och upphovsrättstvister har inget med denna sida att göra. Du måste helt radera ovanstående innehåll från din dator inom 24 timmar efter nedladdning. Om du gillar programmet, vänligen stöd äkta programvara, köp registrering och få bättre äkta tjänster. Om det finns något intrång, vänligen kontakta oss via e-post.

Mail To:help@itsvse.com