Effektivisering av Matlab igen

Permalänk
Entusiast

Effektivisering av Matlab igen

Hej igen, nu sitter jag här med ett exjobb som tar på tok för lång tid att köra. Grunden till problemet är en ineffektiv algoritm för att numeriskt lösa diffekvationer men den är inte så mycket att göra åt i det här läget för jag har helt enkelt inte tid att göra om allt från början. Jag kan däremot leta lite små enkla saker som kan spara mig en del tid. jag har redan gjort mig av med alla globala variabler vilket sparade mig typ 40 % av körtiden. Nu har jag kört ett varv med profiler igen för att se vad som stjäl tid och hittat två bovar som jag inte kan lösa själv och ber därför internet om råd.

Den första är en if-sats som ska kolla ett villkor i en massbalans. Det handlar om att det inte får flyttas mer massa än som finns från ett ställe till ett annat. Den ser ut såhär:

if any((const.r(:,j)./char.faceV)>(1./char.faceV)) disp('Mass balance error. Too much reaction in one cell') keyboard end

Finns det ett smidigare sätt att lösa det där med boolean eller liknande? Jag vet att matlab verkligen inte tycker om if-satser och jag har plockat bort satser från andra ställen redan men här vet jag inte riktigt hur jag ska lösa det.

Nästa problem är de här raderna:

a = -const.u_e(:,j)./2+const.u_w(:,j)./2-ones(const.n_PSD,1).*(const.D./mesh.nodedE(j))-ones(const.n_PSD,1).*(const.D./mesh.nodedW(j)) ... +const.u_exit(:,j)-((const.r(:,j).*char.faceV)./char.shellV); a2 = ((const.r(1:const.n_PSD-1,j).*char.faceV(2:const.n_PSD))./char.shellV(2:end));

Av någon anledning tar a2 ca tre gånger så lång tid som a vilket jag inte förstår.

Koden i stort går ut på att lösa ett par diffekvationer numeriskt. Så jag har diskretiserat problemet och delat upp det i beräkningsceller. Sedan loopar jag igenom alla celler tills jag får en konvergerande lösning. Så i nuläget när jag kör med 100 celler vilket är lite så tar det ca 90 sekunder att göra och matlab ropar på fyra olika funktioner som representerar fyra olika diffekvationer totalt ca 500000 gånger styck innan den når konvergens.

Visa signatur

Q9450, HD4850, 8 GB DDR2 800 MHz, 3x750 GB, Antec 300, Dell 2408WFP, U2410, Qnap TS-419p+ 4x2 TB Samsung F4, Asus UL30A-QX056V, Logitech Z-680, Sennheiser HD380pro, M-Audio FastTrack Pro, Ibanez sa160qm, Ibanez TB 15R, Zoom 505II, Ibanez GSR 200, Ibanez SW 35, Cort AC-15, Squier SD-3 BBL, Yamaha PSR 270, Røde NT1-A, Nikon D200, Nikkor 18-70/3,5-4,5, 70-300VR, 50/1,8, 28/2,8, Tamron 17-50/2,8, 90/2,8, Sigma 30/1,4, SB-800, SB-25, SB-24

Permalänk
Avstängd

Jag vet inte.

Men ville bara säga att din kod är svårläslig. Det är bättre att göra typ så här

pressure = const.u_e(:,j)./2
velocity = const.u_w(:,j)./2
...
a = pressure + velocity - ....

Permalänk
Hedersmedlem
Skrivet av Zotamedu:

if any((const.r(:,j)./char.faceV)>(1./char.faceV))

Är det inte väldigt mycket char.faceV här?

if any(const.r(:,j)>1)

borde väl göra ungefär samma sak (eller motsatsen om char.faceV < 0) fast snabbare (om nu inte matlab optimerar)?

Skrivet av Zotamedu:

Av någon anledning tar a2 ca tre gånger så lång tid som a2 vilket jag inte förstår.

Jag antar att du menar a i något av fallen, men utan att veta hur långa vektorerna är ser det ju ut som att det övre uttrycket faktiskt kräver ungefär tre gånger så många beräkningar...

Permalänk
Entusiast
Skrivet av Elgot:

Är det inte väldigt mycket char.faceV här?

if any(const.r(:,j)>1)

borde väl göra ungefär samma sak (eller motsatsen om char.faceV < 0) fast snabbare (om nu inte matlab optimerar)?

Jag antar att du menar a i något av fallen, men utan att veta hur långa vektorerna är ser det ju ut som att det övre uttrycket faktiskt kräver ungefär tre gånger så många beräkningar...

Får räkna igenom den där första en gång till och kolla så jag får ordning på allt men vill helst bli av med hela if-satsen om det går.

Oj förlåt, ska ändra det. Det är a2, alltså det korta uttrycket som tar tre till fyra gånger så lång tid att köra enligt Matlabs Profiler. Matriserna den jobbar med är för tillfället 11x102 men ska helst bli 11x10002 i framtiden men det är inte realistiskt för tillfället. Dock räknar den bara en kolumn i taget så vektoroperationerna är bara på en 11 element lång vektor för a och 10 element för a2. De ska sedan sättas in som diagonaler i en matris för att lösa ett linjärt ekvationssystem. Därav de till synes dåliga namnen.

Visa signatur

Q9450, HD4850, 8 GB DDR2 800 MHz, 3x750 GB, Antec 300, Dell 2408WFP, U2410, Qnap TS-419p+ 4x2 TB Samsung F4, Asus UL30A-QX056V, Logitech Z-680, Sennheiser HD380pro, M-Audio FastTrack Pro, Ibanez sa160qm, Ibanez TB 15R, Zoom 505II, Ibanez GSR 200, Ibanez SW 35, Cort AC-15, Squier SD-3 BBL, Yamaha PSR 270, Røde NT1-A, Nikon D200, Nikkor 18-70/3,5-4,5, 70-300VR, 50/1,8, 28/2,8, Tamron 17-50/2,8, 90/2,8, Sigma 30/1,4, SB-800, SB-25, SB-24

Permalänk
Hedersmedlem
Skrivet av Zotamedu:

Får räkna igenom den där första en gång till och kolla så jag får ordning på allt men vill helst bli av med hela if-satsen om det går.

För felhantering låter väl en if-sats rimlig, men man kanske kan lägga den utanför loop:en?

if any(const.r(:)>1) disp('Mass balance error. Too much reaction in one cell') keyboard end