Search code examples
c++poker

Improving performance using pokerstove library


I've recently started using the pokerstove library (https://github.com/andrewprock/pokerstove) and managed to perform some basic hand / equity evaluations with it. Unfortunately, as soon as I tried to write a bit more computationally expensive programs, I ran into massive performance issues that couldn't figure out how to deal with.

As an example I've provided the following program that calculates the average equity that the hand Ace-6 of spades has against a completely random hand:

#include <iostream>
#include <vector>
#include <pokerstove/penum/ShowdownEnumerator.h>

int main() {

using namespace pokerstove;
using namespace std;

CardSet completeDeck;
completeDeck.fill();
cout << "The whole deck has " << completeDeck.size() << " cards" << endl;

CardDistribution anyTwo;
anyTwo.fill(completeDeck, 2);
cout << "There are " << anyTwo.size() << " two card combinations"  << endl;

CardDistribution holeCards;
holeCards.parse("As6s");

ShowdownEnumerator showdown;
vector<EquityResult> result = showdown.calculateEquity(
    vector<CardDistribution>{anyTwo, holeCards},
    CardSet(""),
    PokerHandEvaluator::alloc("h")
);

double shareRandom = result.at(0).winShares + result.at(0).tieShares;
double shareHand   = result.at(1).winShares + result.at(1).tieShares;
double total       = shareRandom + shareHand;

cout << "A random hand has "  << shareRandom / total * 100  << " % equity (" << result.at(0).str() << ")" << endl;
cout << "The hand As6s has "  << shareHand   / total * 100  << " % equity (" << result.at(1).str() << ")" << endl;

}

Once it finally stops, it outputs

The whole deck has 52 cards
There are 1326 two card combinations
A random hand has 40.0942 % equity (804780676 36223609 0 0)
The hand As6s has 59.9058 % equity (1220344506 36223609 0 0)

On my machine (which I admit isn't particularly fast) this computation takes roughly 4 minutes! Since this seems unreasonably long I belief that there has to be something wrong (performance-wise) with this implementation.

Hence, I would be very grateful if anybody could point out to me where I'm doing something wrong / inefficient.

I would suspect that one can reduce the number of random hands from 1326 to 169 (due to equivalence of suits), but I didn't find a way to implement that behaviour.

Any help is appreciated!


Solution

  • The short answer is: that's how fast it goes.

    A longer answer is, this version is a general purpose evaluator capable of evaluating any kind of game. It does not do anything fancy like caching results, precomputing large tables, using suit isomorphisms, or anything else.