Repository navigation
Allocate Win32 thread server buffers on first use - #6125
Merged
martin-frbg merged 1 commit intoOct 14, 2026
Merged
Conversation
blas_thread_server allocated its GEMM buffer as the first statement of every worker thread. On Windows that allocation is VirtualAlloc with MEM_RESERVE | MEM_COMMIT, so each idle worker added BUFFER_SIZE to the commit charge of any process that merely loads the library: with the 32 MB buffer used by the numpy wheels, 19 workers on a 20-thread CPU committed 608 MB before a single BLAS call. Allocate the buffer the first time a queued job needs it (sa == NULL), as the pthreads server already does, and only free it if it was allocated. Measured on a 20-thread Windows 11 machine (MinGW-w64 gcc 15, HASWELL, BUFFERSIZE=20, NUM_THREADS=24), private bytes: after load, no BLAS call: 610.6 MB -> 1.5 MB after a 4-thread dgemm: 642.8 MB -> 129.8 MB after all 20 threads have run: 643.0 MB -> 643.0 MB (unchanged) ctest passes 16/16, dgemm/sgemm/zgemm results match a naive reference, and 8 concurrent callers x 40 threaded dgemm from a cold start show no mismatches. Refs OpenMathLib#5587
Closed
Closed
Collaborator
|
Thank you very much |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Refs #5587.
Problem
On Windows,
blas_thread_serverallocates its GEMM buffer as the first statement of every worker thread. The Windows allocator usesVirtualAlloc(MEM_RESERVE | MEM_COMMIT), so each idle worker addsBUFFER_SIZEto the commit charge of any process that merely loads the library, before a single BLAS call. With the 32 MB buffer the numpy wheels use, a 20-thread CPU commits ~608 MB onimport numpy. Processes that load OpenBLAS transitively and never call BLAS pay it in full, once per process.Change
Allocate the per-thread buffer the first time a queued job needs it (
sa == NULL), which is the only place it is used, and free it at shutdown only if it was allocated. The pthreads server (blas_server.c) already allocates lazily on first work; this brings the Win32 server in line.Measurements
Windows 11, 20 logical CPUs, MinGW-w64 gcc 15,
TARGET=HASWELL BUFFERSIZE=20 NUM_THREADS=24 BUILD_WITHOUT_LAPACK=ON, same tree with and without the patch. Private bytes (PROCESS_MEMORY_COUNTERS_EX.PrivateUsage):Once every worker has done work the footprint is unchanged; only workers that never run a job stop paying for a buffer.
Testing
ctest: 16/16 pass with and without the patch.blas_server_win32.c.Not tested locally: MSVC / clang-cl builds and
DYNAMIC_ARCH.