mirror of
https://github.com/official-stockfish/Stockfish.git
synced 2026-07-24 21:57:14 +00:00
Add wasm32 and wasm32-relaxed-simd targets, and light optimizations
Lichess maintains some patches on top of SF dev to get it working with Emscripten. This PR moves some of these patches into SF and adds WASM to CI. It also adds a few changes in places where the x86 intrinsics don't cleanly map onto WebAssembly SIMD instructions; otherwise, we use Emscripten's x86 compatibility layer and take SSE4.1 code paths.
Summary of the compatibility changes:
- Define `wasm32` and `wasm32-relaxed-simd` targets.
- We don't support wasm without SIMD; it'd be a waste of time.
- Add option to disable TBs
- This is required because `tbprobe.cpp` pulls in `mmap`. This option can be used on any target, of course, but it's only enabled by default for wasm.
- Add compilation job + test to CI
And the changes for performance:
- Disable atomics for shared history on wasm
- Atomics are always `seq_cst` there, which can be quite slow (even on the x86, stores are locked `xchg [mem], reg`)
- Add SSE code path to `get_changed_pieces`, modeled after the AVX2 path
- `_mm_mulhi_epi16` has a complicated emulation sequence, so for the pairwise multiplication, use an approach similar to the NEON impl.
- __int128 is gets lowered to runtime functions on wasm, so use the fallback impl for `mul_hi64`
- V8 does a poor job with the NNZ finding, so use a slightly different sequence there
- Add relaxed simd support for `m128_dpbusd`.
Some local perf figures (single-threaded speedtest):
```
wasm
Nodes/second : 902523
sse4.1
Nodes/second : 1155380
avx512icl
Nodes/second : 1676184
```
Further avenues to explore:
- Optimize for performance under V8's experimental AVX revectorizer (Currently it's about +10% in my testing, but could definittely be more)
- Branch hinting. For example, run bench while collecting branch frequency info, then inject it late in the WASM compilation pipeline. I tried this locally and it didn't help much, but maybe I'm missing something.
- PGO. Gives +1.5% NPS locally, but hard to integrate with WASM compilation wrokflows
closes https://github.com/official-stockfish/Stockfish/pull/6875
No functional change
This commit is contained in:
committed by
Joost VandeVondele
parent
dd3e1c4a50
commit
8e711c29fe
+53
-5
@@ -55,6 +55,8 @@ endif
|
||||
### Executable name
|
||||
ifeq ($(target_windows),yes)
|
||||
EXE = stockfish.exe
|
||||
else ifneq (,$(findstring wasm,$(ARCH)))
|
||||
EXE = stockfish.js
|
||||
else
|
||||
EXE = stockfish
|
||||
endif
|
||||
@@ -122,7 +124,9 @@ VPATH = syzygy:nnue:nnue/features
|
||||
# neon = yes/no --- -DUSE_NEON --- Use ARM SIMD architecture
|
||||
# dotprod = yes/no --- -DUSE_NEON_DOTPROD --- Use ARM advanced SIMD Int8 dot product instructions
|
||||
# lsx = yes/no --- -mlsx --- Use Loongson SIMD eXtension
|
||||
# lasx = yes/no --- -mlasx --- use Loongson Advanced SIMD eXtension
|
||||
# lasx = yes/no --- -mlasx --- Use Loongson Advanced SIMD eXtension
|
||||
# relaxedsimd = y/n --- -mrelaxed-simd --- Use WebAssembly relaxed SIMD extension
|
||||
# syzygy = yes/no --- -DNO_TABLEBASES --- Support Syzygy tablebase probing
|
||||
#
|
||||
# Note that Makefile is space sensitive, so when adding new architectures
|
||||
# or modifying existing flags, you have to make sure there are no extra spaces
|
||||
@@ -149,7 +153,7 @@ ifeq ($(ARCH), $(filter $(ARCH), \
|
||||
x86-64-bmi2 x86-64-avx2 x86-64-sse41-popcnt x86-64-modern x86-64-ssse3 x86-64-sse3-popcnt \
|
||||
x86-64 x86-32-sse41-popcnt x86-32-sse2 x86-32 ppc-64 ppc-64-altivec ppc-64-vsx ppc-32 e2k \
|
||||
armv7 armv7-neon armv8 armv8-dotprod arm64-universal apple-silicon general-64 general-32 riscv64 \
|
||||
loongarch64 loongarch64-lsx loongarch64-lasx))
|
||||
loongarch64 loongarch64-lsx loongarch64-lasx wasm32 wasm32-relaxed-simd))
|
||||
SUPPORTED_ARCH=true
|
||||
else
|
||||
SUPPORTED_ARCH=false
|
||||
@@ -186,6 +190,8 @@ dotprod = no
|
||||
arm_version = 0
|
||||
lsx = no
|
||||
lasx = no
|
||||
relaxedsimd = no
|
||||
syzygy = yes
|
||||
STRIP = strip
|
||||
|
||||
ifneq ($(shell which clang-format-20 2> /dev/null),)
|
||||
@@ -389,6 +395,27 @@ ifeq ($(ARCH),apple-silicon)
|
||||
arm_version = 8
|
||||
endif
|
||||
|
||||
# WASM is largely compiled using emcc's x86 compatibility layer, with occasional
|
||||
# WASM-specific intrinsics
|
||||
ifeq ($(ARCH),wasm32)
|
||||
arch = wasm32
|
||||
sse = yes
|
||||
sse2 = yes
|
||||
ssse3 = yes
|
||||
sse41 = yes
|
||||
syzygy = no
|
||||
endif
|
||||
|
||||
ifeq ($(ARCH),wasm32-relaxed-simd)
|
||||
arch = wasm32
|
||||
sse = yes
|
||||
sse2 = yes
|
||||
ssse3 = yes
|
||||
sse41 = yes
|
||||
relaxedsimd = yes
|
||||
syzygy = no
|
||||
endif
|
||||
|
||||
ifeq ($(ARCH),ppc-32)
|
||||
arch = ppc
|
||||
bits = 32
|
||||
@@ -480,7 +507,7 @@ ifeq ($(COMP),gcc)
|
||||
endif
|
||||
else ifeq ($(arch),loongarch64)
|
||||
CXXFLAGS += -latomic
|
||||
else
|
||||
else ifneq ($(arch),wasm32)
|
||||
CXXFLAGS += -m$(bits)
|
||||
LDFLAGS += -m$(bits)
|
||||
endif
|
||||
@@ -490,8 +517,10 @@ ifeq ($(COMP),gcc)
|
||||
endif
|
||||
|
||||
ifneq ($(KERNEL),Darwin)
|
||||
ifneq ($(arch),wasm32)
|
||||
LDFLAGS += -Wl,--no-as-needed
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(target_windows),yes)
|
||||
@@ -654,6 +683,7 @@ ifneq ($(comp),mingw)
|
||||
# Haiku has pthreads in its libroot, so only link it in on other platforms
|
||||
ifneq ($(KERNEL),Haiku)
|
||||
ifneq ($(COMP),ndk)
|
||||
ifneq ($(arch),wasm32)
|
||||
LDFLAGS += -lpthread
|
||||
|
||||
add_lrt = yes
|
||||
@@ -669,6 +699,7 @@ ifneq ($(comp),mingw)
|
||||
LDFLAGS += -lrt
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
@@ -846,6 +877,14 @@ ifeq ($(lsx),yes)
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(arch),wasm32)
|
||||
CXXFLAGS += -pthread -msimd128 -DUSE_POPCNT -DNNUE_EMBEDDING_OFF
|
||||
LDFLAGS += -pthread -sINITIAL_MEMORY=64MB -sALLOW_MEMORY_GROWTH -sSTACK_SIZE=3MB
|
||||
ifeq ($(relaxedsimd),yes)
|
||||
CXXFLAGS += -mrelaxed-simd
|
||||
endif
|
||||
endif
|
||||
|
||||
### 3.7 pext
|
||||
ifeq ($(pext),yes)
|
||||
CXXFLAGS += -DUSE_PEXT
|
||||
@@ -854,6 +893,11 @@ ifeq ($(pext),yes)
|
||||
endif
|
||||
endif
|
||||
|
||||
### Syzygy tablebases
|
||||
ifeq ($(syzygy),no)
|
||||
CXXFLAGS += -DNO_TABLEBASES
|
||||
endif
|
||||
|
||||
### 3.8.1 Try to include git info for versioning and avoid recompiles if nothing changes
|
||||
BUILD_SHA_FILE := .build_sha.txt
|
||||
BUILD_DATE_FILE := .build_date.txt
|
||||
@@ -885,7 +929,8 @@ endif
|
||||
### needs access to the optimization flags.
|
||||
ifeq ($(optimize),yes)
|
||||
ifeq ($(debug),no)
|
||||
ifneq ($(KERNEL),Darwin)
|
||||
ifeq ($(arch),wasm32)
|
||||
else ifneq ($(KERNEL),Darwin)
|
||||
LLD_BIN := $(shell command -v ld.lld 2>/dev/null)
|
||||
ifeq ($(LLD_BIN),)
|
||||
LLD_BIN := $(shell command -v lld 2>/dev/null)
|
||||
@@ -1207,6 +1252,7 @@ config-sanity: net
|
||||
echo "arm_version: '$(arm_version)'" && \
|
||||
echo "lsx: '$(lsx)'" && \
|
||||
echo "lasx: '$(lasx)'" && \
|
||||
echo "syzygy: '$(syzygy)'" && \
|
||||
echo "target_windows: '$(target_windows)'" && \
|
||||
echo "" && \
|
||||
echo "Flags:" && \
|
||||
@@ -1222,7 +1268,8 @@ config-sanity: net
|
||||
(test "$(arch)" = "any" || test "$(arch)" = "x86_64" || test "$(arch)" = "i386" || \
|
||||
test "$(arch)" = "ppc64" || test "$(arch)" = "ppc" || test "$(arch)" = "e2k" || \
|
||||
test "$(arch)" = "armv7" || test "$(arch)" = "armv8" || test "$(arch)" = "arm64" || \
|
||||
test "$(arch)" = "riscv64" || test "$(arch)" = "loongarch64") && \
|
||||
test "$(arch)" = "riscv64" || test "$(arch)" = "loongarch64" || \
|
||||
test "$(arch)" = "wasm32") && \
|
||||
(test "$(bits)" = "32" || test "$(bits)" = "64") && \
|
||||
(test "$(prefetch)" = "yes" || test "$(prefetch)" = "no") && \
|
||||
(test "$(popcnt)" = "yes" || test "$(popcnt)" = "no") && \
|
||||
@@ -1241,6 +1288,7 @@ config-sanity: net
|
||||
(test "$(neon)" = "yes" || test "$(neon)" = "no") && \
|
||||
(test "$(lsx)" = "yes" || test "$(lsx)" = "no") && \
|
||||
(test "$(lasx)" = "yes" || test "$(lasx)" = "no") && \
|
||||
(test "$(syzygy)" = "yes" || test "$(syzygy)" = "no") && \
|
||||
(test "$(comp)" = "gcc" || test "$(comp)" = "icx" || test "$(comp)" = "mingw" || \
|
||||
test "$(comp)" = "clang" || test "$(comp)" = "armv7a-linux-androideabi16-clang" || \
|
||||
test "$(comp)" = "aarch64-linux-android21-clang")
|
||||
|
||||
Reference in New Issue
Block a user