Hacking around CFish NNUE

Discussion of chess software programming and technical issues.

Moderators: Harvey Williamson, bob, hgm

Forum rules
This textbox is used to restore diagrams posted with the [d] tag before the upgrade.
User avatar
maksimKorzh
Posts: 334
Joined: Sat Sep 08, 2018 3:37 pm
Location: Ukraine
Full name: Maksim Korzh
Contact:

Re: Hacking around CFish NNUE

Post by maksimKorzh » Fri Oct 16, 2020 10:23 am

Daniel Shawul wrote:
Fri Oct 16, 2020 12:49 am
maksimKorzh wrote:
Fri Oct 16, 2020 12:22 am
Daniel Shawul wrote:
Thu Oct 15, 2020 10:56 pm
I just finished implementing the library without incremental updates.

https://github.com/dshawul/nnue-probe.git

It has a FEN interface and a pieces[],squares[] interface as well

Code: Select all

DLLExport void _CDECL nnue_init(const char * evalFile);
DLLExport int _CDECL nnue_evaluate(int player, int* pieces, int* squares);
DLLExport int _CDECL nnue_evaluate_fen(const char* fen);
Funny thing is that incremental updates gives only 4.5% speedup on the start position that it may not be worth it at all.
The "NNUE" implementation below was directly implemented in my engine with all the incremental update etc.
The "NNUE without increment" is through the library.

Code: Select all

No NNUE                         = 2100 knps
NNUE                            = 1400 knps
NNUE without increment          = 1337 knps
NNUE without increment + memcpy = 1100 knps
NNUE is about 65% of the speed of classic.
NNUE without incremntal evaluation is just 4.5% slower on the start position.
When I added the updates in makemove with memcpy for Accumulator/DirtyPiece it was 14-18% slower.
But without it, it is so small not to worry about at all.
I've retrieved the score via FEN:

Code: Select all

