Wow, things are getting indeed a bit chaotic! I'll stick with PA_G and PA_H until more tests are done in latest versions (I guess one doesn't need the GTB one if one doesn't use tablebases?)
Meanwhile, here's a cross-post from RF by Ancalagon.
Eelco de Groot wrote:The code becomes a bit simpler a again if there is just one ok_to_use_TT( function, as fruity intended. Then you don't have to test for being in a PV node etc. Especially since there is only one search() for both PV and non PV, this is a bit neater. In non PV nodes the only difference is that beta is alpha +1 because of the zero window searches, but all the ok_to_use_TT( code could function the same in PV nodes and non PV nodes. The only question is if you lose elo by lifting some of the restrictions you have now for accepting a hash value, for instance if an VALUE_EXACT should still be inside the alpha beta window in a PV node. I can't see a real reason for it except that sometimes the PV is too short, or examples where the PV gets stuck in an draw by repetition where actually the opponent has a better move. This probably is some hash effect I have been trying to resolve it just by changes in search but there may be no real solution. If you don't accept hash hits in PV nodes you will at least search deeper and I believe Vas mentioned in a thread many years ago, that at least these hash problems are resolved by searching deeper. Anyway, for the moment all versions need to accepth TT hits in PV nodes so going back to the old scheme from Stockfish is not an option.
But back to the code, implementing it as I think Fonzy, just without requiring that the value should be inside alpha beta and keeping the option to switch of Preserve Analysis, I have it as follows
// Preserve Hash
bool ok_to_use_TT(const TTEntry* tte, Depth depth, Value alpha, Value beta, int ply);
in search()
if (UsePreserveHash ? (tte && ok_to_use_TT(tte, depth, alpha, beta, ply))
: (!PvNode && tte && ok_to_use_TT(tte, depth, alpha, beta, ply)))
{
TT.refresh(tte);
ss->bestMove = ttMove; // Can be MOVE_NONE
return value_from_tt(tte->value(), ply);
}
in qsearch()
if (UsePreserveHash ? (tte && ok_to_use_TT(tte, ttDepth, alpha, beta, ply))
: (!PvNode && tte && ok_to_use_TT(tte, ttDepth, alpha, beta, ply)))
{
ss->bestMove = ttMove; // Can be MOVE_NONE
return value_from_tt(tte->value(), ply);
}
// ok_to_use_TT() returns true if a transposition table score
// can be used at a given point in search.
bool ok_to_use_TT(const TTEntry* tte, Depth depth, Value alpha, Value beta, int ply) {
Value v = value_from_tt(tte->value(), ply);
return ( tte->depth() >= depth
|| v >= Max(value_mate_in(PLY_MAX), beta)
|| v <= Min(value_mated_in(PLY_MAX), alpha))
&& ( ((tte->type() == VALUE_TYPE_LOWER) && v >= beta) // == can also stay & here
|| ((tte->type() == VALUE_TYPE_UPPER) && v <= alpha) // == can also stay & here
|| (tte->type() == VALUE_TYPE_EXACT)); // <- Maybe requiring this case to be inside alpha-beta improves the depth of the PV search
// - it depends on the rest of the code for search<PV>, you can compensate
// according to taste/testrequirements etc. in other places.
}
When there is a read event, I do an ifstream::getline() on the input stream class. The problem occurs when the sending program sends two lines at once, i.e. before the listener task is run again. [...] However, my guess is that the ifstream class has an internal buffer which has the next command inside, so the poll() returns false.
It was my understanding that doing something like 'cin.rdbuf()->pubsetbuf(NULL, 0)' would cause any buffering troubles to stop. I am not sure where the problem resides, but I am experiencing difficulties in this area. [...]
When the interface sends two commands (separated by \n) to the engine quickly the engine gets the first but then fails to read the second or following.
Again I don't think anyone had a solution, so I'm basically just putting these links here for future reference.
Uly wrote:Wow, things are getting indeed a bit chaotic! I'll stick with PA_G and PA_H until more tests are done in latest versions (I guess one doesn't need the GTB one if one doesn't use tablebases?)
Meanwhile, here's a cross-post from RF by Ancalagon.
Eelco de Groot wrote:The code becomes a bit simpler a again if there is just one ok_to_use_TT( function, as fruity intended. Then you don't have to test for being in a PV node etc. Especially since there is only one search() for both PV and non PV, this is a bit neater. In non PV nodes the only difference is that beta is alpha +1 because of the zero window searches, but all the ok_to_use_TT( code could function the same in PV nodes and non PV nodes. The only question is if you lose elo by lifting some of the restrictions you have now for accepting a hash value, for instance if an VALUE_EXACT should still be inside the alpha beta window in a PV node. I can't see a real reason for it except that sometimes the PV is too short, or examples where the PV gets stuck in an draw by repetition where actually the opponent has a better move. This probably is some hash effect I have been trying to resolve it just by changes in search but there may be no real solution. If you don't accept hash hits in PV nodes you will at least search deeper and I believe Vas mentioned in a thread many years ago, that at least these hash problems are resolved by searching deeper. Anyway, for the moment all versions need to accepth TT hits in PV nodes so going back to the old scheme from Stockfish is not an option.
But back to the code, implementing it as I think Fonzy, just without requiring that the value should be inside alpha beta and keeping the option to switch of Preserve Analysis, I have it as follows
// Preserve Hash
bool ok_to_use_TT(const TTEntry* tte, Depth depth, Value alpha, Value beta, int ply);
in search()
if (UsePreserveHash ? (tte && ok_to_use_TT(tte, depth, alpha, beta, ply))
: (!PvNode && tte && ok_to_use_TT(tte, depth, alpha, beta, ply)))
{
TT.refresh(tte);
ss->bestMove = ttMove; // Can be MOVE_NONE
return value_from_tt(tte->value(), ply);
}
in qsearch()
if (UsePreserveHash ? (tte && ok_to_use_TT(tte, ttDepth, alpha, beta, ply))
: (!PvNode && tte && ok_to_use_TT(tte, ttDepth, alpha, beta, ply)))
{
ss->bestMove = ttMove; // Can be MOVE_NONE
return value_from_tt(tte->value(), ply);
}
// ok_to_use_TT() returns true if a transposition table score
// can be used at a given point in search.
bool ok_to_use_TT(const TTEntry* tte, Depth depth, Value alpha, Value beta, int ply) {
Value v = value_from_tt(tte->value(), ply);
return ( tte->depth() >= depth
|| v >= Max(value_mate_in(PLY_MAX), beta)
|| v <= Min(value_mated_in(PLY_MAX), alpha))
&& ( ((tte->type() == VALUE_TYPE_LOWER) && v >= beta) // == can also stay & here
|| ((tte->type() == VALUE_TYPE_UPPER) && v <= alpha) // == can also stay & here
|| (tte->type() == VALUE_TYPE_EXACT)); // <- Maybe requiring this case to be inside alpha-beta improves the depth of the PV search
// - it depends on the rest of the code for search<PV>, you can compensate
// according to taste/testrequirements etc. in other places.
}
Here is one more to keep your head spinning. Includes the code suggested by fruity and Eelco de Groot. I am going to test this one thoroughly before I put out any more.
Looking at the games live, I noticed PA_H very often would be low on time, and would need to play from the increment, while PA_G would be comfortable.
My small hypothesis is that the time management code isn't able to deal with the latest code changes, and it (the time management, not necessarily the new code) may hurt the performance.
I don't think that the changes weaken the engine's time control. These builds are doing just fine. Release 32 and Release 64 are the last versions I posted. The PGO builds don't appear to make a huge improvement, which is good to know. But the best news is that adding these analysis features doesn't appear to weaken the engine significantly against the JA compile. I don't consider a 5 game lead to be significant, they are pretty much running even.
Engine Score SF St SF SF SF Sp S-B
SF Release 64 47,0/75 ··············· 110=110===10=1= 1==1===11=110== 1=1==1======00= 1=0==1=1=====1= =11=111===1=1== 1636,5
Stockfish-201-64-ja 42,0/75 001=001===01=0= ··············· 0======111====0 00==1=10======1 =11=01=====111= =10=01=1111=11= 1466,2
SF PGO 64 41,0/74 0==0===00=001== 1======000====1 ··············· ===1=====1==== ======1===11=1= 1=1011=1111===1 1405,7
SF Release 32 37,5/74 0=0==0======11= 11==0=01======0 ===0=====0==== ··············· ==01=====11=001 =1==0====11=011 1362,0
SF PGO 32 36,5/75 0=1==0=0=====0= =00=10=====000= ======0===00=0= ==10=====00=110 ··············· =1=111111110111 1240,0
Spike1.4 20,0/75 =00=000===0=0== =01=10=0000=00= 0=0100=0000===0 =0==1====00=100 =0=000000001000 ··············· 818,50
224 of 300 games played
Peter C wrote:Jeremy, you might want to add Makefiles to the GitHub repo so that us non-VS users can build it.
I attached the files included with the GTB library and the file I use for compiling Stockfish PA GTB (which is only slightly different from the standard SF makefile).
What time control are you using? This may be exclusive to incremental time controls (or nothing at all, but Rybka's time management specially sucks at incremental TC, so one is used to seeing patterns).
Bozo the Clown at RF suggested to make a new compile of Stockfish Default and use it for the testing, instead of JA's compile, to compare apples to apples (speed of the compile would be a non factor, clear improvements would stand as better code.)
Uly wrote:What time control are you using? This may be exclusive to incremental time controls (or nothing at all, but Rybka's time management specially sucks at incremental TC, so one is used to seeing patterns).
Bozo the Clown at RF suggested to make a new compile of Stockfish Default and use it for the testing, instead of JA's compile, to compare apples to apples (speed of the compile would be a non factor, clear improvements would stand as better code.)
1+1. After I make the PA_J changes, I'll build stock-Stockfish, as well and do a 3-way 64-bit PA_I_GTB v. PA_J_GTB v. Vanilla testing run. Someone else with real hardware might want to do the tests, though. I'm running in a 1-core 64-bit Windows 7 Virtual Machine.
I'm breaking off the current tournament, anyhow. Looks like my Release builds aren't using TBs for some reason (probably ProbeOnlyAtRoot got set at some point, need to check). So I'll start that new one shortly. Stay tuned...