Şi iarăşi poveşti cu optimizări

11 septembrie - Majoratul atacului de la WTC. 29712 numere, a mai crescut cota, deşi după reformulările algoritmice din ultima vreme au început să cam apară multe numere de fond 1 "neluate" în GIG-uri şi LPT-uri. La funcţiile de urcare în fişiere am pus mai bine la punct modulul URC2, care să ajungă la poziţia din fişier unde încep numerele cu prima cifră "pcif" şi-a doua "scif", deci primele două cifre din număr să fie luate ca reper.

În headerul URC.h sunt două funcţii distincte de urcare, SUS() care tratează urcarea până la punctul din fişier unde încep numerele cu un anumit număr de cifre, plus urcarea asta cu prima cifră din număr de o anumită valoare (doar de la 1 la 9 poate fi), şi SUS() se apelează cu URC() şi URC1(), diferenţele dintre ele două fiind de importanţă secundară; apoi, respectiv, funcţia SUS2(), care se apelează când urcarea are neapărat, din linia de comandă, un număr suficient de mare de parametri, anume să fie şi pentru cifra a doua. SUS2() face cele două grade de urcare de mai sus (executate nu simultan, ci condiţional unul sau altul, în funcţie de cum este parametrul "prima cifră"), apoi şi-al treilea grad, condiţionat de cum este dată a doua cifră, şi duce unde încep în fişier numerele cu un anumit număr de cifre, o primă cifră şi-o a doua clar specificate. De această dată, cifra a doua poate fi de la 0 la 9, fireşte. Se ştie bine că un număr NU începe cu 0, poate fi 0. Dar 0 nu are nici el loc pe la numere, doar de la 1 în sus.

Am mai optimizat prin ACTUAL.h şi ACTUAL3.h, în zonele cu mai mulţi paşi pe numărul de cifre (MODUL2 şi MODUL4), felul cum se ţine cont de primele cifre ale numerelor admise la actualizarea marilor fişiere - condiţiile să fie mai simple, mai optimale la viteză, pe principiul "Scurt şi la obiect!". Acum funcţia URC2(), care are treabă cu SUS2()-ul de mai sus, se apelează prin ACTUAL-urile .h pentru modul 4 (cel cu paşi pe numărul de cifre , etapizaţi pe primele două cifre ale numerelor, cu 9*10 paşi - MODUL2 limitându-se la prima cifră, cu "doar" nouă paşi), atât pentru punctele succesive de pornire din marele fişier GIG care trebuie înnoit, cât şi pentru intervalele potrivite din fişierele .NUM cu noutăţi numerice, iar dacă la un pas dat vreun fişier .NUM nu are numere care să fie "primcifrate" şi "subcifrate" cum spune pasul de căutare (de exemplu, numere de 182 de cifre, prima cifră 2, a doua cifră 7 - deci să fie luate toate numerele care încep cu 27 şi mai au alte 180 după, atât la GIG cât şi la NUM-uri), atunci el este pur şi simplu exclus de la culegerea de numere noi* la acel pas, şi se mai bagă în seamă când i-o mai fi vremea.
Desigur, dacă i s-a depăşit limita superioară (urcsus la ACTUAL3, urccur dincolo la ACTUAL), iar nu este luat în seamă, că-i prea jos; sau dacă încă nu s-a ajuns la limita lui de jos (urcjos sau urccur), e exclus că-i prea sus.

Dar pentru că am pus la punct partea cu a doua cifră, se ajunge ceva mai repede la punctele de plecare care ţin cont de ambele cifre. Înainte, când deja ţineam cont şi de cifra a doua, se căuta optim prima cifră (cu fseek-uri sau sărituri înainte prin fişier, dar cu un număr relativ mare de octeţi pe pas, nu câte puţin, din rând - sau string - în rând), iar pentru a doua se cursa din rând în rând, până la satisfacerea celei de-a doua cifre (sigur, dacă ea era 0, rezultatul venea mai repede), deci cu mai mulţi paşi mai mici, şi asta mai trebuia rapidizat.

