Ce altceva am mai făcut cu numerele în 2021 și chiar și în 2022?

Cu reforma numerică din 2021, unde am dat mai multă atenție căutărilor spiralate, am pus în cod o sumedenie de funcții noi pe care le-am denumit, sugestiv, reforma spiralei. Au fost și dăți când am stat târziu peste noapte să meșteresc pe la numere, inclusiv pe Veriton, făcând economie la curent. Nici nu am folosit foarte mult Threadripperul, care avea Arch Linux, ci am stat mult cu Notepad++ în Windows și am verificat funcționarea programelor și cu ajutorul lui g++ din emulatorul cygwin pe 64 de biți, care este o modalitate de a simula unele programe de Linux pe Windows, deși pe pagina lor oficială se spune că acest Cygwin nu este o cale de a rula aplicații native de Linux sub Windows. Și la urma urmei, din practica experienței, cel mai bine se rulează programele de Linux tot pe... Linux. Pe Cygwin pot să apară erori și limitări de configurație care pe Arch Linux să nu fie. Și-apoi chiar și între diferitele Linuxuri (precum Ubuntu versus Arch Linux) pot fi diferențe de comportament la compilare, unde Ubuntu să fie mai sever cu warning-urile și cu erorile, cum Arch Linux nu e, dar la povestea asta am ajuns mai încoace, nu în 2021. În cel mai recent an în care 1 ianuarie și 1 octombrie au început vinerea, am pus multă emfază pe algoritmii de căutare spiralată a numerelor, și pe îmbogățirea parcului de coeficienți de legătură (COEFLEG), căci strict dintre numerele de fond 1, cu VC și VC de MPZ, ieșeau mai puține numere de legătură, mai ales mai mari, și cel mai probabil să găsesc numere de fond 1 unele dintr-aletle vedeam că este când lucrez cu coeficienți mai mici. Oricum, am adunat mai mulți gigabaiți de numere de legătură, mai ales pe 64 de biți, în fișierele COEFLEG.


Care au fost și ele pe trei varietăți: COEFLEG simplu, cu factori pe 64 de biți pentru înmulțit sau împărțit (ori înmulțit ȘI împărțit) numerele cu ei, mai ales la fondul 1, ca să nu mai fac atâta risipă de spațiu și RAM a fondul 2, apoi COEFLEGMPZ, cu numere de legătură peste 64 de biți, dar făcute numai cu numere prime pe 64 de biți, și în sfârșit și MPZCOEFLEGMPZ.TXT, unde factorii de legătură musai să se împartă și cu ceva numere prime mai mari de 2 la a 64-a, iar programele care construiau aceste texte erau și ele separate și se chemau la fel - COEFLEG, COEFLEGMPZ și MPZCOEFLEGMPZ. Dar cel mai mult conținut l-am general la COEFLEG. Celelalte două au rămas mici. Iar de-a lungul timpului am păstrat două versiuni de  COEFLEG.TXT: una mai mică, sub 70 de MB, pentru Veriton, care avea resurse mai mici, și pe cea mare pentru Threadripper. Până ce a venit vremea pentru încă o altă reformă (ajungem noi și-acolo).


Țin minte sigur că în afara lui 13 mai am stat peste noapte și pe 5 și 13 iunie, și se prea poate că au mai fost și altele. Am pus treptat la punct aparatul algoritmic pentru MODNUM-uri, găsind soluții pentru eficientizarea codului la căutările în spirală, precum reducerea între factorul de înmulțire și cel de împărțire, ca ei înșiși să formeze o fracție ireductibilă, fiind așadar cât mai mici posibili și, pe cât posibil, să fie primi între ei, sau oricum fără divizori primi care să se repete de sus până jos. Așa încât înmulțitorul și împărțitorul, separate în criteriile de mărime (64 de biți versus mpz_t), trebuiau:

-să nu fie egale;

-înmulțitorul să nu se împartă la împărțitor;

-nici invers, împărțitorul să nu se împartă la înmulțitor.


Iar dacă aveau alți divizori sau puteri prime în comun, mai departe se făcea oricum CMMDC (fie pe 64 de biți, fie cu mpz_gcd pentru factorii peste 64 de biți, luați cu tipul întreg de la GMP, de mpz_t) și apoi se dădeau mai departe rezultatele împărțirii înmulțitorului și împărțitorului la CMMDC, cu numele de rez1 și rez2, ca pereche redusă pentru spirală, interpretabilă și ea ca fracție ireductibilă ca numărătorul și numitorul abundențial. La 15 iulie 2021 mai aveam de definitivat niște lucruri în legătură cu reducerea abundențială, aveam să mă reocup prin februarie-martie sau mai curând octombrie 2022 și de ele, și de niște noi optimizări pe la VECUN.h, la funcțiile de căutare a numerelor. Astfel am considerat încheiate socotelile cu reforma spiralei din 2021-2022, și am pus la punct și un sistem de generare rapidă a fișierelor de numere prime componente, pentru diferite cazuri de mărime maximă a numerelor (maxim 52 de cifre, maxim 60... din 10 în 10 până la 300 de cifre, apoi pentru maxim 360, 420, 500 și 1910), tot cu vecun și VECUN.h, cu o linie specifică de parametri din linia de comandă. Mai prin 2022 am făcut și un header separat numit VECUNSPIRALMIX.h pentru partea spiralată de căutare a numerelor de fond 1 unele din altele cu sumele divizorilor calculate de la temelie (nu de la zero, că suma începe cu 1 și crește prin înmulțiri) și, pentru silaba MIX, cu amestecarea parităților factorilor primi. Am vrut să nu adun totul într-un singur header, VECUN.h.

