Skip to content

Commit 9bdf051

Browse files
authored
Merge pull request #5838 from ngoldbaum/fix-level3-thread-locks-2
Fix corruption due to lock sharding issues by centralizing locking
2 parents ef20ea1 + 7c7c65e commit 9bdf051

17 files changed

Lines changed: 617 additions & 192 deletions

.github/workflows/dynamic_arch.yml

Lines changed: 249 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,255 @@ jobs:
334334
echo "::endgroup::"
335335
336336
337+
linux_thread_stress:
338+
if: "github.repository == 'OpenMathLib/OpenBLAS'"
339+
name: ${{ matrix.check-name }}
340+
runs-on: ubuntu-latest
341+
342+
strategy:
343+
fail-fast: false
344+
matrix:
345+
include:
346+
- backend: pthread
347+
check-name: "linux_thread_stress (pthread)"
348+
- backend: openmp
349+
check-name: "linux_thread_stress (openmp)"
350+
- backend: tsan
351+
check-name: linux_thread_sanitizer
352+
353+
steps:
354+
- name: Checkout repository
355+
uses: actions/checkout@v6
356+
357+
- name: Install Dependencies
358+
run: |
359+
cat << EOF | sudo tee -a /etc/apt/apt.conf.d/01norecommend
360+
APT::Install-Recommends "0";
361+
APT::Install-Suggests "0";
362+
EOF
363+
sudo apt-get update
364+
sudo apt-get install -y ccache cmake ninja-build
365+
if [ "${{ matrix.backend }}" = "tsan" ]; then
366+
sudo apt-get install -y clang llvm
367+
fi
368+
369+
- name: Compilation cache
370+
uses: actions/cache@v5
371+
with:
372+
path: ~/.ccache
373+
key: ccache-${{ runner.os }}-thread-${{ matrix.backend }}-${{ github.ref }}-${{ github.sha }}
374+
restore-keys: |
375+
ccache-${{ runner.os }}-thread-${{ matrix.backend }}-${{ github.ref }}
376+
ccache-${{ runner.os }}-thread-${{ matrix.backend }}
377+
378+
- name: Configure ccache
379+
# Limit the maximum size and switch on compression to avoid exceeding the total disk or cache quota.
380+
run: |
381+
test -d ~/.ccache || mkdir -p ~/.ccache
382+
echo "max_size = 250M" > ~/.ccache/ccache.conf
383+
echo "compression = true" >> ~/.ccache/ccache.conf
384+
ccache -s
385+
386+
- name: Configure OpenBLAS
387+
run: |
388+
mkdir build && cd build
389+
build_type=Release
390+
c_compiler=gcc
391+
cxx_compiler=g++
392+
dynamic_arch=ON
393+
use_openmp=OFF
394+
cpp_thread_safety_use_openmp=ON
395+
dgemm_args="512;12;4"
396+
dgemm_mixed_args="524288;16;20"
397+
dgemv_args="512;12;4"
398+
sanitizer_flags=
399+
if [ "${{ matrix.backend }}" = "openmp" ]; then
400+
use_openmp=ON
401+
elif [ "${{ matrix.backend }}" = "tsan" ]; then
402+
build_type=RelWithDebInfo
403+
c_compiler=clang
404+
cxx_compiler=clang++
405+
dynamic_arch=OFF
406+
cpp_thread_safety_use_openmp=OFF
407+
dgemm_args="64;4;1"
408+
dgemm_mixed_args="131072;8;10"
409+
dgemv_args="64;4;1"
410+
sanitizer_flags="-fsanitize=thread -g -O1 -fno-omit-frame-pointer"
411+
fi
412+
cmake_args=(
413+
-G Ninja
414+
"-DCMAKE_BUILD_TYPE=$build_type"
415+
"-DCMAKE_C_COMPILER=$c_compiler"
416+
"-DCMAKE_CXX_COMPILER=$cxx_compiler"
417+
-DBUILD_SHARED_LIBS=ON
418+
-DBUILD_STATIC_LIBS=OFF
419+
-DBUILD_WITHOUT_LAPACK=ON
420+
-DBUILD_SINGLE=OFF
421+
-DBUILD_DOUBLE=ON
422+
-DBUILD_COMPLEX=OFF
423+
-DBUILD_COMPLEX16=OFF
424+
"-DDYNAMIC_ARCH=$dynamic_arch"
425+
-DNOFORTRAN=ON
426+
-DUSE_THREAD=ON
427+
"-DUSE_OPENMP=$use_openmp"
428+
-DNUM_THREADS=32
429+
-DNUM_PARALLEL=2
430+
-DTARGET=CORE2
431+
-DCPP_THREAD_SAFETY_TEST=ON
432+
"-DCPP_THREAD_SAFETY_USE_OPENMP=$cpp_thread_safety_use_openmp"
433+
"-DCPP_THREAD_SAFETY_DGEMM_ARGS=$dgemm_args"
434+
"-DCPP_THREAD_SAFETY_DGEMM_MIXED_ARGS=$dgemm_mixed_args"
435+
"-DCPP_THREAD_SAFETY_DGEMV_ARGS=$dgemv_args"
436+
-DCMAKE_C_COMPILER_LAUNCHER=ccache
437+
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache
438+
)
439+
if [ "${{ matrix.backend }}" = "tsan" ]; then
440+
cmake_args+=(
441+
"-DCMAKE_C_FLAGS=$sanitizer_flags"
442+
"-DCMAKE_CXX_FLAGS=$sanitizer_flags"
443+
-DCMAKE_SHARED_LINKER_FLAGS=-fsanitize=thread
444+
-DCMAKE_EXE_LINKER_FLAGS=-fsanitize=thread
445+
)
446+
fi
447+
cmake "${cmake_args[@]}" ..
448+
449+
- name: Build OpenBLAS
450+
run: |
451+
cd build
452+
cmake --build . --target dgemm_thread_safety dgemm_thread_safety_mixed dgemv_thread_safety
453+
454+
- name: Show ccache status
455+
continue-on-error: true
456+
run: ccache -s
457+
458+
- name: Run thread stress tests
459+
timeout-minutes: 30
460+
run: |
461+
cd build
462+
if [ "${{ matrix.backend }}" = "tsan" ]; then
463+
export OPENBLAS_NUM_THREADS=2
464+
export LLVM_SYMBOLIZER_PATH=/usr/bin/llvm-symbolizer
465+
export TSAN_OPTIONS=halt_on_error=1:exitcode=66:second_deadlock_stack=1
466+
else
467+
export OPENBLAS_NUM_THREADS=8
468+
export OMP_NUM_THREADS=16
469+
fi
470+
ctest -R 'dgemm_thread_safety|dgemm_thread_safety_mixed|dgemv_thread_safety' --output-on-failure
471+
472+
473+
msys2_thread_stress:
474+
if: "github.repository == 'OpenMathLib/OpenBLAS'"
475+
runs-on: windows-latest
476+
477+
defaults:
478+
run:
479+
shell: msys2 {0}
480+
481+
env:
482+
CHERE_INVOKING: 1
483+
484+
steps:
485+
- name: Get CPU name
486+
shell: pwsh
487+
run : |
488+
Get-CIMInstance -Class Win32_Processor | Select-Object -Property Name
489+
490+
- name: Install build dependencies
491+
uses: msys2/setup-msys2@v2
492+
with:
493+
msystem: UCRT64
494+
update: true
495+
release: false # Use pre-installed version
496+
install: >-
497+
base-devel
498+
mingw-w64-ucrt-x86_64-cc
499+
mingw-w64-ucrt-x86_64-cmake
500+
mingw-w64-ucrt-x86_64-ninja
501+
mingw-w64-ucrt-x86_64-ccache
502+
503+
- name: Checkout repository
504+
uses: actions/checkout@v6
505+
506+
- name: Prepare ccache
507+
# Get cache location of ccache
508+
# Create key that is used in action/cache/restore and action/cache/save steps
509+
id: ccache-prepare
510+
run: |
511+
echo "ccachedir=$(cygpath -m $(ccache -k cache_dir))" >> $GITHUB_OUTPUT
512+
# We include the commit sha in the cache key, as new cache entries are
513+
# only created if there is no existing entry for the key yet.
514+
echo "key=ccache-msys2-thread-stress-${{ github.ref }}-${{ github.sha }}" >> $GITHUB_OUTPUT
515+
516+
- name: Restore ccache
517+
uses: actions/cache/restore@v5
518+
with:
519+
path: ${{ steps.ccache-prepare.outputs.ccachedir }}
520+
key: ${{ steps.ccache-prepare.outputs.key }}
521+
# Restore a matching ccache cache entry. Prefer same branch.
522+
restore-keys: |
523+
ccache-msys2-thread-stress-${{ github.ref }}
524+
ccache-msys2-thread-stress
525+
526+
- name: Configure ccache
527+
# Limit the maximum size and switch on compression to avoid exceeding the total disk or cache quota.
528+
run: |
529+
which ccache
530+
test -d ${{ steps.ccache-prepare.outputs.ccachedir }} || mkdir -p ${{ steps.ccache-prepare.outputs.ccachedir }}
531+
echo "max_size = 250M" > ${{ steps.ccache-prepare.outputs.ccachedir }}/ccache.conf
532+
echo "compression = true" >> ${{ steps.ccache-prepare.outputs.ccachedir }}/ccache.conf
533+
ccache -p
534+
ccache -s
535+
536+
- name: Configure OpenBLAS
537+
run: |
538+
mkdir build && cd build
539+
cmake -G Ninja \
540+
-DCMAKE_BUILD_TYPE=Release \
541+
-DBUILD_SHARED_LIBS=ON \
542+
-DBUILD_STATIC_LIBS=OFF \
543+
-DBUILD_WITHOUT_LAPACK=ON \
544+
-DBUILD_SINGLE=OFF \
545+
-DBUILD_DOUBLE=ON \
546+
-DBUILD_COMPLEX=OFF \
547+
-DBUILD_COMPLEX16=OFF \
548+
-DDYNAMIC_ARCH=OFF \
549+
-DNOFORTRAN=ON \
550+
-DUSE_THREAD=ON \
551+
-DUSE_OPENMP=OFF \
552+
-DNUM_THREADS=32 \
553+
-DTARGET=CORE2 \
554+
-DCPP_THREAD_SAFETY_TEST=ON \
555+
-DCPP_THREAD_SAFETY_DGEMM_ARGS="384;8;4" \
556+
-DCPP_THREAD_SAFETY_DGEMM_MIXED_ARGS="524288;16;20" \
557+
-DCPP_THREAD_SAFETY_DGEMV_ARGS="384;8;4" \
558+
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
559+
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
560+
..
561+
562+
- name: Build OpenBLAS
563+
run: |
564+
cd build
565+
cmake --build . --target dgemm_thread_safety dgemm_thread_safety_mixed dgemv_thread_safety
566+
567+
- name: Show ccache status
568+
continue-on-error: true
569+
run: ccache -s
570+
571+
- name: Save ccache
572+
# Save the cache after we are done (successfully) building
573+
uses: actions/cache/save@v5
574+
with:
575+
path: ${{ steps.ccache-prepare.outputs.ccachedir }}
576+
key: ${{ steps.ccache-prepare.outputs.key }}
577+
578+
- name: Run thread stress tests
579+
timeout-minutes: 30
580+
run: |
581+
cd build
582+
export PATH="$PWD/lib:$PATH"
583+
OPENBLAS_NUM_THREADS=8 OMP_NUM_THREADS=16 ctest -R 'dgemm_thread_safety|dgemm_thread_safety_mixed|dgemv_thread_safety' --output-on-failure
584+
585+
337586
cross_build:
338587
if: "github.repository == 'OpenMathLib/OpenBLAS'"
339588
runs-on: ubuntu-22.04

