Tento článok je zrkadlovým článkom o strojovom preklade, kliknite sem pre prechod na pôvodný článok.

Pohľad: 42759|Odpoveď: 5

[Zdroj] Prečo je .net/c# úloha pomalšia ako Thread?

[Kopírovať odkaz]
Zverejnené 3. 5. 2017 16:40:28 | | | |
.NET 4 obsahuje nový menný priestor System.Threading.Tasks, ktorý obsahuje triedy abstrahujúce funkcionalitu vlákien. Použi ThreadPool na pozadí. Úloha predstavuje prácu jednotky, ktorá by mala byť dokončená. Práca tejto jednotky môže byť vykonaná v samostatnom vlákne alebo môže byť synchronne spustená úloha, čo vyžaduje čakanie na hlavné ladiace vlákno. Používanie úloh vám nielen poskytuje vrstvu abstrakcie, ale aj veľkú kontrolu nad základnými vláknami.
Úlohy ponúkajú veľkú flexibilitu pri plánovaní práce, ktorú je potrebné vykonať. Napríklad môžete definovať kontinuálnu úlohu – akú prácu by sa mala vykonať po dokončení úlohy. To môže rozhodnúť o úspešnej alebo neúspešnej úlohe. Okrem toho je možné úlohy usporiadať do hierarchie. Napríklad rodičovská úloha môže vytvoriť novú podriadenú úlohu. Tým vzniká závislosť, takže ak zrušíte rodičovskú úlohu, zruší sa aj jej podriadená úloha.


Dnes je populárne používať metódy vykonávania úloh, ktoré sú vysoko výkonné, a neviem, kde sa výkon úloh nachádza.

Sám som testoval Task a Thread a mám pocit, že Task je veľmi pomalý, čo výrazne ovplyvňuje výkon, a testovací kód je nasledovný:

Metódu prechádzame 1000-krát, potom sa metóda blokuje 100 milisekúnd a výsledok testu je nasledovný:



Výsledok:
Vykonanie vlákna trvá 188 milisekúnd
Vykonanie úlohy trvá 14 671 milisekúnd


Rozdiel v rýchlosti medzi nimi je 78-násobný!!

Úloha je veľmi pomalá, neviem, prečo sa to deje, je niečo zlé s mojím testovacím kódom, alebo čo? Dúfam, že mi vysvetlíte, prečo sa to deje...




Predchádzajúci:Posielanie správ pomocou ASP.NET Core
Budúci:C# Paralelný výpočet Parallel.For&Parallel.For
 Prenajímateľ| Zverejnené 13. 10. 2020 10:47:17 |
tongli1996218 Zverejnené 13.10.2020 09:34
Aby som zabezpečil rovnaký kód ako Thread, moja operácia je nasledovný kód, pričom vyššie uvedené je pseudo-kód
PS: Stačí zavolať a čakať na úlohu. Oneskorenie bez pridania ...

Áno, ďakujem

Čas vykonania úlohy: 117.0357

Kód môžete upraviť nasledovne:

Task.Run nahrádza Task.Factory.StartNew, pretože automaticky rozbaľuje interné úlohy.
Task.WaitAll čaká na externú úlohu namiesto internej. Použitie Task.Run nemá vnorené úlohy.


Pri pohľade na dokumentáciu msdn vidíte, že metóda Task.Delay Method vytvára úlohu, ktorá sa dokončí po stanovenom počte milisekúnd. (V skutočnosti sa vytvorí nové vlákno a pridá sa await, aby sa úloha spustila, neviem, či som tomu správne rozumel)

Prihlásenie na hypertextový odkaz je viditeľné.

Okrem toho je rozdiel medzi úlohou a prázdnotou

Úloha vráti asynchrónnu metódu, ktorá môže počkať
Asynchrónna metóda void return nemôže čakať, funguje asynchrónne, nemôžete vedieť, kedy je hotová, nemôžete sledovať stav tej asynchrónnej operácie.


Referencia:

Prihlásenie na hypertextový odkaz je viditeľné.
Prihlásenie na hypertextový odkaz je viditeľné.

Na záver: je problém s kódom, nemal by som používať Thread.Sleep v rámci metódy Task
Zverejnené 21. 7. 2020 13:09:29 |
Mal som dnes rovnaký problém, keď som používal multithreading na AES šifrovanie, Task je oveľa pomalší ako Thread!!
Našiel prenajímateľ dôvod?
Zverejnené 12. 10. 2020 19:24:48 |
Tento príspevok naposledy upravil tongli1996218 dňa 12.10.2020 o 19:43

