Jag har skrivit ett litet program som simulerar pokerspel och det är i VB 6 och uppbyggt kring klasser. Problemet är att det är alltför långsamt. Jag undrar om det bäste är att skriva om det i C++ och ha det objektorienterat där också eller att försöka fixa nån lösning kring arrayer i VB. Jag förstår att det är jättesvårt att säga såhär generellt, men alla åsikter är intressanta. På VBSpeed (http://www.xbeat.net/vbspeed/) finns det lite tester och tips på hur man kan få det snabbare. Man kan förbättra VB-program väsentligt om man har koder i stil med Rent principiellt så blir VB kod rätt skrivet och rätt kompilerat Integer Next 2 1.00 14,424µs Om du läser det de skriver så är det just att next i resp. next inte ger någon som helst skillnad. Det där är enkla mätfel. På vissa mätningar ger Long betydligt bättre prestanda, men inte i det fallet du visar. Det är promille av hela tiden, och då får du räkna med att en For-Loop i regel är extremt mycket snabbare än det som är i den... Rasmus, vad är det i programmet som är långsamt? Jag skulle inte rekommendera att skriva om den typen av applikation till C++. VB:s prestanda borde absolut räcka till. Objektorientering är väl som du är inne på inte känt för att göra programmen snabbare, men fördelarna borde ändå överväga. Förmodligen är det precis som Niklas skriver i föregående inlägg att det är någonting inuti dina loopar som är för långsamt. Sätt timers på olika ställen i ditt program för att identifiera flaskhalsarna och återkom så kan du garanterat få bra hjälp med optimeringen. Klart du kan få det att funka bra i VB. Hej, förlåt att jag försvann från mitt inlägg så länge. Programmet går ut på att simulera tusentals pokerspel för att snabbt ge en uppfattning om hur ens odds är då man spelar poker. Därefter sparas resultatet i en databas för att kunna hämtas senare. Inget avancerat alls egentligen. det som tar längst tid är antagligen att blanda kortleken mellan varje simulering. Jag använder följande kod När du skriver: Den här koden är ungefär dubbelt så snabb som den ursprungliga koden: Och så kan inte jag låte bli att lägge näsan i blöt... Blanda så här istället >CLng() avrundar till närmaste heltal, till skillnad från int() som alltid avrundar neråt. Därför måste man Tack för alla bra tips! Martin Adrians metod gör att det går mycket fortare och genom att ha long i alla loopas har jag fått simuleringen att gå från 11 till 8 sekunder, vilket blir en stor förbättring. >Vad menar ni skulle vara lämpligare än Rnd för att generera slumptal? Snabbare program
Sv: Snabbare program
Sv:Snabbare program
for i = 1 to n
DoThis Tal(i)
next i
Till att istället skicka hela arrayen som
DoThisArray TalSv: Snabbare program
Lika snabbt som de flesta andra språk.
Den intressanta frågan är efter vilka inställningar har du kompilerat ?
Skall vara <b>Optimize for Fast Code och under Advanced skall normalt alla vara förbockade.</b>
Det finns många trix för att optimera för snabb kod så det skulle vara intressant att
se din kod där du bedömmer att det går långsamt.Sv:Snabbare program
Integer Next i 4 1.00 14,464µs
Long Next 1 1.00 14,417µs
Long Next i 3 1.00 14,443µs
Intressant att se att min gamla käpphäst ,
man skall använda (Long och inte Next i) får visst stöd här.
Marginellt men ändå ;-)
Tack för länken ,den åkte till Favoriter direkt.
Sv: Snabbare program
Sv:Snabbare program
/PelleSv: Snabbare program
Ursprungsversionen av den kända P2P plattformen Direct Connect (Neo-Modus) är utvecklad i Visual Basic!
Jag är fullt medveten om att det finns mycket bättre versioner av DC numera som är skrivna i C++. Men nu var det ju ett litet pokerspel vi pratade om. Du har fömodligen gjort några "enkla" missar som går att optimera rätt mycket. Om du postar ett avsnitt av din kod som du har prestandaproblem med kan säkert många här hjälpa dig.Sv:Snabbare program
dim lek(0 To 51, 0 To 1) As Integer
Randomize
Dim i, ett, tva, a, b As Integer
'Blandar om den 400 gånger och hoppas att det räcker
For i = 1 To 1000
a = Int(Rnd * 52)
b = Int(Rnd * 52)
ett = lek(a, 0)
tva = lek(b, 0)
lek(a, 0) = tva
lek(b, 0) = ett
Next
Om jag behöver simulera 10000 gånger för att få en korrekt bild av oddsen för en viss hand behöver alltså den här beräkningen göras 10000 gånger på ca 5-10 sek. Blandningstiden kanske står för 50% av hela tiden. Finns det något sätt att göra det snabbare? Hur mycket snabbare skulle jag kunna förvänta mig att det skulle bli i C++?Sv:Snabbare program
<CODE>
Dim i, ett, tva, a, b As Integer
</CODE>
Så betyder det att alla variabler utom b får datatypen variant, vilket är den långsammaste datatypen i vb. Gör som Ola säger, sätt alla till Long:
<CODE>
Dim i as Long, ett as Long, tva as Long, a as Long, b as Long
</CODE>
/PelleSv: Snabbare program
<CODE>
dim lek(0 To 51) As long
Randomize
Dim i as long, ett as long, tva as long, a as long, b As long
For i = 1 To 100000
a = CLng(Rnd * 51)
b = CLng(Rnd * 51)
ett = lek(a)
tva = lek(b)
lek(a) = tva
lek(b) = ett
Next
</CODE>
Att ha en tvådimensionell array slöade ner litegrann så jag ändrade detta eftersom det ändå inte användes här. Om du vill använda två kortlekar så kanske två variabler kan vara ett alternativ.
CLng() avrundar till närmaste heltal, till skillnad från int() som alltid avrundar neråt. Därför måste man göra Rnd * 51 istf Rnd * 52. Ett alternativ är att skriva CLng((Rnd * 52) - 0.5).
Notera att jag loopar 100000 gånger här. Detta tar på min 800Mhz:are 0.11 sekunder, vilket borde vara snabbt nog.
/PelleSv:Snabbare program
Det är åtminstone en variable för mycket vilket ger onödigt många minnesoperationer. Följande kod torde vara snäppet snabbare:
<CODE>
dim lek(0 To 51) As long
Randomize
Dim i as long, ett as long, a as long, b As long
For i = 1 To 100000
a = CLng(Rnd * 51)
b = CLng(Rnd * 51)
ett = lek(a)
lek(a) = lek(b)
lek(b) = ett
Next
</CODE>
// JohanSv: Snabbare program
<code>
' Fyll leken.
' Behövs bara göras första gången.
' Följande gånger kan du bara blanda
' om den blandade leken
For ii = 0 To 51
lek(ii) = ii
Next
' Algoritmen fungerar så här
' Ta ett slumpmässigt kort i leken och
' lägg det i en annan hög
' Fortsätt tills alla kort är flyttade
' ii markerar hur många kort som är i den nya högen
For ii = 0 To 50
kort = ii + Int(Rnd * (52-ii))
tmp = lek(ii) : lek(ii) = lek(kort) : lek(kort) = tmp
Next
</code>
Är dock lite tveksam till att använda Rnd som slumpgenerator om du skall göra många simlueringar.Sv:Snabbare program
>göra Rnd * 51 istf Rnd * 52. Ett alternativ är att skriva CLng((Rnd * 52) - 0.5).
CLng(Rnd*51) kommer att ge 0 och 51 lägre sannolikhet än de övriga (endast 0-0.499.. ger 0)
CLng(Rnd*52 - 0.5) är bättre men du får nog värdet -1 när Rnd returnerar 0 (tror att Clng avrundar -0.5 till -1)Sv:Snabbare program
Vad menar ni skulle vara lämpligare än Rnd för att generera slumptal? Sv: Snabbare program
Rnd är inte någon bra slumptalsgenerator. Den fungerar om man bara ska några stycken men inte om man skall göra ett stort antal simuleringar.
Dels är perioden på Rnd 2^24, dvs du kan bara få ~16miljoner olika utfall. I ditt fall med blandning av kortlek så innebär det att du med hjälp av Rnd bara kan generare en väldigt liten del av all möjliga följder (2^24/52! = 2-E61)
Dessutom är följden av slumptal inte särskilt slumpmässig vilket antagligen innebär att de 2^24 utfallen inte är representativa utan kan ligga nära varandra.
Programmerar inte i VB så jag känner inte till någon färdig slumptalsgenerator. I c++ hade jag använt mig av någon av de som finns boost.random. Det borde inte vara svårt att hitta någon algoritm som passar på internet.
För blandning av kortlek bör man ha en slumptalsgenerator med minst längden 52! (~2^225) så att varje möjlig blandning har en sannolikhet att användas.