CMakeLists.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,10 @@ else()
5858
set(NO_AFFINITY 1)
5959
endif()
6060

61-
option(CPP_THREAD_SAFETY_TEST "Run a massively parallel DGEMM test to confirm thread safety of the library (requires OpenMP and about 1.3GB of RAM)" OFF)
61+
option(CPP_THREAD_SAFETY_TEST "Run massively parallel DGEMM tests to confirm thread safety of the library (requires about 1.3GB of RAM)" OFF)
62+
option(CPP_THREAD_SAFETY_USE_OPENMP "Use OpenMP to launch the C++ thread safety tests" ON)
6263

63-
option(CPP_THREAD_SAFETY_GEMV "Run a massively parallel DGEMV test to confirm thread safety of the library (requires OpenMP)" OFF)
64+
option(CPP_THREAD_SAFETY_GEMV "Run a massively parallel DGEMV test to confirm thread safety of the library" OFF)
6465
option(BUILD_STATIC_LIBS "Build static library" OFF)
6566
option(BUILD_SHARED_LIBS "Build shared library" OFF)
6667
if(NOT BUILD_STATIC_LIBS AND NOT BUILD_SHARED_LIBS)
@@ -820,4 +821,3 @@ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PN}ConfigVersion.cmake
820821
install(EXPORT "${PN}${SUFFIX64}Targets"
821822
NAMESPACE "${PN}${SUFFIX64}::"
822823
DESTINATION ${CMAKECONFIG_INSTALL_DIR})
823-

