Skip to content

Commit 88eea05

Browse files
committed
cpp_thread_test: ZGEMM thread safety test
The same structure as the DGEMM test, with complex alpha and beta and 384 x 384 matrices. It fails on Apple M4 without the per-thread packing buffers of the SME GEMM kernels.
1 parent b8a10cc commit 88eea05

3 files changed

Lines changed: 122 additions & 2 deletions

File tree

‎cpp_thread_test/CMakeLists.txt‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ set(CPP_THREAD_SAFETY_DGEMM_ARGS "" CACHE STRING "Arguments passed to the DGEMM
2020
set(CPP_THREAD_SAFETY_DGEMM_MIXED_ARGS "" CACHE STRING "Arguments passed to the mixed DGEMM thread safety test")
2121
set(CPP_THREAD_SAFETY_DGEMV_ARGS "" CACHE STRING "Arguments passed to the DGEMV thread safety test")
2222
set(CPP_THREAD_SAFETY_SHUTDOWN_ARGS "" CACHE STRING "Arguments passed to the DGEMM shutdown safety test")
23+
set(CPP_THREAD_SAFETY_ZGEMM_ARGS "" CACHE STRING "Arguments passed to the ZGEMM thread safety test")
2324

2425
if (CPP_THREAD_SAFETY_TEST)
2526
message(STATUS "building thread safety test")
@@ -31,6 +32,10 @@ if (CPP_THREAD_SAFETY_TEST)
3132
target_link_libraries(dgemm_thread_safety_mixed ${CPP_THREAD_SAFETY_LIBS})
3233
add_test(NAME dgemm_thread_safety_mixed COMMAND ${CMAKE_CURRENT_BINARY_DIR}/dgemm_thread_safety_mixed ${CPP_THREAD_SAFETY_DGEMM_MIXED_ARGS})
3334

35+
add_executable(zgemm_thread_safety zgemm_thread_safety.cpp)
36+
target_link_libraries(zgemm_thread_safety ${CPP_THREAD_SAFETY_LIBS})
37+
add_test(NAME zgemm_thread_safety COMMAND ${CMAKE_CURRENT_BINARY_DIR}/zgemm_thread_safety ${CPP_THREAD_SAFETY_ZGEMM_ARGS})
38+
3439
if (WIN32)
3540
add_executable(dgemm_thread_safety_shutdown dgemm_thread_safety_shutdown.cpp)
3641
target_link_libraries(dgemm_thread_safety_shutdown ${CPP_THREAD_SAFETY_LIBS})

‎cpp_thread_test/Makefile‎

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

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

66
ifeq ($(OSNAME), WINNT)
77
all :: dgemm_shutdown_tester
@@ -35,6 +35,10 @@ dgemm_mixed_tester : dgemm_tester
3535
$(CXX) $(COMMON_OPT) -Wall -Wextra -Wshadow -std=c++11 dgemm_thread_safety_mixed.cpp ../$(LIBNAME) $(EXTRALIB) $(FEXTRALIB) -o dgemm_mixed_tester
3636
./dgemm_mixed_tester
3737

38+
zgemm_tester : dgemm_mixed_tester
39+
$(CXX) $(COMMON_OPT) -Wall -Wextra -Wshadow -std=c++11 zgemm_thread_safety.cpp ../$(LIBNAME) $(EXTRALIB) $(FEXTRALIB) -o zgemm_tester
40+
./zgemm_tester
41+
3842
dgemm_shutdown_tester : dgemm_mixed_tester
3943
$(CXX) $(COMMON_OPT) -Wall -Wextra -Wshadow -std=c++11 dgemm_thread_safety_shutdown.cpp ../$(LIBNAME) $(EXTRALIB) $(FEXTRALIB) -o dgemm_shutdown_tester
4044
./dgemm_shutdown_tester
@@ -45,4 +49,4 @@ dgemm_mixed_callback_tester : dgemm_mixed_tester
4549
endif
4650

4751
clean ::
48-
rm -f dgemv_tester dgemm_tester dgemm_mixed_tester dgemm_shutdown_tester
52+
rm -f dgemv_tester dgemm_tester dgemm_mixed_tester zgemm_tester dgemm_shutdown_tester
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
#include <iostream>
2+
#include <vector>
3+
#include <random>
4+
#include <future>
5+
#ifdef OPENBLAS_USE_GENERATED_CBLAS_H
6+
#include "generated/cblas.h"
7+
#else
8+
#include "../cblas.h"
9+
#endif
10+
#include "cpp_thread_safety_common.h"
11+
12+
void launch_cblas_zgemm(double* A, double* B, double* C, const blasint randomMatSize){
13+
const double alpha[2] = {1.0, 0.5}, beta[2] = {0.1, -0.2};
14+
cblas_zgemm(CblasColMajor, CblasNoTrans, CblasNoTrans, randomMatSize, randomMatSize, randomMatSize, alpha, A, randomMatSize, B, randomMatSize, beta, C, randomMatSize);
15+
}
16+
17+
int main(int argc, char* argv[]){
18+
blasint randomMatSize = 384; //dimension of the random square complex matrices used
19+
uint32_t numConcurrentThreads = 96; //number of concurrent calls of the functions being tested
20+
uint32_t numTestRounds = 16; //number of testing rounds before success exit
21+
uint32_t maxHwThreads = GetMaxHwThreads();
22+
23+
if (maxHwThreads < 96)
24+
numConcurrentThreads = maxHwThreads;
25+
26+
if (argc > 4){
27+
std::cout<<"ERROR: too many arguments for thread safety tester"<<std::endl;
28+
abort();
29+
}
30+
31+
if(argc == 4){
32+
std::vector<std::string> cliArgs;
33+
for (int i = 1; i < argc; i++){
34+
cliArgs.push_back(argv[i]);
35+
std::cout<<argv[i]<<std::endl;
36+
}
37+
randomMatSize = std::stoul(cliArgs[0]);
38+
numConcurrentThreads = std::stoul(cliArgs[1]);
39+
numTestRounds = std::stoul(cliArgs[2]);
40+
}
41+
42+
std::uniform_real_distribution<double> rngdist{-1.0, 1.0};
43+
std::vector<std::vector<double>> matBlock(numConcurrentThreads*3);
44+
std::vector<std::future<void>> futureBlock(numConcurrentThreads);
45+
46+
std::cout<<"*----------------------------*\n";
47+
std::cout<<"| ZGEMM thread safety tester |\n";
48+
std::cout<<"*----------------------------*\n";
49+
std::cout<<"Size of random matrices(N=M=K): "<<randomMatSize<<'\n';
50+
std::cout<<"Number of concurrent calls into OpenBLAS : "<<numConcurrentThreads<<'\n';
51+
std::cout<<"Number of testing rounds : "<<numTestRounds<<'\n';
52+
std::cout<<"This test will need "<<(static_cast<uint64_t>(randomMatSize*randomMatSize)*numConcurrentThreads*3*16)/static_cast<double>(1024*1024)<<" MiB of RAM\n"<<std::endl;
53+
54+
FailIfThreadsAreZero(numConcurrentThreads);
55+
56+
std::cout<<"Initializing random number generator..."<<std::flush;
57+
std::mt19937_64 PRNG = InitPRNG();
58+
std::cout<<"done\n";
59+
60+
std::cout<<"Preparing to test CBLAS ZGEMM thread safety\n";
61+
std::cout<<"Allocating matrices..."<<std::flush;
62+
for(uint32_t i=0; i<(numConcurrentThreads*3); i++){
63+
matBlock[i].resize(2*randomMatSize*randomMatSize);
64+
}
65+
std::cout<<"done\n";
66+
//pauser();
67+
std::cout<<"Filling matrices with random numbers..."<<std::flush;
68+
for(uint32_t i=0; i<3; i++){
69+
for(uint32_t j = 0; j < static_cast<uint32_t>(2*randomMatSize*randomMatSize); j++){
70+
matBlock[i][j] = rngdist(PRNG);
71+
}
72+
}
73+
for(uint32_t i=3; i<(numConcurrentThreads*3); i++){
74+
matBlock[i] = matBlock[i%3];
75+
}
76+
//PrintMatrices(matBlock, randomMatSize, numConcurrentThreads, 3);
77+
std::cout<<"done\n";
78+
std::cout<<"Testing CBLAS ZGEMM thread safety\n";
79+
SetLauncherThreads(numConcurrentThreads);
80+
for(uint32_t R=0; R<numTestRounds; R++){
81+
std::cout<<"ZGEMM round #"<<R<<std::endl;
82+
std::cout<<"Launching "<<numConcurrentThreads<<" threads simultaneously"<<LauncherName()<<"..."<<std::flush;
83+
#ifdef CPP_THREAD_SAFETY_USE_OPENMP
84+
#pragma omp parallel for default(none) shared(futureBlock, matBlock, randomMatSize, numConcurrentThreads)
85+
#endif
86+
for(uint32_t i=0; i<numConcurrentThreads; i++){
87+
futureBlock[i] = std::async(std::launch::async, launch_cblas_zgemm, &matBlock[i*3][0], &matBlock[i*3+1][0], &matBlock[i*3+2][0], randomMatSize);
88+
//launch_cblas_zgemm( &matBlock[i][0], &matBlock[i+1][0], &matBlock[i+2][0]);
89+
}
90+
std::cout<<"done\n";
91+
std::cout<<"Waiting for threads to finish..."<<std::flush;
92+
for(uint32_t i=0; i<numConcurrentThreads; i++){
93+
futureBlock[i].get();
94+
}
95+
std::cout<<"done\n";
96+
//PrintMatrices(matBlock, randomMatSize, numConcurrentThreads, 3);
97+
std::cout<<"Comparing results from different threads..."<<std::flush;
98+
for(uint32_t i=3; i<(numConcurrentThreads*3); i+=3){ //i is the index of matrix A, for a given thread
99+
for(uint32_t j = 0; j < static_cast<uint32_t>(2*randomMatSize*randomMatSize); j++){
100+
if (std::abs(matBlock[i+2][j] - matBlock[2][j]) > 1.0E-13){ //i+2 is the index of matrix C, for a given thread
101+
std::cout<<"ERROR: one of the threads returned a different result! Index : "<<i+2<<std::endl;
102+
std::cout<<"CBLAS ZGEMM thread safety test FAILED!"<<std::endl;
103+
return -1;
104+
}
105+
}
106+
}
107+
std::cout<<"OK!\n"<<std::endl;
108+
}
109+
std::cout<<"CBLAS ZGEMM thread safety test PASSED!\n"<<std::endl;
110+
return 0;
111+
}

0 commit comments

Comments
 (0)