Cea mai nouă reformă numerică

 În noiembrie 2023 am pornit o nouă reformă la numere și-am mai făcut progrese.

Am reorganizat fișierele din folderul special de anul trecut, cel numit „countPrimes”, și pe cele concepute pentru GMP și CPU le-am rebotezat la extensie, făcându-le să fie .cc în log de .cu. Le copy-păstuiosem în original din fișierele de CUDA cu logică pentru aritmetica cu operanzi nativi pe 32 de biți, făcându-le redenumiri în corpul de dinaintea extensiei numelui fișierului, adăugând niște 64 prin nume, și adaptând desigur codul-sursă să conțină funcții care să se adreseze logicii pe 64 de biți a CPU-ului, în locul celei pe 32 de biți de la placa video pe CUDA, dar păstrasem headerele de CUDA și conținuturile de declarații de bază + niște comentarii pe care le am și acum pe la fișierele de CUDA. Doar separasem parțial headeristica, să existe headere cu funcții speciale de procesare a datelor de abundență ale numerelor (MPZ și respectiv CUDA/CGBN), mai exact să se construiască factorii de înmulțire-împărțire cu care numerele de fond 1 se obțin unele din altele și să se studieze variația abundenței de la un număr la altul, ca astfel să se ajungă, printr-o formulă optimă, să se descopere rezultate (de multe ori numere de fond 1 deja găsite, dar uneori și lucrurile noi care sunt de fapt ținta tuturor acestor căutări).


Așa că din februarie-martie 2023, de când mă cam lăsasem pe tânjală cu numerele (cu excepția unor mici lucrări prin iunie, când am mărit memoria de la calculator de la 32 la 64 de GB DDR5) până în noiembrie, ziceam că-l mai aștept pe Achim Flammenkamp să mai posteze noutăți cu numerele multiperfecte (nu a făcut-o), și am mai studiat sporadic repository-ul public de Github al CGBN-ului, unde am lăsat anul ăsta în 2023 niște comentarii și, prin toamnă, chiar am deschis un pull request cu o modificare într-un fișier de bază care trata declarațiile de limburi (și din care lipsea structura pentru cazul când parametrul TPI este mai mic decât cel de LIMBS, sau LIMBS să fie multiplu de TPI), am încercat acolo o structură din asta. Mai trebuie să verific. Oricum nu a răspuns nimeni în timp rapid acolo.


Și nu făcusem chiar până la capăt anumite lucruri cu fișierele numerice. Din iarna trecută construisem niște fișiere laaargi cu coeficienți de legătură (potențiali sau mai puțin probabili, scriși pe perechi concrete sau doar pe combinații posibile) pentru numere, și ajunsesem iar să ocup spațiu mult, de genul totalului de sute de GB. M-am mai gândit între timp și la Cloud Computing (nu îi mai zic remote, că este pleonasm), și mai serios la cum aș face să-mi transplantez sau să-mi configurez fișierele pe cluster acolo, mai ales pe cele mari cu coeficienți. Că și generarea lor de la zero (de pildă, dacă mai apar numere noi și trebuie refăcută rețeaua de coeficienți de legătură) cere timp mai ales la  mine pe calculator, unde și memoria este mai mică decât ar fi cu adevărat nevoie. Căci am realizat că tot am nevoie de memorie mare pentru fișierele cu coeficienți de legătură, chiar dacă de această dată mă adresez direct la obiect doar mult mai micului fond 1, nu ca în 2018-2019, când aveam zeci și zeci de TB de numere de umplutură, de manevră, sau „de fond 2”, cu care mă ajutam (dar și pierdeam mult timp și consumam resurse serioase) ca să le găsesc pe cele de fond 1. Deci din nou ajung la ideea că am nevoie de mai mult RAM și de câțiva TB de storage, de data aceasta pe NVME.


Așa că mă gândesc ca la Cloud Computing să optez pentru o arhitectură care să ofere măcar 512 GB de RAM, sau chiar mai mult (1-2 TB), să fie DDR5 și să și aibă frecvență bună, măcar 5000 și ceva de MHz, nu să fie ca de DDR4. Până acolo, aș putea să-mi cumpăr iarna asta câte 192 de GB de DDR5 pentru fiecare dintre cele două calculatoare cu DDR5 din casă, cel cu AMD (pe care lucrez cel mai mult) și cel cu Intel, dar mai ales la AMD mă tem că mi-ar scădea serios frecvența, pe la vreo 4000 sau 4000 și ceva. La Intel poate că aș rămâne la 5000 și ceva. Se pare că la servere memoria cu densitate mare merge cu frecvență mai mare, iar la AMD-ul mainstream de care ține placa de bază X670E ACE am citit de curând că, anul trecut cel puțin, exista o limitare a voltajului de RAM la 1.43 volți, ceea ce înseamnă într-adevăr limitare la overclocking. Eu pe AMD la 64 de GB (4*16) stau pe 6000 de MHz stabil, dar a trebuit să rămân la o versiune de BIOS care nu este tocmai ultima. Dacă aș lua 4*48, ar trebui să dau discard la plăcuțele de 16 GB pe care le-am folosit deja (și la fel și la calculatorul cu Intel). Dar măcar a trecut aproape un an în total (a doua jumătate a lor a venit mai de curând totuși, până în iunie 2023) cu ele. Și totuși, la AMD perspectiva unei mar căderi a frecvenței de RAM dacă optez pentru 192 chiar că nu mă încântă!


Deocamdată însă, am mai reformat aparatul algoritmic numeric: am separat mai bine headerele de CUDA de cele de GMP/CPU cu limbajul C, cu compilator de C++ (g++) pe Linux, față de nvcc care se folosește special pentru fișierele de CUDA. Am convertit fișierele cu cod de GMP la extensia corectă, cea de .cc, și la compilare am văzut că dimensiunea în octeți a executabilelor de C++, așa cum sunt ele generate pe Arch Linux, este de vreo 5-10 ori mai  mică decât a unuia de CUDA, deci o situație mai la locul ei!

Am mai făcut îmbunătățiri prin codul-sursă din ambele părți, unde am mai găsit parametri inutili prin headerele funcțiilor și-am mai avut niște erori stranii care erau legate de stocarea în memorie a unor vectori cu dimensiune prea mare (și inutili), sau de nereturnarea unei valori în mod obligatoriu, atunci când se apelează o metodă de C care are tip returnabil (precum int), în loc de void. Sau dacă dimensiunea stringurilor cu care lucrez nu este mereu chiar cea mai potrivită - așa că trebuie avut grijă să nu se producă depășiri de capacitate. Scopul separării ferme a fișierelor de CUDA de cele de GMP de mai sus este și să mă ajute cu integrarea pe cloud computing a aparatului de fișiere - nu se poate opta simultan pentru un cluster cu CPU foarte puternic și cu video foarte puternic, ar fi două arhitecturi separate cu cost în plus pe măsură. Cel puțin din ce am văzut până acum.


Legat de returnarea unei valori dintr-o metodă de tip int, lipsa acesteia ducea la o eroare neobișnuită în consola de Arch Linux la execuția unui program: în locul obișnuitei Segmentation fault (core dumped), aveam acum o Illegal instruction (core dumped), dar este bine că am rezolvat-o. Mă gândeam și la fișierele cele mari, a căror încărcare pe clusterul de cloud computing nu ar fi una ușoară - în primul rând, acolo nu ar merge cu copierea directă ca în interiorul calculatorului, ci fișierele de la mine din PC ar trebui întâi uploadate undeva pe Internet (în Google Drive dacă au loc, sau eventual pe ceva de tipul File Transfer) și de acolo să le descarc în clusterul de Cloud, la viteza Internetului, în condițiile în care am 1 Gb de la provider (mai așteptăm după 10 sau 50 de gigabiți...).


