2019-06-02 03:30:06 +08:00
# include <iostream>
# include <vector>
# include <random>
# include <future>
2026-06-15 03:54:55 +08:00
# ifdef OPENBLAS_USE_GENERATED_CBLAS_H
# include "generated/cblas.h"
# else
2019-06-02 03:30:06 +08:00
# include "../cblas.h"
2026-06-15 03:54:55 +08:00
# endif
2019-06-02 03:30:06 +08:00
# include "cpp_thread_safety_common.h"
2022-07-24 14:21:25 +08:00
void launch_cblas_dgemv ( double * A , double * x , double * y , const blasint randomMatSize )
{
2019-06-02 03:30:06 +08:00
const blasint inc = 1 ;
cblas_dgemv ( CblasColMajor , CblasNoTrans , randomMatSize , randomMatSize , 1.0 , A , randomMatSize , x , inc , 0.1 , y , inc ) ;
2022-07-24 14:21:25 +08:00
}
2019-06-02 03:30:06 +08:00
2022-07-24 14:21:25 +08:00
int main ( int argc , char * argv [ ] )
{
2019-06-02 03:30:06 +08:00
blasint randomMatSize = 1024 ; //dimension of the random square matrices and vectors being used
uint32_t numConcurrentThreads = 52 ; //number of concurrent calls of the functions being tested
uint32_t numTestRounds = 16 ; //number of testing rounds before success exit
2026-06-15 03:54:55 +08:00
uint32_t maxHwThreads = GetMaxHwThreads ( ) ;
2020-04-11 04:06:44 +08:00
if ( maxHwThreads < 52 )
2020-06-17 22:08:48 +08:00
numConcurrentThreads = maxHwThreads ;
2019-06-02 03:30:06 +08:00
2022-07-24 14:21:25 +08:00
if ( argc > 4 )
{
2019-06-02 03:30:06 +08:00
std : : cout < < " ERROR: too many arguments for thread safety tester " < < std : : endl ;
abort ( ) ;
2022-07-24 14:21:25 +08:00
}
if ( argc = = 4 )
{
2019-06-02 03:30:06 +08:00
std : : vector < std : : string > cliArgs ;
2022-07-24 14:21:25 +08:00
for ( int i = 1 ; i < argc ; i + + )
{
2019-06-02 03:30:06 +08:00
cliArgs . push_back ( argv [ i ] ) ;
std : : cout < < argv [ i ] < < std : : endl ;
2022-07-24 14:21:25 +08:00
}
2019-06-02 03:30:06 +08:00
randomMatSize = std : : stoul ( cliArgs . at ( 0 ) ) ;
numConcurrentThreads = std : : stoul ( cliArgs . at ( 1 ) ) ;
numTestRounds = std : : stoul ( cliArgs . at ( 2 ) ) ;
2022-07-24 14:21:25 +08:00
}
2019-06-02 03:30:06 +08:00
std : : uniform_real_distribution < double > rngdist { - 1.0 , 1.0 } ;
std : : vector < std : : vector < double > > matBlock ( numConcurrentThreads ) ;
std : : vector < std : : vector < double > > vecBlock ( numConcurrentThreads * 2 ) ;
std : : vector < std : : future < void > > futureBlock ( numConcurrentThreads ) ;
std : : cout < < " *----------------------------* \n " ;
std : : cout < < " | DGEMV thread safety tester | \n " ;
std : : cout < < " *----------------------------* \n " ;
std : : cout < < " Size of random matrices and vectors(N=M): " < < randomMatSize < < ' \n ' ;
std : : cout < < " Number of concurrent calls into OpenBLAS : " < < numConcurrentThreads < < ' \n ' ;
std : : cout < < " Number of testing rounds : " < < numTestRounds < < ' \n ' ;
std : : cout < < " This test will need " < < ( ( static_cast < uint64_t > ( randomMatSize * randomMatSize ) * numConcurrentThreads * 8 ) + ( static_cast < uint64_t > ( randomMatSize ) * numConcurrentThreads * 8 * 2 ) ) / static_cast < double > ( 1024 * 1024 ) < < " MiB of RAM \n " < < std : : endl ;
2020-06-17 22:15:44 +08:00
FailIfThreadsAreZero ( numConcurrentThreads ) ;
2019-06-02 03:30:06 +08:00
std : : cout < < " Initializing random number generator... " < < std : : flush ;
std : : mt19937_64 PRNG = InitPRNG ( ) ;
std : : cout < < " done \n " ;
std : : cout < < " Preparing to test CBLAS DGEMV thread safety \n " ;
std : : cout < < " Allocating matrices... " < < std : : flush ;
2022-07-24 14:21:25 +08:00
for ( uint32_t i = 0 ; i < numConcurrentThreads ; i + + )
{
2019-06-02 03:30:06 +08:00
matBlock . at ( i ) . resize ( randomMatSize * randomMatSize ) ;
2022-07-24 14:21:25 +08:00
}
2019-06-02 03:30:06 +08:00
std : : cout < < " done \n " ;
std : : cout < < " Allocating vectors... " < < std : : flush ;
2022-07-24 14:21:25 +08:00
for ( uint32_t i = 0 ; i < ( numConcurrentThreads * 2 ) ; i + + )
{
2019-06-02 03:30:06 +08:00
vecBlock . at ( i ) . resize ( randomMatSize ) ;
2022-07-24 14:21:25 +08:00
}
2019-06-02 03:30:06 +08:00
std : : cout < < " done \n " ;
2022-07-24 14:21:25 +08:00
2019-06-02 03:30:06 +08:00
//pauser();
std : : cout < < " Filling matrices with random numbers... " < < std : : flush ;
FillMatrices ( matBlock , PRNG , rngdist , randomMatSize , numConcurrentThreads , 1 ) ;
//PrintMatrices(matBlock, randomMatSize, numConcurrentThreads);
std : : cout < < " done \n " ;
std : : cout < < " Filling vectors with random numbers... " < < std : : flush ;
FillVectors ( vecBlock , PRNG , rngdist , randomMatSize , numConcurrentThreads , 2 ) ;
std : : cout < < " done \n " ;
std : : cout < < " Testing CBLAS DGEMV thread safety " < < std : : endl ;
2026-06-15 03:54:55 +08:00
SetLauncherThreads ( numConcurrentThreads ) ;
2022-07-24 14:21:25 +08:00
for ( uint32_t R = 0 ; R < numTestRounds ; R + + )
{
2019-06-02 03:30:06 +08:00
std : : cout < < " DGEMV round # " < < R < < std : : endl ;
2026-06-15 03:54:55 +08:00
std : : cout < < " Launching " < < numConcurrentThreads < < " threads simultaneously " < < LauncherName ( ) < < " ... " < < std : : flush ;
# ifdef CPP_THREAD_SAFETY_USE_OPENMP
2019-06-02 03:30:06 +08:00
# pragma omp parallel for default(none) shared(futureBlock, matBlock, vecBlock, randomMatSize, numConcurrentThreads)
2026-06-15 03:54:55 +08:00
# endif
2022-07-24 14:21:25 +08:00
for ( uint32_t i = 0 ; i < numConcurrentThreads ; i + + )
{
2019-06-02 03:30:06 +08:00
futureBlock [ i ] = std : : async ( std : : launch : : async , launch_cblas_dgemv , & matBlock [ i ] [ 0 ] , & vecBlock [ i * 2 ] [ 0 ] , & vecBlock [ i * 2 + 1 ] [ 0 ] , randomMatSize ) ;
2022-07-24 14:21:25 +08:00
}
2019-06-02 03:30:06 +08:00
std : : cout < < " done \n " ;
std : : cout < < " Waiting for threads to finish... " < < std : : flush ;
2022-07-24 14:21:25 +08:00
for ( uint32_t i = 0 ; i < numConcurrentThreads ; i + + )
{
2019-06-02 03:30:06 +08:00
futureBlock [ i ] . get ( ) ;
2022-07-24 14:21:25 +08:00
}
2019-06-02 03:30:06 +08:00
std : : cout < < " done \n " ;
std : : cout < < " Comparing results from different threads... " < < std : : flush ;
for ( uint32_t i = 2 ; i < ( numConcurrentThreads * 2 ) ; i + = 2 ) { //i is the index of vector x, for a given thread
2022-07-24 14:21:25 +08:00
for ( uint32_t j = 0 ; j < static_cast < uint32_t > ( randomMatSize ) ; j + + )
{
2019-06-02 03:30:06 +08:00
if ( std : : abs ( vecBlock [ i + 1 ] [ j ] - vecBlock [ 1 ] [ j ] ) > 1.0E-13 ) { //i+1 is the index of vector y, for a given thread
std : : cout < < " ERROR: one of the threads returned a different result! Index : " < < i + 1 < < std : : endl ;
std : : cout < < " CBLAS DGEMV thread safety test FAILED! " < < std : : endl ;
return - 1 ;
2022-07-24 14:21:25 +08:00
}
2019-06-02 03:30:06 +08:00
}
}
2022-07-24 14:21:25 +08:00
std : : cout < < " OK! \n " < < std : : endl ;
2019-06-02 03:30:06 +08:00
}
std : : cout < < " CBLAS DGEMV thread safety test PASSED! \n " < < std : : endl ;
return 0 ;
2022-07-24 14:21:25 +08:00
}