Tag: poker

How fast is a Raspberry Pi 5?

How fast is a Raspberry Pi 5?

Raspberry PI 5I recently bought one with 8 GB RAM pictured above. I haven’t got an SSD for it yet so am still pottering about with an SD Card.

I’ve installed VS Code, clang. and Rust along with the VS Code extensions Rust-Analyzer and codelldb.

Out of curiosity I compiled and ran a Rust program that reads in a text file of 1,000 lines of text with each line holding 7 random cards like this: AH 6D 2C 4S JD QH QC.

The idea is to load the file into RAM then process each line and determine the best poker hand.

On my PC 11th Gen Intel(R) Core(TM) i7-11700K @ 3.60GHz (which runs Windows 11), I compared running the Rust program in Windows 11, on Ubuntu 24.04 LTS running in a Hyper-V VM on the same PC and on the Raspberry Pi 5 using it’s own Debian (Bookworm) version.

Here are the times per hand.

  • Windows: 175 ns.
  • Ubuntu on Hyper-V 125 ns
  • Raspberry Pi 5: 175 ns.

You can download the project with the test cards from GitHub. This link is a zip file containing the project file.

To run it in release in VS Code, in the terminal type in

cargo run --release 1000_card_hands.txt
Timings running under Ubuntu

 

 

 

Or you can view the test cards which include the results with commemts in the test file. No need to run it release.

cargo run --features=show_cards test_card_hands.txt

Showing cards with test data

What is so suprising is that the time on Windows and Rapberry Pi 5 are the same. Windows is running a virus checker (Windows Defender) and I guess that might slow it a bit.

Bit of a curiosity – Rust runs slower on Windows than Linux

Bit of a curiosity – Rust runs slower on Windows than Linux

And it is a fair comparison because the Linux I’m running (Ubuntu 24.04 LTS) runs on my Windows 11 box in a hyper-V VM. I wrote a Poker hand evaluation program which loaded a text file containing lines of seven playing cards in text format TS 2C 4D sort of thing. It was seven cards because there’s two in your hand and five on the table.

There were 1,000 lines of these and the program loaded the file into memory, holding the cards in a Vec<Vec<Card>>. Then it loops through the 1,000 elements and figures out the best hand for each set.  The bit that was timed was the loop not the loading the file into memory.

The source file is on GitHub. It has the project files plus some test cards. You can try it yourself. Note at the bottom of this article is a link to a much faster version.

https://github.com/David-H-Bolton/Projects/blob/main/rust_pokerhand.zip

On my PC, the Windows one average time per hand is 768 ns. On Ubuntu is 540ns. Mad eh! The same program runs in 70% of the time on Linux compared to Windows. Both are run with this command from a terminal/command line.

cargo run --release 1000_card_hads.txt

You can also try the test_card_hands.txt but you need to enable the show_cards feature. That shows the cards but doesn’t do timing. The default is do the timing but don’t show the cards or the evaluation.

cargo run --release --features show_card test_card_hands.txt

Shows the Rust program with the feature

 

 

 

 

 

 

 

 

 

 

 

 

The test cards say what each hand is and the output at the bottom is the program working out each hand.
The file

https://github.com/David-H-Bolton/Projects/blob/main/rust_pokerhand_faster.zip

contains a much faster version. On Linux it takes about 127 ns per hand. On Windows it’s about 190 ns.

Rust – Sometimes you don’t need to use HashMap or HashSet

Rust – Sometimes you don’t need to use HashMap or HashSet

Seven playing cardsI wrote a Poker Hand evaluator. It read in a file of a 1,000 randomly generated sets of seven cards like this AC 8H JC …and figured out what was the best hand. It’s in Rust and on GitHub. That takes you to a projects folder and the whole rust project complete with two test sets of cards are included. Look for the file Rust_pokerhand.zip.

Now in the Hand evaluation I used both a HashMap and HashSet.  Here for example is the code to count how many of each Rank there are.

    let mut rank_counts = HashMap::new();
    for card in cards.iter() {
        *rank_counts.entry(card.rank).or_insert(0) += 1;
    }

