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.

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

Lisa kommentaar

Kommenteerimiseks palun logi sisse, kasutades üht neist võimalustest:

WordPress.com Logo

Sa kommenteerid kasutades oma WordPress.com kontot. Logi välja / Muuda )

Twitter picture

Sa kommenteerid kasutades oma Twitter kontot. Logi välja / Muuda )

Facebook photo

Sa kommenteerid kasutades oma Facebook kontot. Logi välja / Muuda )

Google+ photo

Sa kommenteerid kasutades oma Google+ kontot. Logi välja / Muuda )

Connecting to %s

%d bloggers like this: