kyrsjo Skrevet 12. september 2007 Del Skrevet 12. september 2007 Hei! Jeg driver og løser differentsiallikninger på datamaskin, noe som går sinnsykt fort (problemet mitt (Poisssonlikningen i en dimensjon) kan reduseres til å radredusere en Nx(N+1)-matrise - og det tar under ett sekund selv for *STORE* N - type 10^6 - algoritmen skalerer som 6(n-1)). Problemet mitt ligger i utskriften til fil - denne tar langt mer tid - det er en del data som skal ut (sist gang endte det vel på ~500 MB). Harddisklampa forteller meg med all mulig tydelighet at det er ikke IO-båndbredde som er problemet. Anyway, her er den aktuelle løkka: //Write the solution to a file - it takes time... void file_output(char* filename, int arraylength, double* y) { //SETUP const int precision = 20; const int fieldwidth = precision + 10; ofstream ofile; ofile.open(filename); ofile << setiosflags(ios::showpoint | ios::uppercase); double h = 1/(arraylength+1.0); //Yes, i'm making assumptions to make it go faster for(int i = 0; i < arraylength; i++) { ofile << setw(fieldwidth) << setprecision(precision) << (i+1)*h; //Ditto - i don't want to waste mem on this ofile << setw(fieldwidth) << setprecision(precision) << y[i] << endl; } ofile.close(); } Grunnen til at jeg skriver det ut til fil, er at det skal mates til gnuplot etterpå. En annen ting som tar tid, er å initialisere array'ene: //Initialize arrays cout << "Initializing arrays...\n"; double* fn = new double[N]; //Function values double* an = new double[N]; //Diagonal entries double h = 1/(N+1.0); for(int i = 0; i < N; i++) { an[i] = 2; } //arrayprint(an,N); //Debug check for(int i = 0; i < N; i++) { fn[i] = h*h*function1((i+1)*h); } //arrayprint(fn,N); //Debug check Her kaller jeg på denne funksjonen: //Calculate the function value. Yes, i know it is poor naming. inline double function1(double x) { return (3*x + x*x)*exp(x); } Merk at denne er inline, så en skulle tro at jeg slapp overhead ved funksjonskall inne i løkke. Forøvrig: $ time ./poissson 100000 Solving with 100000 meshpoints, saving data to outdata.dat Initializing arrays... Eliminating anything beneath the diagonal... Backward-substituting... Cleanup: Delete an[]... Writing solution to outdata.dat... real 0m0.793s user 0m0.468s sys 0m0.324s Egentlig ikke så veldig ille Plattform er GNU/LINUX (Fedora 7), gcc 4.1.2-12, Intel centrino duo 2.0 ghz m. 4 MB cache pr. kjerne Lenke til kommentar
Dj_Offset Skrevet 12. september 2007 Del Skrevet 12. september 2007 Anyway, her er den aktuelle løkka: //Write the solution to a file - it takes time... void file_output(char* filename, int arraylength, double* y) { //SETUP const int precision = 20; const int fieldwidth = precision + 10; ofstream ofile; ofile.open(filename); ofile << setiosflags(ios::showpoint | ios::uppercase); double h = 1/(arraylength+1.0); //Yes, i'm making assumptions to make it go faster for(int i = 0; i < arraylength; i++) { ofile << setw(fieldwidth) << setprecision(precision) << (i+1)*h; //Ditto - i don't want to waste mem on this ofile << setw(fieldwidth) << setprecision(precision) << y[i] << endl; } ofile.close(); } Testet her med algoritmen du skrev og N=1000000 real 0m48.556s user 0m8.745s sys 0m6.852s Med minimale endringer av koden ovenfor: real 0m12.748s user 0m6.624s sys 0m0.284s setw og setprecision er *tregt*. Alternativ løsning som ikke tar hensyn til at formateringen blir *helt* lik. char buf[fieldwidth*2+1]; char buf1[fieldwidth+1]; char buf2[fieldwidth+1]; const char* fmt = "%.20f"; const char* format = "%30s%30s\n";*/ for(int i = 0; i < arraylength; i++) { sprintf(buf1, fmt, (double) (i+1)*h); sprintf(buf2, fmt, (double) y[i]); sprintf(buf, format, buf1, buf2); ofile << buf; } fstream i seg selv er også treg, men optimaliseringen sålangt er kanskje god nok? Lenke til kommentar
kyrsjo Skrevet 12. september 2007 Forfatter Del Skrevet 12. september 2007 Takker, skal prøve så fort jeg kommer hjem fra jobb! Ante meg at de var treige ja, men ikke så treige! Kan være jeg prøver å redusere antall siffer noe, 20 siffer og double gir egentlig ikke så veldig mening (spesiellt mtp. at det bare skal plottes uansett...) Kan det være seg at det lønner seg å f.eks. buffre x antall linjer, og så dumpe alle til fila *smakk*? IO-båndbredde sitter forøvrig og kjeder seg slik det er i dag... Lenke til kommentar
kyrsjo Skrevet 12. september 2007 Forfatter Del Skrevet 12. september 2007 Med ny utskriftsløkke: [kyrre@sinus taskC]$ time ./poissson 10000 Solving with 10000 meshpoints, saving data to outdata.dat Initializing arrays... Eliminating anything beneath the diagonal... Backward-substituting... Cleanup: Delete an[]... Writing solution to outdata.dat... real 0m0.041s user 0m0.030s sys 0m0.010s Litt bedre i allefall. Spurte foreleseren, han mente at det kanskje var cout som var synderen, og at bytte til "printf for fil" (C ikke C++) kanskje ville gjøre nytten. Men: Denne filutskriften er buffret, ja? Er egentlig ikke så veldig farlig, bare irriterer meg over at jeg har funnet den mest "über-effektive"-gaus-eliminasjonen, men filutskriften trekker så grøsslig ned... Lenke til kommentar
Roptaty Skrevet 20. september 2007 Del Skrevet 20. september 2007 Ingen hemmelighet at streams i C++ er kjempetregt. Du kan prøve å bruke open, og write kallene. $ man 2 write Lenke til kommentar
Coaxmetal Skrevet 12. oktober 2007 Del Skrevet 12. oktober 2007 » x=A\b; » n=1000000; » e=ones(n,1); » A=spdiags([e -2*e e], -1:1,n,n); » h=1/(n+1); » X=[h:h:(1-h)]'; » b=1/pi^2*sin(pi*X); » x=A\b; I Matlab (antar du har 0 på randa, samt høyreside lik 1/pi^2sin(pix), trenger bare marginale endringer for å endre høyresida og sånt..)... Tok tida og med en million ukjente tok det 0.1719 (cputime), du vil gå tom for minne før du når en spesielt ufin kjørtid (du vi lagre 3n tall i dp i A, n i x og n i høyresida, så 5n tall i dp, dvs 40 MB med n=1*10^6..) Dessuten har du tilgang til langt bedre plottemuligheter i matlab.. Men for all del, det er jo gunstig å lære seg å skrive i c++ også Senere når du evt må løse din egen ligning på en superdatamaskin må du jo kode i c for å utnytte paralelliseringen etc. Lenke til kommentar
kyrsjo Skrevet 13. oktober 2007 Forfatter Del Skrevet 13. oktober 2007 Viste ikke om spdiags i MATLAB. Programmet mitt ble uansett temmelig effektivt Ang. plotting, så er det mye man kan gjøre med gnuplot og (skall)skripts, bare kjedelig at du (så vidt jeg vet?) må gå via disk for å kunne bruke gnuplot. Hadde jo vært überkult å kunne overføre hele arrayet til gnuplot og plotta på den måten, uten å gå via disk... Evt. kan gnuplot lese ting som ikke er i ASCII-format? Akkurat dette progget er uansett ikke egnet for paralellisering da det er temmelig seriellt, hele algoritma... Lenke til kommentar
Mr.Garibaldi Skrevet 13. oktober 2007 Del Skrevet 13. oktober 2007 Viste ikke om spdiags i MATLAB. Programmet mitt ble uansett temmelig effektivt Ang. plotting, så er det mye man kan gjøre med gnuplot og (skall)skripts, bare kjedelig at du (så vidt jeg vet?) må gå via disk for å kunne bruke gnuplot. Hadde jo vært überkult å kunne overføre hele arrayet til gnuplot og plotta på den måten, uten å gå via disk... Evt. kan gnuplot lese ting som ikke er i ASCII-format? Det er mulig at du kan bruke gnuplot_i for å laste data direkte inn i gnuplot.. Det skal være mulig å laste inn data direkte, da gnuplot-py sier den kan gjøre det... Mulig du må lete litt i kildekodene for å finne hvor/hvordan det gjøres, men det kan kanskje være verdt det... Lenke til kommentar
kyrsjo Skrevet 14. oktober 2007 Forfatter Del Skrevet 14. oktober 2007 Det er mulig at du kan bruke gnuplot_i for å laste data direkte inn i gnuplot.. Det skal være mulig å laste inn data direkte, da gnuplot-py sier den kan gjøre det... Mulig du må lete litt i kildekodene for å finne hvor/hvordan det gjøres, men det kan kanskje være verdt det... *BOOKMARKED* Lenke til kommentar
Anbefalte innlegg
Opprett en konto eller logg inn for å kommentere
Du må være et medlem for å kunne skrive en kommentar
Opprett konto
Det er enkelt å melde seg inn for å starte en ny konto!
Start en kontoLogg inn
Har du allerede en konto? Logg inn her.
Logg inn nå