Progress on Loki

Discussion of chess software programming and technical issues.

Moderators: hgm, Rebel, chrisw

User avatar
mvanthoor
Posts: 1784
Joined: Wed Jul 03, 2019 4:42 pm
Location: Netherlands
Full name: Marcel Vanthoor

Re: Progress on Loki

Post by mvanthoor »

niel5946 wrote: Sun Apr 25, 2021 12:01 am UCI rework update: I have finished re-writing the UCI implementation to C++, but the CheckUp function, called in search, is still from Vice. I don't really know how to implement that optimally. I will try using a thread to listen for input from the GUI, but I fear it will be slow..

All in all, I would say the development of Loki is going great :D
Good :) I have a function that checks the board and game state, but it only runs in debug mode. It degrades engine performance by 75%.

My suggestion would (still) be to not try and implement more than one function at the time. Implement LMR, and try to get the most ELO-gain possible. Then implement LMP, and do the same there. Then implement staged move generation. In the end, when you know all three functions are working perfectly, you can fiddle with the values of LMR and LMP to try and increase playing strength even more.
Author of Rustic, an engine written in Rust.
Releases | Code | Docs | Progress | CCRL
Sven
Posts: 4052
Joined: Thu May 15, 2008 9:57 pm
Location: Berlin, Germany
Full name: Sven Schüle

Re: Progress on Loki

Post by Sven »

@Niels: are you sure you did not change anything else than your UCI code? On your branch I also see some little changes regarding the TT size but I have been unable to see whether these were only formal changes ...
Sven Schüle (engine author: Jumbo, KnockOut, Surprise)
niel5946
Posts: 174
Joined: Thu Nov 26, 2020 10:06 am
Full name: Niels Abildskov

Re: Progress on Loki

Post by niel5946 »

mvanthoor wrote: Wed Apr 28, 2021 1:50 pm My suggestion would (still) be to not try and implement more than one function at the time. Implement LMR, and try to get the most ELO-gain possible. Then implement LMP, and do the same there. Then implement staged move generation. In the end, when you know all three functions are working perfectly, you can fiddle with the values of LMR and LMP to try and increase playing strength even more.
You are right regarding working on one thing at a time, and I also think I am doing that. Whenever I want to work on something else, I create a branch from master and then make the changes. If they show an increase, I merge them with master. This way, I make sure that no changes that I make at the same time cancel each other out.
The reason I haven't worked on LMR/LMP/staged movegen lately has been that I wanted to get the UCI-rework out of the way. I/O isn't really my cup of tea, so I might as well get it done now.

Sven wrote: Wed Apr 28, 2021 3:27 pm @Niels: are you sure you did not change anything else than your UCI code? On your branch I also see some little changes regarding the TT size but I have been unable to see whether these were only formal changes ...
Where do you see that? I am just looking through the changes between master and the UCI-rework branch, and I can't spot anything about the TT. Other than a new way of parsing the setoption command ofc.
Author of Loki, a C++ work in progress.
Code | Releases | Progress Log |
Sven
Posts: 4052
Joined: Thu May 15, 2008 9:57 pm
Location: Berlin, Germany
Full name: Sven Schüle

Re: Progress on Loki

Post by Sven »

It seems the diff was too hard to understand for me ... :wink: I thought there were changes in uci.cpp in commit f7c9812 but now it appears to me that you only moved around some code regarding the "Hash" option without changing semantics.

My problem may also be related to being used to see smaller commits ... ;-)
Sven Schüle (engine author: Jumbo, KnockOut, Surprise)
niel5946
Posts: 174
Joined: Thu Nov 26, 2020 10:06 am
Full name: Niels Abildskov

Re: Progress on Loki

Post by niel5946 »

Sven wrote: Wed Apr 28, 2021 5:22 pm My problem may also be related to being used to see smaller commits ... ;-)
I'll take a note about that. Usually I make all changes that I can think of before making a commit in order to not have non-functioning - also partly functioning for that matter - code in the repo. But you're probably right; smaller commits are better :)
Author of Loki, a C++ work in progress.
Code | Releases | Progress Log |
niel5946
Posts: 174
Joined: Thu Nov 26, 2020 10:06 am
Full name: Niels Abildskov

Re: Progress on Loki

Post by niel5946 »

UCI-rework endgame

I decided to throw the multithreaded idea in the bin and go for an implementation similar to what HGM suggested in another topic .
As said earlier today, I have gotten the (direct) Vice influence down to one function (the InputWaiting one), which Bluefever got from another place himself. I therefore think this is acceptable, and the input parsing while searching is now the following:
Every 2047 nodes, I check for an aborted search with the following method:

Code: Select all

// The checkup function sees if we need to stop the search
void check_stopped_search(SearchThread_t* ss) {
	// Only the 0'th (main) thread should check if the UCI has sent us commands to quit.
	if (ss->thread_id == 0) {
		if (ss->info->timeset && getTimeMs() >= ss->info->stoptime) {
			ss->info->stopped = true;
		}
		ReadInput(ss->info->stopped, ss->info->quit);

		// We've been told to stop, so let's tell the other threads.
		if (ss->info->stopped) {
			Search::isStop = true;
		}
	}
	// All the other threads will check if the time has expired or the main thread has set the isStop flag.
	else {
		if (ss->info->timeset && getTimeMs() >= ss->info->stoptime) {
			ss->info->stopped = true;
		}

		// See if the main thread has told us to stop searching.
		if (Search::isStop.load(std::memory_order_relaxed)) {
			ss->info->stopped = true;
		}
	}
}
Where the ReadInput method is the following:

