![]() |
|
#141
|
|||
|
|||
|
Hi Steve!!
[ QUOTE ] h |= ((Hand_T)1 << deck[r]); [/ QUOTE ] Interesting you had this outside the eval routine... The equivelent statement for me is: <font class="small">Code:</font><hr /><pre> h = HR[h + deck[r]]; </pre><hr /> Please initialize h to 53 before the beginning of the hand loop. The lookup loop for me will be: <font class="small">Code:</font><hr /><pre> handTypeSum[hands[i] >> 12]++; </pre><hr /> I think you will find that this might be a little quicker... [img]/images/graemlins/wink.gif[/img] Of course if this isn't a good alternative, put the hand init (quoted code above) into the same for loop in the eval section, I think you will find similar results. I think the for loop inside the eval area is definitely a killer in this... Either way, even if there really was a speed difference (and I don't think it is as big as it looks), how often would you do a million random hands? If you had to do them, would the half a sec make a big difference? How does your evaluator do for the big enumerations (that at least I seem to always be running)? What evaluator did you use to do the comparison? Thank you for the info, definitely had something interesting there... Ray... |
|
#142
|
|||
|
|||
|
RayW,
Thanks for your very interesting post. I successfully ported your code into .Net 2.0 (C#) to test it side by side with the Hand Evaluator I am using. I am using a derivative work of poker source port bye Keith Rule (http://www.codeproject.com/csharp/pokerhandevaldoc.asp). Anyway, on my Pentium M 2.0G I get the following comparison benchmarks using the algorithm in your test method: <font class="small">Code:</font><hr /><pre>***** PokerOddsCalc.HandEvaluatorTest.Test30_Throughput_ HandEvaluator (Keith Rule Hand Evaluator) Iterations: 369052320 Execution Time: 15000ms Throughput: 24603.488 eps </pre><hr /> <font class="small">Code:</font><hr /><pre>***** PokerOddsCalc.HandEvaluatorTest.Test31_Throughput_ FiveCardEvaluator_Fast (Paul Senzee's optimization of Cactus Kev Evaluator) Iterations: 470411760 Execution Time: 15000ms Throughput: 31360.784 eps </pre><hr /> <font class="small">Code:</font><hr /><pre>***** PokerOddsCalc.HandEvaluatorTest.Test32_Throughput_ HandRanks (RayW HandRank Evaluator port) Iterations: 2675691200 Execution Time: 15218.75ms Throughput: 175815.438193018 eps </pre><hr /> Using the standard nested loop algorithm in all three, your evaluator certainly blows the others away which is excellent for complete equity comparisons. When I benchmarked using random cards during each iteration the scores reversed themselves with the Poker Src port performing much better than the other two, and yours slowest (But your previous post acknowledges this). Your algorithm is better suited for the kinds of appications that need this kind of performance, so I'll be implementing it more widely soon. Mostly, I just wanted to let you know your algorithm is up and running in C#, and its working great! |
|
#143
|
|||
|
|||
|
Hi!
This is getting translated like crazy and it is only a day old... Was it easy to move to C#? I gotta say that I love this thread! Ray... |
|
#144
|
|||
|
|||
|
Yeah, it was a cinch to port to C#. I imagine Java will be easy.
|
|
#145
|
|||
|
|||
|
Ray,
Random hands are useful for sampling situations where its impractical to do a full enumeration. While its true that a million hands isn't that much slower in absolute terms, think about what happens with a billion hands or more. This is not to take anything away from your algorithm. Its a huge improvement for enumeration, just not appropriate for every application. Nothing wrong with that. |
|
#146
|
|||
|
|||
|
RayW said,[ QUOTE ]
[ QUOTE ] h |= ((Hand_T)1 << deck[r]); [/ QUOTE ] Interesting you had this outside the eval routine... The equivelent statement for me is: <font class="small">Code:</font><hr /><pre> h = HR[h + deck[r]]; </pre><hr /> [/ QUOTE ] Hmm. I'm not sure we're going to agree on this. For each evaluator, as part of the pre-test initialization I set up 1M hand specifications in the form that the evaluator takes: 7 cards (ints in 1..52) for yours, and a 52-bit string for mine.[ QUOTE ] Please initialize h to 53 before the beginning of the hand loop. The lookup loop for me will be: <font class="small">Code:</font><hr /><pre> handTypeSum[hands[i] >> 12]++; </pre><hr /> [/ QUOTE ] (The init to 53 was done -- it's 6 lines up from the closing brace in my post.) But continuing on the theme... where does the test harness end and the test begin? With respect to your evaluator, I think it has to begin with the first of seven lookups, not the last. With respect to mine, I did what I think is reasonable.[ QUOTE ] I think you will find that this might be a little quicker... [img]/images/graemlins/wink.gif[/img] Of course if this isn't a good alternative, put the hand init (quoted code above) into the same for loop in the eval section, I think you will find similar results. I think the for loop inside the eval area is definitely a killer in this... [/ QUOTE ]With this code...<font class="small">Code:</font><hr /><pre> int* h = hands[0]; for (int i = 0; i < 1000000; i++) { int p = HR[53 + *h++]; p = HR[p + *h++]; p = HR[p + *h++]; p = HR[p + *h++]; p = HR[p + *h++]; p = HR[p + *h++]; handTypeSum[HR[p + *h++] >> 12]++; //handTypeSum[(Hand_7_Eval(hands[i]) >> 24)+1]++; count++; } </pre><hr />The result is: Validation seconds = 0.5940 Total HighPrecision Clocks = 1991107088 HighPrecision clocks per lookup = 1991.107088 ...i.e., no change in timing.[ QUOTE ] Either way, even if there really was a speed difference (and I don't think it is as big as it looks), how often would you do a million random hands? If you had to do them, would the half a sec make a big difference? How does your evaluator do for the big enumerations (that at least I seem to always be running)? What evaluator did you use to do the comparison? [/ QUOTE ] Sometimes research -- stuff that may run for hours or days -- requires large numbers of evaluations of random hands. (More to the point, I theorize, is large numbers of evaluations with chronologically close references to large data tables that are not part of the evaluator.) My evaluator is, I think, in the same ballpark as the pokersource EvalN routine. Mine is about a dozen years old, with a few interim changes. Its source is available at http://www.stevebrecher.com/Software/software.html. The only reason I used mine as a comparison was that it was a low-RAM alternative that I have handy. My point was only to confirm by experiment mykey1961's claim that the table-lookup eval degrades under some conditions. [ QUOTE ] Thank you for the info, definitely had something interesting there... [/ QUOTE ]Hey, obviously we're all sick enough to love this stuff! But seriously... I think the lesson here is that it's good to have a kit, rather than just one tool. |
|
#147
|
|||
|
|||
|
Hi Steve!!
[ QUOTE ] I think the lesson here is that it's good to have a kit, rather than just one tool. [/ QUOTE ] You are absolutely right. I know that the code I posted wasn't everything to all people (just good enough for me [img]/images/graemlins/smirk.gif[/img]) Everything has good and not as good points, and it would help us to find ways to get around them. I really think if we work together, we can come up with a good set of routines that will work for everyone. Perhaps if we integrate this code with pokersource it would be the cat's meow. Pokersource could handle the random evals, and the thread's routine could handle the enumerations (which is the way they are set-up anyway). We could definitely use the pokersource eval routine for the training run... What do you folks think? Ray... |
|
#148
|
|||
|
|||
|
[ QUOTE ]
Hi Steve!! [ QUOTE ] I think the lesson here is that it's good to have a kit, rather than just one tool. [/ QUOTE ] You are absolutely right. I know that the code I posted wasn't everything to all people (just good enough for me [img]/images/graemlins/smirk.gif[/img]) Everything has good and not as good points, and it would help us to find ways to get around them. I really think if we work together, we can come up with a good set of routines that will work for everyone. Perhaps if we integrate this code with pokersource it would be the cat's meow. Pokersource could handle the random evals, and the thread's routine could handle the enumerations (which is the way they are set-up anyway). We could definitely use the pokersource eval routine for the training run... What do you folks think? Ray... [/ QUOTE ] I tried to look at Pokersource a while back but since I'm not fluent in C, and what I saw appeared to use every trick in the C language I couldn't make heads or tails of it. If someone can give measure the cycles/hand that pokersource acheives for random hands, we can possibly improve on that method too. |
|
#149
|
|||
|
|||
|
[ QUOTE ]
If someone can give measure the cycles/hand that pokersource acheives for random hands, we can possibly improve on that method too. [/ QUOTE ] The Keith Rule evaluator I benchmarked above is a derivative of Poker Source. I think some other posters in the thread posted their timings of poker source also. In my testing RayW's code performed 752% over the poker source based code for a complete enumeration whereas it trailed by 22% when performing random evaluations. <font class="small">Code:</font><hr /><pre>***** PokerOddsCalc.HandEvaluatorTest.Test30_Throughput_ HandEvaluator (Keith Rule Hand Evaluator) Iterations: 369052320 Execution Time: 15000ms Throughput: 24603.488 eps </pre><hr /> |
|
#150
|
|||
|
|||
|
[ QUOTE ]
I successfully ported your code into .Net 2.0 (C#)... [/ QUOTE ] Could you please post it? Thanks in advance!!! |
![]() |
|
|