Ce altceva am mai făcut la VECUN.h: funcțiile de populare cu factori de legătură a vectorilor specifici, care de tip întreg nativ pe 64 de biți, care mpz_t, care de tip COEFLEG, care de tip VC... și generarea separată, par/impar și gmp_ui/mpz_t, în fișiere diferite și cu funcții diferite (VC contra VCPAR), a factorilor de legătură aflați strict între numerele de fond 1, ordonate crescător în fișierul N3.TXT - iar după generarea acestora, programul vecun să se oprească, deci caz special. Ultima dată când am umblat acolo și am și pus numere de fond 1 derivate din multiperfectele lui Achim Flammenkamp a fost pe la mijlocul lunii octombrie 2022, în noaptea de 15 spre 16 iarăși am stat. Era sfârșit de săptămână, sâmbătă spre duminică. Tot atunci am mai optimizat pe la funcțiile acelea din VECUN.h și, dacă nu am uitat, atunci am și separat funcțiile de acolo de cele din VECUNSPIRAL.h, fiecare header cu răspunderea sa.

Dar VECUNSPIRAL trebuia inclus din VECUN.h. Am făcut-o!


Până în toamna lui 2022 am tot stat pe Veriton, apoi am făcut upgrade la viteza de Internet la un gigabit, în locul celor 100 de Mb de dinainte, așa că apoi am trecut la SLI PLUS din 3 octombrie până după 20 noiembrie, am migrat Windows-ul acolo (făcut între timp 11) cu o cheie de Retail, ca să pot scăpa de OEM-ul de pe Veriton, iar după 20 noiembrie am încercat și cu Asuspraimul, cu Threadripper pe Linux și Windows-ul eliberat... dar din nou, ajungem și acolo.

După 2021 nu am mai făcut căutări de numere de fond 2 pe nicăieri, am părăsit cu totul practica păguboasă de luat pe ocolite și folosit muuulte numere de manevră pentru a atinge ce voiam de fapt. Scăparea de sub strategia de acumulat numere de fond 2 pentru găsirea celor de fond 1 mă elibera de povara terabaiților și-a munților de RAM, care desigur că au atârnat și ei mult-mult la bani. De creditul moștenit de la progresul calculatoristic din 2017-2019 am scăpat de tot în septembrie 2021, am mai acumulat bani de la noul job, și m-am gândit și la viitorul acela în care să folosim remote echipamentele hardware foarte puternice (Remote Cloud Computing), pentru un preț mult mai mic decât dacă ne cumpărăm și construim acasă + consumăm curent. Însă consideram că mai avem până acolo și că între timp tot mai este loc pentru niște măgăoi acasă, de această dată cu o concentrare pe partea video pentru CUDA (și pe viteza memoriei mai mici, și pe CPU-uri, dar nu cu aceeași foame de nuclee multe ca la Threadripper). Prin 2019 descoperisem potențialul plăcilor video la viteză. Dar nici nu mai aveam bani deoparte pentru ele, deja investisem atât de mult în celelalte componente și aveam credit, iar salariul rămăsese mic.


Legat de reducerea la nivel de fracție ireductibilă a înmulțitorului și împărțitorului pentru căutările numerice spiralate, de care ziceam mai sus, aveam funcții cu nume precum VERIFREDUCT (pentru 64 de biți), VERIFREDUCTMPZ pentru factorii mai mari, și VERIFREDUCTSIMPL (tot la 64 de biți). unde se considera din start că înmulțitorul și împărțitorul sunt diferite și în funcție nu se mai verifica inegalitatea lor, ci restul (non-divizibilitatea lor de orice fel, CMMDC).

Și prin august 2022 cu 2021 am mai meșterit niște programe care calculau deplasarea prin spațiul cosmic a unei nave care ar folosi progresia aritmetică, respectiv pe cea geometrică, cu depășirea vitezei luminii.

