Esileht > Uncategorized > Rööpülesannete algväärtustamine

Rööpülesannete algväärtustamine


Rööplemine toimub eraldi lõimedes, ja juhtumitel, kui on tarvis ligi pääseda objektile, mis ei ole lõimeturvaline, peaks selle objekti lukustama, aga see võib viia olukorda, kus rööplemisest ei ole mingit tolku, kuna kõik lõimed istuvad ikka ühes järjekorras.

Siin tuleb abiks rööplõimede algväärtustamine, kus igale ülesandele saab luua oma objektid.

Kõige lihtsam näide, kus seda võib vaja minna, on juhuarvude generaator, mis ei ole lõimeturvaline.

double[] prices = new double[10000];

Parallel.For<Random>
(
  0,
  prices.Length,
  () => new Random(),
  (i, state, random) => { prices[i] = random.NextDouble(); return random; },
  random => { }
);

Parallel.For() võtab lisaks miinimum- ja maksimumväärtusele ka kolm funktsiooni.

Esimene käivitatakse iga ülesande alguses, teine iga tsükli jaoks ja kolmas ülesannet lõpetades.

Esimeses funktsioonis me loome Random-objekti (tõele au andes tuleks tunnistada, et see näide on liiga lihtsustatud, sest parema tulemuse jaoks peaks arvestama, et iga Random-objekt vajab erinevat seemet, kuna need luuakse peaaegu üheaegselt).

Teine funktsioon saab positsiooni, staatuse objekti ja ülesande jaoks algväärtustamisel loodud Random-objekti. Seda kasutatakse järgmise juhuarvu genereerimiseks ja massiivi salvestamiseks. Funktsioon peab tagastama järgmises tsüklis kasutatava objekti (meie juhtumil ei ole tarvis seda muuta).

Kolmas funktsioon oleks kasulik, kui Random-objekt vajaks lõpetuseks mingit protseduuri. Meie seda antud näites ei vaja.

Aggregate()

See on tore meetod, mida saab kasutada oma koondfunktsioonide loomiseks, kui sisseehitatutest ei piisa. Kujutan ette, et see kulub marjaks ära laenukalkulaatorite ja statistikaülesannete jaoks. Aga meie teeme midagi väga tavalist: võtame kõigi väärtuste keskmise.

double d = prices.AsParallel().Aggregate
(
  () => new double[2],
  (accum, element) => { accum[0] += element; accum[1]++; return accum; },
  (accumA, accumB) => { accumA[0] += accumB[0]; accumA[1] += accumB[1]; return accumA; },
  accum => accum[0] / accum[1]
);

Seda protseduuri ei saa teostada ülesannet algväärtustamata, sest me ei saa kõigile lõimedele anda ühiskasutatavat double[2]-muutujat. Niisiis vajab iga ülesanne oma muutujat.

Esimene funktsioon loob kohaliku muutuja (millele edaspidi viidatakse nimega accum).

Teine funktsioon on tsükli käitamiseks. Masiivi 0-positsioon on väärtuste summa ja 1-positsioon on väärtuste koguarv. Nagu For-meetodis, tuleb ka siin tagastada muutuja ise. Funktsiooni teine parameeter, element, on loomulikult tsüklis töödeldav sisendväärtus.

Kolmas funktsioon on see, mis käivitatakse kõiki erinevaid lõimesid kokku võttes. See koondab kõigi lõimede tulemused, antud juhul summeerib kõik väärtused, võttes kaks sisendparameetrit ja tagastades summa.

Neljas funktsioon käivitatakse üks kord: siis kui kõik lõimed on summeeritud. Siin me jagame summa väärtuste koguarvuga ja saamegi keskmise.

Kolm varianti

Selle ülesande saaks loomulikult teostada palju lihtsamalt: prices.Average() jadana ja prices.AsParallel().Average() rööpes.

Aga ma loodan, et see näide aitas mõista, mida on vaja, et teostada funktsiooni, mida standardvalikus ei leidu.

Muuseas, nagu võib arvata, ei tarvitse jadas ja rööpes teostatud koondfunktsioonide tulemused täielikult ühtida, sest rööpes tehakse kõik tööd kahes astmes (iga lõime jaoks eraldi ja seejärel koondatuna), mis annab erineva vea kui jadaülesandes.

Minu katse puhul tuli minu enda koodijupi ja AsParallel().Average() vastus sama, kuid jadaprogrammi vastus viimase numbrikoha osas pisut erinev:

0.497030457169437
0.497030457169437
0.497030457169439

See ongi oodatud tulemus, mis näitab, et rööpkoondfunktsioonid töötavad sisemiselt kaheastmelistena.

Rubriigid:Uncategorized
  1. Kommentaare veel pole.
  1. No trackbacks yet.

Lisa kommentaar

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Muuda )

Twitter picture

You are commenting using your Twitter account. Log Out / Muuda )

Facebook photo

You are commenting using your Facebook account. Log Out / Muuda )

Google+ photo

You are commenting using your Google+ account. Log Out / Muuda )

Connecting to %s

%d bloggers like this: