Avatar billede nanders Nybegynder
02. juli 2003 - 10:29 Der er 25 kommentarer og
1 løsning

Hastighedsforøgelse i VBA

Kære eksperter,

Jeg har lavet et edb-program i VBA, der fylder godt 20 sider, alt inklusive. Programmet simulerer forholdene i et luftrensningsfilter, mht. gasser, koncentrationer, pH osv.

Der indgår, og skal indgå, utrolig mange variable.

For at beregne pH skal jeg finde nulpunkter i et 11-12 grads polynomium. Jeg finder nulpunkterne ved sekant metoden, der minder meget om Newton Raphson metoden. Nulpunkterne findes med 15 decimalers nøjagtighed (nødvendigt) 50 gange i sekundet i fem forskellige modellag. Derudover indgår der en vis mængde mere almindelige beregninger med +, -, * og %.

Mit problem er, at modelafviklingen er for langsomt på en 600Mhz m. 128MB Ram maskine (Det er standard på Uni).

Har du forslag til tricks der kan bruges til at gøre programmet hurtigere ?

Programmet er lineært, og jeg kalder ikke metoder oa - det hele ligger altså i programmeringsteksten.

Er der nogen der også tør skønne over hvor meget hurtigere det kunne gå i JAVA ?

Med venlig hilsen

nanders
Avatar billede dk_akj Nybegynder
02. juli 2003 - 10:38 #1
Er det VB eller vba (excel) ??

Er det vba vil jeg GÆTTE på at det vil tage ca 75 % med java/vb og ca 50% med c++

//akj
Avatar billede nanders Nybegynder
02. juli 2003 - 10:48 #2
Hej akj,

Det er VBA, som jeg får adgang til fra Excel (Alt F11). Jeg ville gerne tage de 50% ekstra (som jeg forstår din kommentar) ved at programmere fra Java, der jo nok også kan noget hvis jeg f.eks. skal ligge programmet ud på nettet så andre kan prøve det.
Avatar billede dk_akj Nybegynder
02. juli 2003 - 10:53 #3
VBA er jo ikke kendt som den hurtigste kode at afvikle da den ikke er kompileret.


Laver du indsættelse af data i celler vil jeg foreslå du laver en application.screenupdating = false inden du starter med dine loops og application.screenupdating = false = true når du har beregnet.

//akj
Avatar billede nanders Nybegynder
02. juli 2003 - 11:02 #4
Hej akj,

Det har jeg gjort, det forslog som en skrædder et vist sted.

Jeg printer også kun ud til excel en gang pr. 15000'ende iteration, så det er vist ikke der hunden er begravet. Men hvorfor: application.screenupdating = false = true og ikke bare application.screenupdating = true ?

/nanders
Avatar billede martin_moth Mester
02. juli 2003 - 11:22 #5
Du skal sætte screenupdate = FALSE, så din PC ikke bruger kræfter på at sende beregningsresultater til skærmen, hvis du da ellers gør det under beregningen..

Når beregningen er slut, sætter du den til true...
Avatar billede dk_akj Nybegynder
02. juli 2003 - 11:36 #6
sorry min fejl copy-paste du ved.


//akj
Avatar billede roenving Novice
02. juli 2003 - 11:45 #7
<spam>
Man kunne måske påstå, at matin havde slået sin screenupdate fra en ½ times tid *gg*
</nospam>
Avatar billede martin_moth Mester
02. juli 2003 - 12:04 #8
<svar på spam>
Jeg forsøger bare at svare på det spørgsmål nanders stillede kl. 11:02:35.
Men OK, jeg kan se, at jeg måske skulle have læst lidt bedre... ;o)
</svar på spam>
Avatar billede bak Forsker
02. juli 2003 - 16:19 #9
Nok er VBA ikke det hurtigste programmeringssprog, men hastighedsproblemer plejer at ligge i selve kodens udformning.
En af de ting, der sløver, er hvis du har nogle ´steder hvor du bruger Select.

Har du mulighed for at identificere stedet hvor den virkelig bruger tid, og vise den kodestump?
Avatar billede nanders Nybegynder
03. juli 2003 - 09:04 #10
Det er virkelig fornemt at du gider se det.

Her er en type programstump der skal eksekveres 250 gange i sekundet.

Dim x1 As Double
Dim x2 As Double
Dim fx1 As Double
Dim fx2 As Double
   
x1 = H_1 * 1.0001
x2 = H_1 * 0.9999
         
Do Until Abs(x1 - x2) < 0.000000000000001
 
fx1 = (-(TNH4_NH3_1 / (1 + (KeNH4 / x1))) + (TNO2_HNO2_1 / (1 + (x1 / KeHNO2))) - (TCH3NH2_CH3NH3_1 / (1 + (KeCH3NH2 / x1))) + (TCH3SH_CH3S_1 / (1 + (x1 / KeCH3SH))) + (TBIC_1 / (1 + (x1 / KeCO2) + (KeHCO3 / x1))) + (2 * TBIC_1 / (1 + (x1 * x1 / (KeHCO3 * KeCO2) + (x1 / KeHCO3)))) + (TH2S_HS_1 / (1 + (x1 / KeH2S))) - x1 + 2 * SO4_1 + NO3_1 - Z_1)
   
fx2 = (-(TNH4_NH3_1 / (1 + (KeNH4 / x2))) + (TNO2_HNO2_1 / (1 + (x2 / KeHNO2))) - (TCH3NH2_CH3NH3_1 / (1 + (KeCH3NH2 / x2))) + (TCH3SH_CH3S_1 / (1 + (x2 / KeCH3SH))) + (TBIC_1 / (1 + (x2 / KeCO2) + (KeHCO3 / x2))) + (2 * TBIC_1 / (1 + (x2 * x2 / (KeHCO3 * KeCO2) + (x2 / KeHCO3)))) + (TH2S_HS_1 / (1 + (x2 / KeH2S))) - x2 + 2 * SO4_1 + NO3_1 - Z_1)
   
x1 = x2 - (((x2 - x1) * fx2) / (fx2 - fx1))
x2 = x2 - (((x2 - x1) * fx2) / (fx2 - fx1))
 
Loop
         
H_1 = (x1 + x2) / 2

Med venlig hilsen

Anders Nielsen
Avatar billede nanders Nybegynder
03. juli 2003 - 09:37 #11
Det er virkelig fornemt at du gider se det.

Her er en type programstump der skal eksekveres 250 gange i sekundet.

Dim x1 As Double
Dim x2 As Double
Dim fx1 As Double
Dim fx2 As Double
   
x1 = H_1 * 1.0001
x2 = H_1 * 0.9999
         
Do Until Abs(x1 - x2) < 0.000000000000001
 
fx1 = (-(TNH4_NH3_1 / (1 + (KeNH4 / x1))) + (TNO2_HNO2_1 / (1 + (x1 / KeHNO2))) - (TCH3NH2_CH3NH3_1 / (1 + (KeCH3NH2 / x1))) + (TCH3SH_CH3S_1 / (1 + (x1 / KeCH3SH))) + (TBIC_1 / (1 + (x1 / KeCO2) + (KeHCO3 / x1))) + (2 * TBIC_1 / (1 + (x1 * x1 / (KeHCO3 * KeCO2) + (x1 / KeHCO3)))) + (TH2S_HS_1 / (1 + (x1 / KeH2S))) - x1 + 2 * SO4_1 + NO3_1 - Z_1)
   
fx2 = (-(TNH4_NH3_1 / (1 + (KeNH4 / x2))) + (TNO2_HNO2_1 / (1 + (x2 / KeHNO2))) - (TCH3NH2_CH3NH3_1 / (1 + (KeCH3NH2 / x2))) + (TCH3SH_CH3S_1 / (1 + (x2 / KeCH3SH))) + (TBIC_1 / (1 + (x2 / KeCO2) + (KeHCO3 / x2))) + (2 * TBIC_1 / (1 + (x2 * x2 / (KeHCO3 * KeCO2) + (x2 / KeHCO3)))) + (TH2S_HS_1 / (1 + (x2 / KeH2S))) - x2 + 2 * SO4_1 + NO3_1 - Z_1)
   
x1 = x2 - (((x2 - x1) * fx2) / (fx2 - fx1))
x2 = x2 - (((x2 - x1) * fx2) / (fx2 - fx1))
 
Loop
         
H_1 = (x1 + x2) / 2

Med venlig hilsen

Anders Nielsen

NB. Hvordan giver man point til dem der hjælper en ?
Avatar billede martin_moth Mester
03. juli 2003 - 09:40 #12
Du kan kun give points til dem der har lagt et svar - så når en lægger et svar (ikke en kommentar) som du synes er værd at belønne kan du tildele points til ham/hende/dem... :o)
Avatar billede dk_akj Nybegynder
03. juli 2003 - 09:44 #13
Tja... koden kan der ikke optimeres meget på.
Om formlerne kan forkortes aner jeg ikke....

Prøv lige at sætte en tæller ind i loopet og se hvor mange gange loopet bliver kørt. Det eneste der kan korte afviklingstiden ned er at formindske antallet af loops.

//akj
Avatar billede martin_moth Mester
03. juli 2003 - 09:56 #14
Prøv at ændre

  Do Until Abs(x1 - x2) < 0.000000000000001

til

  Do Until Abs(x1 - x2) < 0.1

Så går det med garanti hurtigere

(Kunne ikke lade være ;o)

Det kunne være sjovt at smide al din kode over i VB (ikke VBA) og kompilere til en .exe og se om det gør nogen forskel. Hvis du ikke bruger en masse kontroller osv, men koden er lige til at copy/paste, kan du sende hele koden til mig (med mindre der er forretningshemmeligheder i den), så kan jeg smiden ind i VB og berette om resultatet...
Avatar billede dk_akj Nybegynder
03. juli 2003 - 09:59 #15
martin >> Jeg lavede en test med en:
for i = 1 to 100000
s = s & cstr(now)
next

I vba og vb (.exe) tog det ca. samme tid