int main()
{
    nnue_init("nn-04cf2b4ed1da.nnue");
    int score = nnue_evaluate_fen("rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e3 0 1");
    printf("score: %d\n", score);
    return 0;
}
But what confuses me slightly a bit is the output score (probably I'm doing something wrong)
e.g. above code gives output: 108
while same network in JS interface gives: 57 (0.28)

to try it yourself you can navigate here: file:///home/maksim/Desktop/nnue.html -> go to NNUE tab, download network (I used nn-04cf2b4ed1da.nnue from https://tests.stockfishchess.org/nns)

Is this the matter of different implementations or I did something horribly wrong?
There was a bug that I just fixed with decoding FEN.
Here is how you probe it from FEN

Code: Select all

from ctypes import *
nnue = cdll.LoadLibrary("libnnueprobe.so")
nnue.nnue_init("/home/daniel/Scorpio/nets-scorpio/nn-baeb9ef2d183.nnue")
score = nnue.nnue_evaluate_fen("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1")
print "Score = ", score
I'm a bit confused with following error when compiling test.c wilt libnnue.so:

Code: Select all

In file included from nnue.h:4:0,
                 from test.c:1:
misc.h:52:41: error: expected ‘;’, ‘,’ or ‘)’ before ‘&’ token
 void decode_fen(const char* fen_str, int& player, int& castle,
                                         ^
In file included from test.c:1:0:
nnue.h:44:3: error: expected specifier-qualifier-list before ‘alignas’
   alignas(64) int16_t accumulation[2][256];
   ^~~~~~~
nnue.h:59:19: error: unknown type name ‘Position’
 int nnue_evaluate(Position* pos);
                   ^~~~~~~~
nnue.h:15:29: error: expected identifier or ‘(’ before string constant
 #   define DLLExport extern "C"
                             ^
nnue.h:64:1: note: in expansion of macro ‘DLLExport’
 DLLExport void _CDECL nnue_init(
 ^~~~~~~~~
nnue.h:15:29: error: expected identifier or ‘(’ before string constant
 #   define DLLExport extern "C"
                             ^
nnue.h:71:1: note: in expansion of macro ‘DLLExport’
 DLLExport int _CDECL nnue_evaluate_fen(
 ^~~~~~~~~
nnue.h:15:29: error: expected identifier or ‘(’ before string constant
 #   define DLLExport extern "C"
                             ^
nnue.h:91:1: note: in expansion of macro ‘DLLExport’
 DLLExport int _CDECL nnue_evaluate(
 ^~~~~~~~~
test.c: In function ‘main’:
test.c:5:5: warning: implicit declaration of function ‘nnue_init’ [-Wimplicit-function-declaration]
     nnue_init("nn-04cf2b4ed1da.nnue");
comiling command:

Code: Select all

gcc -L/home/maksim/Desktop/nnue-probe/src test.c -lnnueprobe -o test
source of test.c

Code: Select all

#include "nnue.h"

int main()
{
    nnue_init("nn-04cf2b4ed1da.nnue");

    return 0;
}

User avatar
maksimKorzh
Posts: 334
Joined: Sat Sep 08, 2018 3:37 pm
Location: Ukraine
Full name: Maksim Korzh
Contact:

Re: Hacking around CFish NNUE

Post by maksimKorzh » Fri Oct 16, 2020 11:04 am

maksimKorzh wrote:
Fri Oct 16, 2020 10:23 am
Daniel Shawul wrote:
Fri Oct 16, 2020 12:49 am
maksimKorzh wrote:
Fri Oct 16, 2020 12:22 am
Daniel Shawul wrote:
Thu Oct 15, 2020 10:56 pm
I just finished implementing the library without incremental updates.

https://github.com/dshawul/nnue-probe.git

It has a FEN interface and a pieces[],squares[] interface as well

Code: Select all

DLLExport void _CDECL nnue_init(const char * evalFile);
DLLExport int _CDECL nnue_evaluate(int player, int* pieces, int* squares);
DLLExport int _CDECL nnue_evaluate_fen(const char* fen);
Funny thing is that incremental updates gives only 4.5% speedup on the start position that it may not be worth it at all.
The "NNUE" implementation below was directly implemented in my engine with all the incremental update etc.
The "NNUE without increment" is through the library.

Code: Select all

No NNUE                         = 2100 knps
NNUE                            = 1400 knps
NNUE without increment          = 1337 knps
NNUE without increment + memcpy = 1100 knps
NNUE is about 65% of the speed of classic.
NNUE without incremntal evaluation is just 4.5% slower on the start position.
When I added the updates in makemove with memcpy for Accumulator/DirtyPiece it was 14-18% slower.
But without it, it is so small not to worry about at all.
I've retrieved the score via FEN:

Code: Select all

int main()
{
    nnue_init("nn-04cf2b4ed1da.nnue");
    int score = nnue_evaluate_fen("rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e3 0 1");
    printf("score: %d\n", score);
    return 0;
}
But what confuses me slightly a bit is the output score (probably I'm doing something wrong)
e.g. above code gives output: 108
while same network in JS interface gives: 57 (0.28)

to try it yourself you can navigate here: file:///home/maksim/Desktop/nnue.html -> go to NNUE tab, download network (I used nn-04cf2b4ed1da.nnue from https://tests.stockfishchess.org/nns)

Is this the matter of different implementations or I did something horribly wrong?
There was a bug that I just fixed with decoding FEN.
Here is how you probe it from FEN

Code: Select all

from ctypes import *
nnue = cdll.LoadLibrary("libnnueprobe.so")
nnue.nnue_init("/home/daniel/Scorpio/nets-scorpio/nn-baeb9ef2d183.nnue")
score = nnue.nnue_evaluate_fen("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1")
print "Score = ", score
I'm a bit confused with following error when compiling test.c wilt libnnue.so:

Code: Select all

In file included from nnue.h:4:0,
                 from test.c:1:
misc.h:52:41: error: expected ‘;’, ‘,’ or ‘)’ before ‘&’ token
 void decode_fen(const char* fen_str, int& player, int& castle,
                                         ^
In file included from test.c:1:0:
nnue.h:44:3: error: expected specifier-qualifier-list before ‘alignas’
   alignas(64) int16_t accumulation[2][256];
   ^~~~~~~
nnue.h:59:19: error: unknown type name ‘Position’
 int nnue_evaluate(Position* pos);
                   ^~~~~~~~
nnue.h:15:29: error: expected identifier or ‘(’ before string constant
 #   define DLLExport extern "C"
                             ^
nnue.h:64:1: note: in expansion of macro ‘DLLExport’
 DLLExport void _CDECL nnue_init(
 ^~~~~~~~~
nnue.h:15:29: error: expected identifier or ‘(’ before string constant
 #   define DLLExport extern "C"
                             ^
nnue.h:71:1: note: in expansion of macro ‘DLLExport’
 DLLExport int _CDECL nnue_evaluate_fen(
 ^~~~~~~~~
nnue.h:15:29: error: expected identifier or ‘(’ before string constant
 #   define DLLExport extern "C"
                             ^
nnue.h:91:1: note: in expansion of macro ‘DLLExport’
 DLLExport int _CDECL nnue_evaluate(
 ^~~~~~~~~
test.c: In function ‘main’:
test.c:5:5: warning: implicit declaration of function ‘nnue_init’ [-Wimplicit-function-declaration]
     nnue_init("nn-04cf2b4ed1da.nnue");
comiling command:

Code: Select all

gcc -L/home/maksim/Desktop/nnue-probe/src test.c -lnnueprobe -o test
source of test.c

Code: Select all

#include "nnue.h"

int main()
{
    nnue_init("nn-04cf2b4ed1da.nnue");

    return 0;
}
Above errors are fixed by using g++ instead of gcc

Post Reply