From 1f9f5493af5cfb45ccf2562a029a499483d02275 Mon Sep 17 00:00:00 2001 From: ZHG Date: Mon, 5 Aug 2019 11:05:46 +0200 Subject: [PATCH 1/5] Activated the usage of cublas --- benchmarks/benchmark-dgemm.C | 2 +- configure.ac | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/benchmarks/benchmark-dgemm.C b/benchmarks/benchmark-dgemm.C index 3867ed106..db5fec8d3 100644 --- a/benchmarks/benchmark-dgemm.C +++ b/benchmarks/benchmark-dgemm.C @@ -18,7 +18,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * ========LICENCE======== */ - +#define CUDA_BLAS //#include "goto-def.h" #include "fflas-ffpack/fflas-ffpack-config.h" diff --git a/configure.ac b/configure.ac index 04df5b84f..9f228dd49 100644 --- a/configure.ac +++ b/configure.ac @@ -287,7 +287,7 @@ FF_OPENBLAS_NUM_THREADS # BLAS_LIBS="-L/${BLAS_PATH} ${LAPACK_LIBS} ${BLAS_LIBS}" # AC_SUBST(BLAS_LIBS) -# FF_CHECK_CUDA + FF_CHECK_CUDA # AM_CONDITIONAL(FFLASFFPACK_HAVE_BLAS, test "x$BLAS_FOUND" != "xfalse") From 5ee9f2a21fddadbe1b901cabd2e8130db8d8aef3 Mon Sep 17 00:00:00 2001 From: ZHG Date: Tue, 20 Aug 2019 13:11:56 +0200 Subject: [PATCH 2/5] Draft version that works but need to be cleaned up for benchmark-dgemm --- benchmarks/benchmark-dgemm.C | 49 +++++++++++++++++++++++++++++++++--- fflas-ffpack/config-blas.h | 12 ++++++++- 2 files changed, 57 insertions(+), 4 deletions(-) diff --git a/benchmarks/benchmark-dgemm.C b/benchmarks/benchmark-dgemm.C index db5fec8d3..c31227eb0 100644 --- a/benchmarks/benchmark-dgemm.C +++ b/benchmarks/benchmark-dgemm.C @@ -19,6 +19,8 @@ * ========LICENCE======== */ #define CUDA_BLAS +#include +#include //#include "goto-def.h" #include "fflas-ffpack/fflas-ffpack-config.h" @@ -37,12 +39,16 @@ typedef FFLAS::OMPTimer TTimer; typedef FFLAS::Timer TTimer; #endif +#include + #ifndef __SGEMM__ typedef double Floats; #define CBLAS_GEMM cblas_dgemm +#define CUBLAS_GEMM cublasDgemm #else typedef float Floats; #define CBLAS_GEMM cblas_sgemm +#define CUBLAS_GEMM cublasDgemm #endif @@ -68,7 +74,7 @@ int main(int argc, char** argv) { FFLAS::parseArguments(argc,argv,as); - typedef Givaro::ModularBalanced Field; + typedef Givaro::Modular Field; typedef Field::Element Element; Field F(q); @@ -77,7 +83,7 @@ int main(int argc, char** argv) { double time=0.0;// time2=0.0; Element * A, * B, * C; - +/* if (iter>1) { if (!file1.empty()){ FFLAS::ReadMatrix (file1.c_str(),F,n,n,A); @@ -105,14 +111,19 @@ int main(int argc, char** argv) { C = FFLAS::fflas_new(n*n); + #if defined(CUDA_BLAS) + CUBLAS_GEMM ('n', 'n', n,n,n, F.one, + A, n, B, n, F.zero, C,n); // @fixme CUBLAS ALWAYS COLUMN MAJOR + #else CBLAS_GEMM (CblasRowMajor, CblasNoTrans, CblasNoTrans, n,n,n, F.one, A, n, B, n, F.zero, C,n); + #endif FFLAS::fflas_delete( A); FFLAS::fflas_delete( B); FFLAS::fflas_delete( C); } - +*/ for (size_t it=0;it(n*n); chrono.clear(); chrono.start(); + + #if defined(CUDA_BLAS) + + // Allocate device storage for A,B,C + Element *d_A, *d_B, *d_C; + cudaMalloc((void**)&d_A, n*n*sizeof(Element)); + cudaMalloc((void**)&d_B, n*n*sizeof(Element)); + cudaMalloc((void**)&d_C, n*n*sizeof(Element)); + + // Create cublas instance + cublasHandle_t handle; + cublasCreate(&handle); + + // Set input matrices on device + cublasSetMatrix(n, n, sizeof(Element), A, n, d_A, n); + cublasSetMatrix(n, n, sizeof(Element), B, n, d_B, n); + cublasSetMatrix(n, n, sizeof(Element), C, n, d_C, n); + + +// CUBLAS_GEMM ( 'n', 'n', n,n,n, F.one, A, n, B, n, F.zero, C,n); +CUBLAS_GEMM (handle, CUBLAS_OP_N, CUBLAS_OP_N, n,n,n, &F.one, d_A, n, d_B, n, &F.zero, d_C,n); + + // Retrieve result matrix from device + cublasGetMatrix(n, n, sizeof(Element), d_C, n, C, n); + + #else CBLAS_GEMM (CblasRowMajor, CblasNoTrans, CblasNoTrans, n,n,n, F.one, A, n, B, n, F.zero, C,n); + #endif + + std::cout << "C = A * B: " << fmod(C[0], q) << " expected " << fmod(A[0] * B[0], q) << std::endl; + chrono.stop(); time+=chrono.usertime(); diff --git a/fflas-ffpack/config-blas.h b/fflas-ffpack/config-blas.h index a38023837..f4409ec2f 100644 --- a/fflas-ffpack/config-blas.h +++ b/fflas-ffpack/config-blas.h @@ -57,11 +57,21 @@ #endif /* CBLAS_INT */ #ifdef CUDA_BLAS - +/* #define sgemv_ cublas_sgemv #define sgemm_ cublas_sgemm #define strsm_ cublas_strsm #define strmm_ cublas_strmm +*/ +/* +#define sgemv_ cublasSgemv +#define sgemm_ cublasSgemm +#define strsm_ cublasStrsm +#define strmm_ cublasStrmm +#define dgemv_ cublasDgemv +#define dgemm_ cublasDgemm +#define dtrsm_ cublasDtrsm +#define dtrmm_ cublasDtrmm*/ #endif // CUDA_BLAS From 23abe8770329f34944cedf620f03624584505d1b Mon Sep 17 00:00:00 2001 From: Alexis Breust Date: Mon, 26 Aug 2019 15:23:31 +0200 Subject: [PATCH 3/5] More setup --- benchmarks/benchmark-dgemm.C | 10 ++-- fflas-ffpack/config-blas.h | 29 ++++------- .../fflas/fflas_fgemm/fgemm_classical.inl | 40 ++++++++++++--- macros/cuda-check.m4 | 50 +++++++++---------- 4 files changed, 71 insertions(+), 58 deletions(-) diff --git a/benchmarks/benchmark-dgemm.C b/benchmarks/benchmark-dgemm.C index c31227eb0..f2a37ecf5 100644 --- a/benchmarks/benchmark-dgemm.C +++ b/benchmarks/benchmark-dgemm.C @@ -18,9 +18,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * ========LICENCE======== */ -#define CUDA_BLAS -#include -#include + //#include "goto-def.h" #include "fflas-ffpack/fflas-ffpack-config.h" @@ -39,8 +37,6 @@ typedef FFLAS::OMPTimer TTimer; typedef FFLAS::Timer TTimer; #endif -#include - #ifndef __SGEMM__ typedef double Floats; #define CBLAS_GEMM cblas_dgemm @@ -168,7 +164,7 @@ int main(int argc, char** argv) { // Create cublas instance cublasHandle_t handle; cublasCreate(&handle); - + // Set input matrices on device cublasSetMatrix(n, n, sizeof(Element), A, n, d_A, n); cublasSetMatrix(n, n, sizeof(Element), B, n, d_B, n); @@ -187,7 +183,7 @@ CUBLAS_GEMM (handle, CUBLAS_OP_N, CUBLAS_OP_N, n,n,n, &F.one, d_A, n, d_B, n, #endif std::cout << "C = A * B: " << fmod(C[0], q) << " expected " << fmod(A[0] * B[0], q) << std::endl; - + chrono.stop(); time+=chrono.usertime(); diff --git a/fflas-ffpack/config-blas.h b/fflas-ffpack/config-blas.h index f4409ec2f..db002b518 100644 --- a/fflas-ffpack/config-blas.h +++ b/fflas-ffpack/config-blas.h @@ -42,9 +42,18 @@ #ifdef __FFLASFFPACK_HAVE_MKL #include +#endif +#ifdef HAVE_CUDA +#define __FFLASFFPACK_HAVE_CUDA #endif +#ifdef __FFLASFFPACK_HAVE_CUDA +#define __FFLASFFPACK_HAVE_CUBLAS +#include +#include +#include +#endif #ifndef CBLAS_INT #ifdef blasint /* openblas */ @@ -56,26 +65,6 @@ #endif /* blasint */ #endif /* CBLAS_INT */ -#ifdef CUDA_BLAS -/* -#define sgemv_ cublas_sgemv -#define sgemm_ cublas_sgemm -#define strsm_ cublas_strsm -#define strmm_ cublas_strmm -*/ -/* -#define sgemv_ cublasSgemv -#define sgemm_ cublasSgemm -#define strsm_ cublasStrsm -#define strmm_ cublasStrmm -#define dgemv_ cublasDgemv -#define dgemm_ cublasDgemm -#define dtrsm_ cublasDtrsm -#define dtrmm_ cublasDtrmm*/ - -#endif // CUDA_BLAS - - #ifndef __FFLASFFPACK_HAVE_MKL #define CBLAS_ENUM_DEFINED_H diff --git a/fflas-ffpack/fflas/fflas_fgemm/fgemm_classical.inl b/fflas-ffpack/fflas/fflas_fgemm/fgemm_classical.inl index 334046af7..c19c59b9c 100644 --- a/fflas-ffpack/fflas/fflas_fgemm/fgemm_classical.inl +++ b/fflas-ffpack/fflas/fflas_fgemm/fgemm_classical.inl @@ -249,12 +249,40 @@ namespace FFLAS { FFLASFFPACK_check(lda); FFLASFFPACK_check(ldb); FFLASFFPACK_check(ldc); -#if defined(__FFLASFFPACK_OPENBLAS_NUM_THREADS) and not defined (__FFLASFFPACK_OPENBLAS_NT_ALREADY_SET) - openblas_set_num_threads(__FFLASFFPACK_OPENBLAS_NUM_THREADS); -#endif - cblas_dgemm (CblasRowMajor, (CBLAS_TRANSPOSE) ta, (CBLAS_TRANSPOSE) tb, - (int)m, (int)n, (int)k, (Givaro::DoubleDomain::Element) alpha, - Ad, (int)lda, Bd, (int)ldb, (Givaro::DoubleDomain::Element) beta, Cd, (int)ldc); + + #if defined(__FFLASFFPACK_HAVE_CUBLAS) + // Allocate device storage for A,B,C + using Element = Givaro::DoubleDomain::Element; + Element *d_A, *d_B, *d_C; + cudaMalloc((void**)&d_A, m*k*sizeof(Element)); + cudaMalloc((void**)&d_B, k*n*sizeof(Element)); + cudaMalloc((void**)&d_C, m*n*sizeof(Element)); + + // Create cublas instance + cublasHandle_t handle; + cublasCreate(&handle); + + // Set input matrices on device + cublasSetMatrix(m, k, sizeof(Element), Ad, lda, d_A, k); + cublasSetMatrix(k, n, sizeof(Element), Bd, ldb, d_B, n); + cublasSetMatrix(m, n, sizeof(Element), Cd, ldc, d_C, n); + + auto d_ta = (ta == FFLAS_TRANSPOSE::FflasNoTrans) ? CUBLAS_OP_N : CUBLAS_OP_T; + auto d_tb = (tb == FFLAS_TRANSPOSE::FflasNoTrans) ? CUBLAS_OP_N : CUBLAS_OP_T; + + cublasDgemm(handle, d_ta, d_tb, m,n,k, &F.one, d_A, k, d_B, n, &F.zero, d_C,n); + + // Retrieve result matrix from device + cublasGetMatrix(m, n, sizeof(Element), d_C, n, Cd, ldc); + #else + #if defined(__FFLASFFPACK_OPENBLAS_NUM_THREADS) and not defined (__FFLASFFPACK_OPENBLAS_NT_ALREADY_SET) + openblas_set_num_threads(__FFLASFFPACK_OPENBLAS_NUM_THREADS); + #endif + + cblas_dgemm (CblasRowMajor, (CBLAS_TRANSPOSE) ta, (CBLAS_TRANSPOSE) tb, + (int)m, (int)n, (int)k, (Givaro::DoubleDomain::Element) alpha, + Ad, (int)lda, Bd, (int)ldb, (Givaro::DoubleDomain::Element) beta, Cd, (int)ldc); + #endif } inline void fgemm (const Givaro::FloatDomain& F, diff --git a/macros/cuda-check.m4 b/macros/cuda-check.m4 index 7fc760932..7101ca989 100644 --- a/macros/cuda-check.m4 +++ b/macros/cuda-check.m4 @@ -63,54 +63,54 @@ do if test -r "$CUDA_HOME/include/cuda.h" ; then CUDA_CFLAGS="-I${CUDA_HOME}/include" CUDA_PATH="-L${CUDA_HOME}/lib64" - CUDA_LIBS="-L${CUDA_HOME}/lib64 -lcusparse" + CUDA_LIBS="-L${CUDA_HOME}/lib64 -lcusparse -lcublas -lcudart" else echo "($CUDA_HOME) seems an invalid CUDA prefix" echo "Searching CUDA in PATH" CUDA_CFLAGS="" - CUDA_LIBS="-lcusparse" + CUDA_LIBS="-lcusparse -lcublas -lcudart" fi else CUDA_CFLAGS="" - CUDA_LIBS="-lcusparse" + CUDA_LIBS="-lcusparse -lcublas -lcudart" fi CXXFLAGS="${CXXFLAGS} ${CUDA_CFLAGS}" LIBS="${LIBS} ${CUDA_LIBS}" CODE_CUDA=`cat macros/CodeChunk/cuda.C` + dnl This checks if cuda is installed, which ensures that cublas is available. + AC_TRY_LINK( [ - #include + #include ], - [ CUresult a;], + [ CUresult a; ], [ - dnl # See if we are running CUDA 4.0 with --enable-cxx - AC_TRY_RUN( - [ ${CODE_CUDA} ], - [ - AC_MSG_RESULT(found) - AC_DEFINE(HAVE_CUDA,1,[Define if CUDA is installed]) - - dnl CUDA_VERSION="" dnl I could find it but why is it here ? - CUDA_LIBS="${CUDA_PATH} -lcusparse" - dnl AC_SUBST(CUDA_VERSION) - AC_SUBST(CUDA_LIBS) - AC_SUBST(CUDA_CFLAGS) - break; - ],[ - AC_MSG_RESULT(no : cuda is too old or not found) - dnl AC_SUBST(CUDA_VERSION) - ],[ dnl This should never happen - AC_MSG_RESULT(no) - ]) + dnl # See if we are running CUDA 4.0 with --enable-cxx + AC_TRY_RUN( + [ ${CODE_CUDA} ], + [ + AC_MSG_RESULT(found) + + CUDA_LIBS="${CUDA_PATH} ${CUDA_LIBS}" + AC_SUBST(CUDA_LIBS) + AC_SUBST(CUDA_CFLAGS) + AC_DEFINE(HAVE_CUDA,1,[Define if CUDA blas is installed]) + break; + ],[ + AC_MSG_RESULT(no : cuda is too old or not found) + ],[ + AC_MSG_RESULT(no) + ] + ) ],[ AC_MSG_RESULT(unknown) echo "WARNING: You appear to be cross compiling, so there is no way to determine" echo "whether your CUDA version is new enough. I am assuming it is." AC_SUBST(CUDA_CFLAGS) AC_SUBST(CUDA_LIBS) - AC_DEFINE(HAVE_CUDA,1,[Define if CUDA is installed]) + AC_DEFINE(HAVE_CUDA,1,[Define if CUDA blas is installed]) ]) unset CUDA_CFLAGS unset CUDA_LIBS From 9c7fd1a52854bddcd2de98dca3f670e20bb3b761 Mon Sep 17 00:00:00 2001 From: ZHG Date: Mon, 26 Aug 2019 15:38:55 +0200 Subject: [PATCH 4/5] Removed useless line --- macros/cuda-check.m4 | 1 - 1 file changed, 1 deletion(-) diff --git a/macros/cuda-check.m4 b/macros/cuda-check.m4 index 7101ca989..1a391d087 100644 --- a/macros/cuda-check.m4 +++ b/macros/cuda-check.m4 @@ -93,7 +93,6 @@ do [ AC_MSG_RESULT(found) - CUDA_LIBS="${CUDA_PATH} ${CUDA_LIBS}" AC_SUBST(CUDA_LIBS) AC_SUBST(CUDA_CFLAGS) AC_DEFINE(HAVE_CUDA,1,[Define if CUDA blas is installed]) From 5a3586125ec411da85418038225e9ed96b2e6116 Mon Sep 17 00:00:00 2001 From: ZHG Date: Mon, 26 Aug 2019 16:51:36 +0200 Subject: [PATCH 5/5] Wrapped the call of cublas into the fgemm --- fflas-ffpack/config-blas.h | 4 -- .../fflas/fflas_fgemm/fgemm_classical.inl | 55 +++++++++++++++---- 2 files changed, 43 insertions(+), 16 deletions(-) diff --git a/fflas-ffpack/config-blas.h b/fflas-ffpack/config-blas.h index db002b518..86aa91126 100644 --- a/fflas-ffpack/config-blas.h +++ b/fflas-ffpack/config-blas.h @@ -44,10 +44,6 @@ #include #endif -#ifdef HAVE_CUDA -#define __FFLASFFPACK_HAVE_CUDA -#endif - #ifdef __FFLASFFPACK_HAVE_CUDA #define __FFLASFFPACK_HAVE_CUBLAS #include diff --git a/fflas-ffpack/fflas/fflas_fgemm/fgemm_classical.inl b/fflas-ffpack/fflas/fflas_fgemm/fgemm_classical.inl index c19c59b9c..1f59e1337 100644 --- a/fflas-ffpack/fflas/fflas_fgemm/fgemm_classical.inl +++ b/fflas-ffpack/fflas/fflas_fgemm/fgemm_classical.inl @@ -41,6 +41,7 @@ #include "fflas-ffpack/fflas/fflas_igemm/igemm.h" #endif +#include "fflas-ffpack/utils/fflas_io.h" namespace FFLAS { // F is a field supporting delayed reductions @@ -263,17 +264,18 @@ namespace FFLAS { cublasCreate(&handle); // Set input matrices on device - cublasSetMatrix(m, k, sizeof(Element), Ad, lda, d_A, k); - cublasSetMatrix(k, n, sizeof(Element), Bd, ldb, d_B, n); - cublasSetMatrix(m, n, sizeof(Element), Cd, ldc, d_C, n); - + cublasSetMatrix(k, m, sizeof(Element), Ad, lda, d_A, k); // @note Device's leading dimensions are for column major matrices. + cublasSetMatrix(n, k, sizeof(Element), Bd, ldb, d_B, n); + cublasSetMatrix(n, m, sizeof(Element), Cd, ldc, d_C, n); + + // @note As cublas works in column-major, we inverse the transpose here. auto d_ta = (ta == FFLAS_TRANSPOSE::FflasNoTrans) ? CUBLAS_OP_N : CUBLAS_OP_T; auto d_tb = (tb == FFLAS_TRANSPOSE::FflasNoTrans) ? CUBLAS_OP_N : CUBLAS_OP_T; - cublasDgemm(handle, d_ta, d_tb, m,n,k, &F.one, d_A, k, d_B, n, &F.zero, d_C,n); + cublasDgemm(handle, d_tb, d_ta, n,m,k, &alpha, d_B, n, d_A, k, &beta, d_C, n); // Retrieve result matrix from device - cublasGetMatrix(m, n, sizeof(Element), d_C, n, Cd, ldc); + cublasGetMatrix(n, m, sizeof(Element), d_C, n, Cd, ldc); #else #if defined(__FFLASFFPACK_OPENBLAS_NUM_THREADS) and not defined (__FFLASFFPACK_OPENBLAS_NT_ALREADY_SET) openblas_set_num_threads(__FFLASFFPACK_OPENBLAS_NUM_THREADS); @@ -300,12 +302,41 @@ namespace FFLAS { FFLASFFPACK_check(ldb); FFLASFFPACK_check(ldc); -#if defined(__FFLASFFPACK_OPENBLAS_NUM_THREADS) and not defined (__FFLASFFPACK_OPENBLAS_NT_ALREADY_SET) - openblas_set_num_threads(__FFLASFFPACK_OPENBLAS_NUM_THREADS); -#endif - cblas_sgemm (CblasRowMajor, (CBLAS_TRANSPOSE) ta, (CBLAS_TRANSPOSE) tb, - (int)m, (int)n, (int)k, (Givaro::FloatDomain::Element) alpha, - Ad, (int)lda, Bd, (int)ldb, (Givaro::FloatDomain::Element) beta,Cd, (int)ldc); + #if defined(__FFLASFFPACK_HAVE_CUBLAS) + // Allocate device storage for A,B,C + using Element = Givaro::FloatDomain::Element; + Element *d_A, *d_B, *d_C; + cudaMalloc((void**)&d_A, m*k*sizeof(Element)); + cudaMalloc((void**)&d_B, k*n*sizeof(Element)); + cudaMalloc((void**)&d_C, m*n*sizeof(Element)); + + // Create cublas instance + cublasHandle_t handle; + cublasCreate(&handle); + + // Set input matrices on device + cublasSetMatrix(k, m, sizeof(Element), Ad, lda, d_A, k); // @note Device's leading dimensions are for column major matrices. + cublasSetMatrix(n, k, sizeof(Element), Bd, ldb, d_B, n); + cublasSetMatrix(n, m, sizeof(Element), Cd, ldc, d_C, n); + + // @note As cublas works in column-major, we inverse the transpose here. + auto d_ta = (ta == FFLAS_TRANSPOSE::FflasNoTrans) ? CUBLAS_OP_N : CUBLAS_OP_T; + auto d_tb = (tb == FFLAS_TRANSPOSE::FflasNoTrans) ? CUBLAS_OP_N : CUBLAS_OP_T; + + cublasSgemm(handle, d_tb, d_ta, n,m,k, &alpha, d_B, n, d_A, k, &beta, d_C, n); + + // Retrieve result matrix from device + cublasGetMatrix(n, m, sizeof(Element), d_C, n, Cd, ldc); + #else + #if defined(__FFLASFFPACK_OPENBLAS_NUM_THREADS) and not defined (__FFLASFFPACK_OPENBLAS_NT_ALREADY_SET) + openblas_set_num_threads(__FFLASFFPACK_OPENBLAS_NUM_THREADS); + #endif + cblas_sgemm (CblasRowMajor, (CBLAS_TRANSPOSE) ta, (CBLAS_TRANSPOSE) tb, + (int)m, (int)n, (int)k, (Givaro::FloatDomain::Element) alpha, + Ad, (int)lda, Bd, (int)ldb, (Givaro::FloatDomain::Element) beta,Cd, (int)ldc); + #endif + + } inline void fgemm (const Givaro::ZRing& F,