I'm currently developing a bitboard-based chess engine for fun and can generate around 5.5 million positions per second on perft tests. I ran the same tests on Stockfish, which can do around 130 million positions per second. What is it that makes Stockfish (and other engines) so much faster?
There are a number of reasons. The Main one is its aggressive Alpha Beta pruning and late move reductions.
To explain a bit further. AB Pruning is a search algorithm which basically cuts out the number of nodes in its search tree. How it works is it stops evaluating when it determines and proves the move to be worse than another examined moves.
Late move reduction is a slightly harder concept but it again searches the "tree" more efficiently. It does this by effectively diving down a "algorithmically" more probably tree.
If I remember the release paper correctly the elo for Stockfish 14 is 3350 +/-5% and that was based off a 4 threaded CPU.
In short there are the implementation of mathematically proven formulae to do with pruning infinite possibilities to the most correct, whilst also searching deeper down the most probably correct line.
Perft speed can be affected by:
- Coding language - for example, compiled vs interpreted.
- Bulk counting - whether you un-make leaf nodes - I believe SF doesn't do this, which makes it significantly faster.
- How your move generator works - for example, whether it performs legality checks on the generated moves.
- Whether you're using CPU or GPU for move generation.
- CPU speed/frequency.
- CPU multi-processing - for example, whether your perft is single-threaded or multi-threaded.
- CPU cache size.
- Which position you're using for perft.
Without knowing these variables, it's hard to say whether your perft numbers are reasonable or not.
As an example, my single-threaded C# magic bitboard code does perft from the standard starting position at around 100 million nodes per second on a single core of a Ryzen 5950X processor.
5.5 million moves per seconds is very decent I would say. Enough to make a 2700 or 2800 rating engine with a good evaluation function. I made a bot without any bitboard and got to around 2.5-3.5 knps and managed to beat 2300-2400 bots on chess.com with a mediocre evaluation function. 130 million positions per second is 100% for multi threading bots. No way you can achieve that with only one core. I knew an a version of minmax with multithreading but I don't really suggest implementing it since it quite hard to get it right.