Po otestovaní kódu vlastníka, keď sa program spustí a spustí viackrát, čas úlohy sa naďalej skracuje a na mojom počítači sa zníži na menej ako Thread, pričom Thread je v tomto čase stabilný.

Neskôr sa zistilo, že metóda Thread.Sleep(100) mala negatívny vplyv na úlohy, ale nie na Thread, a Thread.Sleep(100) mohol byť nahradený iným časovo náročným overovaním programu, ako je numerické samosčítanie alebo čakanie na úlohu.Delay(100).

PS: Thread.Sleep ukončí aktuálny čas rezania vlákien po zavolaní, napríklad Thread.Sleep(0) ukončí aktuálny čas rezania vlákien a prenesie ho do iných vlákien na spustenie. Vo vnútri úlohy sa nachádza thread pool, ktorý dokáže optimalizovať prepínanie kontextu vlákien a znížiť čas straty CPU (najmä pri optimalizácii viacjadrového CPU), zatiaľ čo Thread.Sleep(100) naruší logiku prepínania pôvodného poolu vlákien úlohy, čo spôsobuje veľkú stratu času CPU

Ak nahradíte Thread.Sleep(100) za await Task.Delay(100), zistíte, že časová spotreba úlohy je len viac ako 100 milisekúnd, ako je uvedené nižšie:
private void TaskTest()
{
        Thread.Sleep(100);
         ... Vykonajte akciu
}
Nahradené
private async void TaskTest()
{
      čakať na úlohu. Oneskorenie (100);
      ... Vykonanie trvá viac ako 100 milisekúnd, čo je rovnaké ako pôvodný Thread.Sleep(100) pre Thread
}




 Prenajímateľ| Zverejnené 12. 10. 2020 22:53:05 |
tongli1996218 Zverejnené 12.10.2020 19:24
Po otestovaní kódu vlastníka, keď sa program spustí, čas úlohy sa po viacerých spusteniach bude naďalej znižovať a na mojom počítači sa zníži na menej ako Thread...

Skúsil som to zmeniť na kód takto:
Úloha.Oneskorenie(100000);

Čas vykonania úlohy:14,1306 ms, celkový čas je naozaj veľmi krátky, avšak zistil som, že metóda volaná úlohou nedokončila vykonanie.
Zverejnené 13. 10. 2020 9:34:33 |
Tento príspevok naposledy upravil tongli1996218 dňa 13.10.2020 o 09:40
Publikované 12.10.2020 o 22:53
Skúsil som to zmeniť na kód takto:
Úloha.Oneskorenie (100000);

Aby som zabezpečil rovnaký kód ako Thread, moja operácia je nasledovný kód, pričom vyššie uvedené je pseudo-kód
PS: Stačí zavolať await Task.Delay a potom pridať žiadny kód, vlákno otvorené úlohou sa okamžite vráti, aby sa zabezpečila simulácia výpočtovo viazaná, ktorú môžete použiť pre (int a = 0; a< 1000000; ++a){}; Takéto metódy namiesto toho

private async static void TaskTest()
        {
            čakať na úlohu. Oneskorenie (100000);
             Interlocked. Increment (ref run);    zámok, ale režijné náklady sú menšie
            if(run == j)
             {
                Stopky. Stop(); Prestaňte monitorovať
                TimeSpan časový rozsah = stopky. Uplynulo;  Získa celkový čas meraný aktuálnou inštanciou
                Console.WriteLine("Čas vykonania úloh:" + časový rozsah. TotalMilisekundy); Celkové milisekundy
              }
        Čas potrebný na to je tiež veľmi krátky


Vyhlásenie:
Všetok softvér, programovacie materiály alebo články publikované spoločnosťou Code Farmer Network slúžia len na vzdelávacie a výskumné účely; Vyššie uvedený obsah nesmie byť použitý na komerčné alebo nezákonné účely, inak nesú všetky následky používateľmi. Informácie na tejto stránke pochádzajú z internetu a spory o autorské práva s touto stránkou nesúvisia. Musíte úplne vymazať vyššie uvedený obsah zo svojho počítača do 24 hodín od stiahnutia. Ak sa vám program páči, podporte originálny softvér, zakúpte si registráciu a získajte lepšie originálne služby. Ak dôjde k akémukoľvek porušeniu, kontaktujte nás prosím e-mailom.

Mail To:help@itsvse.com