Makefile.install

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,7 @@ endif
355355
endif
356356
ifeq ($(CPP_THREAD_SAFETY_TEST), 1)
357357
@install -m 666 cpp_thread_test/dgemm_tester $(DESTDIR)$(OPENBLAS_BINARY_DIR)
358+
@install -m 666 cpp_thread_test/dgemm_mixed_tester $(DESTDIR)$(OPENBLAS_BINARY_DIR)
358359
@install -m 666 cpp_thread_test/dgemv_tester $(DESTDIR)$(OPENBLAS_BINARY_DIR)
359360
endif
360361
endif
361-

Makefile.rule

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -290,10 +290,10 @@ COMMON_PROF = -pg
290290
# This is mostly intended as a developer feature to spot regressions, but users and
291291
# package maintainers can enable this if they have doubts about the thread safety of
292292
# the library, given the configuration in this file.
293-
# By default, the thread safety tester launches 52 concurrent calculations at the same
294-
# time.
293+
# By default, the thread safety testers launch many concurrent calculations at
294+
# the same time.
295295
#
296-
# Please note that the test uses ~1300 MiB of RAM for the DGEMM test.
296+
# Please note that the tests use ~1300 MiB of RAM for the DGEMM test.
297297
#
298298
# The test requires CBLAS to be built, a C++11 capable compiler and the presence of
299299
# an OpenMP implementation. If you are cross-compiling this test will probably not