La 0.5-1 TB de fișiere (din care grosul și chiar mai puțin grosul îl fac fișierele noi cu coeficienți de legătură), chiar ar dura câteva ore descărcarea pe cluster, și fiecare oră acolo costă! Însă și regenerarea lor de la zero pe cloud, chiar în condiții de forță de procesare sporită (192, 224 sau 256 de threaduri de CPU, că în primă fază cel puțin, nu aș opta pentru CUDA care are memorie mai mică și este mai scumpă) și cu RAM mai mult, tot ar cere atenție și pregătire pentru procesarea fișierelor, și-ar dura și acolo câteva ore într-un caz optimist, dar pentru aceasta scenariile de generare a fișierelor trebuiesc bine pregătite din timp, ca pe cluster să trec direct la acțiune. Că nu trebuie pierdut timp, acolo chiar se adeverește zicala aceea cu iz materialist care spune „Timpul costă bani”. Și pentru o optimă generare a acestor fișiere, mai trebuiau făcute îmbunătățiri în algoritmi și pe partea aceasta!


Și atunci, în a doua jumătate și-n special în ultima săptămână din luna noiembrie 2023, m-am ocupat mai îndeaproape de lucrurile de mai sus. Prin iunie mai reorganizasem ceva în procesul de generare a fișierelor de legătură dintre numere, profitând de proaspătul upgade de la 32 la 64 de GB de RAM pe calculator, dar acum am luat-o mai serios, voind o listă mai exhaustivă și mai bine împărțită a fișierelor și coeficienților (deocamdată, nu din orice combinații posibile de coeficienți înmulțire-împărțire dintre numere, mai ales că acolo se poate ajunge la terabaiți întregi și tot să nu se termine, dacă ar fi să scot din ei perechile posibile de înmulțire-împărțire și să le stochez în fișiere în loc să le fac din memoria calculatorului de fiecare dată - ci perechile de coeficienți cu care numerele de fond 1 chiar se obțin direct și dovedit unele din altele, și ale căror dimensiuni sunt mai variate).


Chiar și așa (eliminând o sumedenie de coeficienți care sunt doar „potențiali” și ale căror combinații pot rezulta în conținut pluriterabaitic și foarte dificil de stocat și de procesat prin citire-scriere din fișiere, sau chiar prin lucrul repetat din memorie asupra lor), și aceste perechi de coeficienți direcți ocupă câteva sute de GB, dacă acoperă toată gama de mărime de până la numărul 10 la puterea 1910. Le lucrez deocamdată pe partea de GMP/CPU, deși am făcut îmbunătățiri și revizuiri și prin fișierele de CUDA, și le-am separat în fișiere pare și impare (unde prin impare se înțeleg fișierele care conțin perechi de coeficienți de legătură între numere, care conțin doar numere impare, iar prin fișiere pare, cele ale căror perechi au măcar un element par, deci pur pare și mixte). În funcție de paritatea fișierelor de coeficienți, se apelează anumite programe (pregătite pentru procesare de coeficienți exclusiv impari, sau cu paritate omogenă ori mixtă - într-al doilea caz fiind implicate și niște puteri de 2). Astfel, fac o separare a responsabilităților programelor și se optimizează astfel distribuția de funcționalitate: într-un fel se lucrează cu numerele impare și altfel cu cele pare, și știi când și cu ce lucrezi! Încă de iarna trecută am făcut împărțiri între fișiere pe baza parităților coeficienților, iar acum am aprofundat.


După construirea fiecărui fișier de coeficienți direcți de legătură între numere, are loc împărțirea lui în pare și impare (câte 2 sub-fișiere), iar fișierul original se șterge, pentru economie de spațiu. Și pentru pragmatism - căci de lucrat se va lucra ori cu cel par, ori cu cel impar, nu cu tot fișierul-părinte luat bulk. Am făcut la GMP fișiere de legătură astfel:

- pentru coeficienți mai mici de 2 la puterea 64, numiți și coeficienți de legătură mici, sau care pot fi tratați ca întregi nativi de către CPU, respectiv gmp_ui sau unsigned long long (ori chiar uint64_t), și nu ca mpz_t, ceea ce duce la o mai bună viteză de lucru cu ei;

- pentru coeficienți mai mici de 10 la puterea 100, apoi 200, 500, 800 și 1910 - cazuri în care ambii coeficienți trebie să fie mai mici decât limita de sus, iar cel puțin unul dintre ei să fie m ai mare decât cea de jos, celălalt putând fi și mai mic (de pildă, pentru coeficienții mai mici de 10 la 200, minimul este 10 la 100, iar unul dintre cei 2 coeficienți din fiecare pereche poate fi mai mic de 10 la 100, dar măcar celălalt obligatoriu să fie mai mare decât acel minim, care a fost deja tratat în generarea unor fișiere de coeficienți precedente, cu maximul 10 la 100).