The program reads in the cards into a Vec<Vec<Card>> and then calculate the average time to evaluate a hand.

Now there’s nothing wrong with the program. One of the card sets is called test_card_hands.txt and has an instance of each hand type along with a comment.

5H AS 2D 6C 3S KD 7C - High card
7H 3D 8S 7C 4H 9H JC - One Pair
AD 7H 8C AC 5S 8D KS - Two Pairs

You can run that with this command:

cargo run --release --features "show_cards" test_card_hands.txt

Or if you run the other test set with this, it doesn’t show the cards but does calculate the average time.

cargo run --release 1000_card_hands.txt

If I run this on Windows it evaluates a hand in 780 ns on average and on Ubuntu 24.04 on the same PC, (running under Hyper-V), it’s faster typically 550 ns.

So, I was looking for ways to speed it up and thought.  The HasmMap and HashSets are running on small numbers of Cards. 13 for Ranks and 4 for suits so what if I use them as arrays. Would it be faster?

It was, roughly four times faster.

As an example, the code above I replaced with this:

    let mut rank_counts = [0,0,0,0,0,0,0,0,0,0,0,0,0];
    for card in cards.iter() {
       rank_counts[&card.rank.value()-2] += 1;
    }

That needed a value() method that mapped all the Ranks starting at 2, onto 2-14.

I also redid the code for working out a straight.

The original is this, plus a bit more to check for A2345:

    let mut values: HashSet<u8> = cards.iter().map(|card| card.rank.value()).collect();
    let mut unique_values: Vec<u8> = values.drain().collect();
    unique_values.sort_unstable();

    let mut straight_length = 1;
    for i in 1..unique_values.len() {
        if unique_values[i] == unique_values[i - 1] + 1 {
            straight_length += 1;
            if straight_length == 5 {
                is_straight = true;
                break;
            }
        } else {
            straight_length = 1;
        }
    }
The improved version uses this constant

static STRAIGHTS: &'static [i32]=&[7936, 3968, 1984, 992, 496, 248, 124, 62, 31, 7681];

Plus a binvalue function which maps the card Ranks onto 1,2,4,8 etc. Just or the Cards binValues together and ‘ands’ (&) it with the individual STRAIGHTS values.

      let mut bivalue=0;
      for card in cards.iter() {
        bivalue |= card.rank.binvalue();
      }   

      for i in 0..STRAIGHTS.len(){
        if &binvalue & STRAIGHTS[i]== STRAIGHTS[i] {
            is_straight= true;
            break;
        }
    }
Mobile game development progress

Mobile game development progress

Manana Banana Screenshot on AndroidDevelopment continues with the first game, which is a card game. I know the game as Top Banana, but I think that is the name of a commercial game, so for now the working title is Manana Banana. All it does currently is display the cards and backs as you can see. No photo this time, I learnt how to take snapshots on the phone (Hold down the power and Lower volume buttons at the same time) As it’s plugged in to my PC,. copying it across was not difficult.

This uses my virtual screen technology working on an 800 x 1400 virtual screen then scaling output onto the real screen which in this case on the Alps X27 Plus is 480 wide by 960 deep. As you can see I have a black rectangle at the top and the Android controls are visible at the bottom, neither of which I programmed for. I’ll get those fixed.

You play this game by clicking on the six top cards one-by-one and then tap the back of the card where you want to play that top card. So you end up with three poker hands. In this case I’d put the 7 and 9 on the top row for one pair, the two fives on the 2nd row also for a apir and the King and Jack for an Ace-high straight on the bottom row. The gap on the right will show the text of the hand so will say Pair, Pair and Ace Straight or something like that.

Next thing is making the cards clickable. That is the top six cards and the the three sets of two backs below. Once that’s done I’ll make that bit work then plug in the Jessie Chunn’s poker hand evaluation code to figure out what each hand of five cards is and more importantly give it a numeric score.

The gradient that covers the screen came from Unsplash.com.