common_thread.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,9 @@ int exec_blas(BLASLONG num_cpu, blas_param_t *param, void *buffer);
191191

192192
#ifndef ASSEMBLER
193193

194+
void blas_level3_thread_enter(void);
195+
void blas_level3_thread_leave(void);
196+
194197
int blas_level1_thread(int mode, BLASLONG m, BLASLONG n, BLASLONG k, void *alpha,
195198
void *a, BLASLONG lda,
196199
void *b, BLASLONG ldb,

cpp_thread_test/CMakeLists.txt

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,35 @@ enable_language(CXX)
55

66
set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -DADD${BU} -DCBLAS")
77

8-
if (USE_OPENMP)
9-
if (CPP_THREAD_SAFETY_TEST)
10-
message(STATUS building thread safety test)
11-
add_executable(dgemm_thread_safety dgemm_thread_safety.cpp)
12-
target_link_libraries(dgemm_thread_safety ${OpenBLAS_LIBNAME})
13-
add_test( dgemm_thread_safety ${CMAKE_CURRENT_BINARY_DIR}/dgemm_thread_safety)
8+
set(CPP_THREAD_SAFETY_LIBS ${OpenBLAS_LIBNAME})
9+
find_package(Threads REQUIRED)
10+
list(APPEND CPP_THREAD_SAFETY_LIBS Threads::Threads)
11+
add_definitions(-DOPENBLAS_USE_GENERATED_CBLAS_H)
12+
13+
if ((CPP_THREAD_SAFETY_TEST OR CPP_THREAD_SAFETY_GEMV) AND CPP_THREAD_SAFETY_USE_OPENMP)
14+
find_package(OpenMP REQUIRED COMPONENTS CXX)
15+
list(APPEND CPP_THREAD_SAFETY_LIBS OpenMP::OpenMP_CXX)
16+
add_definitions(-DCPP_THREAD_SAFETY_USE_OPENMP)
1417
endif()
1518

19+
set(CPP_THREAD_SAFETY_DGEMM_ARGS "" CACHE STRING "Arguments passed to the DGEMM thread safety test")
20+
set(CPP_THREAD_SAFETY_DGEMM_MIXED_ARGS "" CACHE STRING "Arguments passed to the mixed DGEMM thread safety test")
21+
set(CPP_THREAD_SAFETY_DGEMV_ARGS "" CACHE STRING "Arguments passed to the DGEMV thread safety test")
1622

17-
if (CPP_THREAD_SAFETY_TEST OR CPP_THREAD_SAFETY_GEMV)
18-
add_executable(dgemv_thread_safety dgemv_thread_safety.cpp)
19-
target_link_libraries(dgemv_thread_safety ${OpenBLAS_LIBNAME})
20-
add_test(dgemv_thread_safety ${CMAKE_CURRENT_BINARY_DIR}/dgemv_thread_safety)
23+
if (CPP_THREAD_SAFETY_TEST)
24+
message(STATUS "building thread safety test")
25+
add_executable(dgemm_thread_safety dgemm_thread_safety.cpp)
26+
target_link_libraries(dgemm_thread_safety ${CPP_THREAD_SAFETY_LIBS})
27+
add_test(NAME dgemm_thread_safety COMMAND ${CMAKE_CURRENT_BINARY_DIR}/dgemm_thread_safety ${CPP_THREAD_SAFETY_DGEMM_ARGS})
28+
29+
add_executable(dgemm_thread_safety_mixed dgemm_thread_safety_mixed.cpp)
30+
target_link_libraries(dgemm_thread_safety_mixed ${CPP_THREAD_SAFETY_LIBS})
31+
add_test(NAME dgemm_thread_safety_mixed COMMAND ${CMAKE_CURRENT_BINARY_DIR}/dgemm_thread_safety_mixed ${CPP_THREAD_SAFETY_DGEMM_MIXED_ARGS})
2132
endif()
2233

34+
35+
if (CPP_THREAD_SAFETY_TEST OR CPP_THREAD_SAFETY_GEMV)
36+
add_executable(dgemv_thread_safety dgemv_thread_safety.cpp)
37+
target_link_libraries(dgemv_thread_safety ${CPP_THREAD_SAFETY_LIBS})
38+
add_test(NAME dgemv_thread_safety COMMAND ${CMAKE_CURRENT_BINARY_DIR}/dgemv_thread_safety ${CPP_THREAD_SAFETY_DGEMV_ARGS})
2339
endif()

cpp_thread_test/Makefile

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,19 @@
11
TOPDIR = ..
22
include $(TOPDIR)/Makefile.system
33

4-
all :: dgemv_tester dgemm_tester
4+
all :: dgemv_tester dgemm_tester dgemm_mixed_tester
55

66
dgemv_tester :
7-
$(CXX) $(COMMON_OPT) -Wall -Wextra -Wshadow -fopenmp -std=c++11 dgemv_thread_safety.cpp ../$(LIBNAME) $(EXTRALIB) $(FEXTRALIB) -o dgemv_tester
7+
$(CXX) $(COMMON_OPT) -Wall -Wextra -Wshadow -std=c++11 dgemv_thread_safety.cpp ../$(LIBNAME) $(EXTRALIB) $(FEXTRALIB) -o dgemv_tester
88
./dgemv_tester
99

1010
dgemm_tester : dgemv_tester
11-
$(CXX) $(COMMON_OPT) -Wall -Wextra -Wshadow -fopenmp -std=c++11 dgemm_thread_safety.cpp ../$(LIBNAME) $(EXTRALIB) $(FEXTRALIB) -o dgemm_tester
11+
$(CXX) $(COMMON_OPT) -Wall -Wextra -Wshadow -std=c++11 dgemm_thread_safety.cpp ../$(LIBNAME) $(EXTRALIB) $(FEXTRALIB) -o dgemm_tester
1212
./dgemm_tester
1313

14+
dgemm_mixed_tester : dgemm_tester
15+
$(CXX) $(COMMON_OPT) -Wall -Wextra -Wshadow -std=c++11 dgemm_thread_safety_mixed.cpp ../$(LIBNAME) $(EXTRALIB) $(FEXTRALIB) -o dgemm_mixed_tester
16+
./dgemm_mixed_tester
17+
1418
clean ::
15-
rm -f dgemv_tester dgemm_tester
19+
rm -f dgemv_tester dgemm_tester dgemm_mixed_tester

0 commit comments

Comments
 (0)