Am căutat să optimizez și timpul de generare a fișierelor, și numărul de fișiere folosite, rapidizând algoritmii de generare-sortare lexicografică a perechilor de coeficienți, care sunt interpretate ca stringuri, nu ca numere de precizie aritmetică arbitrară - tot din rațiuni legate de rapiditatea procesării. Desigur că limita de 64 de GB a memoriei se resimte, chiar fără ca numărul de „doar” 32 de threaduri ale procesorului 7950X să apuce să constituie o problemă. Și în consecință și pe cloud computing, unde numărul de procesoare avute la dispoziție nu trebuie să fie o problemă, RAM-ul trebuie să asigure faptul că nu sunt limitări legate de memoria disponibilă. De aceea, dacă voi intra pe cloud computing, memoria va trebui să fie cât mai mare, chiar la extrema de 1-2 TB. Dacă sistemul de CPU va fi, spre exemplu, un cuplu de EPYC-uri de câte 128 de threaduri fiecare (deci total 256 de procesoare virtuale), sai măcar să fie 224, atunci va fi foarte bine.


Și spațiul de stocare să fie de tip NVME și să aibă măcar 2 TB (chiar 4), însă atunci ar putea costa destul de mult, vreo 20 de USD pe oră, dacă nu chiar mai mult. Și dacă mă obligă să închiriez cu luna, prețul pe lună va fi chiar inaccesibil - sigur peste 10000 de dolari. Însă și platforma de cloud trebuie să mă accepte pe ea - am încercat sptămâna trecută să îmi fac cont pe Linode (Akamai) și am primit de 2 ori Signup cancellation, ce au mai pățit și alți oameni. Ar trebui vorbit cu suportul lor. Și oricum, chiar dacă forțau închirierea cu luna (nu lăsau cu ora) la un echipament extrem, cu peste 10000 USD pe lună pentru ce mi-aș fi dorit, totuși generația de CPU EPYC nu era ultima. Era din 7000+, nu din 9000+. Adică și cu DDR4 în loc de DDR5. Bine măcar că există calculatoare online care te lasă să simulezi cât de mult ar costa o anumită configurare de cloud computing, cu ora sau cu luna. Așa mai pot să aflu orientativ cât aș plăti pentru următoarea treaptă a dezmățului hardwareistic-numeric. Nici pe Google Cloud nu am găsit ceva care să corespundă bine cu exigențele de memorie și CPU.

Dar categoric trebuie să pot închiria cu ora, procesoarele să fie cumplit de puternice și de ultimă generație, iar memoria DDR5 să aibă viteză bună și să fie multă, multă! Acolo este un tip diferit de DDR5, Registered sau ECC, nu non-registered precum cea pe care o pot avea acasă, de asta cred că și poate rula la frecvențe mai mari când densitatea este mare. Că la asta non-registered, dacă este dual-rank (= densitate mare, 32 sau 48 de GB pe plăcuță) și mai și umple toate sloturile, frecvența scade mult-mult față de 2*16, care nici acelea nu funcționează chiar foarte rapid peste tot!


La video există, pe lângă 4090-uri care deja sunt închiriabile, și plăci cu memorie mai mare, de 48 sau 80 de GB (RTX 6000, sau Teslele). Dar acelea sunt mai scumpe decât 4090-urile, și în general configurațiile video cred că-s mai scumpe decât cele de CPU!


În legătură cu spațiul de stocare pe NVME, am început să reconsider capacitatea celor două NVME-uri de PCI-E 5.0 pe care le aștept (și ale căror viteze de citire-scriere pe secundă trebuie să treacă de 14 gigaocteți): să aibă câte 4 TB,  nu câte 2. Ca să fie loc la fișierele de coeficienți pentru numere. 4 TB este oricum capacitatea maximă așteptabilă, la început, pentru noile NVME-uri de pe piață! Până la 8 mai este.

