QUDA v0.4.0
A library for QCD on GPUs
|
00001 #include <stdlib.h> 00002 #include <stdio.h> 00003 #include <time.h> 00004 #include <math.h> 00005 00006 #include <test_util.h> 00007 #include <blas_reference.h> 00008 #include <domain_wall_dslash_reference.h> 00009 00010 // In a typical application, quda.h is the only QUDA header required. 00011 #include <quda.h> 00012 00013 int main(int argc, char **argv) 00014 { 00015 // set QUDA parameters 00016 00017 int device = 0; // CUDA device number 00018 00019 QudaPrecision cpu_prec = QUDA_DOUBLE_PRECISION; 00020 QudaPrecision cuda_prec = QUDA_SINGLE_PRECISION; 00021 QudaPrecision cuda_prec_sloppy = QUDA_HALF_PRECISION; 00022 00023 QudaGaugeParam gauge_param = newQudaGaugeParam(); 00024 QudaInvertParam inv_param = newQudaInvertParam(); 00025 00026 gauge_param.X[0] = 16; 00027 gauge_param.X[1] = 16; 00028 gauge_param.X[2] = 16; 00029 gauge_param.X[3] = 16; 00030 inv_param.Ls = 16; 00031 00032 gauge_param.anisotropy = 1.0; 00033 gauge_param.type = QUDA_WILSON_LINKS; 00034 gauge_param.gauge_order = QUDA_QDP_GAUGE_ORDER; 00035 gauge_param.t_boundary = QUDA_ANTI_PERIODIC_T; 00036 00037 gauge_param.cpu_prec = cpu_prec; 00038 gauge_param.cuda_prec = cuda_prec; 00039 gauge_param.reconstruct = QUDA_RECONSTRUCT_12; 00040 gauge_param.cuda_prec_sloppy = cuda_prec_sloppy; 00041 gauge_param.reconstruct_sloppy = QUDA_RECONSTRUCT_12; 00042 gauge_param.gauge_fix = QUDA_GAUGE_FIXED_NO; 00043 00044 inv_param.dslash_type = QUDA_DOMAIN_WALL_DSLASH; 00045 inv_param.inv_type = QUDA_CG_INVERTER; 00046 00047 inv_param.mass = 0.01; 00048 inv_param.m5 = -1.5; 00049 double kappa5 = 0.5/(5 + inv_param.m5); 00050 00051 inv_param.tol = 5e-8; 00052 inv_param.maxiter = 1000; 00053 inv_param.reliable_delta = 0.1; 00054 00055 inv_param.solution_type = QUDA_MAT_SOLUTION; 00056 inv_param.solve_type = QUDA_NORMEQ_PC_SOLVE; 00057 inv_param.matpc_type = QUDA_MATPC_EVEN_EVEN; 00058 inv_param.dagger = QUDA_DAG_NO; 00059 inv_param.mass_normalization = QUDA_KAPPA_NORMALIZATION; 00060 00061 inv_param.cpu_prec = cpu_prec; 00062 inv_param.cuda_prec = cuda_prec; 00063 inv_param.cuda_prec_sloppy = cuda_prec_sloppy; 00064 inv_param.prec_precondition = cuda_prec_sloppy; 00065 inv_param.preserve_source = QUDA_PRESERVE_SOURCE_NO; 00066 inv_param.gamma_basis = QUDA_DEGRAND_ROSSI_GAMMA_BASIS; 00067 inv_param.dirac_order = QUDA_DIRAC_ORDER; 00068 00069 inv_param.tune = QUDA_TUNE_YES; 00070 00071 gauge_param.ga_pad = 0; // 24*24*24; 00072 inv_param.sp_pad = 0; // 24*24*24; 00073 inv_param.cl_pad = 0; // 24*24*24; 00074 00075 inv_param.verbosity = QUDA_VERBOSE; 00076 00077 // Everything between here and the call to initQuda() is application-specific. 00078 00079 // set parameters for the reference Dslash, and prepare fields to be loaded 00080 setDims(gauge_param.X, inv_param.Ls); 00081 00082 size_t gSize = (gauge_param.cpu_prec == QUDA_DOUBLE_PRECISION) ? sizeof(double) : sizeof(float); 00083 size_t sSize = (inv_param.cpu_prec == QUDA_DOUBLE_PRECISION) ? sizeof(double) : sizeof(float); 00084 00085 void *gauge[4]; 00086 00087 for (int dir = 0; dir < 4; dir++) { 00088 gauge[dir] = malloc(V*gaugeSiteSize*gSize); 00089 } 00090 construct_gauge_field(gauge, 1, gauge_param.cpu_prec, &gauge_param); 00091 00092 void *spinorIn = malloc(V*spinorSiteSize*sSize*inv_param.Ls); 00093 void *spinorOut = malloc(V*spinorSiteSize*sSize*inv_param.Ls); 00094 void *spinorCheck = malloc(V*spinorSiteSize*sSize*inv_param.Ls); 00095 00096 // create a point source at 0 00097 if (inv_param.cpu_prec == QUDA_SINGLE_PRECISION) *((float*)spinorIn) = 1.0; 00098 else *((double*)spinorIn) = 1.0; 00099 00100 // start the timer 00101 double time0 = -((double)clock()); 00102 00103 // initialize the QUDA library 00104 initQuda(device); 00105 00106 // load the gauge field 00107 loadGaugeQuda((void*)gauge, &gauge_param); 00108 00109 // perform the inversion 00110 invertQuda(spinorOut, spinorIn, &inv_param); 00111 00112 // stop the timer 00113 time0 += clock(); 00114 time0 /= CLOCKS_PER_SEC; 00115 00116 printf("Device memory used:\n Spinor: %f GiB\n Gauge: %f GiB\n", 00117 inv_param.spinorGiB, gauge_param.gaugeGiB); 00118 printf("\nDone: %i iter / %g secs = %g Gflops, total time = %g secs\n", 00119 inv_param.iter, inv_param.secs, inv_param.gflops/inv_param.secs, time0); 00120 00121 if (inv_param.solution_type == QUDA_MAT_SOLUTION) { 00122 mat(spinorCheck, gauge, spinorOut, kappa5, 0, inv_param.cpu_prec, 00123 gauge_param.cpu_prec, inv_param.mass); 00124 if (inv_param.mass_normalization == QUDA_MASS_NORMALIZATION) 00125 ax(0.5/kappa5, spinorCheck, V*spinorSiteSize, inv_param.cpu_prec); 00126 } else if(inv_param.solution_type == QUDA_MATPC_SOLUTION) { 00127 matpc(spinorCheck, gauge, spinorOut, kappa5, inv_param.matpc_type, 0, 00128 inv_param.cpu_prec, gauge_param.cpu_prec, inv_param.mass); 00129 if (inv_param.mass_normalization == QUDA_MASS_NORMALIZATION) 00130 ax(0.25/(kappa5*kappa5), spinorCheck, V*spinorSiteSize, inv_param.cpu_prec); 00131 } 00132 00133 mxpy(spinorIn, spinorCheck, V*spinorSiteSize, inv_param.cpu_prec); 00134 double nrm2 = norm_2(spinorCheck, V*spinorSiteSize, inv_param.cpu_prec); 00135 double src2 = norm_2(spinorIn, V*spinorSiteSize, inv_param.cpu_prec); 00136 printf("Relative residual: requested = %g, actual = %g\n", inv_param.tol, sqrt(nrm2/src2)); 00137 00138 // finalize the QUDA library 00139 endQuda(); 00140 00141 return 0; 00142 }