From c4c72685a3d05c6dfa225e57e2b7ded4b5b77d0d Mon Sep 17 00:00:00 2001 From: "tempy@maggie" Date: Wed, 20 Jan 2016 11:18:45 +0200 Subject: [PATCH] SpMV using MKL for shared memory has been added --- spmv/mkl_shmem/CMakeLists.txt | 60 ++++ spmv/mkl_shmem/mklspmv.c | 229 +++++++++++++++ spmv/mkl_shmem/mmio.c | 511 ++++++++++++++++++++++++++++++++++ spmv/mkl_shmem/mmio.h | 133 +++++++++ spmv/mkl_shmem/test.mtx | 13 + 5 files changed, 946 insertions(+) create mode 100644 spmv/mkl_shmem/CMakeLists.txt create mode 100644 spmv/mkl_shmem/mklspmv.c create mode 100644 spmv/mkl_shmem/mmio.c create mode 100644 spmv/mkl_shmem/mmio.h create mode 100644 spmv/mkl_shmem/test.mtx diff --git a/spmv/mkl_shmem/CMakeLists.txt b/spmv/mkl_shmem/CMakeLists.txt new file mode 100644 index 0000000..eb1efbd --- /dev/null +++ b/spmv/mkl_shmem/CMakeLists.txt @@ -0,0 +1,60 @@ + +# ================================================================================================== +# This file is part of the CodeVault project. The project is licensed under Apache Version 2.0. +# CodeVault is part of the EU-project PRACE-4IP (WP7.3.C). +# +# Author(s): +# Valeriu Codreanu +# +# ================================================================================================== +cmake_minimum_required(VERSION 2.8.10 FATAL_ERROR) +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../../../../cmake/Modules") +set(CMAKE_VERBOSE_MAKEFILE ON) + +find_package(MKL) + + +include(${CMAKE_CURRENT_SOURCE_DIR}/../../../../cmake/common.cmake) + +# ================================================================================================== + +if ("${DWARF_PREFIX}" STREQUAL "") + set(DWARF_PREFIX 2_sparse) +endif() +set(NAME ${DWARF_PREFIX}_spmv_mkl_shmem) + +# ================================================================================================== +# C++ compiler settings + +find_package(Common) + +select_compiler_flags(cxx_flags + GNU "-march=native" # I suggest remove "-O3" as this is controlled by the CMAKE_BUILD_TYPE + CLANG "-march=native" # same here + Intel "-axavx2,avx") +set(CXX_FLAGS ${cxx_flags}) +if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") + set(CXX_FLAGS "${CXX_FLAGS} -Wall -Wno-comment") + if(APPLE) + set(CXX_FLAGS "${CXX_FLAGS} -Wa,-q") + endif() +endif() +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_FLAGS}") + +# ================================================================================================== + +# LUD with the MKL library +if (MKL_FOUND) + include_directories(${MKL_INCLUDE_DIR}) + link_directories(${MKL_LIBRARY_DIR}) + add_executable(${NAME} mklspmv.c mmio.c) + target_link_libraries(${NAME} mkl_intel_lp64 mkl_sequential mkl_core pthread m) + install(TARGETS ${NAME} DESTINATION bin) +else () + message("## Skipping '${NAME}': no MKL support found") + install(CODE "MESSAGE(\"${NAME} can only be built with MKL.\")") +endif() + +unset(NAME) + +# ================================================================================================== diff --git a/spmv/mkl_shmem/mklspmv.c b/spmv/mkl_shmem/mklspmv.c new file mode 100644 index 0000000..0c26b86 --- /dev/null +++ b/spmv/mkl_shmem/mklspmv.c @@ -0,0 +1,229 @@ +/*includes {{{*/ +#include +#include +#include +#include +#include "mmio.h" +/*}}}*/ + +/* global varibles and defines {{{*/ +int nrepeat = 100; +int option_print_matrices = 0; +#define OPTION_NOPRINT_MATRICES 0 +#define OPTION_PRINT_MATRICES 1 +char transa = 'n'; +/*}}}*/ + +/* method declarations {{{*/ +int main(int argc, char* argv[]); +void printmm_one(int m, double* Aval, int* AJ, int* AI); +void printfilemm_one(char* file, int m, int n, double* Aval, int* AJ, int* AI); +void printmm_zero(int m, double* Aval, int* AJ, int* AI); +/*}}}*/ + +/** Multiply two sparse matrices which are stored in CSR format. MKL is used */ +void mkl_cpu_spmv(const MKL_INT Am, const MKL_INT An, double* Aval, MKL_INT* AJ, MKL_INT* AI, double* xvec, double* yvec, double* time) { /*{{{*/ + +MKL_INT ierr; +MKL_INT request = 1; // symbolic multiplication +double alpha = 1.0; +double beta = 0.0; +char* matdescra = "G NF"; + +double time_st = dsecnd(); +int i; +for(i = 0; i < nrepeat; i++) { + /** y := alpha*A*x + beta*y */ + mkl_dcsrmv(&transa, &Am, &An, &alpha, matdescra, Aval, AJ, AI, (AI+1), xvec, &beta, yvec); +} +double time_end = dsecnd(); +*time = (time_end - time_st)/nrepeat; +} /*}}}*/ + +/** Read Matrix Market file into COO matrix */ +void read_mm(char* strpath, int* pM, int* pN, int* prealnnz, int** pI, int** pJ, double** pval){ /*{{{*/ +/* +* taken from Matrix Market I/O library for ANSI C +* +* See http://math.nist.gov/MatrixMarket for details. +* +* +*/ + +int i, M, N, nz, *I, *J; +double* val; +int ret_code; +MM_typecode matcode; +FILE* f; +if ((f = fopen(strpath, "r")) == NULL) {fprintf(stderr, "Input matrix file %s cannot be opened to read.", strpath);exit(1);} +/* READ MATRIX */ +if (mm_read_banner(f, &matcode) != 0) { + printf("Could not process Matrix Market banner.\n"); exit(1); +} +/* This is how one can screen matrix types if their application */ +/* only supports a subset of the Matrix Market data types. */ +if (mm_is_complex(matcode) && mm_is_matrix(matcode) && mm_is_sparse(matcode) ) { + printf("Sorry, this application does not support "); + printf("Market Market type: [%s]\n", mm_typecode_to_str(matcode));exit(1); +} +/* find out size of sparse matrix .... */ +if ((ret_code = mm_read_mtx_crd_size(f, &M, &N, &nz)) !=0) exit(1); +/* reseve memory for matrices */ +I = (int *) malloc((mm_is_symmetric(matcode) ? 2*nz : nz) * sizeof(int)); +J = (int *) malloc((mm_is_symmetric(matcode) ? 2*nz : nz) * sizeof(int)); +val = (double *) malloc((mm_is_symmetric(matcode) ? 2*nz : nz) * sizeof(double)); +*pI = I; +*pJ = J; +*pval = val; +/* NOTE: when reading in doubles, ANSI C requires the use of the "l" */ +/* specifier as in "%lg", "%lf", "%le", otherwise errors will occur */ +/* (ANSI C X3.159-1989, Sec. 4.9.6.2, p. 136 lines 13-15) */ +int realnnz = 0; +for (i=0; i 0) { + mkl_set_num_threads(nthreads); +} else { + nthreads = mkl_get_max_threads(); +} +option_print_matrices = strcmp(argv[iarg], "PRINT_YES")==0?OPTION_PRINT_MATRICES:OPTION_NOPRINT_MATRICES; iarg++; +assert(nrequired_args == iarg); + +/** read matrix market file for A matrix */ +MKL_INT Am, An, Annz; +MKL_INT *Ax, *Ay; +double *Anz; +read_mm(strpathA, &Am, &An, &Annz, &Ax, &Ay, &Anz); + +/** construct csr storage for A matrix */ +MKL_INT* AJ = (MKL_INT*) mkl_malloc( Annz * sizeof( MKL_INT ), 64 ); +MKL_INT* AI = (MKL_INT*) mkl_malloc( (Am+1) * sizeof( MKL_INT ), 64 ); +double* Aval = (double*) mkl_malloc( Annz * sizeof( double ), 64 ); +coo_to_csr(Am, Annz, Ax, Ay, Anz, AI, AJ, Aval); + +double* xvec = (double*) mkl_malloc( An * sizeof( double ), 64 ); +double* yvec = (double*) mkl_malloc( Am * sizeof( double ), 64 ); +int i; +for(i=0;i +#include +#include +#include + +#include "mmio.h" + +int mm_read_unsymmetric_sparse(const char *fname, int *M_, int *N_, int *nz_, + double **val_, int **I_, int **J_) +{ + FILE *f; + MM_typecode matcode; + int M, N, nz; + int i; + double *val; + int *I, *J; + + if ((f = fopen(fname, "r")) == NULL) + return -1; + + + if (mm_read_banner(f, &matcode) != 0) + { + printf("mm_read_unsymetric: Could not process Matrix Market banner "); + printf(" in file [%s]\n", fname); + return -1; + } + + + + if ( !(mm_is_real(matcode) && mm_is_matrix(matcode) && + mm_is_sparse(matcode))) + { + fprintf(stderr, "Sorry, this application does not support "); + fprintf(stderr, "Market Market type: [%s]\n", + mm_typecode_to_str(matcode)); + return -1; + } + + /* find out size of sparse matrix: M, N, nz .... */ + + if (mm_read_mtx_crd_size(f, &M, &N, &nz) !=0) + { + fprintf(stderr, "read_unsymmetric_sparse(): could not parse matrix size.\n"); + return -1; + } + + *M_ = M; + *N_ = N; + *nz_ = nz; + + /* reseve memory for matrices */ + + I = (int *) malloc(nz * sizeof(int)); + J = (int *) malloc(nz * sizeof(int)); + val = (double *) malloc(nz * sizeof(double)); + + *val_ = val; + *I_ = I; + *J_ = J; + + /* NOTE: when reading in doubles, ANSI C requires the use of the "l" */ + /* specifier as in "%lg", "%lf", "%le", otherwise errors will occur */ + /* (ANSI C X3.159-1989, Sec. 4.9.6.2, p. 136 lines 13-15) */ + + for (i=0; i