6#include <cuda_runtime.h>
14#define MIN(x,y) (x<y?x:y)
21#define MAX(x,y) (x>y?x:y)
33__device__ __forceinline__ T
conj(
const T& z){
34 return T(z.real(),-z.imag());
50__global__
void Real_convert(
float *a,
double *b,
const unsigned int len,
const bool dtof){
51 const unsigned int gsize = gridDim.x*gridDim.y*gridDim.z;
52 const unsigned int bsize = blockDim.x*blockDim.y*blockDim.z;
53 const unsigned int blockId = blockIdx.x+ blockIdx.y * gridDim.x+ gridDim.x * gridDim.y * blockIdx.z;
54 const unsigned int bthreadId= (threadIdx.z * blockDim.y+ threadIdx.y)* blockDim.x+ threadIdx.x;
55 const unsigned int gthreadId= blockId * bsize+bthreadId;
59 for(
unsigned int i = gthreadId; i<len;i+=gsize*bsize)
63 for(
unsigned int i = gthreadId; i<len;i+=gsize*bsize)
79 const unsigned int gsize = gridDim.x*gridDim.y*gridDim.z;
80 const unsigned int bsize = blockDim.x*blockDim.y*blockDim.z;
81 const unsigned int blockId = blockIdx.x+ blockIdx.y * gridDim.x+ gridDim.x * gridDim.y * blockIdx.z;
82 const unsigned int bthreadId= (threadIdx.z * blockDim.y+ threadIdx.y)* blockDim.x+ threadIdx.x;
83 const unsigned int gthreadId= blockId * bsize+bthreadId;
85 for(
unsigned int i = gthreadId; i<
kvol;i+=gsize*bsize)
86 for(
unsigned short idirac = 0; idirac<
ndirac; idirac++)
87 for(
unsigned short ic= 0; ic<
nc; ic++)
89 smallPhi[i +
kvol * (ic +
nc * idirac)] = Phi[i +
kvol * (ic +
nc * (idirac +
ngorkov * na))];
103 const unsigned int gsize = gridDim.x*gridDim.y*gridDim.z;
104 const unsigned int bsize = blockDim.x*blockDim.y*blockDim.z;
105 const unsigned int blockId = blockIdx.x+ blockIdx.y * gridDim.x+ gridDim.x * gridDim.y * blockIdx.z;
106 const unsigned int bthreadId= (threadIdx.z * blockDim.y+ threadIdx.y)* blockDim.x+ threadIdx.x;
107 const unsigned int gthreadId= blockId * bsize+bthreadId;
109 for(
unsigned int i = gthreadId; i<
kvol;i+=gsize*bsize)
110 for(
unsigned short idirac = 0; idirac <
ndirac; idirac++){
145 const unsigned int gsize = gridDim.x*gridDim.y*gridDim.z;
146 const unsigned int bsize = blockDim.x*blockDim.y*blockDim.z;
147 const unsigned int blockId = blockIdx.x+ blockIdx.y * gridDim.x+ gridDim.x * gridDim.y * blockIdx.z;
148 const unsigned int bthreadId= (threadIdx.z * blockDim.y+ threadIdx.y)* blockDim.x+ threadIdx.x;
149 const unsigned int gthreadId= blockId * bsize+bthreadId;
150 for(
unsigned int i=gthreadId; i<
kvol*
ndim; i+=gsize*bsize){
153 double anorm=sqrt(
conj(u11t[i])*u11t[i]+
conj(u12t[i])*u12t[i]).real();
177 const unsigned int gsize = gridDim.x*gridDim.y*gridDim.z;
178 const unsigned int bsize = blockDim.x*blockDim.y*blockDim.z;
179 const unsigned int blockId = blockIdx.x+ blockIdx.y * gridDim.x+ gridDim.x * gridDim.y * blockIdx.z;
180 const unsigned int bthreadId= (threadIdx.z * blockDim.y+ threadIdx.y)* blockDim.x+ threadIdx.x;
181 const unsigned int gthreadId= blockId * bsize+bthreadId;
182 for(
unsigned int i=gthreadId;i<
kvol;i+=gsize*bsize){
187 const unsigned int ind = i+
kvol*mu;
188 double AAA = d*sqrt(pp[ind]*pp[ind]\
191 double CCC = cos(AAA);
192 double SSS = d*sin(AAA)/AAA;
198 u11t[ind] = a11*b11-a12*
conj(u12t[ind]);
199 u12t[ind] = a11*u12t[ind]+a12*
conj(b11);
207 const char *funcname =
"blockInit";
209 int device=-1; cudaGetDevice(&device);
210 cudaDeviceProp prop; cudaGetDeviceProperties(&prop, device);
212 int tpb=prop.maxThreadsPerBlock/8;
214 int tpw=prop.warpSize;
217 while(bx<=x/2 && bx<tpb)
221 while(by<=y/2 && bx*by<tpb)
228 int res= ((
nx*
ny)/(bx*by) > 1) ? (
nx*
ny)/(bx*by) :1;
235 while(bz<z/2 && bx*by*bz<tpb)
241 fprintf(stderr,
"Alert %i in %s: Suboptimal block size for warp size %d. bx=%d by=%d bz=%d\n",
243 int res= ((
nx*
ny)/(bx*by) > 1) ? (
nx*
ny)/(bx*by) :1;
246 printf(
"Block: (%d,%d,%d)\tGrid: (%d,%d,%d)\n",
dimBlock->x,
dimBlock->y,
dimBlock->z,
dimGrid->x,
dimGrid->y,
dimGrid->z);
249 double *dk4p,
unsigned int *iu,
unsigned int *
id){
250 const char *funcname =
"Init_CUDA";
252 cudaGetDevice(&device);
281 const char *funcname =
"cuComplex_convert";
285 const char *funcname =
"cuComplex_convert";
299 for(
int mu=0;mu<
ndim;mu++)
304template __device__ __forceinline__ complex<float>
conj(
const complex<float>& z);
305template __device__ __forceinline__ complex<double>
conj(
const complex<double>& z);
#define BLOCKALERT
Alert with block size.
void blockInit(int x, int y, int z, int t, dim3 *dimBlock, dim3 *dimGrid)
Initialises the CUDA grid and block size for a given lattice.
__global__ void Real_convert(float *a, double *b, const unsigned int len, const bool dtof)
takes an array of real float and double precision numbers and converts the precision
void cuReunitarise(Complex *ut[2], dim3 dimGrid, dim3 dimBlock)
Reunitarises u11t and u12t as in conj(u11t[i])*u11t[i]+conj(u12t[i])*u12t[i]=1.
void Init_CUDA(Complex *u11t, Complex *u12t, Complex gamval[20], Complex_f gamval_f[20], unsigned short gamin[16], double *dk4m, double *dk4p, unsigned int *iu, unsigned int *id)
Initialise CUDA cuInit was taken already by CUDA (unsurprisingly).
void cuUpDownPart(const unsigned int na, Complex *X0, Complex *R1, dim3 dimBlock, dim3 dimGrid)
Up/Down partitioning of the pseudofermion field.
__device__ __forceinline__ T conj(const T &z)
Complex Conjugation.
__global__ void cuReunitarise(complex< T > *u11t, complex< T > *u12t)
Reunitarises u11t and u12t as in conj(u11t[i])*u11t[i]+conj(u12t[i])*u12t[i]=1.
__global__ void cuUpDownPart(const unsigned int na, Complex *X0, Complex *R1)
Up/Down partitioning of the pseudofermion field.
void cuReal_convert(float *a, double *b, const unsigned int len, const bool dtof, dim3 dimBlock, dim3 dimGrid)
takes an array of real-valued float and double precision numbers and converts the precision
void cuComplex_convert(Complex_f *a, Complex *b, const unsigned int len, const bool dtof, dim3 dimBlock, dim3 dimGrid)
takes an array of complex float and double precision numbers and converts the precision
void cuFill_Small_Phi(const unsigned int na, Complex *smallPhi, Complex *Phi, dim3 dimBlock, dim3 dimGrid)
Copies necessary (2*4*kvol) elements of Phi into a vector variable.
__global__ void cuFill_Small_Phi(const unsigned int na, Complex *smallPhi, Complex *Phi)
Copies necessary (2*4*kvol) elements of Phi into a vector variable.
void cuGauge_Update(const double d, double *pp, Complex *ut[2], dim3 dimGrid, dim3 dimBlock)
CUDA wrapper for the gauge update during the integration step of the HMC.
__global__ void cuGauge_Update(const double d, double *pp, Complex *u11t, Complex *u12t, int mu)
Gauge update for the integration step of the HMC.
#define nt
Lattice temporal extent. This also corresponds to the inverse temperature.
#define nx
Lattice x extent.
#define ngorkov
Gor'kov indices.
#define nadj
adjacent spatial indices
#define kvol
Sublattice volume.
#define Complex
Double precision complex number.
#define ndirac
Dirac indices.
#define cudaDeviceSynchronise()
Get rid of that bastardised yankee English.
dim3 dimBlockOne
block size of one
dim3 dimGridOne
Grid size of one.
#define Complex_f
Single precision complex number.
dim3 dimGrid
Default grid size. First component is normally nt. Second and third depend whatever is needed to get ...
#define nz
Lattice z extent. We normally use cubic lattices so this is the same as nx.
#define ny
Lattice y extent. We normally use cubic lattices so this is the same as nx.
dim3 dimBlock
Default block size. Usually 128.
Function declarations for most of the routines.
cudaStream_t streams[ndirac *ndim *nadj]
An array of concurrent GPU streams to keep it busy.
#define I
Define I in double precision using C standard notation.