Alt lucru făcut prin 2022 a fost să declar niște headere cu variabile comune (array-uri 2D, de exemplu) pentru fișierele de MODNUM și nu numai, cu silaba DECL în denumire, care să aibă aceste globale acolo și să nu mai duplic cod cu ele în toate fișierele .cc. Precum MODVERNUMDECL.h sau MODNUMDECLSPIRAL.h, altfel suita de matrici declarate acolo ar fi tot apărut de la capăt prin .cc-uri. Deși practica intensivă a globalelor mai taie din viteza de execuție, totuși prin mărimea cerută de aceste array-uri devenea improbabilă posibilitatea folosirii lor strict ca locale, dacă depășim memoria de cache L1 a CPU-ului (sau de pe unde s-o aloca memoria stack în limbajul C).

În 2021 mai lucram la alte varietăți de căutare a numerelor cu factori în sus/în jos, de tipul TOL, unde fie se citește un număr (de preferat de fond 1) de la tastatură și se merge în sus sau în jos la alegere, fie se trece prin mai multe astfel de numere de fond 1 din N3.TXT și, cu factori de legătură neprimi de tipul MODIFSUM, pari ori impari, să se calculeze; am făcut variante pentru mpz_t și 64 de biți, cu nume de genul MODIFTOL sau MODVERTOL. În practica obștească însă, nici nu le-am rulat, dar măcar mă mai uitam dacă se compilează fără erori. Căutările pe care le-am făcut cu adevărat au fost din sfera NUMSIMPL, MODPRIME, MODNUM (fără pare, doar impare, și cu legături pe 64 de biți, fără mpz_t, dacă nu îmi scapă ceva) și spiralele acestora, tot impare, dar fără a avea altceva decât acele trei numere noi din luna mai, la capitolul noutăți, și se înțelege că făcând abstracție de derivatele multiperfectelor lui Achim Flammenkamp, când mai era vorba despre ele (deși până prin 2022 a fost pauză și pe-acolo, s-ar fi zis că a murit cercetarea lor pe partea asta).


Tot în perioada mai-iulie 2021, am mai stat să lucrez la echivalentul programelor de mai sus, făcute special numai pentru numere pe 64 de biți, fără mpz_t, și care aveau în mod obsedant în numele fișierelor particula „VER” de la Veriton, în ideea că vor fi folosite pe Veriton pentru lucrul cu numerele pe 64 de biți, de tip unsigned long long, și prin lipsa gamelor de mărime de la mpz_t sau a numerelor prime diferite de 64 de biți + a puterilor prime mai mari de 64 de biți, cazurile de utilizare erau mai puține, însă tot a fost ceva de meșterit și pentru VER-uri. Și NUMSIMPL, și MODPRIME, și MODNUM, și VECUN au avut variante de VER, cu toate sub-combinațiile de par, impar, spirală, factori COEFLEG sau VC, și MODNUM generalist. Fișierele generaliste conțineau și silaba GEN, cele care aveau și căutare cu factori pari, și cu impari și sus, și jos, așa încât se puteau întâlni nume ca MPZMODNUMLEGGENSPIRAL (căutare cu factori de legătură mai mari de 64 de biți - MPZ - divizibili cu numere prime pe 64 de biți -  MODNUM - luați din fișierul text cu valori de tip mpz_t care leagă direct numerele de fond 1 - LEG - și cu toate paritățile, paritate generalizată - GEN -  și-apoi în spirală - SPIRAL), MODNUMLEGGEN, MODVERNUMLEGGEN (varianta de Veriton).


Și o altă găselniță numerică, dar tardivă, de toamnă 2022, a fost la sfârșitul calculelor pentru abundența unui număr, unde pentru reducerea operațiilor de împărțire, când nr și nm modificate erau gata, în loc să le fac mpz_gcd și să văd dacă rezultatul * 11 e mai mare decât nm, alegeam să înmulțesc nr cu 2520 (care este cel mai mic multiplu comun al numerelor de la 1 la 10, numitorii abundențiali tolerați pentru fondul 1), iar dacă rezultatul era divizibil cu nm, atunci să fac o împărțire la nm și după ea CMMDC-ul întreg nativ dintre rezultat și 2520 (căci nu putea fi vorba de numere mai mari de zona până în 30000) și, dacă produsul dintre numărul 11 și acest CMMDC depășea 2520, atunci numitorul abundențial al noului număr mare mpz_t era maxim 10, căci câtul dintre 2520 și CMMDC însemna că este maxim 10. Oricare era situația, era de preferat schema asta față de mpz_gcd, dacă mpz_gcd face cam multe împărțiri mpz_t. Plus comparația finală, strict între întregi nativi mici, nu între mpz_t-uri.

Împărțirea, mai ales la tipuri de date artificiale cu numere mai mari decât cele direct suportate de procesor, este o operație costisitoare ca timp, și trebuie să fim deștepți când scriem codul sursă și să evităm împărțirea pe cât posibil. Înmulțirea și mai ales adunarea (ori scăderea, dacă este nevoie de ea) au rapiditate. Un programator trebuie să fie deștept când își scrie codul-sursă, cu sau fără hardware puternic la îndemână, fie el remote prin cloud sau măgăoi acasă.

Comentarii

Postări populare