magma_int_t magma_d_applyprecond( magma_d_sparse_matrix A, magma_d_vector b, magma_d_vector *x, magma_d_preconditioner *precond ) { if( precond->solver == Magma_JACOBI ){ magma_djacobi_diagscal( A.num_rows, precond->d.val, b.val, x->val ); return MAGMA_SUCCESS; } else if( precond->solver == Magma_PASTIX ){ magma_dapplypastix( b, x, precond ); return MAGMA_SUCCESS; } else if( precond->solver == Magma_ILU ){ magma_d_vector tmp; magma_d_vinit( &tmp, Magma_DEV, A.num_rows, MAGMA_D_MAKE(1.0, 0.0) ); // magma_dapplycuilu_l( b, &tmp, precond ); // magma_dapplycuilu_r( tmp, x, precond ); magma_d_vfree( &tmp ); return MAGMA_SUCCESS; } else if( precond->solver == Magma_ICC ){ magma_d_vector tmp; magma_d_vinit( &tmp, Magma_DEV, A.num_rows, MAGMA_D_MAKE(1.0, 0.0) ); // magma_dtrisv_l_nu( precond->L, b, &tmp ); // magma_dtrisv_r_nu( precond->L, tmp, x ); magma_d_vfree( &tmp ); return MAGMA_SUCCESS; } else{ printf( "error: preconditioner type not yet supported.\n" ); return MAGMA_ERR_NOT_SUPPORTED; } }
/* //////////////////////////////////////////////////////////////////////////// -- Debugging file */ int main( int argc, char** argv) { TESTING_INIT(); magma_d_solver_par solver_par; magma_d_preconditioner precond_par; solver_par.epsilon = 10e-16; solver_par.maxiter = 1000; solver_par.verbose = 0; precond_par.solver = Magma_JACOBI; magma_dsolverinfo_init( &solver_par, &precond_par ); double one = MAGMA_D_MAKE(1.0, 0.0); double zero = MAGMA_D_MAKE(0.0, 0.0); magma_d_sparse_matrix A, B, B_d; magma_d_vector x, b; // generate matrix of desired structure and size magma_int_t n=10; // size is n*n magma_int_t nn = n*n; magma_int_t offdiags = 2; magma_index_t *diag_offset; double *diag_vals; magma_dmalloc_cpu( &diag_vals, offdiags+1 ); magma_index_malloc_cpu( &diag_offset, offdiags+1 ); diag_offset[0] = 0; diag_offset[1] = 1; diag_offset[2] = n; diag_vals[0] = MAGMA_D_MAKE( 4.0, 0.0 ); diag_vals[1] = MAGMA_D_MAKE( -1.0, 0.0 ); diag_vals[2] = MAGMA_D_MAKE( -1.0, 0.0 ); magma_dmgenerator( nn, offdiags, diag_offset, diag_vals, &A ); // convert marix into desired format B.storage_type = Magma_SELLC; B.blocksize = 8; B.alignment = 8; // scale matrix magma_dmscale( &A, Magma_UNITDIAG ); magma_d_mconvert( A, &B, Magma_CSR, B.storage_type ); magma_d_mtransfer( B, &B_d, Magma_CPU, Magma_DEV ); // vectors and initial guess magma_d_vinit( &b, Magma_DEV, A.num_cols, one ); magma_d_vinit( &x, Magma_DEV, A.num_cols, one ); magma_d_spmv( one, B_d, x, zero, b ); // b = A x magma_d_vfree(&x); magma_d_vinit( &x, Magma_DEV, A.num_cols, zero ); // solver magma_dpcg( B_d, b, &x, &solver_par, &precond_par ); // solverinfo magma_dsolverinfo( &solver_par, &precond_par ); magma_dsolverinfo_free( &solver_par, &precond_par ); magma_d_mfree(&B_d); magma_d_mfree(&B); magma_d_mfree(&A); magma_d_vfree(&x); magma_d_vfree(&b); TESTING_FINALIZE(); return 0; }
magma_int_t magma_dcg_merge( magma_d_sparse_matrix A, magma_d_vector b, magma_d_vector *x, magma_d_solver_par *solver_par ){ // prepare solver feedback solver_par->solver = Magma_CGMERGE; solver_par->numiter = 0; solver_par->info = 0; // some useful variables double c_zero = MAGMA_D_ZERO, c_one = MAGMA_D_ONE; magma_int_t dofs = A.num_rows; // GPU stream magma_queue_t stream[2]; magma_event_t event[1]; magma_queue_create( &stream[0] ); magma_queue_create( &stream[1] ); magma_event_create( &event[0] ); // GPU workspace magma_d_vector r, d, z; magma_d_vinit( &r, Magma_DEV, dofs, c_zero ); magma_d_vinit( &d, Magma_DEV, dofs, c_zero ); magma_d_vinit( &z, Magma_DEV, dofs, c_zero ); double *d1, *d2, *skp; magma_dmalloc( &d1, dofs*(1) ); magma_dmalloc( &d2, dofs*(1) ); // array for the parameters magma_dmalloc( &skp, 6 ); // skp = [alpha|beta|gamma|rho|tmp1|tmp2] // solver variables double alpha, beta, gamma, rho, tmp1, *skp_h; double nom, nom0, r0, betanom, den; // solver setup magma_dscal( dofs, c_zero, x->val, 1) ; // x = 0 magma_dcopy( dofs, b.val, 1, r.val, 1 ); // r = b magma_dcopy( dofs, b.val, 1, d.val, 1 ); // d = b nom0 = betanom = magma_dnrm2( dofs, r.val, 1 ); nom = nom0 * nom0; // nom = r' * r magma_d_spmv( c_one, A, d, c_zero, z ); // z = A d den = MAGMA_D_REAL( magma_ddot(dofs, d.val, 1, z.val, 1) ); // den = d'* z solver_par->init_res = nom0; // array on host for the parameters magma_dmalloc_cpu( &skp_h, 6 ); alpha = rho = gamma = tmp1 = c_one; beta = magma_ddot(dofs, r.val, 1, r.val, 1); skp_h[0]=alpha; skp_h[1]=beta; skp_h[2]=gamma; skp_h[3]=rho; skp_h[4]=tmp1; skp_h[5]=MAGMA_D_MAKE(nom, 0.0); magma_dsetvector( 6, skp_h, 1, skp, 1 ); if ( (r0 = nom * solver_par->epsilon) < ATOLERANCE ) r0 = ATOLERANCE; if ( nom < r0 ) return MAGMA_SUCCESS; // check positive definite if (den <= 0.0) { printf("Operator A is not postive definite. (Ar,r) = %f\n", den); return -100; } //Chronometry real_Double_t tempo1, tempo2; magma_device_sync(); tempo1=magma_wtime(); if( solver_par->verbose > 0 ){ solver_par->res_vec[0] = (real_Double_t) nom0; solver_par->timing[0] = 0.0; } // start iteration for( solver_par->numiter= 1; solver_par->numiter<solver_par->maxiter; solver_par->numiter++ ){ magmablasSetKernelStream(stream[0]); // computes SpMV and dot product magma_dcgmerge_spmv1( A, d1, d2, d.val, z.val, skp ); // updates x, r, computes scalars and updates d magma_dcgmerge_xrbeta( dofs, d1, d2, x->val, r.val, d.val, z.val, skp ); // check stopping criterion (asynchronous copy) magma_dgetvector_async( 1 , skp+1, 1, skp_h+1, 1, stream[1] ); betanom = sqrt(MAGMA_D_REAL(skp_h[1])); if( solver_par->verbose > 0 ){ magma_device_sync(); tempo2=magma_wtime(); if( (solver_par->numiter)%solver_par->verbose==0 ) { solver_par->res_vec[(solver_par->numiter)/solver_par->verbose] = (real_Double_t) betanom; solver_par->timing[(solver_par->numiter)/solver_par->verbose] = (real_Double_t) tempo2-tempo1; } } if ( betanom < r0 ) { break; } } magma_device_sync(); tempo2=magma_wtime(); solver_par->runtime = (real_Double_t) tempo2-tempo1; double residual; magma_dresidual( A, b, *x, &residual ); solver_par->iter_res = betanom; solver_par->final_res = residual; if( solver_par->numiter < solver_par->maxiter){ solver_par->info = 0; }else if( solver_par->init_res > solver_par->final_res ){ if( solver_par->verbose > 0 ){ if( (solver_par->numiter)%solver_par->verbose==0 ) { solver_par->res_vec[(solver_par->numiter)/solver_par->verbose] = (real_Double_t) betanom; solver_par->timing[(solver_par->numiter)/solver_par->verbose] = (real_Double_t) tempo2-tempo1; } } solver_par->info = -2; } else{ if( solver_par->verbose > 0 ){ if( (solver_par->numiter)%solver_par->verbose==0 ) { solver_par->res_vec[(solver_par->numiter)/solver_par->verbose] = (real_Double_t) betanom; solver_par->timing[(solver_par->numiter)/solver_par->verbose] = (real_Double_t) tempo2-tempo1; } } solver_par->info = -1; } magma_d_vfree(&r); magma_d_vfree(&z); magma_d_vfree(&d); magma_free( d1 ); magma_free( d2 ); magma_free( skp ); magma_free_cpu( skp_h ); return MAGMA_SUCCESS; } /* magma_dcg_merge */
/* //////////////////////////////////////////////////////////////////////////// -- testing sparse matrix vector product */ int main( int argc, char** argv ) { TESTING_INIT(); magma_queue_t queue; magma_queue_create( /*devices[ opts->device ],*/ &queue ); magma_d_sparse_matrix hA, hA_SELLP, hA_ELL, dA, dA_SELLP, dA_ELL; hA_SELLP.blocksize = 8; hA_SELLP.alignment = 8; real_Double_t start, end, res; magma_int_t *pntre; double c_one = MAGMA_D_MAKE(1.0, 0.0); double c_zero = MAGMA_D_MAKE(0.0, 0.0); magma_int_t i, j; for( i = 1; i < argc; ++i ) { if ( strcmp("--blocksize", argv[i]) == 0 ) { hA_SELLP.blocksize = atoi( argv[++i] ); } else if ( strcmp("--alignment", argv[i]) == 0 ) { hA_SELLP.alignment = atoi( argv[++i] ); } else break; } printf( "\n# usage: ./run_dspmv" " [ --blocksize %d --alignment %d (for SELLP) ]" " matrices \n\n", (int) hA_SELLP.blocksize, (int) hA_SELLP.alignment ); while( i < argc ) { if ( strcmp("LAPLACE2D", argv[i]) == 0 && i+1 < argc ) { // Laplace test i++; magma_int_t laplace_size = atoi( argv[i] ); magma_dm_5stencil( laplace_size, &hA, queue ); } else { // file-matrix test magma_d_csr_mtx( &hA, argv[i], queue ); } printf( "\n# matrix info: %d-by-%d with %d nonzeros\n\n", (int) hA.num_rows,(int) hA.num_cols,(int) hA.nnz ); real_Double_t FLOPS = 2.0*hA.nnz/1e9; magma_d_vector hx, hy, dx, dy, hrefvec, hcheck; // init CPU vectors magma_d_vinit( &hx, Magma_CPU, hA.num_rows, c_zero, queue ); magma_d_vinit( &hy, Magma_CPU, hA.num_rows, c_zero, queue ); // init DEV vectors magma_d_vinit( &dx, Magma_DEV, hA.num_rows, c_one, queue ); magma_d_vinit( &dy, Magma_DEV, hA.num_rows, c_zero, queue ); #ifdef MAGMA_WITH_MKL // calling MKL with CSR pntre = (magma_int_t*)malloc( (hA.num_rows+1)*sizeof(magma_int_t) ); pntre[0] = 0; for (j=0; j<hA.num_rows; j++ ) { pntre[j] = hA.row[j+1]; } MKL_INT num_rows = hA.num_rows; MKL_INT num_cols = hA.num_cols; MKL_INT nnz = hA.nnz; MKL_INT *col; TESTING_MALLOC_CPU( col, MKL_INT, nnz ); for( magma_int_t t=0; t < hA.nnz; ++t ) { col[ t ] = hA.col[ t ]; } MKL_INT *row; TESTING_MALLOC_CPU( row, MKL_INT, num_rows ); for( magma_int_t t=0; t < hA.num_rows; ++t ) { row[ t ] = hA.col[ t ]; } start = magma_wtime(); for (j=0; j<10; j++ ) { mkl_dcsrmv( "N", &num_rows, &num_cols, MKL_ADDR(&c_one), "GFNC", MKL_ADDR(hA.val), col, row, pntre, MKL_ADDR(hx.val), MKL_ADDR(&c_zero), MKL_ADDR(hy.val) ); } end = magma_wtime(); printf( "\n > MKL : %.2e seconds %.2e GFLOP/s (CSR).\n", (end-start)/10, FLOPS*10/(end-start) ); TESTING_FREE_CPU( row ); TESTING_FREE_CPU( col ); free(pntre); #endif // MAGMA_WITH_MKL // copy matrix to GPU magma_d_mtransfer( hA, &dA, Magma_CPU, Magma_DEV, queue ); // SpMV on GPU (CSR) -- this is the reference! start = magma_sync_wtime( queue ); for (j=0; j<10; j++) magma_d_spmv( c_one, dA, dx, c_zero, dy, queue ); end = magma_sync_wtime( queue ); printf( " > MAGMA: %.2e seconds %.2e GFLOP/s (standard CSR).\n", (end-start)/10, FLOPS*10/(end-start) ); magma_d_mfree(&dA, queue ); magma_d_vtransfer( dy, &hrefvec , Magma_DEV, Magma_CPU, queue ); // convert to ELL and copy to GPU magma_d_mconvert( hA, &hA_ELL, Magma_CSR, Magma_ELL, queue ); magma_d_mtransfer( hA_ELL, &dA_ELL, Magma_CPU, Magma_DEV, queue ); magma_d_mfree(&hA_ELL, queue ); magma_d_vfree( &dy, queue ); magma_d_vinit( &dy, Magma_DEV, hA.num_rows, c_zero, queue ); // SpMV on GPU (ELL) start = magma_sync_wtime( queue ); for (j=0; j<10; j++) magma_d_spmv( c_one, dA_ELL, dx, c_zero, dy, queue ); end = magma_sync_wtime( queue ); printf( " > MAGMA: %.2e seconds %.2e GFLOP/s (standard ELL).\n", (end-start)/10, FLOPS*10/(end-start) ); magma_d_mfree(&dA_ELL, queue ); magma_d_vtransfer( dy, &hcheck , Magma_DEV, Magma_CPU, queue ); res = 0.0; for(magma_int_t k=0; k<hA.num_rows; k++ ) res=res + MAGMA_D_REAL(hcheck.val[k]) - MAGMA_D_REAL(hrefvec.val[k]); if ( res < .000001 ) printf("# tester spmv ELL: ok\n"); else printf("# tester spmv ELL: failed\n"); magma_d_vfree( &hcheck, queue ); // convert to SELLP and copy to GPU magma_d_mconvert( hA, &hA_SELLP, Magma_CSR, Magma_SELLP, queue ); magma_d_mtransfer( hA_SELLP, &dA_SELLP, Magma_CPU, Magma_DEV, queue ); magma_d_mfree(&hA_SELLP, queue ); magma_d_vfree( &dy, queue ); magma_d_vinit( &dy, Magma_DEV, hA.num_rows, c_zero, queue ); // SpMV on GPU (SELLP) start = magma_sync_wtime( queue ); for (j=0; j<10; j++) magma_d_spmv( c_one, dA_SELLP, dx, c_zero, dy, queue ); end = magma_sync_wtime( queue ); printf( " > MAGMA: %.2e seconds %.2e GFLOP/s (SELLP).\n", (end-start)/10, FLOPS*10/(end-start) ); magma_d_vtransfer( dy, &hcheck , Magma_DEV, Magma_CPU, queue ); res = 0.0; for(magma_int_t k=0; k<hA.num_rows; k++ ) res=res + MAGMA_D_REAL(hcheck.val[k]) - MAGMA_D_REAL(hrefvec.val[k]); printf("# |x-y|_F = %8.2e\n", res); if ( res < .000001 ) printf("# tester spmv SELL-P: ok\n"); else printf("# tester spmv SELL-P: failed\n"); magma_d_vfree( &hcheck, queue ); magma_d_mfree(&dA_SELLP, queue ); // SpMV on GPU (CUSPARSE - CSR) // CUSPARSE context // cusparseHandle_t cusparseHandle = 0; cusparseStatus_t cusparseStatus; cusparseStatus = cusparseCreate(&cusparseHandle); cusparseSetStream( cusparseHandle, queue ); cusparseMatDescr_t descr = 0; cusparseStatus = cusparseCreateMatDescr(&descr); cusparseSetMatType(descr,CUSPARSE_MATRIX_TYPE_GENERAL); cusparseSetMatIndexBase(descr,CUSPARSE_INDEX_BASE_ZERO); double alpha = c_one; double beta = c_zero; magma_d_vfree( &dy, queue ); magma_d_vinit( &dy, Magma_DEV, hA.num_rows, c_zero, queue ); // copy matrix to GPU magma_d_mtransfer( hA, &dA, Magma_CPU, Magma_DEV, queue ); start = magma_sync_wtime( queue ); for (j=0; j<10; j++) cusparseStatus = cusparseDcsrmv(cusparseHandle,CUSPARSE_OPERATION_NON_TRANSPOSE, hA.num_rows, hA.num_cols, hA.nnz, &alpha, descr, dA.dval, dA.drow, dA.dcol, dx.dval, &beta, dy.dval); end = magma_sync_wtime( queue ); if (cusparseStatus != 0) printf("error in cuSPARSE CSR\n"); printf( " > CUSPARSE: %.2e seconds %.2e GFLOP/s (CSR).\n", (end-start)/10, FLOPS*10/(end-start) ); cusparseMatDescr_t descrA; cusparseStatus = cusparseCreateMatDescr(&descrA); if (cusparseStatus != 0) printf("error\n"); cusparseHybMat_t hybA; cusparseStatus = cusparseCreateHybMat( &hybA ); if (cusparseStatus != 0) printf("error\n"); magma_d_vtransfer( dy, &hcheck , Magma_DEV, Magma_CPU, queue ); res = 0.0; for(magma_int_t k=0; k<hA.num_rows; k++ ) res=res + MAGMA_D_REAL(hcheck.val[k]) - MAGMA_D_REAL(hrefvec.val[k]); printf("# |x-y|_F = %8.2e\n", res); if ( res < .000001 ) printf("# tester spmv cuSPARSE CSR: ok\n"); else printf("# tester spmv cuSPARSE CSR: failed\n"); magma_d_vfree( &hcheck, queue ); magma_d_vfree( &dy, queue ); magma_d_vinit( &dy, Magma_DEV, hA.num_rows, c_zero, queue ); cusparseDcsr2hyb(cusparseHandle, hA.num_rows, hA.num_cols, descrA, dA.dval, dA.drow, dA.dcol, hybA, 0, CUSPARSE_HYB_PARTITION_AUTO); start = magma_sync_wtime( queue ); for (j=0; j<10; j++) cusparseStatus = cusparseDhybmv( cusparseHandle, CUSPARSE_OPERATION_NON_TRANSPOSE, &alpha, descrA, hybA, dx.dval, &beta, dy.dval); end = magma_sync_wtime( queue ); if (cusparseStatus != 0) printf("error in cuSPARSE HYB\n"); printf( " > CUSPARSE: %.2e seconds %.2e GFLOP/s (HYB).\n", (end-start)/10, FLOPS*10/(end-start) ); magma_d_vtransfer( dy, &hcheck , Magma_DEV, Magma_CPU, queue ); res = 0.0; for(magma_int_t k=0; k<hA.num_rows; k++ ) res=res + MAGMA_D_REAL(hcheck.val[k]) - MAGMA_D_REAL(hrefvec.val[k]); printf("# |x-y|_F = %8.2e\n", res); if ( res < .000001 ) printf("# tester spmv cuSPARSE HYB: ok\n"); else printf("# tester spmv cuSPARSE HYB: failed\n"); magma_d_vfree( &hcheck, queue ); cusparseDestroyMatDescr( descrA ); cusparseDestroyHybMat( hybA ); cusparseDestroy( cusparseHandle ); magma_d_mfree(&dA, queue ); printf("\n\n"); // free CPU memory magma_d_mfree(&hA, queue ); magma_d_vfree(&hx, queue ); magma_d_vfree(&hy, queue ); magma_d_vfree(&hrefvec, queue ); // free GPU memory magma_d_vfree(&dx, queue ); magma_d_vfree(&dy, queue ); i++; } magma_queue_destroy( queue ); TESTING_FINALIZE(); return 0; }
extern "C" magma_int_t magma_dpastixsetup( magma_d_sparse_matrix A, magma_d_vector b, magma_d_preconditioner *precond, magma_queue_t queue ) { #if defined(HAVE_PASTIX) #if defined(PRECISION_d) pastix_data_t *pastix_data = NULL; /* Pointer to a storage structure needed by pastix */ pastix_int_t ncol; /* Size of the matrix */ pastix_int_t *colptr = NULL; /* Indexes of first element of each column in row and values */ pastix_int_t *rows = NULL; /* Row of each element of the matrix */ pastix_float_t *values = NULL; /* Value of each element of the matrix */ pastix_float_t *rhs = NULL; /* right hand side */ pastix_int_t *iparm = NULL; /* integer parameters for pastix */ double *dparm = NULL; /* floating parameters for pastix */ pastix_int_t *perm = NULL; /* Permutation tabular */ pastix_int_t *invp = NULL; /* Reverse permutation tabular */ pastix_int_t mat_type; magma_d_sparse_matrix A_h1, B; magma_d_vector diag, c_t, b_h; magma_d_vinit( &c_t, Magma_CPU, A.num_rows, MAGMA_D_ZERO, queue ); magma_d_vinit( &diag, Magma_CPU, A.num_rows, MAGMA_D_ZERO, queue ); magma_d_vtransfer( b, &b_h, A.memory_location, Magma_CPU, queue ); if ( A.storage_type != Magma_CSR ) { magma_d_mtransfer( A, &A_h1, A.memory_location, Magma_CPU, queue ); magma_d_mconvert( A_h1, &B, A_h1.storage_type, Magma_CSR, queue ); } else { magma_d_mtransfer( A, &B, A.memory_location, Magma_CPU, queue ); } rhs = (pastix_float_t*) b_h.dval; ncol = B.num_rows; colptr = B.drow; rows = B.dcol; values = (pastix_float_t*) B.dval; mat_type = API_SYM_NO; iparm = (pastix_int_t*)malloc(IPARM_SIZE*sizeof(pastix_int_t)); dparm = (pastix_float_t*)malloc(DPARM_SIZE*sizeof(pastix_float_t)); /*******************************************/ /* Initialize parameters to default values */ /*******************************************/ iparm[IPARM_MODIFY_PARAMETER] = API_NO; pastix(&pastix_data, MPI_COMM_WORLD, ncol, colptr, rows, values, perm, invp, rhs, 1, iparm, dparm); iparm[IPARM_THREAD_NBR] = 16; iparm[IPARM_SYM] = mat_type; iparm[IPARM_FACTORIZATION] = API_FACT_LU; iparm[IPARM_VERBOSE] = API_VERBOSE_YES; iparm[IPARM_ORDERING] = API_ORDER_SCOTCH; iparm[IPARM_INCOMPLETE] = API_NO; iparm[IPARM_RHS_MAKING] = API_RHS_B; //iparm[IPARM_AMALGAMATION] = 5; iparm[IPARM_LEVEL_OF_FILL] = 0; /* if (incomplete == 1) { dparm[DPARM_EPSILON_REFINEMENT] = 1e-7; } */ /* * Matrix needs : * - to be in fortran numbering * - to have only the lower triangular part in symmetric case * - to have a graph with a symmetric structure in unsymmetric case * If those criteria are not matched, the csc will be reallocated and changed. */ iparm[IPARM_MATRIX_VERIFICATION] = API_YES; perm = (pastix_int_t*)malloc(ncol*sizeof(pastix_int_t)); invp = (pastix_int_t*)malloc(ncol*sizeof(pastix_int_t)); /*******************************************/ /* Step 1 - Ordering / Scotch */ /* Perform it only when the pattern of */ /* matrix change. */ /* eg: mesh refinement */ /* In many cases users can simply go from */ /* API_TASK_ORDERING to API_TASK_ANALYSE */ /* in one call. */ /*******************************************/ /*******************************************/ /* Step 2 - Symbolic factorization */ /* Perform it only when the pattern of */ /* matrix change. */ /*******************************************/ /*******************************************/ /* Step 3 - Mapping and Compute scheduling */ /* Perform it only when the pattern of */ /* matrix change. */ /*******************************************/ /*******************************************/ /* Step 4 - Numerical Factorisation */ /* Perform it each time the values of the */ /* matrix changed. */ /*******************************************/ iparm[IPARM_START_TASK] = API_TASK_ORDERING; iparm[IPARM_END_TASK] = API_TASK_NUMFACT; pastix(&pastix_data, MPI_COMM_WORLD, ncol, colptr, rows, values, perm, invp, NULL, 1, iparm, dparm); precond->int_array_1 = (magma_int_t*) perm; precond->int_array_2 = (magma_int_t*) invp; precond->M.dval = (double*) values; precond->M.dcol = (magma_int_t*) colptr; precond->M.drow = (magma_int_t*) rows; precond->M.num_rows = A.num_rows; precond->M.num_cols = A.num_cols; precond->M.memory_location = Magma_CPU; precond->pastix_data = pastix_data; precond->iparm = iparm; precond->dparm = dparm; if ( A.storage_type != Magma_CSR) { magma_d_mfree( &A_h1, queue ); } magma_d_vfree( &b_h, queue ); magma_d_mfree( &B, queue ); #else printf( "error: only double precision supported yet.\n"); #endif #else printf( "error: pastix not available.\n"); #endif return MAGMA_SUCCESS; }
magma_int_t magma_dpgmres( magma_d_sparse_matrix A, magma_d_vector b, magma_d_vector *x, magma_d_solver_par *solver_par, magma_d_preconditioner *precond_par ){ // prepare solver feedback solver_par->solver = Magma_PGMRES; solver_par->numiter = 0; solver_par->info = 0; // local variables double c_zero = MAGMA_D_ZERO, c_one = MAGMA_D_ONE, c_mone = MAGMA_D_NEG_ONE; magma_int_t dofs = A.num_rows; magma_int_t i, j, k, m = 0; magma_int_t restart = min( dofs-1, solver_par->restart ); magma_int_t ldh = restart+1; double nom, rNorm, RNorm, nom0, betanom, r0 = 0.; // CPU workspace magma_setdevice(0); double *H, *HH, *y, *h1; magma_dmalloc_pinned( &H, (ldh+1)*ldh ); magma_dmalloc_pinned( &y, ldh ); magma_dmalloc_pinned( &HH, ldh*ldh ); magma_dmalloc_pinned( &h1, ldh ); // GPU workspace magma_d_vector r, q, q_t, z, z_t, t; magma_d_vinit( &t, Magma_DEV, dofs, c_zero ); magma_d_vinit( &r, Magma_DEV, dofs, c_zero ); magma_d_vinit( &q, Magma_DEV, dofs*(ldh+1), c_zero ); magma_d_vinit( &z, Magma_DEV, dofs*(ldh+1), c_zero ); magma_d_vinit( &z_t, Magma_DEV, dofs, c_zero ); q_t.memory_location = Magma_DEV; q_t.val = NULL; q_t.num_rows = q_t.nnz = dofs; double *dy, *dH = NULL; if (MAGMA_SUCCESS != magma_dmalloc( &dy, ldh )) return MAGMA_ERR_DEVICE_ALLOC; if (MAGMA_SUCCESS != magma_dmalloc( &dH, (ldh+1)*ldh )) return MAGMA_ERR_DEVICE_ALLOC; // GPU stream magma_queue_t stream[2]; magma_event_t event[1]; magma_queue_create( &stream[0] ); magma_queue_create( &stream[1] ); magma_event_create( &event[0] ); magmablasSetKernelStream(stream[0]); magma_dscal( dofs, c_zero, x->val, 1 ); // x = 0 magma_dcopy( dofs, b.val, 1, r.val, 1 ); // r = b nom0 = betanom = magma_dnrm2( dofs, r.val, 1 ); // nom0= || r|| nom = nom0 * nom0; solver_par->init_res = nom0; H(1,0) = MAGMA_D_MAKE( nom0, 0. ); magma_dsetvector(1, &H(1,0), 1, &dH(1,0), 1); if ( (r0 = nom * solver_par->epsilon) < ATOLERANCE ) r0 = ATOLERANCE; if ( nom < r0 ) return MAGMA_SUCCESS; //Chronometry real_Double_t tempo1, tempo2; magma_device_sync(); tempo1=magma_wtime(); if( solver_par->verbose > 0 ){ solver_par->res_vec[0] = nom0; solver_par->timing[0] = 0.0; } // start iteration for( solver_par->numiter= 1; solver_par->numiter<solver_par->maxiter; solver_par->numiter++ ){ magma_dcopy(dofs, r.val, 1, q(0), 1); // q[0] = 1.0/H(1,0) r magma_dscal(dofs, 1./H(1,0), q(0), 1); // (to be fused) for(k=1; k<=restart; k++) { q_t.val = q(k-1); magmablasSetKernelStream(stream[0]); // preconditioner // z[k] = M^(-1) q(k) magma_d_applyprecond_left( A, q_t, &t, precond_par ); magma_d_applyprecond_right( A, t, &z_t, precond_par ); magma_dcopy(dofs, z_t.val, 1, z(k-1), 1); // r = A q[k] magma_d_spmv( c_one, A, z_t, c_zero, r ); if (solver_par->ortho == Magma_MGS ) { // modified Gram-Schmidt magmablasSetKernelStream(stream[0]); for (i=1; i<=k; i++) { H(i,k) =magma_ddot(dofs, q(i-1), 1, r.val, 1); // H(i,k) = q[i] . r magma_daxpy(dofs,-H(i,k), q(i-1), 1, r.val, 1); // r = r - H(i,k) q[i] } H(k+1,k) = MAGMA_D_MAKE( magma_dnrm2(dofs, r.val, 1), 0. ); // H(k+1,k) = sqrt(r . r) if (k < restart) { magma_dcopy(dofs, r.val, 1, q(k), 1); // q[k] = 1.0/H[k][k-1] r magma_dscal(dofs, 1./H(k+1,k), q(k), 1); // (to be fused) } } else if (solver_par->ortho == Magma_FUSED_CGS ) { // fusing dgemv with dnrm2 in classical Gram-Schmidt magmablasSetKernelStream(stream[0]); magma_dcopy(dofs, r.val, 1, q(k), 1); // dH(1:k+1,k) = q[0:k] . r magmablas_dgemv(MagmaTrans, dofs, k+1, c_one, q(0), dofs, r.val, 1, c_zero, &dH(1,k), 1); // r = r - q[0:k-1] dH(1:k,k) magmablas_dgemv(MagmaNoTrans, dofs, k, c_mone, q(0), dofs, &dH(1,k), 1, c_one, r.val, 1); // 1) dH(k+1,k) = sqrt( dH(k+1,k) - dH(1:k,k) ) magma_dcopyscale( dofs, k, r.val, q(k), &dH(1,k) ); // 2) q[k] = q[k] / dH(k+1,k) magma_event_record( event[0], stream[0] ); magma_queue_wait_event( stream[1], event[0] ); magma_dgetvector_async(k+1, &dH(1,k), 1, &H(1,k), 1, stream[1]); // asynch copy dH(1:(k+1),k) to H(1:(k+1),k) } else { // classical Gram-Schmidt (default) // > explicitly calling magmabls magmablasSetKernelStream(stream[0]); magmablas_dgemv(MagmaTrans, dofs, k, c_one, q(0), dofs, r.val, 1, c_zero, &dH(1,k), 1); // dH(1:k,k) = q[0:k-1] . r #ifndef DNRM2SCALE // start copying dH(1:k,k) to H(1:k,k) magma_event_record( event[0], stream[0] ); magma_queue_wait_event( stream[1], event[0] ); magma_dgetvector_async(k, &dH(1,k), 1, &H(1,k), 1, stream[1]); #endif // r = r - q[0:k-1] dH(1:k,k) magmablas_dgemv(MagmaNoTrans, dofs, k, c_mone, q(0), dofs, &dH(1,k), 1, c_one, r.val, 1); #ifdef DNRM2SCALE magma_dcopy(dofs, r.val, 1, q(k), 1); // q[k] = r / H(k,k-1) magma_dnrm2scale(dofs, q(k), dofs, &dH(k+1,k) ); // dH(k+1,k) = sqrt(r . r) and r = r / dH(k+1,k) magma_event_record( event[0], stream[0] ); // start sending dH(1:k,k) to H(1:k,k) magma_queue_wait_event( stream[1], event[0] ); // can we keep H(k+1,k) on GPU and combine? magma_dgetvector_async(k+1, &dH(1,k), 1, &H(1,k), 1, stream[1]); #else H(k+1,k) = MAGMA_D_MAKE( magma_dnrm2(dofs, r.val, 1), 0. ); // H(k+1,k) = sqrt(r . r) if( k<solver_par->restart ){ magmablasSetKernelStream(stream[0]); magma_dcopy(dofs, r.val, 1, q(k), 1); // q[k] = 1.0/H[k][k-1] r magma_dscal(dofs, 1./H(k+1,k), q(k), 1); // (to be fused) } #endif } } magma_queue_sync( stream[1] ); for( k=1; k<=restart; k++ ){ /* Minimization of || b-Ax || in H_k */ for (i=1; i<=k; i++) { #if defined(PRECISION_z) || defined(PRECISION_c) cblas_ddot_sub( i+1, &H(1,k), 1, &H(1,i), 1, &HH(k,i) ); #else HH(k,i) = cblas_ddot(i+1, &H(1,k), 1, &H(1,i), 1); #endif } h1[k] = H(1,k)*H(1,0); if (k != 1) for (i=1; i<k; i++) { for (m=i+1; m<k; m++){ HH(k,m) -= HH(k,i) * HH(m,i); } HH(k,k) -= HH(k,i) * HH(k,i) / HH(i,i); HH(k,i) = HH(k,i)/HH(i,i); h1[k] -= h1[i] * HH(k,i); } y[k] = h1[k]/HH(k,k); if (k != 1) for (i=k-1; i>=1; i--) { y[i] = h1[i]/HH(i,i); for (j=i+1; j<=k; j++) y[i] -= y[j] * HH(j,i); } m = k; rNorm = fabs(MAGMA_D_REAL(H(k+1,k))); } magma_dsetmatrix_async(m, 1, y+1, m, dy, m, stream[0]); magmablasSetKernelStream(stream[0]); magma_dgemv(MagmaNoTrans, dofs, m, c_one, z(0), dofs, dy, 1, c_one, x->val, 1); magma_d_spmv( c_mone, A, *x, c_zero, r ); // r = - A * x magma_daxpy(dofs, c_one, b.val, 1, r.val, 1); // r = r + b H(1,0) = MAGMA_D_MAKE( magma_dnrm2(dofs, r.val, 1), 0. ); // RNorm = H[1][0] = || r || RNorm = MAGMA_D_REAL( H(1,0) ); betanom = fabs(RNorm); if( solver_par->verbose > 0 ){ magma_device_sync(); tempo2=magma_wtime(); if( (solver_par->numiter)%solver_par->verbose==0 ) { solver_par->res_vec[(solver_par->numiter)/solver_par->verbose] = (real_Double_t) betanom; solver_par->timing[(solver_par->numiter)/solver_par->verbose] = (real_Double_t) tempo2-tempo1; } } if ( betanom < r0 ) { break; } } magma_device_sync(); tempo2=magma_wtime(); solver_par->runtime = (real_Double_t) tempo2-tempo1; double residual; magma_dresidual( A, b, *x, &residual ); solver_par->iter_res = betanom; solver_par->final_res = residual; if( solver_par->numiter < solver_par->maxiter){ solver_par->info = 0; }else if( solver_par->init_res > solver_par->final_res ){ if( solver_par->verbose > 0 ){ if( (solver_par->numiter)%solver_par->verbose==0 ) { solver_par->res_vec[(solver_par->numiter)/solver_par->verbose] = (real_Double_t) betanom; solver_par->timing[(solver_par->numiter)/solver_par->verbose] = (real_Double_t) tempo2-tempo1; } } solver_par->info = -2; } else{ if( solver_par->verbose > 0 ){ if( (solver_par->numiter)%solver_par->verbose==0 ) { solver_par->res_vec[(solver_par->numiter)/solver_par->verbose] = (real_Double_t) betanom; solver_par->timing[(solver_par->numiter)/solver_par->verbose] = (real_Double_t) tempo2-tempo1; } } solver_par->info = -1; } // free pinned memory magma_free_pinned( H ); magma_free_pinned( y ); magma_free_pinned( HH ); magma_free_pinned( h1 ); // free GPU memory magma_free(dy); if (dH != NULL ) magma_free(dH); magma_d_vfree(&t); magma_d_vfree(&r); magma_d_vfree(&q); magma_d_vfree(&z); magma_d_vfree(&z_t); // free GPU streams and events magma_queue_destroy( stream[0] ); magma_queue_destroy( stream[1] ); magma_event_destroy( event[0] ); magmablasSetKernelStream(NULL); return MAGMA_SUCCESS; } /* magma_dgmres */
magma_int_t magma_dbicgstab_merge2( magma_d_sparse_matrix A, magma_d_vector b, magma_d_vector *x, magma_d_solver_par *solver_par ){ // prepare solver feedback solver_par->solver = Magma_BICGSTABMERGE2; solver_par->numiter = 0; solver_par->info = 0; // some useful variables double c_zero = MAGMA_D_ZERO, c_one = MAGMA_D_ONE; magma_int_t dofs = A.num_rows; // GPU stream magma_queue_t stream[2]; magma_event_t event[1]; magma_queue_create( &stream[0] ); magma_queue_create( &stream[1] ); magma_event_create( &event[0] ); // workspace magma_d_vector q, r,rr,p,v,s,t; double *d1, *d2, *skp; magma_dmalloc( &d1, dofs*(2) ); magma_dmalloc( &d2, dofs*(2) ); // array for the parameters magma_dmalloc( &skp, 8 ); // skp = [alpha|beta|omega|rho_old|rho|nom|tmp1|tmp2] magma_d_vinit( &q, Magma_DEV, dofs*6, c_zero ); // q = rr|r|p|v|s|t rr.memory_location = Magma_DEV; rr.val = NULL; rr.num_rows = rr.nnz = dofs; r.memory_location = Magma_DEV; r.val = NULL; r.num_rows = r.nnz = dofs; p.memory_location = Magma_DEV; p.val = NULL; p.num_rows = p.nnz = dofs; v.memory_location = Magma_DEV; v.val = NULL; v.num_rows = v.nnz = dofs; s.memory_location = Magma_DEV; s.val = NULL; s.num_rows = s.nnz = dofs; t.memory_location = Magma_DEV; t.val = NULL; t.num_rows = t.nnz = dofs; rr.val = q(0); r.val = q(1); p.val = q(2); v.val = q(3); s.val = q(4); t.val = q(5); // solver variables double alpha, beta, omega, rho_old, rho_new, *skp_h; double nom, nom0, betanom, r0, den; // solver setup magma_dscal( dofs, c_zero, x->val, 1) ; // x = 0 magma_dcopy( dofs, b.val, 1, q(0), 1 ); // rr = b magma_dcopy( dofs, b.val, 1, q(1), 1 ); // r = b rho_new = magma_ddot( dofs, r.val, 1, r.val, 1 ); // rho=<rr,r> nom = MAGMA_D_REAL(magma_ddot( dofs, r.val, 1, r.val, 1 )); nom0 = betanom = sqrt(nom); // nom = || r || rho_old = omega = alpha = MAGMA_D_MAKE( 1.0, 0. ); beta = rho_new; solver_par->init_res = nom0; // array on host for the parameters magma_dmalloc_cpu( &skp_h, 8 ); skp_h[0]=alpha; skp_h[1]=beta; skp_h[2]=omega; skp_h[3]=rho_old; skp_h[4]=rho_new; skp_h[5]=MAGMA_D_MAKE(nom, 0.0); magma_dsetvector( 8, skp_h, 1, skp, 1 ); magma_d_spmv( c_one, A, r, c_zero, v ); // z = A r den = MAGMA_D_REAL( magma_ddot(dofs, v.val, 1, r.val, 1) );// den = z dot r if ( (r0 = nom * solver_par->epsilon) < ATOLERANCE ) r0 = ATOLERANCE; if ( nom < r0 ) return MAGMA_SUCCESS; // check positive definite if (den <= 0.0) { printf("Operator A is not postive definite. (Ar,r) = %f\n", den); return -100; } //Chronometry real_Double_t tempo1, tempo2; magma_device_sync(); tempo1=magma_wtime(); if( solver_par->verbose > 0 ){ solver_par->res_vec[0] = nom0; solver_par->timing[0] = 0.0; } // start iteration for( solver_par->numiter= 1; solver_par->numiter<solver_par->maxiter; solver_par->numiter++ ){ magmablasSetKernelStream(stream[0]); // computes p=r+beta*(p-omega*v) magma_dbicgmerge1( dofs, skp, v.val, r.val, p.val ); magma_dbicgmerge_spmv1( A, d1, d2, q(2), q(0), q(3), skp ); magma_dbicgmerge2( dofs, skp, r.val, v.val, s.val ); // s=r-alpha*v magma_dbicgmerge_spmv2( A, d1, d2, q(4), q(5), skp); magma_dbicgmerge_xrbeta( dofs, d1, d2, q(0), q(1), q(2), q(4), q(5), x->val, skp); // check stopping criterion (asynchronous copy) magma_dgetvector_async( 1 , skp+5, 1, skp_h+5, 1, stream[1] ); betanom = sqrt(MAGMA_D_REAL(skp_h[5])); if( solver_par->verbose > 0 ){ magma_device_sync(); tempo2=magma_wtime(); if( (solver_par->numiter)%solver_par->verbose==0 ) { solver_par->res_vec[(solver_par->numiter)/solver_par->verbose] = (real_Double_t) betanom; solver_par->timing[(solver_par->numiter)/solver_par->verbose] = (real_Double_t) tempo2-tempo1; } } if ( betanom < r0 ) { break; } } magma_device_sync(); tempo2=magma_wtime(); solver_par->runtime = (real_Double_t) tempo2-tempo1; double residual; magma_dresidual( A, b, *x, &residual ); solver_par->iter_res = betanom; solver_par->final_res = residual; if( solver_par->numiter < solver_par->maxiter){ solver_par->info = 0; }else if( solver_par->init_res > solver_par->final_res ){ if( solver_par->verbose > 0 ){ if( (solver_par->numiter)%solver_par->verbose==0 ) { solver_par->res_vec[(solver_par->numiter)/solver_par->verbose] = (real_Double_t) betanom; solver_par->timing[(solver_par->numiter)/solver_par->verbose] = (real_Double_t) tempo2-tempo1; } } solver_par->info = -2; } else{ if( solver_par->verbose > 0 ){ if( (solver_par->numiter)%solver_par->verbose==0 ) { solver_par->res_vec[(solver_par->numiter)/solver_par->verbose] = (real_Double_t) betanom; solver_par->timing[(solver_par->numiter)/solver_par->verbose] = (real_Double_t) tempo2-tempo1; } } solver_par->info = -1; } magma_d_vfree(&q); // frees all vectors magma_free(d1); magma_free(d2); magma_free( skp ); magma_free_cpu( skp_h ); return MAGMA_SUCCESS; } /* dbicgstab_merge2 */
extern "C" magma_int_t magma_dpbicgstab( magma_d_sparse_matrix A, magma_d_vector b, magma_d_vector *x, magma_d_solver_par *solver_par, magma_d_preconditioner *precond_par, magma_queue_t queue ) { // set queue for old dense routines magma_queue_t orig_queue; magmablasGetKernelStream( &orig_queue ); // prepare solver feedback solver_par->solver = Magma_PBICGSTAB; solver_par->numiter = 0; solver_par->info = MAGMA_SUCCESS; // some useful variables double c_zero = MAGMA_D_ZERO, c_one = MAGMA_D_ONE, c_mone = MAGMA_D_NEG_ONE; magma_int_t dofs = A.num_rows; // workspace magma_d_vector r,rr,p,v,s,t,ms,mt,y,z; magma_d_vinit( &r, Magma_DEV, dofs, c_zero, queue ); magma_d_vinit( &rr, Magma_DEV, dofs, c_zero, queue ); magma_d_vinit( &p, Magma_DEV, dofs, c_zero, queue ); magma_d_vinit( &v, Magma_DEV, dofs, c_zero, queue ); magma_d_vinit( &s, Magma_DEV, dofs, c_zero, queue ); magma_d_vinit( &t, Magma_DEV, dofs, c_zero, queue ); magma_d_vinit( &ms, Magma_DEV, dofs, c_zero, queue ); magma_d_vinit( &mt, Magma_DEV, dofs, c_zero, queue ); magma_d_vinit( &y, Magma_DEV, dofs, c_zero, queue ); magma_d_vinit( &z, Magma_DEV, dofs, c_zero, queue ); // solver variables double alpha, beta, omega, rho_old, rho_new; double nom, betanom, nom0, r0, den, res; // solver setup magma_dscal( dofs, c_zero, x->dval, 1) ; // x = 0 magma_dcopy( dofs, b.dval, 1, r.dval, 1 ); // r = b magma_dcopy( dofs, b.dval, 1, rr.dval, 1 ); // rr = b nom0 = betanom = magma_dnrm2( dofs, r.dval, 1 ); // nom = || r || nom = nom0*nom0; rho_new = omega = alpha = MAGMA_D_MAKE( 1.0, 0. ); solver_par->init_res = nom0; magma_d_spmv( c_one, A, r, c_zero, v, queue ); // z = A r den = MAGMA_D_REAL( magma_ddot(dofs, v.dval, 1, r.dval, 1) ); // den = z' * r if ( (r0 = nom * solver_par->epsilon) < ATOLERANCE ) r0 = ATOLERANCE; if ( nom < r0 ) { magmablasSetKernelStream( orig_queue ); return MAGMA_SUCCESS; } // check positive definite if (den <= 0.0) { printf("Operator A is not postive definite. (Ar,r) = %f\n", den); magmablasSetKernelStream( orig_queue ); return MAGMA_NONSPD; } //Chronometry real_Double_t tempo1, tempo2; tempo1 = magma_sync_wtime( queue ); if ( solver_par->verbose > 0 ) { solver_par->res_vec[0] = nom0; solver_par->timing[0] = 0.0; } // start iteration for( solver_par->numiter= 1; solver_par->numiter<solver_par->maxiter; solver_par->numiter++ ) { rho_old = rho_new; // rho_old=rho rho_new = magma_ddot( dofs, rr.dval, 1, r.dval, 1 ); // rho=<rr,r> beta = rho_new/rho_old * alpha/omega; // beta=rho/rho_old *alpha/omega magma_dscal( dofs, beta, p.dval, 1 ); // p = beta*p magma_daxpy( dofs, c_mone * omega * beta, v.dval, 1 , p.dval, 1 ); // p = p-omega*beta*v magma_daxpy( dofs, c_one, r.dval, 1, p.dval, 1 ); // p = p+r // preconditioner magma_d_applyprecond_left( A, p, &mt, precond_par, queue ); magma_d_applyprecond_right( A, mt, &y, precond_par, queue ); magma_d_spmv( c_one, A, y, c_zero, v, queue ); // v = Ap alpha = rho_new / magma_ddot( dofs, rr.dval, 1, v.dval, 1 ); magma_dcopy( dofs, r.dval, 1 , s.dval, 1 ); // s=r magma_daxpy( dofs, c_mone * alpha, v.dval, 1 , s.dval, 1 ); // s=s-alpha*v // preconditioner magma_d_applyprecond_left( A, s, &ms, precond_par, queue ); magma_d_applyprecond_right( A, ms, &z, precond_par, queue ); magma_d_spmv( c_one, A, z, c_zero, t, queue ); // t=As // preconditioner magma_d_applyprecond_left( A, s, &ms, precond_par, queue ); magma_d_applyprecond_left( A, t, &mt, precond_par, queue ); // omega = <ms,mt>/<mt,mt> omega = magma_ddot( dofs, mt.dval, 1, ms.dval, 1 ) / magma_ddot( dofs, mt.dval, 1, mt.dval, 1 ); magma_daxpy( dofs, alpha, y.dval, 1 , x->dval, 1 ); // x=x+alpha*p magma_daxpy( dofs, omega, z.dval, 1 , x->dval, 1 ); // x=x+omega*s magma_dcopy( dofs, s.dval, 1 , r.dval, 1 ); // r=s magma_daxpy( dofs, c_mone * omega, t.dval, 1 , r.dval, 1 ); // r=r-omega*t res = betanom = magma_dnrm2( dofs, r.dval, 1 ); nom = betanom*betanom; if ( solver_par->verbose > 0 ) { tempo2 = magma_sync_wtime( queue ); if ( (solver_par->numiter)%solver_par->verbose==0 ) { solver_par->res_vec[(solver_par->numiter)/solver_par->verbose] = (real_Double_t) res; solver_par->timing[(solver_par->numiter)/solver_par->verbose] = (real_Double_t) tempo2-tempo1; } } if ( res/nom0 < solver_par->epsilon ) { break; } } tempo2 = magma_sync_wtime( queue ); solver_par->runtime = (real_Double_t) tempo2-tempo1; double residual; magma_dresidual( A, b, *x, &residual, queue ); solver_par->final_res = residual; solver_par->iter_res = res; if ( solver_par->numiter < solver_par->maxiter) { solver_par->info = MAGMA_SUCCESS; } else if ( solver_par->init_res > solver_par->final_res ) { if ( solver_par->verbose > 0 ) { if ( (solver_par->numiter)%solver_par->verbose==0 ) { solver_par->res_vec[(solver_par->numiter)/solver_par->verbose] = (real_Double_t) betanom; solver_par->timing[(solver_par->numiter)/solver_par->verbose] = (real_Double_t) tempo2-tempo1; } } solver_par->info = MAGMA_SLOW_CONVERGENCE; } else { if ( solver_par->verbose > 0 ) { if ( (solver_par->numiter)%solver_par->verbose==0 ) { solver_par->res_vec[(solver_par->numiter)/solver_par->verbose] = (real_Double_t) betanom; solver_par->timing[(solver_par->numiter)/solver_par->verbose] = (real_Double_t) tempo2-tempo1; } } solver_par->info = MAGMA_DIVERGENCE; } magma_d_vfree(&r, queue ); magma_d_vfree(&rr, queue ); magma_d_vfree(&p, queue ); magma_d_vfree(&v, queue ); magma_d_vfree(&s, queue ); magma_d_vfree(&t, queue ); magma_d_vfree(&ms, queue ); magma_d_vfree(&mt, queue ); magma_d_vfree(&y, queue ); magma_d_vfree(&z, queue ); magmablasSetKernelStream( orig_queue ); return MAGMA_SUCCESS; } /* magma_dbicgstab */
magma_int_t magma_dpcg( magma_d_sparse_matrix A, magma_d_vector b, magma_d_vector *x, magma_d_solver_par *solver_par, magma_d_preconditioner *precond_par ){ // prepare solver feedback solver_par->solver = Magma_PCG; solver_par->numiter = 0; solver_par->info = 0; // local variables double c_zero = MAGMA_D_ZERO, c_one = MAGMA_D_ONE; magma_int_t dofs = A.num_rows; // GPU workspace magma_d_vector r, rt, p, q, h; magma_d_vinit( &r, Magma_DEV, dofs, c_zero ); magma_d_vinit( &rt, Magma_DEV, dofs, c_zero ); magma_d_vinit( &p, Magma_DEV, dofs, c_zero ); magma_d_vinit( &q, Magma_DEV, dofs, c_zero ); magma_d_vinit( &h, Magma_DEV, dofs, c_zero ); // solver variables double alpha, beta; double nom, nom0, r0, gammaold, gammanew, den, res; // solver setup magma_dscal( dofs, c_zero, x->val, 1) ; // x = 0 magma_dcopy( dofs, b.val, 1, r.val, 1 ); // r = b // preconditioner magma_d_applyprecond_left( A, r, &rt, precond_par ); magma_d_applyprecond_right( A, rt, &h, precond_par ); magma_dcopy( dofs, h.val, 1, p.val, 1 ); // p = h nom = MAGMA_D_REAL( magma_ddot(dofs, r.val, 1, h.val, 1) ); nom0 = magma_dnrm2( dofs, r.val, 1 ); magma_d_spmv( c_one, A, p, c_zero, q ); // q = A p den = MAGMA_D_REAL( magma_ddot(dofs, p.val, 1, q.val, 1) );// den = p dot q solver_par->init_res = nom0; if ( (r0 = nom * solver_par->epsilon) < ATOLERANCE ) r0 = ATOLERANCE; if ( nom < r0 ) return MAGMA_SUCCESS; // check positive definite if (den <= 0.0) { printf("Operator A is not postive definite. (Ar,r) = %f\n", den); return -100; } //Chronometry real_Double_t tempo1, tempo2; magma_device_sync(); tempo1=magma_wtime(); if( solver_par->verbose > 0 ){ solver_par->res_vec[0] = (real_Double_t)nom0; solver_par->timing[0] = 0.0; } // start iteration for( solver_par->numiter= 1; solver_par->numiter<solver_par->maxiter; solver_par->numiter++ ){ // preconditioner magma_d_applyprecond_left( A, r, &rt, precond_par ); magma_d_applyprecond_right( A, rt, &h, precond_par ); gammanew = MAGMA_D_REAL( magma_ddot(dofs, r.val, 1, h.val, 1) ); // gn = < r,h> if( solver_par->numiter==1 ){ magma_dcopy( dofs, h.val, 1, p.val, 1 ); // p = h }else{ beta = MAGMA_D_MAKE(gammanew/gammaold, 0.); // beta = gn/go magma_dscal(dofs, beta, p.val, 1); // p = beta*p magma_daxpy(dofs, c_one, h.val, 1, p.val, 1); // p = p + h } magma_d_spmv( c_one, A, p, c_zero, q ); // q = A p den = MAGMA_D_REAL(magma_ddot(dofs, p.val, 1, q.val, 1)); // den = p dot q alpha = MAGMA_D_MAKE(gammanew/den, 0.); magma_daxpy(dofs, alpha, p.val, 1, x->val, 1); // x = x + alpha p magma_daxpy(dofs, -alpha, q.val, 1, r.val, 1); // r = r - alpha q gammaold = gammanew; res = magma_dnrm2( dofs, r.val, 1 ); if( solver_par->verbose > 0 ){ magma_device_sync(); tempo2=magma_wtime(); if( (solver_par->numiter)%solver_par->verbose==0 ) { solver_par->res_vec[(solver_par->numiter)/solver_par->verbose] = (real_Double_t) res; solver_par->timing[(solver_par->numiter)/solver_par->verbose] = (real_Double_t) tempo2-tempo1; } } if ( res/nom0 < solver_par->epsilon ) { break; } } magma_device_sync(); tempo2=magma_wtime(); solver_par->runtime = (real_Double_t) tempo2-tempo1; double residual; magma_dresidual( A, b, *x, &residual ); solver_par->iter_res = res; solver_par->final_res = residual; if( solver_par->numiter < solver_par->maxiter){ solver_par->info = 0; }else if( solver_par->init_res > solver_par->final_res ){ if( solver_par->verbose > 0 ){ if( (solver_par->numiter)%solver_par->verbose==0 ) { solver_par->res_vec[(solver_par->numiter)/solver_par->verbose] = (real_Double_t) res; solver_par->timing[(solver_par->numiter)/solver_par->verbose] = (real_Double_t) tempo2-tempo1; } } solver_par->info = -2; } else{ if( solver_par->verbose > 0 ){ if( (solver_par->numiter)%solver_par->verbose==0 ) { solver_par->res_vec[(solver_par->numiter)/solver_par->verbose] = (real_Double_t) res; solver_par->timing[(solver_par->numiter)/solver_par->verbose] = (real_Double_t) tempo2-tempo1; } } solver_par->info = -1; } magma_d_vfree(&r); magma_d_vfree(&rt); magma_d_vfree(&p); magma_d_vfree(&q); magma_d_vfree(&h); return MAGMA_SUCCESS; } /* magma_dcg */
extern "C" magma_int_t magma_dbpcg( magma_d_sparse_matrix A, magma_d_vector b, magma_d_vector *x, magma_d_solver_par *solver_par, magma_d_preconditioner *precond_par, magma_queue_t queue ) { // set queue for old dense routines magma_queue_t orig_queue; magmablasGetKernelStream( &orig_queue ); magma_int_t stat_dev = 0, stat_cpu = 0; magma_int_t i, num_vecs = b.num_rows/A.num_rows; // prepare solver feedback solver_par->solver = Magma_PCG; solver_par->numiter = 0; solver_par->info = MAGMA_SUCCESS; // local variables double c_zero = MAGMA_D_ZERO, c_one = MAGMA_D_ONE; magma_int_t dofs = A.num_rows; // GPU workspace magma_d_vector r, rt, p, q, h; magma_d_vinit( &r, Magma_DEV, dofs*num_vecs, c_zero, queue ); magma_d_vinit( &rt, Magma_DEV, dofs*num_vecs, c_zero, queue ); magma_d_vinit( &p, Magma_DEV, dofs*num_vecs, c_zero, queue ); magma_d_vinit( &q, Magma_DEV, dofs*num_vecs, c_zero, queue ); magma_d_vinit( &h, Magma_DEV, dofs*num_vecs, c_zero, queue ); // solver variables double *alpha, *beta; alpha = NULL; beta = NULL; stat_cpu += magma_dmalloc_cpu(&alpha, num_vecs); stat_cpu += magma_dmalloc_cpu(&beta, num_vecs); double *nom, *nom0, *r0, *gammaold, *gammanew, *den, *res, *residual; nom = NULL; nom0 = NULL; r0 = NULL; gammaold = NULL; gammanew = NULL; den = NULL; res = NULL; residual = NULL; stat_cpu += magma_dmalloc_cpu(&residual, num_vecs); stat_cpu += magma_dmalloc_cpu(&nom, num_vecs); stat_cpu += magma_dmalloc_cpu(&nom0, num_vecs); stat_cpu += magma_dmalloc_cpu(&r0, num_vecs); stat_cpu += magma_dmalloc_cpu(&gammaold, num_vecs); stat_cpu += magma_dmalloc_cpu(&gammanew, num_vecs); stat_cpu += magma_dmalloc_cpu(&den, num_vecs); stat_cpu += magma_dmalloc_cpu(&res, num_vecs); stat_cpu += magma_dmalloc_cpu(&residual, num_vecs); if( stat_cpu != 0 ){ magma_free_cpu( nom ); magma_free_cpu( nom0 ); magma_free_cpu( r0 ); magma_free_cpu( gammaold ); magma_free_cpu( gammanew ); magma_free_cpu( den ); magma_free_cpu( res ); magma_free_cpu( alpha ); magma_free_cpu( beta ); magma_free_cpu( residual ); magmablasSetKernelStream( orig_queue ); printf("error: memory allocation.\n"); return MAGMA_ERR_HOST_ALLOC; } // solver setup magma_dscal( dofs*num_vecs, c_zero, x->dval, 1) ; // x = 0 magma_dcopy( dofs*num_vecs, b.dval, 1, r.dval, 1 ); // r = b // preconditioner magma_d_applyprecond_left( A, r, &rt, precond_par, queue ); magma_d_applyprecond_right( A, rt, &h, precond_par, queue ); magma_dcopy( dofs*num_vecs, h.dval, 1, p.dval, 1 ); // p = h for( i=0; i<num_vecs; i++) { nom[i] = MAGMA_D_REAL( magma_ddot(dofs, r(i), 1, h(i), 1) ); nom0[i] = magma_dnrm2( dofs, r(i), 1 ); } magma_d_spmv( c_one, A, p, c_zero, q, queue ); // q = A p for( i=0; i<num_vecs; i++) den[i] = MAGMA_D_REAL( magma_ddot(dofs, p(i), 1, q(i), 1) ); // den = p dot q solver_par->init_res = nom0[0]; if ( (r0[0] = nom[0] * solver_par->epsilon) < ATOLERANCE ) r0[0] = ATOLERANCE; // check positive definite if (den[0] <= 0.0) { printf("Operator A is not postive definite. (Ar,r) = %f\n", den[0]); magmablasSetKernelStream( orig_queue ); return MAGMA_NONSPD; solver_par->info = MAGMA_NONSPD;; } if ( nom[0] < r0[0] ) { magmablasSetKernelStream( orig_queue ); return MAGMA_SUCCESS; } //Chronometry real_Double_t tempo1, tempo2; tempo1 = magma_sync_wtime( queue ); if ( solver_par->verbose > 0 ) { solver_par->res_vec[0] = (real_Double_t)nom0[0]; solver_par->timing[0] = 0.0; } // start iteration for( solver_par->numiter= 1; solver_par->numiter<solver_par->maxiter; solver_par->numiter++ ) { // preconditioner magma_d_applyprecond_left( A, r, &rt, precond_par, queue ); magma_d_applyprecond_right( A, rt, &h, precond_par, queue ); for( i=0; i<num_vecs; i++) gammanew[i] = MAGMA_D_REAL( magma_ddot(dofs, r(i), 1, h(i), 1) ); // gn = < r,h> if ( solver_par->numiter==1 ) { magma_dcopy( dofs*num_vecs, h.dval, 1, p.dval, 1 ); // p = h } else { for( i=0; i<num_vecs; i++) { beta[i] = MAGMA_D_MAKE(gammanew[i]/gammaold[i], 0.); // beta = gn/go magma_dscal(dofs, beta[i], p(i), 1); // p = beta*p magma_daxpy(dofs, c_one, h(i), 1, p(i), 1); // p = p + h } } magma_d_spmv( c_one, A, p, c_zero, q, queue ); // q = A p // magma_d_bspmv_tuned( dofs, num_vecs, c_one, A, p.dval, c_zero, q.dval, queue ); for( i=0; i<num_vecs; i++) { den[i] = MAGMA_D_REAL(magma_ddot(dofs, p(i), 1, q(i), 1)); // den = p dot q alpha[i] = MAGMA_D_MAKE(gammanew[i]/den[i], 0.); magma_daxpy(dofs, alpha[i], p(i), 1, x->dval+dofs*i, 1); // x = x + alpha p magma_daxpy(dofs, -alpha[i], q(i), 1, r(i), 1); // r = r - alpha q gammaold[i] = gammanew[i]; res[i] = magma_dnrm2( dofs, r(i), 1 ); } if ( solver_par->verbose > 0 ) { tempo2 = magma_sync_wtime( queue ); if ( (solver_par->numiter)%solver_par->verbose==0 ) { solver_par->res_vec[(solver_par->numiter)/solver_par->verbose] = (real_Double_t) res[0]; solver_par->timing[(solver_par->numiter)/solver_par->verbose] = (real_Double_t) tempo2-tempo1; } } if ( res[0]/nom0[0] < solver_par->epsilon ) { break; } } tempo2 = magma_sync_wtime( queue ); solver_par->runtime = (real_Double_t) tempo2-tempo1; magma_dresidual( A, b, *x, residual, queue ); solver_par->iter_res = res[0]; solver_par->final_res = residual[0]; if ( solver_par->numiter < solver_par->maxiter) { solver_par->info = MAGMA_SUCCESS; } else if ( solver_par->init_res > solver_par->final_res ) { if ( solver_par->verbose > 0 ) { if ( (solver_par->numiter)%solver_par->verbose==0 ) { solver_par->res_vec[(solver_par->numiter)/solver_par->verbose] = (real_Double_t) res[0]; solver_par->timing[(solver_par->numiter)/solver_par->verbose] = (real_Double_t) tempo2-tempo1; } } solver_par->info = MAGMA_SLOW_CONVERGENCE; } else { if ( solver_par->verbose > 0 ) { if ( (solver_par->numiter)%solver_par->verbose==0 ) { solver_par->res_vec[(solver_par->numiter)/solver_par->verbose] = (real_Double_t) res[0]; solver_par->timing[(solver_par->numiter)/solver_par->verbose] = (real_Double_t) tempo2-tempo1; } } solver_par->info = MAGMA_DIVERGENCE; } for( i=0; i<num_vecs; i++) { printf("%.4e ",res[i]); } printf("\n"); for( i=0; i<num_vecs; i++) { printf("%.4e ",residual[i]); } printf("\n"); magma_d_vfree(&r, queue ); magma_d_vfree(&rt, queue ); magma_d_vfree(&p, queue ); magma_d_vfree(&q, queue ); magma_d_vfree(&h, queue ); magma_free_cpu(alpha); magma_free_cpu(beta); magma_free_cpu(nom); magma_free_cpu(nom0); magma_free_cpu(r0); magma_free_cpu(gammaold); magma_free_cpu(gammanew); magma_free_cpu(den); magma_free_cpu(res); magmablasSetKernelStream( orig_queue ); return MAGMA_SUCCESS; } /* magma_dbpcg */
extern "C" magma_int_t magma_diterref( magma_d_sparse_matrix A, magma_d_vector b, magma_d_vector *x, magma_d_solver_par *solver_par, magma_d_preconditioner *precond_par, magma_queue_t queue ) { // set queue for old dense routines magma_queue_t orig_queue; magmablasGetKernelStream( &orig_queue ); // prepare solver feedback solver_par->solver = Magma_ITERREF; solver_par->numiter = 0; solver_par->info = MAGMA_SUCCESS; double residual; magma_dresidual( A, b, *x, &residual, queue ); solver_par->init_res = residual; // some useful variables double c_zero = MAGMA_D_ZERO, c_one = MAGMA_D_ONE, c_mone = MAGMA_D_NEG_ONE; magma_int_t dofs = A.num_rows; // workspace magma_d_vector r,z; magma_d_vinit( &r, Magma_DEV, dofs, c_zero, queue ); magma_d_vinit( &z, Magma_DEV, dofs, c_zero, queue ); // solver variables double nom, nom0, r0; // solver setup magma_dscal( dofs, c_zero, x->dval, 1) ; // x = 0 magma_dcopy( dofs, b.dval, 1, r.dval, 1 ); // r = b nom0 = magma_dnrm2(dofs, r.dval, 1); // nom0 = || r || nom = nom0 * nom0; solver_par->init_res = nom0; if ( (r0 = nom * solver_par->epsilon) < ATOLERANCE ) r0 = ATOLERANCE; if ( nom < r0 ) { magmablasSetKernelStream( orig_queue ); return MAGMA_SUCCESS; } //Chronometry real_Double_t tempo1, tempo2; tempo1 = magma_sync_wtime( queue ); if ( solver_par->verbose > 0 ) { solver_par->res_vec[0] = nom0; solver_par->timing[0] = 0.0; } // start iteration for( solver_par->numiter= 1; solver_par->numiter<solver_par->maxiter; solver_par->numiter++ ) { magma_dscal( dofs, MAGMA_D_MAKE(1./nom, 0.), r.dval, 1) ; // scale it magma_d_precond( A, r, &z, precond_par, queue ); // inner solver: A * z = r magma_dscal( dofs, MAGMA_D_MAKE(nom, 0.), z.dval, 1) ; // scale it magma_daxpy(dofs, c_one, z.dval, 1, x->dval, 1); // x = x + z magma_d_spmv( c_mone, A, *x, c_zero, r, queue ); // r = - A x magma_daxpy(dofs, c_one, b.dval, 1, r.dval, 1); // r = r + b nom = magma_dnrm2(dofs, r.dval, 1); // nom = || r || if ( solver_par->verbose > 0 ) { tempo2 = magma_sync_wtime( queue ); if ( (solver_par->numiter)%solver_par->verbose==0 ) { solver_par->res_vec[(solver_par->numiter)/solver_par->verbose] = (real_Double_t) nom; solver_par->timing[(solver_par->numiter)/solver_par->verbose] = (real_Double_t) tempo2-tempo1; } } if ( nom < r0 ) { break; } } tempo2 = magma_sync_wtime( queue ); solver_par->runtime = (real_Double_t) tempo2-tempo1; magma_dresidual( A, b, *x, &residual, queue ); solver_par->final_res = residual; solver_par->iter_res = nom; if ( solver_par->numiter < solver_par->maxiter) { solver_par->info = MAGMA_SUCCESS; } else if ( solver_par->init_res > solver_par->final_res ) { if ( solver_par->verbose > 0 ) { if ( (solver_par->numiter)%solver_par->verbose==0 ) { solver_par->res_vec[(solver_par->numiter)/solver_par->verbose] = (real_Double_t) nom; solver_par->timing[(solver_par->numiter)/solver_par->verbose] = (real_Double_t) tempo2-tempo1; } } solver_par->info = MAGMA_SLOW_CONVERGENCE; } else { if ( solver_par->verbose > 0 ) { if ( (solver_par->numiter)%solver_par->verbose==0 ) { solver_par->res_vec[(solver_par->numiter)/solver_par->verbose] = (real_Double_t) nom; solver_par->timing[(solver_par->numiter)/solver_par->verbose] = (real_Double_t) tempo2-tempo1; } } solver_par->info = MAGMA_DIVERGENCE; } magma_d_vfree(&r, queue ); magma_d_vfree(&z, queue ); magmablasSetKernelStream( orig_queue ); return MAGMA_SUCCESS; } /* magma_diterref */
/* //////////////////////////////////////////////////////////////////////////// -- Debugging file */ int main( int argc, char** argv) { TESTING_INIT(); magma_d_solver_par solver_par; magma_d_preconditioner precond_par; solver_par.epsilon = 10e-16; solver_par.maxiter = 1000; solver_par.verbose = 0; solver_par.restart = 30; solver_par.num_eigenvalues = 0; solver_par.ortho = Magma_CGS; double one = MAGMA_D_MAKE(1.0, 0.0); double zero = MAGMA_D_MAKE(0.0, 0.0); magma_d_sparse_matrix A, B, B_d; magma_d_vector x, b; // generate matrix of desired structure and size magma_int_t n=100; // size is n*n magma_int_t nn = n*n; magma_int_t offdiags = 2; magma_index_t *diag_offset; double *diag_vals; magma_dmalloc_cpu( &diag_vals, offdiags+1 ); magma_index_malloc_cpu( &diag_offset, offdiags+1 ); diag_offset[0] = 0; diag_offset[1] = 1; diag_offset[2] = n; diag_vals[0] = MAGMA_D_MAKE( 4.1, 0.0 ); diag_vals[1] = MAGMA_D_MAKE( -1.0, 0.0 ); diag_vals[2] = MAGMA_D_MAKE( -1.0, 0.0 ); magma_dmgenerator( nn, offdiags, diag_offset, diag_vals, &A ); // convert marix into desired format B.storage_type = Magma_SELLC; B.blocksize = 8; B.alignment = 8; // scale matrix magma_dmscale( &A, Magma_UNITDIAG ); magma_d_mconvert( A, &B, Magma_CSR, B.storage_type ); magma_d_mtransfer( B, &B_d, Magma_CPU, Magma_DEV ); // test CG #################################### // vectors and initial guess magma_d_vinit( &b, Magma_DEV, A.num_cols, one ); magma_d_vinit( &x, Magma_DEV, A.num_cols, one ); magma_d_spmv( one, B_d, x, zero, b ); // b = A x magma_d_vfree(&x); magma_d_vinit( &x, Magma_DEV, A.num_cols, zero ); magma_dsolverinfo_init( &solver_par, &precond_par ); // solver magma_dcg_res( B_d, b, &x, &solver_par ); // solverinfo magma_dsolverinfo( &solver_par, &precond_par ); if( solver_par.numiter > 150 ){ printf("error: test not passed!\n"); exit(-1); } magma_dsolverinfo_free( &solver_par, &precond_par ); magma_d_vfree(&x); magma_d_vfree(&b); // test PCG Jacobi ############################ // vectors and initial guess magma_d_vinit( &b, Magma_DEV, A.num_cols, one ); magma_d_vinit( &x, Magma_DEV, A.num_cols, one ); magma_d_spmv( one, B_d, x, zero, b ); // b = A x magma_d_vfree(&x); magma_d_vinit( &x, Magma_DEV, A.num_cols, zero ); magma_dsolverinfo_init( &solver_par, &precond_par ); // Preconditioner precond_par.solver = Magma_JACOBI; magma_d_precondsetup( B_d, b, &precond_par ); // solver magma_dpcg( B_d, b, &x, &solver_par, &precond_par ); // solverinfo magma_dsolverinfo( &solver_par, &precond_par ); if( solver_par.numiter > 150 ){ printf("error: test not passed!\n"); exit(-1); } magma_dsolverinfo_free( &solver_par, &precond_par ); magma_d_vfree(&x); magma_d_vfree(&b); // test PCG IC ################################ // vectors and initial guess magma_d_vinit( &b, Magma_DEV, A.num_cols, one ); magma_d_vinit( &x, Magma_DEV, A.num_cols, one ); magma_d_spmv( one, B_d, x, zero, b ); // b = A x magma_d_vfree(&x); magma_d_vinit( &x, Magma_DEV, A.num_cols, zero ); magma_dsolverinfo_init( &solver_par, &precond_par ); // Preconditioner precond_par.solver = Magma_ICC; magma_d_precondsetup( B_d, b, &precond_par ); // solver magma_dpcg( B_d, b, &x, &solver_par, &precond_par ); // solverinfo magma_dsolverinfo( &solver_par, &precond_par ); if( solver_par.numiter > 150 ){ printf("error: test not passed!\n"); exit(-1); } magma_dsolverinfo_free( &solver_par, &precond_par ); magma_d_vfree(&x); magma_d_vfree(&b); // test PCG IC ################################ // vectors and initial guess magma_d_vinit( &b, Magma_DEV, A.num_cols, one ); magma_d_vinit( &x, Magma_DEV, A.num_cols, one ); magma_d_spmv( one, B_d, x, zero, b ); // b = A x magma_d_vfree(&x); magma_d_vinit( &x, Magma_DEV, A.num_cols, zero ); magma_dsolverinfo_init( &solver_par, &precond_par ); // Preconditioner precond_par.solver = Magma_ICC; magma_d_precondsetup( B_d, b, &precond_par ); // solver magma_dpcg( B_d, b, &x, &solver_par, &precond_par ); // solverinfo magma_dsolverinfo( &solver_par, &precond_par ); if( solver_par.numiter > 150 ){ printf("error: test not passed!\n"); exit(-1); } magma_dsolverinfo_free( &solver_par, &precond_par ); magma_d_vfree(&x); magma_d_vfree(&b); // test BICGSTAB #################################### // vectors and initial guess magma_d_vinit( &b, Magma_DEV, A.num_cols, one ); magma_d_vinit( &x, Magma_DEV, A.num_cols, one ); magma_d_spmv( one, B_d, x, zero, b ); // b = A x magma_d_vfree(&x); magma_d_vinit( &x, Magma_DEV, A.num_cols, zero ); magma_dsolverinfo_init( &solver_par, &precond_par ); // solver magma_dbicgstab( B_d, b, &x, &solver_par ); // solverinfo magma_dsolverinfo( &solver_par, &precond_par ); if( solver_par.numiter > 150 ){ printf("error: test not passed!\n"); exit(-1); } magma_dsolverinfo_free( &solver_par, &precond_par ); magma_d_vfree(&x); magma_d_vfree(&b); // test PBICGSTAB Jacobi ############################ // vectors and initial guess magma_d_vinit( &b, Magma_DEV, A.num_cols, one ); magma_d_vinit( &x, Magma_DEV, A.num_cols, one ); magma_d_spmv( one, B_d, x, zero, b ); // b = A x magma_d_vfree(&x); magma_d_vinit( &x, Magma_DEV, A.num_cols, zero ); magma_dsolverinfo_init( &solver_par, &precond_par ); // Preconditioner precond_par.solver = Magma_JACOBI; magma_d_precondsetup( B_d, b, &precond_par ); // solver magma_dpbicgstab( B_d, b, &x, &solver_par, &precond_par ); // solverinfo magma_dsolverinfo( &solver_par, &precond_par ); if( solver_par.numiter > 150 ){ printf("error: test not passed!\n"); exit(-1); } magma_dsolverinfo_free( &solver_par, &precond_par ); magma_d_vfree(&x); magma_d_vfree(&b); /* // test PBICGSTAB ILU ############################### // vectors and initial guess magma_d_vinit( &b, Magma_DEV, A.num_cols, one ); magma_d_vinit( &x, Magma_DEV, A.num_cols, one ); magma_d_spmv( one, B_d, x, zero, b ); // b = A x magma_d_vfree(&x); magma_d_vinit( &x, Magma_DEV, A.num_cols, zero ); magma_dsolverinfo_init( &solver_par, &precond_par ); // Preconditioner precond_par.solver = Magma_ILU; magma_d_precondsetup( B_d, b, &precond_par ); // solver magma_dpbicgstab( B_d, b, &x, &solver_par, &precond_par ); // solverinfo magma_dsolverinfo( &solver_par, &precond_par ); if( solver_par.numiter > 150 ){ printf("error: test not passed!\n"); exit(-1); } magma_dsolverinfo_free( &solver_par, &precond_par ); magma_d_vfree(&x); magma_d_vfree(&b); // test PBICGSTAB ILU ############################### // vectors and initial guess magma_d_vinit( &b, Magma_DEV, A.num_cols, one ); magma_d_vinit( &x, Magma_DEV, A.num_cols, one ); magma_d_spmv( one, B_d, x, zero, b ); // b = A x magma_d_vfree(&x);printf("here\n"); magma_d_vinit( &x, Magma_DEV, A.num_cols, zero ); magma_dsolverinfo_init( &solver_par, &precond_par ); // Preconditioner precond_par.solver = Magma_ILU; magma_d_precondsetup( B_d, b, &precond_par ); // solver magma_dpbicgstab( B_d, b, &x, &solver_par, &precond_par ); // solverinfo magma_dsolverinfo( &solver_par, &precond_par ); if( solver_par.numiter > 150 ){ printf("error: test not passed!\n"); exit(-1); } magma_dsolverinfo_free( &solver_par, &precond_par ); magma_d_vfree(&x); magma_d_vfree(&b); // test GMRES #################################### // vectors and initial guess magma_d_vinit( &b, Magma_DEV, A.num_cols, one ); magma_d_vinit( &x, Magma_DEV, A.num_cols, one ); magma_d_spmv( one, B_d, x, zero, b ); // b = A x magma_d_vfree(&x); magma_d_vinit( &x, Magma_DEV, A.num_cols, zero ); magma_dsolverinfo_init( &solver_par, &precond_par ); // solver magma_dgmres( B_d, b, &x, &solver_par ); // solverinfo magma_dsolverinfo( &solver_par, &precond_par ); magma_dsolverinfo_free( &solver_par, &precond_par ); magma_d_vfree(&x); magma_d_vfree(&b); // test PGMRES Jacobi ############################ // vectors and initial guess magma_d_vinit( &b, Magma_DEV, A.num_cols, one ); magma_d_vinit( &x, Magma_DEV, A.num_cols, one ); magma_d_spmv( one, B_d, x, zero, b ); // b = A x magma_d_vfree(&x); magma_d_vinit( &x, Magma_DEV, A.num_cols, zero ); magma_dsolverinfo_init( &solver_par, &precond_par ); // Preconditioner precond_par.solver = Magma_JACOBI; magma_d_precondsetup( B_d, b, &precond_par ); // solver magma_dpgmres( B_d, b, &x, &solver_par, &precond_par ); // solverinfo magma_dsolverinfo( &solver_par, &precond_par ); magma_dsolverinfo_free( &solver_par, &precond_par ); magma_d_vfree(&x); magma_d_vfree(&b);*/ // test PGMRES ILU ############################### // vectors and initial guess magma_d_vinit( &b, Magma_DEV, A.num_cols, one ); magma_d_vinit( &x, Magma_DEV, A.num_cols, one ); magma_d_spmv( one, B_d, x, zero, b ); // b = A x magma_d_vfree(&x); magma_d_vinit( &x, Magma_DEV, A.num_cols, zero ); magma_dsolverinfo_init( &solver_par, &precond_par ); // Preconditioner precond_par.solver = Magma_ILU; magma_d_precondsetup( B_d, b, &precond_par ); // solver magma_dpgmres( B_d, b, &x, &solver_par, &precond_par ); // solverinfo magma_dsolverinfo( &solver_par, &precond_par ); if( solver_par.numiter > 150 ){ printf("error: test not passed!\n"); exit(-1); } magma_dsolverinfo_free( &solver_par, &precond_par ); magma_d_vfree(&x); magma_d_vfree(&b); printf("all tests passed.\n"); magma_d_mfree(&B_d); magma_d_mfree(&B); magma_d_mfree(&A); TESTING_FINALIZE(); return 0; }