Iar cele de 1 TB sau mai mici ar și tinde să fie mai încete decât cele de 2 TB și mai sus așa că, chiar dacă ar costa ceva, trăiască spațiul rapid și mare de stocare!

Pentru noile căutări cu  numerele am mai umblat în BIOS, pentru mărirea forței procesorului: AMD-urile de teapa lui 7950X suportă niște setări numite Precision Boost Overdrive și CBS (dacă le-am ținut bine minte numele). Pe la frecvența memoriei nu prea am curaj să umblu că mi-e că iar nu mai pornește sistemul și trebuie să dau reset la BIOS. Stau momentan cu 6000 de MHz pe AMD. Dar am activat și la ea o setare avansată pentru opțiunile de lucru. Pare că se mișcă mai bine mașinăria!


Și am și descoperit un număr nou, urcând de la cota 32287 - la care rămăsesem înțepenit pe 20 februarie în 2023 - la 32288! Are 152 de cifre. L-am găsit în miercurea de 29 noiembrie 2023 folosind coeficienții impari de spirală dintre numerele de fond 1, dar desperecheați și neduplicați. Pentru că am luat în calcul și căutarea cu ajutorul acestor coeficienți fără ca ei să stea exact în perechile de înmulțire-împărțire (sau invers, împărțire-înmulțire) în care sunt găsiți, ci să fie împerecheați și separat, în toate combinațiile lor posibile (de această dată calculate în memorie, nu scrise prin alte fișiere, că nu mi-ar ajunge spațiul de stocare să le scriu pe toate nici dacă aș avea câteva sute de TB de NVME-uri în loc de hard disk-uri - plus că și citirea intensă din fișiere ar aduce presiunea și overheadul ei), că sigur nu au fost împerecheate în toate combinațiile posibile. Așa că pot și sorta lexicografic crescător fișierele cu perechile de numere, număr cu număr. Fiind sortare de stringuri și nu de numere mari, nu se sortează aritmetic crescător, ci lexicografic crescător.


Zilele acestea care au urmat, am mai îmbunătățit algoritmii care scriu perechile de coeficienți de legătură în fișiere: să folosească în mod mai economic resursele de memorie, ca să și pot genera mai repede conținuturile, fără teama atât de stringentă că ating limitele memoriei de 64 de GB. Că deocamdată nu o să iau loturi de 192 de GB de RAM pentru acasă, nici nu mă grăbesc la cloud computing. Mai caut cu ce am acasă!


Și am mai avut un caz special și pe la programul care face înmagazinarea de numere noi - când este cazul - în depozit: VECUNG2.cc, unde după ce am transmis fișierul greșit (factori pari la un program pentru numere impare de legătură), am avut u fals număr nou, care se voia a fi al 33289-lea, dar de fapt era numărul 2 la puterea 4500 și ceva, o putere de doi atât de mare încât a reușit să treacă digul de apărare al numerelor împotriva membrilor paraziți - așa că a trebuit să am grijă și acolo.

Am mai făcut ordine în indentarea și formatarea pe paragrafe a fișierelor cu cod-sursă (C și CUDA) din ultimul an, ca să fie mai ușor de citit și fără spații goale fără rost prin ele. Contează și ordinea din interior, nu numai să meargă programele corect și rapid! Iar în afară de noile îmbunătățiri, ordonări și căutări, am mai salvat aparatul algoritmic și numeric (dar fără cele mai mari fișiere de coeficienți, că ocupă spațiu mult) și pe internet, că pe calculator mai pot să apară greșeli și prostii.


Faptul că a mai existat cel puțin un număr de găsit, și fără ajutorul indirect al lui Achim Flammenkamp, înseamnă că povestea cu numerele mai este de interes și că mai pot fi căutate lucruri cu ea! Nu s-a oprit totul definitiv în februarie 2023. Noua cercetare asupra numerelor a dat și prilejul rezolvării unor probleme nemaibăgate în seamă și găsirii unor idei noi!


Iată și cum poate să decurgă o acțiune de căutare a numerelor al căror raport dintre suma divizorilor și ele însele, exprimat ca fracție ireductibilă, are numitorul cel mult egal cu zece. La război cu numerele!



Comentarii

Postări populare