&K+Z4;k_Uhle$;FH5Z-Z^YD(=b_4Qwr@S2E1`()gul7SZ!u1G
zw#AWs8Xl2e^s}94?_|#KWrn;ygc9l1A-p<-S3Jw!kTaNenygKJyy+AksBMEI^FmY}
z`40P34SQ#Oe&)AP=0J@b2=25sY(Z;&_D>KaTVWB~&@z>KiMGbVg-%7;5_-Quc&@9BsP@K@#
zU|4?5_K|=2Aae{gj~%)`J;sD@E{CqSsT$W}l{R+vdRvBEyGEQ*#^41$oh<1w{geRl
zo8z%UwMZ8($KbP(T&j`A7`!@{3$!nOjUrcSU%bE4gI#K?lWVfCHCd61voD^a$W_`G
zx8Ppyx*2
z$N5otMBlv%{W2$#ow-FMqMy@5^p=|F9)Z^jJkx*`+4<;SQ%?wg`mIis$4f-Ao#I0+{#^-MlKP80!h6zN3(ksQTk@K^C&P2SH^xK&a99XLieB-AjIBfU~|n2$8-
z4-a)q)JVvoemQDL9~KR*6VJE&85()y6x>&&@k-^?$SK$ym7k`-OLNl}Wsp;FP$Y_;
zg8vbC^b}N#F)HS@qmWZTKgNmjczIcHjfBw*Hu-
z@zeuE1^2QY3vB9t@$v|jjc*7~`m#cV)ynA;f%}JOTt5Sy$YeG$U&zw9zFP#?1TLT3
zxDmw=mc7vCDiBtu)reXn%$kfEXyDIdi4ZNKD7@ak1Ld!H`CE?ck&VA~K;*YPDk0wJ!x?dx$q_k+3cM?-|Kr&D2AgXJ
ztf{7Sg+8N2(tHs`p8|<|yu@28ic)W*vTi4QEI1jRQ{BR9ustHSH%;Tf3}Jm-;BL{v
zMFM|`=X{^H=L_LepJBv)AbjEyjJo_$bzQ?;Zkw9T%h6P3)WMVX=H7H8!_y+eYVNa<
zmp<-Ezs9cC{`;FXaA?-7x5cT5vFeT*gQ6w7`l$AA8GJzMx FT6QHrvP;|hCS9l#!Iyy@_z
z#tJod1LMS%M|S`6B}G^H
z7bc};qo-BVrp>IIJf&eo>4?(NN>ke^4|`y>J?YxU=EfCG%an%YtD0A_K`Z`|@r(cH
q#6Dher=9)}>ZWo}$Jgp@*%zrQ}~l94NT}
delta 10482
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
DWmPBu
diff --git a/GPUs/cuBLAS.cu b/GPUs/cuBLAS.cu
index 02408da..dfffef9 100644
--- a/GPUs/cuBLAS.cu
+++ b/GPUs/cuBLAS.cu
@@ -38,6 +38,7 @@ int main(int argc, char **argv)
}
else error("Too many Arguments");
+ /* Allocate space */
double *x = (double *) malloc(m * sizeof(*x));
double *y = (double *) malloc(n * sizeof(*y));
double *M = (double *) malloc(n * m * sizeof(*M));
@@ -54,6 +55,7 @@ int main(int argc, char **argv)
vec_init_rand(x, m, 1.0);
vec_init(y, n, 0.0);
+ /* Initialize cuda/cublas variables */
int device_num=0;
cudaGetDeviceCount(&device_num);
if (!device_num) printf("No available Cuda Devices");
@@ -64,6 +66,8 @@ int main(int argc, char **argv)
cublasStatus_t stat;
cublasHandle_t handle;
double *A, * y, *x_c;
+
+ /* Initialize Unified memmory */
cudaMallocManaged(&A, m*n * sizeof(double));
cudaMallocManaged(&y, n * sizeof(double));
cudaMallocManaged(&x_c, m * sizeof(double));
@@ -86,12 +90,13 @@ int main(int argc, char **argv)
timer = csecond() - timer;
cudaCheckErrors("cublasDgemv failed");
-#ifdef _DEBUG_ /* Output y in a file for debug purposes */
- FILE * fp;
- char * filename = "/users/guest/petyros/Training/Outputs/Debug/cuBLAS.out" ;
- if(( fp = fopen( filename, "w")) == NULL) error("Output file creation failed\n");
- for (k = 0; k < n; ++k) fprintf(fp, "%lf ", y[k]) ;
- fclose(fp) ;
+#ifdef _DEBUG_
+ /* Output y vector to a file for debugging */
+ FILE * fp;
+ char * filename = "/users/guest/petyros/Training/Outputs/Debug/cuBLAS.out" ;
+ if(( fp = fopen( filename, "w")) == NULL) error("Output file creation failed\n");
+ for (k = 0; k < n; ++k) fprintf(fp, "%lf ", y[k]) ;
+ fclose(fp) ;
#endif
report_results(timer);
}
diff --git a/GPUs/cuBLAS_MultiGPU b/GPUs/cuBLAS_MultiGPU
new file mode 100755
index 0000000000000000000000000000000000000000..d7cf7745cfa6d457b305458f378f46353e618113
GIT binary patch
literal 29936
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
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "/users/guest/petyros/Training/External_Functions/matrix_op.h"
+#include "/users/guest/petyros/Training/External_Functions/util.h"
+#include "/users/guest/petyros/Training/External_Functions/input.h"
+#include "/users/guest/petyros/Training/External_Functions/gpu_util.h"
+
+
+
+int main(int argc, char ** argv)
+{
+ int rank,size;
+ int global_nm[2],local_nm[2]; //global matrix dimensions and local matrix dimensions (2D-domain, 2D-subdomain)
+ int global_padded_nm[2]; //padded global matrix dimensions (if padding is not needed, global_padded=global)
+ int i,j,k, sparse=0, *cooCol, n_z, *I;
+ double * M, *M_cl, * A, * x, * y, *local_y, *x_c, * cooVal, comm_t, comp_t;
+
+
+ MPI_Init(&argc,&argv);
+ MPI_Comm_size(MPI_COMM_WORLD,&size);
+ MPI_Comm_rank(MPI_COMM_WORLD,&rank);
+
+ if (argc < 2) error("Too few Arguments");
+ else if ( argc == 2) /* ./Program Input_File -> File Input to COO */
+ {
+ if(!mtx_read(&I, &cooCol, &cooVal, &global_nm[0], &global_nm[1], &n_z, argv[1])) error("input and/or COO convertion failed");
+ sparse = 1;
+ }
+ else if ( argc == 3) { /*./Program N M -> Generate random NxM matrix */
+ global_nm[0]=atoi(argv[1]);
+ global_nm[1]=atoi(argv[2]);
+ }
+ else error("Too many Arguments");
+
+ /* Padd N if needed */
+ local_nm[1]=global_nm[1];
+ global_padded_nm[1]=global_nm[1];
+
+ if (global_nm[0]%size==0) {
+ local_nm[0]=global_nm[0]/size;
+ global_padded_nm[0]=global_nm[0];
+ }
+ else {
+ local_nm[0]=(global_nm[0]/size)+1;
+ global_padded_nm[0]=local_nm[0]*size;
+ }
+
+ x = (double *) malloc(global_padded_nm[1] * sizeof(*x));
+ if (rank==0) {
+ M = (double *) malloc(global_padded_nm[0] * global_padded_nm[1] * sizeof(*M));
+ M_cl = (double *) malloc(global_padded_nm[0] * global_padded_nm[1] * sizeof(*M_cl));
+ vec_init_rand(x, global_padded_nm[1], 1.0);
+ y = (double *) malloc(global_padded_nm[0] * sizeof(*y));
+ vec_init(y, global_padded_nm[0], 0.0);
+ if( !y || !x || !M || !M_cl ) error("memory allocation failed");
+
+ /* Initialize matrices */
+ if (sparse) {
+ ; //regenerate_matrix_coo(M, I, cooCol, cooVal, n, m, n_z); /* Sparse matrices read from .mtx format */
+ }
+ else ser_matrix_init_rand_p(M, global_nm[0], global_nm[1], global_padded_nm[1] * (global_padded_nm[0] - global_nm[0]), 1.0); /* Normal matrices generated randomly */
+ }
+ //if(rank==0) printf("Local[0]=%d Local[1]=%d global_padded[0]=%d global_padded[1]=%d\n",local[0],local[1],global_padded[0],global_padded[1]);
+
+
+ /* Initialize Unified memmory */
+ cudaMallocManaged(&A, local_nm[0] * local_nm[1] * sizeof(double));
+
+ cudaMallocManaged(&local_y, local_nm[0] * sizeof(*local_y));
+ vec_init(local_y, local_nm[0], 0.0);
+
+ cudaMallocManaged(&x_c, m * sizeof(double));
+ cudaDeviceSynchronize();
+ cudaCheckErrors("Unified Alloc failed");
+ if ( !A || !y || !x_c) error("unified alloc failed");
+ matrix_col_major(M, M_cl, n, m);
+
+ /* Rank 0 scatters the global matrix */
+ double * gsendbuf;
+ if (rank == 0){
+ gsendbuf = &(M_cl[0]);
+ comm_t= MPI_Wtime();
+ }
+
+ MPI_Scatter(gsendbuf, local_nm[1] * local_nm[0], MPI_DOUBLE, A, local_nm[1] * local_nm[0], MPI_DOUBLE, 0, MPI_COMM_WORLD);
+ //if (rank == 0) printf("Scatter complete\n");
+ MPI_Bcast(x, global_padded_nm[1], MPI_DOUBLE, 0, MPI_COMM_WORLD);
+ for (i = 0; i < m; i++) x_c[i] = x[i];
+
+ /* Initialize cuda/cublas variables */
+ int device_num=0;
+ cudaGetDeviceCount(&device_num);
+ if (!device_num) printf("No available Cuda Devices");
+ else {
+
+ double alf=1.0; /* Y=a*A*x+b */
+ double beta=0.0;
+ cublasStatus_t stat;
+ cublasHandle_t handle;
+ stat = cublasCreate(&handle);
+
+ /* Warmup */
+ stat=cublasDgemv(handle, CUBLAS_OP_N, local_nm[0], local_nm[1], &alf, A , local_nm[0], x_c, 1, &beta, local_y, 1);
+ cudaDeviceSynchronize();
+
+ if (rank==0) {
+ printf("Multi GPU CUDA-MPI Version(N=%d, M=%d, GPUs/Node=%d, Nodes=%s, Tasks/Node=%s): ", n, m, device_num, getenv("SLURM_JOB_NUM_NODES"), getenv("SLURM_NTASKS_PER_NODE")) ;
+ comp_t= MPI_Wtime();
+ }
+
+ for (j = 0; j < NR_ITER; ++j) {
+ stat=cublasDgemv(handle, CUBLAS_OP_N, local_nm[0], local_nm[1], &alf, A , local_nm[0], x_c, 1, &beta, local_y, 1);
+ cudaDeviceSynchronize();
+ }
+ cudaCheckErrors("cublasDgemv failed");
+
+ MPI_Barrier(MPI_COMM_WORLD);
+ if (rank==0) comp_t= MPI_Wtime() - comp_t;
+ MPI_Gather(local_y, local_nm[0], MPI_DOUBLE, y, local_nm[0], MPI_DOUBLE, 0, MPI_COMM_WORLD);
+ if (rank==0) comm_t = MPI_Wtime() - comm_t - comp_t;
+
+#ifdef _DEBUG_
+ /* Output y vector to a file for debugging */
+ if (rank == 0) {
+ FILE * fp;
+ char * filename = "/users/guest/petyros/Training/Outputs/Debug/cuBLAS_MultiGPU.out" ;
+ if(( fp = fopen( filename, "w")) == NULL) error("Output file creation failed\n");
+ for (k = 0; k < global_nm[0]; ++k) fprintf(fp, "%lf ", y[k]) ;
+ fclose(fp) ;
+#endif
+ report_mpi_results(comm_t, comp_t);
+ free(M);
+ free(y);
+ }
+ free(x);
+ free(local_y);
+ free(A);
+
+ MPI_Finalize();
+ return 0;
+}
+
+
+
diff --git a/GPUs/gpu_util.o b/GPUs/gpu_util.o
index 7fa63c29355575a2adfd7d780dcf4607ffe8f4d5..fe0d98b88d49068ba0415350cc29cec8b89f16cb 100644
GIT binary patch
delta 433
zcmZ2rvchD7hWHH*1~_m4vm6+N83Z=k|6<>KP=ue6k!A8lQSr$vECPZCq7ao6m?5;_
zWKJ=6MwZQiV&aTo1qUP`5>SdkaB`>ke6Y+73>i;}`yd(34^SBkMyR1ciVuik&O(?K
z$Rf^Z0TrG*xsXMEasUg<Tjav--jqb``V1CwDOa&iF=4~wx`a_Z&=o)e5<)?^>PlPswfnI)4&__qK}
K+kBk=Ckp`gj6}Ks
delta 451
zcmZ2svcP15hIoP~0~|PjSq==s3_=_2f3Z(yWf5PzftQ&vcyghj_~Z=&ETTdTj128i
z_5M(L^W=>J;*$HA7#KjZ*PxR3_Kg{r!g_6ZNA2|m}|47BtPTiExZDP8KMxS4eSt_
zce1CHJ0r{FiBk5AESoP%O$RH}d?5pou7FSsyg-@@h&iBq2`DW%`Js$BX9Y+a2-+q$
xO36>2z{@gOLq=fo0bUlt1A-8l9ZV3KZ}LeQea;FI2=66W{RT;i%@cS#xB)(=B$NOE
delta 228
zcmaE0^}uR^hWG+W1~_m4vm6-s8TdBZPh(=7u=yI(Vy?-oeBzS}_*pjJ5p3b!T)`{A
zs0dLA*T+sOcz`q)5OYBJ
xVCl(?0^*Ye_*euhcp<_&m>@LoKtiyB2cqBy
g)GnUM9|iQe3iu$R(u|X}_~j-i@JVcb!SRCy099@_a{vGU
delta 271
zcmeBB?oghfA@0G)00$0WmIDJX1J6eLVn!Bzc?X8g+ZfL?GEUgs#w-t_ma%|%lgrp_
zgx#H;trRre{X#VrO!O@EjDVUqA7$fV+FZ%Q&pP=6#|K4-d0<1q#0zc+TY(Wmb4`B8
zsn57^@brw)3@lFAT|I1
delta 243
zcmZ3%yMlLuhPVbZ0~|PjSq=<*47?NVPfc!O6rcQoiDk14YY*dM4n{^rh&)_5Lk1Is
zZ2%SGo~+5F&$xMVBUq!rF5S
pp1{Z=$iWB^wt&(+lUK6nb2>oH(3t#?Nq({eiv;Hes7NVD1OVkqBklkI
diff --git a/GPUs/util.o b/GPUs/util.o
index 26ba20a666e79a65dc63bc46da818b49938c90ab..c7553f6c77631def65ffd99e2827628cbd03ddda 100644
GIT binary patch
delta 274
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
z |