//akj
Avatar billede martin_moth Mester
03. juli 2003 - 10:02 #16
ok :o)
Avatar billede martin_moth Mester
03. juli 2003 - 10:09 #17
Jamen såp er der vel kun tilbage at skifte til hurtigere PC eller hurtigere sprog (fx. c++) - det første er nok det hurtigste.

Jeg sidder med en 1,7 GHz med 256 MB RAM - jeg kunen prøve at køre koden, for at se hvor meget bedre det bliver af det...

Det lader jo til at nanders har helt godt styr på programmering, så jeg tvivler på at der er alvorlige fejl i koden.
Men at eksekvare et Loop 250 gange i sekundtet - det er jo heller ikke småting der bedes om. Hvor mange gange det enkelte loop skal køre før Abs(x1 - x2) < 0.000000000000001 ved jeg ikke - men skal det køres bare 10 gange, er det 2500 gange i sekundtet at adskellige variabler skifter værdi... Og muligvis køres det langt flere gange end 10...
Avatar billede martin_moth Mester
03. juli 2003 - 10:12 #18
" det første er nok det hurtigste."
Jeg mener
  " det første er nok det NEMMESTE."
Det første jeg skrev kan misforstås...
Avatar billede -mundi- Nybegynder
03. juli 2003 - 10:21 #19
det ser ikke ud til at variable som f.eks TBIC_1 skifter værdi i dit loop, så små dele som f.eks 2 * TBIC_1 og 2 * SO4_1 kunne du jo udregne uden for loopet og lægge de i variabler. Det er ikke meget regnekraft du sparer, men mange bække små
Avatar billede -mundi- Nybegynder
03. juli 2003 - 10:25 #20
250 (gange i sekundet) * 4 (beregninger) * 10 (før Abs(x1 - x2) < 0.000000000000001 bare som eksempel)  er alligevel 10000 beregninger du sparer der
Avatar billede -mundi- Nybegynder
03. juli 2003 - 10:26 #21
per sekund
Avatar billede nanders Nybegynder
03. juli 2003 - 11:15 #22
Kære eksperter,

Martin Moth, tak for de rosende ord - men mit kendskab til programmering er dog begrænset.

Mundi, du har ret - der kunne jeg jo spare det du angiver.

Jeg tænker bare, at der vel foregår en form for kompilering af programkoden der konstaterer, at  2*TBIC_1 og 2*SO4_1 udregnes hele tiden - hvorefter det lægges i een variabel til hurtig adgang - eller er det ikke sådan det fungerer ?

Mon ikke Java kan gøre det hurtigere.

Programmet har kommerciel interesse, så på sigt er det hensigten, at det skal kunne afvikles fra nettet, og det kan ihvertfald (nok) ikke lade sig gøre fra VBA.
Avatar billede -mundi- Nybegynder
03. juli 2003 - 11:17 #23
det er muligt at kompileringen finder ud af det selv, men hvorfor ikke være 100% sikker :-)
Avatar billede nanders Nybegynder
03. juli 2003 - 11:31 #24
Forresten er konvergensen af min vistnok lidt modificerede sekant-metode utrolig hurtig. Kun 2 gange skal loop'et bruge for at finde den rigtige værdi.

Før brugte jeg bisektions-metoden og nok omkring 50 iterationer pr. loop.

Den proces jeg har været igennem, som følge af jeres svar, har fået mig til at indse, at mange af de andre beregninger jeg udfører (af gaspartialtryk flux, strømning oa. har forholdsmæssig stor betydning for den samlede beregningstid.

Dem har jeg desværre næppe mulighed for at skære ned på, da de, i programmeringsmæssig henseende, er lige ud af landevejen.

Jeg vil dog nok vende tilbage senere med andre emner. Blandt andet når jeg skal implementere mine biofilm differentialligninger i modellen og have det over i Java.

Jeg siger mange tak til de af jer der er kommet med brugbare forslag.

Hvis I sender mig svar, og er interesseret i at modtage point, vil jeg dele dem ud til de af jer der er kommet med gode kommentarer.

Med venlig hilsen

nanders
Avatar billede -mundi- Nybegynder
03. juli 2003 - 11:36 #25
svar
Avatar billede dk_akj Nybegynder
03. juli 2003 - 11:39 #26
Hvis du skal afvikle det fra web har du 2 muligheder.

1:
Bruger indtaster data i en html form som submittes til webserveren,
på serveren modtager du data og kører beregningerne. Hvis du laver server side delen i ASP kan du genbruge din vb(a) kode.

Fordelen er at brugeren ikke får fat i din formel.
Ulempen er at du belaster serveren med programafviklingen

2:
Du laver det clientside med javascript.

Ulempe : Brugeren kan se din programkode
Fordel : Du belaster ikke din server.

Held og lykke med projektet.

//akj
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester

Seneste spørgsmål Seneste aktivitet
I går 10:21 Ny printer, men hvilken Af mort1 i Printere
13/0819:41 USB på Linux Af Uvanga i Linux
12/0818:26 Hvilken type mus Af mort1 i PC
11/0813:21 ms Forms Af leahcim i Andet software
10/0821:30 Blokeret på Snapchat? Af LineP i Chat & Messaging