XE7 - IFuture druhé podání

vložil Radek Červinka 5. prosince 2014 00:59

Narazil jsem na pěkné vysvětlení IFuture s pěkným příkladem od Malcolma Grovese. Zásadní informace je, že IFuture není hodnota, kterou budete počítat v budoucnu, ale hodnota, kterou budete v budoucnu potřebovat. Tato jemná nuance je zásadní.

Krása použití paralelního programování v XE7 vynikne, až člověk změní myšlení. Přiznám se, že mi to trvá.

Uvedený příklad z klasického programování. Mějme metodu, která provádí operaci po dvou dlouhých suboperacích.

procedure TFormThreading.OrderItem(const CustomerID,  ItemID: String; OrderQty: Integer);
var
  StockLevel : Integer;
  PaidTheirBills : Boolean;
begin
  StockLevel := GetStockLevel(ItemID); // velmi pomalé
  PaidTheirBills := HaveTheyPaid(CustomerID); // také velmi pomalé

  if (StockLevel >= OrderQty) and (PaidTheirBills) then
    // proveď objednávku
end;

Pokud použijeme paralelní zpracování, konkrétně IFuture (a budou splněny podmínky jako počet procesorů, resp. např. neblokování připojení k DB), dosáhneme velmi výrazné úspory, která závisí na tom, jaký je poměr délky vykonávání dílčích úkolů. Pokud trvají zhruba stejně, dostaneme se na polovinu celkového času.

procedure TFormThreading.OrderItem(const CustomerID, ItemID: String; OrderQty: Integer);
var
  StockLevel : IFuture<Integer>;
  PaidTheirBills : Boolean;
begin
  StockLevel := TTask.Future(function : Integer
                             begin
                               // velmi pomalé
                               Result := GetStockLevel(ItemID);
                             end);
  PaidTheirBills := HaveTheyPaid(CustomerID); // také velmi pomalé

  if (StockLevel.Value >= OrderQty) and (PaidTheirBills) then
    // proveď objednávku
end;

Všimněte si prosím, jak StockLevel je prováděn přes IFuture za pomocí anonymní metody. Tímto je StockLevel prováděn paralelně a hlavní vykonávání začíná počítat PaidTheirBills.

Výsledná podmínka je kritická, protože:

  • na podmínku se dostaneme až je PaidTheirBills dokončen
  • ale, pokud není StockLevel dokončen, je hodnota StockLevel.Value blokována a čeká na dokončení

Tudíž celá podmínka je provedena až po dokončení výpočtu obou hodnot.

Není to krása?

Tagy: ,

Novinky v Delphi

Komentáře

6.12.2014 22:27:36 #

Daniel Andrascik

ty brdo...

Daniel Andrascik

7.12.2014 16:17:51 #

Zdeněk Vašků

Ano, ta změna myšlení je opravdu potřeba. My například používáme OmniThreadLibrary + klasický TThread, ale většinou se jedná o paralelizaci na větší úrovni (velké logické celky). Díky přehlednosti s použitím anonymních metod, se dostává paralelizace i na kratší kousky kódu.

Rakdu máš pochvalu a jen více článků tohoto typu :-)

Zdeněk Vašků

7.12.2014 20:32:29 #

Geby

Zabyva se to taky nejak problematikou mezithreadove synchronizace a pristupu ke koliznim zdrojum?

Geby

8.12.2014 0:13:38 #

radekc

Můžeš použít TThread.Synchronize, resp.TMonitor a další. V této verzi nic speciálního co vím, kromě čekání na ukončení nebo události.

radekc

8.12.2014 0:47:39 #

Geby

Moment... v tom, co jsi tu ukazal, preci zadny TThread neni, ne? Jde mi o kod vykonavany uvnitr IFuture.

Kdyz se tolik hrabou v tom paralelismu, tak mi prijde skoda, ze nevymysleli nejaka sikovna jednoducha udelatka i na tu mezithreadovou komunikaci, na volani GUI z threadu, atd. Jiste, mohu si to udelat sam, ale ruku na srdce, v tomhle mnoho lidi chybuje, takze by to byl prinos.

Geby

8.12.2014 10:45:05 #

radekc

IFuture je jen hezká obálka nad jádrem, které je momentálně implementováno jako TThread (a je to rozumné). Novinka je ale, že je tam ale přidán TThreadPool se kterým všechno spolupracuje, což je jednoznačně plus.
Takže můžeš použít libovolné prostředky, které již používáš pro synchronizaci.