Code: Select all

void ReadInput(bool& isStop, bool& isQuit) {
	if (InputWaiting()) {
		isStop = true;
		
		std::string input = "";
		std::getline(std::cin, input);

		if (input.find("quit") != std::string::npos) {
			isQuit = true;
		}
	}
}
Thus, when we run the check_stopped_search method, we check for a timeout. If we're the main thread, we read the stdin for pending input and parse it. If the GUI has told us to stop, we'll tell all other threads by setting the std::atomic<bool> isStop flag.

Now on to cleaning up the UCI-rework, testing for bugs one last time and finally some search improvements again! :D
Author of Loki, a C++ work in progress.
Code | Releases | Progress Log |
Sven
Posts: 4052
Joined: Thu May 15, 2008 9:57 pm
Location: Berlin, Germany
Full name: Sven Schüle

Re: Progress on Loki

Post by Sven »

niel5946 wrote: Wed Apr 28, 2021 6:29 pm UCI-rework endgame

I decided to throw the multithreaded idea in the bin and go for an implementation similar to what HGM suggested [...]
If we're the main thread, we read the stdin for pending input and parse it. If the GUI has told us to stop, we'll tell all other threads by setting the std::atomic<bool> isStop flag.
What did I miss here? Multithreaded or not?
Sven Schüle (engine author: Jumbo, KnockOut, Surprise)
amanjpro
Posts: 883
Joined: Sat Mar 13, 2021 1:47 am
Full name: Amanj Sherwany

Re: Progress on Loki

Post by amanjpro »

mvanthoor wrote: Wed Apr 28, 2021 1:50 pm
niel5946 wrote: Sun Apr 25, 2021 12:01 am UCI rework update: I have finished re-writing the UCI implementation to C++, but the CheckUp function, called in search, is still from Vice. I don't really know how to implement that optimally. I will try using a thread to listen for input from the GUI, but I fear it will be slow..

All in all, I would say the development of Loki is going great :D
Good :) I have a function that checks the board and game state, but it only runs in debug mode. It degrades engine performance by 75%.

My suggestion would (still) be to not try and implement more than one function at the time. Implement LMR, and try to get the most ELO-gain possible. Then implement LMP, and do the same there. Then implement staged move generation. In the end, when you know all three functions are working perfectly, you can fiddle with the values of LMR and LMP to try and increase playing strength even more.
Problem, the R value that is good for LMR alone, might be terrible when you add LMP on top of it. That can easily explode.
niel5946
Posts: 174
Joined: Thu Nov 26, 2020 10:06 am
Full name: Niels Abildskov

Re: Progress on Loki

Post by niel5946 »

Sven wrote: Wed Apr 28, 2021 7:38 pm
niel5946 wrote: Wed Apr 28, 2021 6:29 pm UCI-rework endgame

I decided to throw the multithreaded idea in the bin and go for an implementation similar to what HGM suggested [...]
If we're the main thread, we read the stdin for pending input and parse it. If the GUI has told us to stop, we'll tell all other threads by setting the std::atomic<bool> isStop flag.
What did I miss here? Multithreaded or not?
It is not multi-threaded. I formulated that poorly. What I meant to say was that, the main thread runs the search function (and spawns helpers if SMP is set) and then every 2047 nodes, it will check for pending input on stdin itself. This means that there's no separate thread doing the input listening.
Author of Loki, a C++ work in progress.
Code | Releases | Progress Log |
niel5946
Posts: 174
Joined: Thu Nov 26, 2020 10:06 am
Full name: Niels Abildskov

Re: Progress on Loki

Post by niel5946 »

amanjpro wrote: Thu Apr 29, 2021 1:19 pm
mvanthoor wrote: Wed Apr 28, 2021 1:50 pm
niel5946 wrote: Sun Apr 25, 2021 12:01 am UCI rework update: I have finished re-writing the UCI implementation to C++, but the CheckUp function, called in search, is still from Vice. I don't really know how to implement that optimally. I will try using a thread to listen for input from the GUI, but I fear it will be slow..

All in all, I would say the development of Loki is going great :D
Good :) I have a function that checks the board and game state, but it only runs in debug mode. It degrades engine performance by 75%.

My suggestion would (still) be to not try and implement more than one function at the time. Implement LMR, and try to get the most ELO-gain possible. Then implement LMP, and do the same there. Then implement staged move generation. In the end, when you know all three functions are working perfectly, you can fiddle with the values of LMR and LMP to try and increase playing strength even more.
Problem, the R value that is good for LMR alone, might be terrible when you add LMP on top of it. That can easily explode.
What do you mean by that? If a good LMR reduction value is chosen, can't LMP just be adjusted to match that if they're implemented one after another?
Author of Loki, a C++ work in progress.
Code | Releases | Progress Log |