From 18fc042ae27f117db099a3a11b1303d2449cde7a Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Thu, 11 Feb 2021 20:58:25 +0900 Subject: [PATCH] Ceval with Stockfish NNUE --- .gitignore | 1 + ui/ceval/src/ctrl.ts | 16 ++++++++++++---- ui/ceval/src/pool.ts | 6 ++++-- ui/ceval/src/types.ts | 3 ++- ui/ceval/src/view.ts | 6 ++++-- ui/site/package.json | 1 + ui/site/rollup.config.js | 9 +++++++++ yarn.lock | 5 +++++ 8 files changed, 38 insertions(+), 9 deletions(-) diff --git a/.gitignore b/.gitignore index b10dbb9cb4..167c524a7f 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,7 @@ public/vendor/highcharts-4.2.5 public/vendor/hopscotch public/vendor/tagify public/vendor/stockfish.wasm +public/vendor/stockfish-nnue.wasm public/vendor/stockfish-mv.wasm public/vendor/stockfish.js public/css/ diff --git a/ui/ceval/src/ctrl.ts b/ui/ceval/src/ctrl.ts index 49e1ae58f9..3ec5289ad8 100644 --- a/ui/ceval/src/ctrl.ts +++ b/ui/ceval/src/ctrl.ts @@ -65,6 +65,11 @@ export default function (opts: CevalOpts): CevalCtrl { const sharedMem = sharedWasmMemory(8, 16); if (sharedMem) { technology = 'wasmx'; + // prettier-ignore + const source_with_simd = Uint8Array.from([0, 97, 115, 109, 1, 0, 0, 0, 1, 5, 1, 96, 0, 1, 123, 3, 2, 1, 0, 7, 8, 1, 4, 116, 101, 115, 116, 0, 0, 10, 15, 1, 13, 0, 65, 0, 253, 17, 65, 0, 253, 17, 253, 186, 1, 11]); + if (officialStockfish(opts.variant.key) && WebAssembly.validate(source_with_simd)) { + technology = 'nnue'; + } try { sharedMem.grow(8); growableSharedMem = true; @@ -105,12 +110,13 @@ export default function (opts: CevalOpts): CevalCtrl { wasmx: officialStockfish(opts.variant.key) ? 'vendor/stockfish.wasm/stockfish.js' : 'vendor/stockfish-mv.wasm/stockfish.js', + nnue: 'vendor/stockfish-nnue.wasm/stockfish.js', }, { minDepth, variant: opts.variant.key, - threads: technology == 'wasmx' && (() => Math.min(parseInt(threads()), maxThreads)), - hashSize: technology == 'wasmx' && (() => Math.min(parseInt(hashSize()), maxHashSize)), + threads: (technology == 'wasmx' || technology == 'nnue') && (() => Math.min(parseInt(threads()), maxThreads)), + hashSize: (technology == 'wasmx' || technology == 'nnue') && (() => Math.min(parseInt(hashSize()), maxHashSize)), } ); @@ -141,6 +147,8 @@ export default function (opts: CevalOpts): CevalCtrl { if (knps > 3500) depth = 25; if (knps > 5000) depth = 26; if (knps > 7000) depth = 27; + // TODO: Maybe we want to get deeper for slow NNUE? + depth += 2 * Number(technology === 'nnue'); maxDepth(depth); if (values.length > 40) values.shift(); } @@ -252,8 +260,8 @@ export default function (opts: CevalOpts): CevalCtrl { possible: opts.possible, enabled, multiPv, - threads: technology == 'wasmx' ? threads : undefined, - hashSize: technology == 'wasmx' ? hashSize : undefined, + threads: technology == 'wasmx' || technology == 'nnue' ? threads : undefined, + hashSize: technology == 'wasmx' || technology == 'nnue' ? hashSize : undefined, maxThreads, maxHashSize, infinite, diff --git a/ui/ceval/src/pool.ts b/ui/ceval/src/pool.ts index 05af5cd58c..a34ad8fa29 100644 --- a/ui/ceval/src/pool.ts +++ b/ui/ceval/src/pool.ts @@ -131,9 +131,11 @@ export class Pool { warmup(): void { if (this.workers.length) return; - if (this.poolOpts.technology == 'wasmx') + if (this.poolOpts.technology == 'nnue') { + this.workers.push(new ThreadedWasmWorker(this.poolOpts.nnue, this.poolOpts, this.protocolOpts)); + } else if (this.poolOpts.technology == 'wasmx') { this.workers.push(new ThreadedWasmWorker(this.poolOpts.wasmx, this.poolOpts, this.protocolOpts)); - else { + } else { for (let i = 1; i <= 2; i++) this.workers.push( new WebWorker( diff --git a/ui/ceval/src/types.ts b/ui/ceval/src/types.ts index c808e358fd..b9a5a15904 100644 --- a/ui/ceval/src/types.ts +++ b/ui/ceval/src/types.ts @@ -2,7 +2,7 @@ import { Outcome } from 'chessops/types'; import { Prop } from 'common'; import { StoredProp, StoredBooleanProp } from 'common/storage'; -export type CevalTechnology = 'asmjs' | 'wasm' | 'wasmx'; +export type CevalTechnology = 'asmjs' | 'wasm' | 'wasmx' | 'nnue'; export interface Eval { cp?: number; @@ -33,6 +33,7 @@ export interface PoolOpts { wasm: string; wasmx: string; asmjs: string; + nnue: string; } export interface CevalOpts { diff --git a/ui/ceval/src/view.ts b/ui/ceval/src/view.ts index 4d1e50e15d..791e60f420 100644 --- a/ui/ceval/src/view.ts +++ b/ui/ceval/src/view.ts @@ -77,9 +77,11 @@ function engineName(ctrl: CevalCtrl): VNode[] { h( 'span', version ? { attrs: { title: `${version} (classical eval)` } } : {}, - ctrl.technology == 'wasmx' ? 'Stockfish 12+' : 'Stockfish 10+' + ctrl.technology == 'wasmx' || ctrl.technology == 'nnue' ? 'Stockfish 12+' : 'Stockfish 10+' ), - ctrl.technology == 'wasmx' + ctrl.technology == 'nnue' + ? h('span.wasmx', { attrs: { title: 'Multi-threaded WebAssembly NNUE (strongest)' } }, 'nnue') + : ctrl.technology == 'wasmx' ? h('span.wasmx', { attrs: { title: 'Multi-threaded WebAssembly (fastest)' } }, 'wasmx') : ctrl.technology == 'wasm' ? h('span.wasm', { attrs: { title: 'Single-threaded WebAssembly fallback (second fastest)' } }, 'wasm') diff --git a/ui/site/package.json b/ui/site/package.json index 2e73942f5b..7082910ac5 100644 --- a/ui/site/package.json +++ b/ui/site/package.json @@ -21,6 +21,7 @@ "hopscotch": "^0.3.1", "jquery-bar-rating": "^1.2.2", "stockfish-mv.wasm": "^0.5.2", + "stockfish-nnue.wasm": "0.0.1", "stockfish.js": "^10.0.2", "stockfish.wasm": "^0.9.1", "tablesort": "^5.1", diff --git a/ui/site/rollup.config.js b/ui/site/rollup.config.js index 86d9e42fad..e9d06a8915 100644 --- a/ui/site/rollup.config.js +++ b/ui/site/rollup.config.js @@ -61,6 +61,15 @@ export default rollupProject({ ].map(require.resolve), dest: '../../public/vendor/stockfish-mv.wasm', }, + // stockfish-nnue.wasm + { + src: [ + 'stockfish-nnue.wasm/stockfish.js', + 'stockfish-nnue.wasm/stockfish.wasm', + 'stockfish-nnue.wasm/stockfish.worker.js', + ].map(require.resolve), + dest: '../../public/vendor/stockfish-nnue.wasm', + }, ], }), replace({ diff --git a/yarn.lock b/yarn.lock index d6f982b1ba..ac26aa3c61 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4137,6 +4137,11 @@ stockfish-mv.wasm@^0.5.2: resolved "https://registry.yarnpkg.com/stockfish-mv.wasm/-/stockfish-mv.wasm-0.5.2.tgz#08faca73ae2f5b69fb28bd04c20074e443cdaa7e" integrity sha512-MujfrAVAzDkRoVEiYMkGaiAw9wei2hRR8sxD5l7emHDyCbmc0KdlqoIZtS+coQ9CVNaZa1o5JokTKJVv8wJhUQ== +stockfish-nnue.wasm@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/stockfish-nnue.wasm/-/stockfish-nnue.wasm-0.0.1.tgz#945a9904c5a1152bab98b9fdde7c517b1342e83f" + integrity sha512-ePulPKbGimjJEtTUYECh4986JnZv1rYVDsSlBOXu+1tvjWKjJSzoHhKpmtdGDG59iVtIBRamix593rfYqMqK2Q== + stockfish.js@^10.0.2: version "10.0.2" resolved "https://registry.yarnpkg.com/stockfish.js/-/stockfish.js-10.0.2.tgz#c8206aa3b0290171ace52b463a74112ea1f83989"