Tema
/
Algoritmai ir duomenų struktūros GO
Pamoka 15 / 15 Svoriniai grafai ~60 min
Teorija

72.7 karto darbo, 16.9 karto laiko

Pirmame žingsnyje užsirašei du skaičius: kiek kartų daugiau darbo ir kiek kartų ilgiau.

$ algo frontier
nodes 1000, edges 742, 561 reachable destinations from 0

                                   queue work         time
  binary heap (lesson 13)             5567392         32ms
  linear min-scan                   404796000        546ms

  identical cost on 561 of 561 destinations
  work ratio  72.7x
  time ratio  16.9x

Pirmiausia — eilutė, be kurios visa lentelė nieko nereikštų:

identical cost on 561 of 561 destinations.

Eilės pakeitimas nekeičia atsakymo. Keičiasi tik tai, kiek laiko jo laukiama. Todėl du likę skaičiai apskritai palyginami.

Ir jie nesutampa

darbo santykis   72.7x
laiko santykis   16.9x

Skaitiklis sako, kad tiesinė versija atlieka 72.7 karto daugiau darbo. Laikrodis sako, kad ji trunka 16.9 karto ilgiau.

Skirtumas — daugiau nei keturis kartus.

Kodėl skaitiklis pervertina

Tiesinės peržiūros darbas yra for v := 0; v < n; v++ per gretimą masyvą. Procesorius tokį ciklą mėgsta: adresai nuspėjami, duomenys traukiami paketais, šaka visada ta pati. Vienas žingsnis ten yra pigus.

Krūvos darbas yra kilimas ir leidimasis šokinėjant po 2i+1 ir (i−1)/2 — adresai peršoka, kiekvienas palyginimas gali laukti atminties, o šaka nenuspėjama. Vienas žingsnis ten brangesnis.

Skaitiklis abu vadina „vienu". Jie nėra vienas.

Šeštas kartas — ir pirmas šia kryptimi

Ši riba kurse jau pažįstama, bet iki šiol ji visada veikė ta pačia puse:

pamoka ką pasakė skaitiklis ką pasakė laikrodis
4 nulis (atmintis nematoma) krūva augo
6 persikirtimas ties n ≈ 3 ties n ≈ 6 — prietaisas pakeitė matavimą
11 identiška: 5000.5 abiem 4.5 karto skirtumas
12 AVL pigesnis 23 % AVL 1.65 karto brangesnis
13 identiška abiem krūvoms 1.66 karto skirtumas
15 72.7 karto 16.9 karto

Ketvirtu, vienuoliktu ir trylikta kartais skaitiklis nuvertino skirtumą. Dvyliktą kartą jis apsiriko ženklu.

Čia jis pervertina — pirmą kartą kurse. Ir tai ne todėl, kad jis blogesnis, o todėl, kad matuojamas dydis kitas.

Skaitiklis matuoja, kiek operacijų atliekama. Laikrodis matuoja, kiek kainuoja jas atlikti. Kai operacijos nevienodos, du skaičiai išsiskiria — ir abu teisingi.

transit tą patį mato didesniu masteliu

Mūsų matavimas (docs/reference/transit-benchmarks.md), trys užklausos:

užklausa tiesinės eilės darbas krūvos darbas darbo santykis laiko santykis
cross-city 92 200 762 370 053 249× 16.0×
slow-naive 95 179 989 370 009 257× 18.9×
worst-case 988 259 147 3 047 930 324× 16.4×

Darbo santykis ten yra 15–20 kartų didesnis už laiko santykį. Mūsų — 4.3 karto. Ta pati kryptis, tas pats mechanizmas, skirtingas mastelis.

Ir atkreipk dėmesį į laiko stulpelį: 16.0, 18.9, 16.4. Mūsų — 16.9. Skirtingas grafas, skirtingi duomenys, skirtinga programa, tas pats skaičius.

Tai ir yra tikrasis Dijkstros eilės pagerinimo dydis: maždaug 16–19 kartų.

Ką iš to pasiimti

Ne „skaitikliu nepasitikėk". Pirma pamoka jį pasirinko teisingai ir dėl teisingos priežasties — jis nepriklauso nuo mašinos, o laikrodis priklauso.

Bet po penkiolikos pamokų atsakymas tikslesnis:

Skaitiklis pasako, kaip algoritmas AUGA. Laikrodis pasako, ką jis KAINUOJA šiandien, šioje mašinoje. Sudėtingumui reikia pirmojo, sprendimui — abiejų.