Ano byl by to přínos a pokud vím, tak se to plánuje.

Ohledně volání GUI: hodně už byla (dříve rozšířena TThread). Můžeš použít TThread.Synchronize s parametrem anonymní metody, můžeš testovat CurrentThread.ThreadID = MainThreadID a podle toho se zachovat (ale jednodušší je podle mne to Synchronize, které je IMHO už dávno nepoužívá zprávy).

radekc

8.12.2014 16:55:22 #

Zdeněk Vašků

Co se týká OmniThreadLibrary, tak tam se dá použít TOmniValue pro hodnoty případně je dáno, která část paralelního zpracování (většinou na konci) se provede v hlavním vlákně.

Zdeněk Vašků

18.12.2014 23:25:20 #

tomts

Já při psaní jádra největšího v ČR SCADA ŘS v Delphi jsem si musel z TThread vytvořit vlastní objekt TWinThread s vlastním hidden oknem (založeným v kontextu vlákna) a se systémem vlastních zpráv zpráv (dosti magic inline operace).  Potom nebyl problém v kontextu 20-50 threadů vykonávat vše paralelně a synchronizovat vše přes fronty vzájemných zpráv a kompatibilně s apartment-therad COM modelem.  Samozřejmě při sdílení Delphi (system atd.) nereentrantních a non-therad-safe global objektů je třeba použít synchronizační objekty (kritická sekce, semafory...) a totéž i pro vlastní globální sdílené objekty.  Ovšem poměrně brzy přijdete na to, že apartment-threaded WIN aplikace není to "pravé ořechové" - tedy v případě spolupráce více aplikací (na local PC, v LAN, DCOM atd.), protože se čeká na výběr zpráv v okně (na synchronizaci s threadovou frontou zpráv), což zdržuje obsluhu klient-požadavků.  Takže potom skončíte u free-theraded aplikace, kde sice uvnitř local aplikace vše chodí paralelně ve 20-50 vláknech a synchronizuje se přes fronty threadových okenních zpráv,  ale vnější klient-požadavky musíte obsloužit okamžitě a tedy musítě použít vlastní synchronizační objekty (nemůžete se spoléhat na apartment model, že to udělá za vás).  Bohužel WIN32 Delphi nebyla už od počátku 2/1996  (Delphi2+) navržena kvalitně a inteligentně - vícevláknově (trh = rychlost a výnos a spotřeba jsou nade vše... což platí dodnes).  To je z pohledu WIN32-64 programátora naprostá a totální katastrofa, protože si musí ze zdrojáků jádra Delphi v max. rychlosti vyzjistit, co je a není thread-safe (fóra, tisíce pokusů).  OVŠEM Z DNEŠNÍHO MULTIPLATFORMNÍHO OS KONTEXTU cca DELPHI XE5+ JE NAJEDNOU SPÍŠE VÝHODA, ŽE DELPHI NEBYLA NAPSÁNA NA MÍRU WIN (ale byla kdysi velmi odbyta) A JSEM ZVĚDAV, JAK EMTD POŘEŠÍ PARALELNÍ ZPRACOVÁNÍ NYNÍ NEZÁVISLE NA OS - zda opět vyhraje trh nad kvalitou (jako je tomu dnes bohužel skoro všude - díky úchylným zmršeným konvencím této společnosti).

tomts

3.1.2015 15:23:58 #

radekc

Hold po bitve je kazdy general. A na tvoji otazku, resi to myslim velmi rozumne, a ne pres najaky bastl s hidden oknem.

a CAPS LOCK ZAPINA MOJI PRAVDU.

radekc

Komentování ukončeno

Naše nabídka

MVP
Ing. Radek Červinka - Embarcadero MVP
profil na linkedin, Twitter:@delphicz

Nabízím placené poradenství a konzultace v oblasti programování a vývoje SW.
Dále nabízíme i vývoj speciálního software na zakázku.

Neváhejte nás kontaktovat (i ohledně reklamy).

love Delphi

O Delphi.cz

Delphi je moderní RAD nástroj podporující tvorbu nativních aplikací pro platformu Win32, Win64, Mac OSX, Linux a na iPhone a Android.

Delphi.cz je nezávislý portál pro uživatele Delphi. Portál není koncipován pro úplné začátečníky, i když i ti se zde nebudou nudit, ale spíše na programátory, kteří již něco znají a chtějí své znalosti dále rozvíjet a sledovat novinky.

Poslední komentáře

Comment RSS

Dle měsíců