Skip to content

Commit 9363452

Browse files
committed
Fix corruption due to lock sharding issues by centralizing locking
1 parent 7aa79fb commit 9363452

17 files changed

Lines changed: 604 additions & 192 deletions

.github/workflows/dynamic_arch.yml

Lines changed: 236 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,242 @@ 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+
"-DDYNAMIC_ARCH=$dynamic_arch"
421+
-DNOFORTRAN=ON
422+
-DUSE_THREAD=ON
423+
"-DUSE_OPENMP=$use_openmp"
424+
-DNUM_THREADS=32
425+
-DNUM_PARALLEL=2
426+
-DTARGET=CORE2
427+
-DCPP_THREAD_SAFETY_TEST=ON
428+
"-DCPP_THREAD_SAFETY_USE_OPENMP=$cpp_thread_safety_use_openmp"
429+
"-DCPP_THREAD_SAFETY_DGEMM_ARGS=$dgemm_args"
430+
"-DCPP_THREAD_SAFETY_DGEMM_MIXED_ARGS=$dgemm_mixed_args"
431+
"-DCPP_THREAD_SAFETY_DGEMV_ARGS=$dgemv_args"
432+
-DCMAKE_C_COMPILER_LAUNCHER=ccache
433+
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache
434+
)
435+
if [ "${{ matrix.backend }}" = "tsan" ]; then
436+
cmake_args+=(
437+
"-DCMAKE_C_FLAGS=$sanitizer_flags"
438+
"-DCMAKE_CXX_FLAGS=$sanitizer_flags"
439+
-DCMAKE_SHARED_LINKER_FLAGS=-fsanitize=thread
440+
-DCMAKE_EXE_LINKER_FLAGS=-fsanitize=thread
441+
)
442+
fi
443+
cmake "${cmake_args[@]}" ..
444+
445+
- name: Build OpenBLAS
446+
run: cd build && cmake --build .
447+
448+
- name: Show ccache status
449+
continue-on-error: true
450+
run: ccache -s
451+
452+
- name: Run thread stress tests
453+
timeout-minutes: 30
454+
run: |
455+
cd build
456+
if [ "${{ matrix.backend }}" = "tsan" ]; then
457+
export OPENBLAS_NUM_THREADS=2
458+
export LLVM_SYMBOLIZER_PATH=/usr/bin/llvm-symbolizer
459+
export TSAN_OPTIONS=halt_on_error=1:exitcode=66:second_deadlock_stack=1
460+
else
461+
export OPENBLAS_NUM_THREADS=8
462+
export OMP_NUM_THREADS=16
463+
fi
464+
ctest -R 'dgemm_thread_safety|dgemm_thread_safety_mixed|dgemv_thread_safety' --output-on-failure
465+
466+
467+
msys2_thread_stress:
468+
if: "github.repository == 'OpenMathLib/OpenBLAS'"
469+
runs-on: windows-latest
470+
471+
defaults:
472+
run:
473+
shell: msys2 {0}
474+
475+
env:
476+
CHERE_INVOKING: 1
477+
478+
steps:
479+
- name: Get CPU name
480+
shell: pwsh
481+
run : |
482+
Get-CIMInstance -Class Win32_Processor | Select-Object -Property Name
483+
484+
- name: Install build dependencies
485+
uses: msys2/setup-msys2@v2
486+
with:
487+
msystem: UCRT64
488+
update: true
489+
release: false # Use pre-installed version
490+
install: >-
491+
base-devel
492+
mingw-w64-ucrt-x86_64-cc
493+
mingw-w64-ucrt-x86_64-cmake
494+
mingw-w64-ucrt-x86_64-ninja
495+
mingw-w64-ucrt-x86_64-ccache
496+
497+
- name: Checkout repository
498+
uses: actions/checkout@v6
499+
500+
- name: Prepare ccache
501+
# Get cache location of ccache
502+
# Create key that is used in action/cache/restore and action/cache/save steps
503+
id: ccache-prepare
504+
run: |
505+
echo "ccachedir=$(cygpath -m $(ccache -k cache_dir))" >> $GITHUB_OUTPUT
506+
# We include the commit sha in the cache key, as new cache entries are
507+
# only created if there is no existing entry for the key yet.
508+
echo "key=ccache-msys2-thread-stress-${{ github.ref }}-${{ github.sha }}" >> $GITHUB_OUTPUT
509+
510+
- name: Restore ccache
511+
uses: actions/cache/restore@v5
512+
with:
513+
path: ${{ steps.ccache-prepare.outputs.ccachedir }}
514+
key: ${{ steps.ccache-prepare.outputs.key }}
515+
# Restore a matching ccache cache entry. Prefer same branch.
516+
restore-keys: |
517+
ccache-msys2-thread-stress-${{ github.ref }}
518+
ccache-msys2-thread-stress
519+
520+
- name: Configure ccache
521+
# Limit the maximum size and switch on compression to avoid exceeding the total disk or cache quota.
522+
run: |
523+
which ccache
524+
test -d ${{ steps.ccache-prepare.outputs.ccachedir }} || mkdir -p ${{ steps.ccache-prepare.outputs.ccachedir }}
525+
echo "max_size = 250M" > ${{ steps.ccache-prepare.outputs.ccachedir }}/ccache.conf
526+
echo "compression = true" >> ${{ steps.ccache-prepare.outputs.ccachedir }}/ccache.conf
527+
ccache -p
528+
ccache -s
529+
530+
- name: Configure OpenBLAS
531+
run: |
532+
mkdir build && cd build
533+
cmake -G Ninja \
534+
-DCMAKE_BUILD_TYPE=Release \
535+
-DBUILD_SHARED_LIBS=ON \
536+
-DBUILD_STATIC_LIBS=OFF \
537+
-DBUILD_WITHOUT_LAPACK=ON \
538+
-DDYNAMIC_ARCH=ON \
539+
-DNOFORTRAN=ON \
540+
-DUSE_THREAD=ON \
541+
-DUSE_OPENMP=OFF \
542+
-DNUM_THREADS=32 \
543+
-DTARGET=CORE2 \
544+
-DCPP_THREAD_SAFETY_TEST=ON \
545+
-DCPP_THREAD_SAFETY_DGEMM_ARGS="384;8;4" \
546+
-DCPP_THREAD_SAFETY_DGEMM_MIXED_ARGS="524288;16;20" \
547+
-DCPP_THREAD_SAFETY_DGEMV_ARGS="384;8;4" \
548+
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
549+
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
550+
..
551+
552+
- name: Build OpenBLAS
553+
run: cd build && cmake --build .
554+
555+
- name: Show ccache status
556+
continue-on-error: true
557+
run: ccache -s
558+
559+
- name: Save ccache
560+
# Save the cache after we are done (successfully) building
561+
uses: actions/cache/save@v5
562+
with:
563+
path: ${{ steps.ccache-prepare.outputs.ccachedir }}
564+
key: ${{ steps.ccache-prepare.outputs.key }}
565+
566+
- name: Run thread stress tests
567+
timeout-minutes: 30
568+
run: |
569+
cd build
570+
OPENBLAS_NUM_THREADS=8 OMP_NUM_THREADS=16 ctest -R 'dgemm_thread_safety|dgemm_thread_safety_mixed|dgemv_thread_safety' --output-on-failure
571+
572+
337573
cross_build:
338574
if: "github.repository == 'OpenMathLib/OpenBLAS'"
339575
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)