Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Increase performance by saving the result of pos.value(move) instead of computing it multiple times #39

Open
Recursing opened this issue Aug 14, 2016 · 5 comments

Comments

@Recursing
Copy link
Contributor

Recursing commented Aug 14, 2016

pos.value(move) gets called with the same arguments three times on lines 274, 276 and 278
By just making making pos.gen_moves() return a list of tuples of the form (value, move) and making pos.move take move_value as an argument I think I obtained roughly a 35% speed improvement (with NODES_SEARCHED = 1e5, on pypy on my computer it goes from 2m24.644s to 1m35.306s for 4 moves)

I don't think this is the best way to do it, but the current implementation seems very inefficient.

Also, are there plans to make the position mutable, or do you think it would increase complexity too much?

I understand that the main focus of this project is to keep it simple and short, but it looks like it would play reasonably well with just a ~10x performance improvement, that seems reachable (at least, I think so)

@thomasahle
Copy link
Owner

thomasahle commented Aug 14, 2016

This sounds like an interesting improvement, that probably wouldnt increase complexity too much. If you want to, you can also test the improvement by letting the new and old versions play each other. The test.py script allows you to do this easily, with the arena option.

There are no immediate plans to make position mutable. At least I dont know a way to do this, that wouldnt also require an unmove method, which would easily take 10-15 lines. Also Im wondering how much it would help, since the expensive operations (string copying) are done in C rather than Python, whereas with mutable code everything would be in Python. Its worth trying though. Say it wins enough that we can remove the value method and just reevaluate the board after each move, then perhaps it wins the lines back.

@thomasahle
Copy link
Owner

@Recursing Did you have any luck with either of these improvements? As mentioned, it is easy to test whether a change is an improvement or not, by saving the new version as sunfish_new.py and running python3 test.py arena --games=4000 --seconds=60 --plus=0 sunfish sunfish_new.

@Recursing
Copy link
Contributor Author

Recursing commented Aug 25, 2017 via email

@thomasahle
Copy link
Owner

Something like

for score, move in sorted((pos.value(m), m) for m in pos.gen_moves(), reverse=True):
    if depth > 0 or score >= QS_LIMIT:
        yield move, -self.bound(pos.move(move, score), 1-gamma, depth-1, root=False)

could work (where pos.move is modified to take an optional pre-computed score value.)

A more involved approach would be to have gen_moves also generate the score. That might be able to save some lines as well, by removing the entire value method.

@thomasahle
Copy link
Owner

This is now implemented.
Except that pos.move still calls pos.value again.
I'll leave it open in case I try that optimization too.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants