diff --git a/src/engine.cpp b/src/engine.cpp --- a/src/engine.cpp +++ b/src/engine.cpp @@ -53,8 +53,14 @@ Engine::Engine(std::optional path) : states(new std::deque(1)), threads(), networks(numaContext, +#ifdef __EMSCRIPTEN__ + // Construct the sole local WASM copy directly in its owner. + std::make_unique( + NN::EvalFile{EvalFileDefaultNameBig, "None", ""})) { +#else // Heap-allocate because sizeof(NN::Networks) is large std::make_unique(std::make_unique( NN::EvalFile{EvalFileDefaultNameBig, "None", ""}))) { +#endif pos.set(StartFEN, &states->back()); diff --git a/src/nnue/network.h b/src/nnue/network.h --- a/src/nnue/network.h +++ b/src/nnue/network.h @@ -121,5 +121,10 @@ struct Networks { Networks(std::unique_ptr&& nB) : big(std::move(*nB)) {} +#ifdef __EMSCRIPTEN__ + explicit Networks(EvalFile file) : + big(file) {} +#endif + NetworkBig big; }; diff --git a/src/nnue/network.cpp b/src/nnue/network.cpp --- a/src/nnue/network.cpp +++ b/src/nnue/network.cpp @@ -204,6 +204,10 @@ template void Network::load_user_net(const std::string& dir, const std::string& evalfilePath) { +#ifdef PIKAFISH_WASM_RAW_NNUE + std::ifstream stream(dir + evalfilePath, std::ios::binary); +#else std::stringstream stream(read_compressed_nnue(dir + evalfilePath)); +#endif auto description = load(stream); if (description.has_value()) diff --git a/src/numa.h b/src/numa.h --- a/src/numa.h +++ b/src/numa.h @@ -1336,9 +1336,15 @@ class LazyNumaReplicatedSystemWide: public NumaReplicatedBase { template void modify_and_replicate(FuncT&& f) { +#ifdef __EMSCRIPTEN__ + // A single-thread WebAssembly build has exactly one local instance. Mutating it + // in place avoids full NNUE copies during load and option changes. + std::forward(f)(const_cast(*instances[0])); +#else auto source = std::make_unique(*instances[0]); std::forward(f)(*source); prepare_replicate_from(std::move(source)); +#endif } void on_numa_config_changed() override { @@ -1409,7 +1415,7 @@ class LazyNumaReplicatedSystemWide: public NumaReplicatedBase { { assert(cfg.num_numa_nodes() == 1); #ifdef __EMSCRIPTEN__ - instances.emplace_back(SystemWideSharedConstant(std::move(*source))); + instances.emplace_back(SystemWideSharedConstant(std::move(source))); #else instances.emplace_back(SystemWideSharedConstant(*source, get_discriminator(0))); #endif diff --git a/src/shm.h b/src/shm.h --- a/src/shm.h +++ b/src/shm.h @@ -475,11 +475,13 @@ struct SharedMemoryBackendFallback { SharedMemoryBackendFallback() = default; +#ifdef __EMSCRIPTEN__ + SharedMemoryBackendFallback(const std::string&, const T& value) : + fallback_object(std::make_unique(value)) {} + SharedMemoryBackendFallback(const std::string&, std::unique_ptr&& value) : + fallback_object(std::move(value)) {} +#else SharedMemoryBackendFallback(const std::string&, const T& value) : fallback_object(make_unique_large_page(value)) {} - -#ifdef __EMSCRIPTEN__ - SharedMemoryBackendFallback(const std::string&, T&& value) : - fallback_object(make_unique_large_page(std::move(value))) {} #endif void* get() const { return fallback_object.get(); } @@ -508,7 +511,11 @@ struct SharedMemoryBackendFallback { } private: +#ifdef __EMSCRIPTEN__ + std::unique_ptr fallback_object; +#else LargePagePtr fallback_object; +#endif }; // Platform-independent wrapper @@ -564,8 +571,8 @@ struct SystemWideSharedConstant { } #ifdef __EMSCRIPTEN__ - SystemWideSharedConstant(T&& value, std::size_t = 0) : - backend(SharedMemoryBackendFallback("", std::move(value))) {} + SystemWideSharedConstant(std::unique_ptr&& value, std::size_t = 0) : + backend(SharedMemoryBackendFallback("", std::move(value))) {} #endif SystemWideSharedConstant(const SystemWideSharedConstant&) = delete;