*Numere de fond 2 sau "de manevră". Ele sunt mult mai multe decât numerele preţioase (le subinclud, în fapt, sunt o supermulţime a lor) şi cu ajutorul lor se găsesc cele preţioase, ca atunci când într-o mină se scormoneşte prin multitudinea de pământ ca să fie găsite scumpătăţile incluse în el. Numitorul fracţiei ireductibile suma divizorilor/număr este sub 11 la preţioase, şi sub 1333334 la tot fondul 2, dar fără să excludă partea cu "sub 11" în funcţia de validare pentru fondul 2, aşa că fondul 1 < fondul 2 (am vrut să spun "inclus" în fondul 2, dar tastatura nu are acel simbol matematic aici), nu sunt disjuncte în N-uri şi GIG-uri, sau n-ar trebui să fie, pentru că după introducerea variantei celei îmbunătăţite de URC2 la actualizarea depozitelor numerice, din ce văd la filtrarea după numere de fond 1 a segmentelor de noutăţi de fond 2, apar şi destule numere de fond 1 care există deja în N-uri, şi credeam că sunt deja şi în GIG-uri - ciudat lucru, doar n-or merge prost dintr-o dată sortarea şi căutarea binară, cu care stabilesc care sunt noutăţile, şi nu taman acum când cu urcarea optimizată printre numere, în fişiere.
Poate cumva chiar nu erau îndeajuns de prezente numerele preţioase prin GIG-uri... în fine, şi aşa mai vin noutăţi veritabile, căci cota creşte. 29712 acela de mai sus este categoric superior situării din ultima parte a săptămânii trecute.

La NUMSIMPL, MODPRIME şi HMODIFSUM am pus să se dea exit(0) cu mesaj de alertă (Interzis zero.) dacă reies 0 coeficienţi de legătură pentru căutare, adică 0 factori primi la primele două programe şi compuşi la ultimul - dacă intervalul e atât de strâns încât nu are, sau oricum nu are coeficienţi cu care să se înmulţească sau să se împartă numerele existente, pentru obţinerea altora noi, atunci să nu se mai încerce nimic.

În loc de a==b, putem să mai zicem !(a^b).
Am mai vrut să optimizez ceva pe la NUMNUM.cc, care trebuie să numere numerele din GIG-uri - să se paralelizeze cu OMP, să poată număra din mai multe GIG-uri deodată, pentru viteză. Nu ştiu dacă e bine, trebuie văzut cum rulează.

Am mărit intervalele de cuprindere pentru coeficienţii de căutare, atunci când se lansează pe fişierele LPT (variantele mici ale GIG-urilor) cele trei programe zise mai sus: astfel, NUMSIMPL va căuta noutăţi folosind factori primi de până la 50000 în loc de 44444 (înmulţirea cu ei a numerelor nedivizibile cu ei, şi împărţirea celor o singură dată divizibile), MODPRIM va căuta cu factori primi până la 50000000 în locul lui 44444444 (asta doar de dragul formei numerice, realitatea fiind că tot numărul acela de factori primi din plaja componentă a numerelor este folosit), făcând înmulţirea cu ei pentru numerele divizibile minim o dată cu ei şi împărţirea pentru cele divizibile de măcar două ori, iar HMODIFSUM va folosi factori compuşi până la 5000 în loc de 4444, împărţiţi în patru intervale egale cu 1250, 2500, 3750 şi 5000, după ce au fost 1111, 2222, 3333 şi 4444.

Şi compuşii de la HMODIFSUM trebuie să fie produsele a măcar două numere prime la putere-unitate, iar numerele acestea prime să fie mai mult dintre cele capabile să apară la putere multiplă în factorizările numerelor, fiind aceste numere prime componente uzual incluse în rândul celor "H" elemente din vectorul primelor, adică la multiputere, de unde şi denumirea cu H în faţă. Sigur că există şi MODIFSUM, nefolosit în mod cotidian, unde factorii compuşi de căutare se fac din numere prime non-H.
Factorii compuşi pentru HMODIFSUM şi MODIFSUM sunt luaţi din fişierul /COEFLEG.h, unde sunt sortate crescător numere prime şi compuse.

Comentarii

Postări populare