Statistiques
| Révision :

root / Ising / GPU / Ising2D-GPU-Global.py @ 93

Historique | Voir | Annoter | Télécharger (8,86 ko)

1 93 equemene
#!/usr/bin/env python
2 93 equemene
#
3 93 equemene
# Ising2D model using PyOpenCL
4 93 equemene
#
5 93 equemene
# CC BY-NC-SA 2011 : <emmanuel.quemener@ens-lyon.fr>
6 93 equemene
#
7 93 equemene
# Thanks to Andreas Klockner for PyOpenCL:
8 93 equemene
# http://mathema.tician.de/software/pyopencl
9 93 equemene
#
10 93 equemene
# Interesting links:
11 93 equemene
# http://viennacl.sourceforge.net/viennacl-documentation.html
12 93 equemene
# http://enja.org/2011/02/22/adventures-in-pyopencl-part-1-getting-started-with-python/
13 93 equemene
14 93 equemene
import pyopencl as cl
15 93 equemene
import numpy
16 93 equemene
from numpy.random import randint as nprnd
17 93 equemene
from PIL import Image
18 93 equemene
import time
19 93 equemene
import sys
20 93 equemene
import getopt
21 93 equemene
import matplotlib.pyplot as plt
22 93 equemene
23 93 equemene
# 2097152 on HD5850 (with 1GB of RAM)
24 93 equemene
#  262144 on GT218
25 93 equemene
#STEP=262144
26 93 equemene
#STEP=1048576
27 93 equemene
#STEP=2097152
28 93 equemene
#STEP=4194304
29 93 equemene
#STEP=8388608
30 93 equemene
STEP=16777216
31 93 equemene
32 93 equemene
KERNEL_CODE="""
33 93 equemene

34 93 equemene
// Marsaglia RNG very simple implementation
35 93 equemene

36 93 equemene
#define znew (z=36969*(z&65535)+(z>>16))
37 93 equemene
#define wnew (w=18000*(w&65535)+(w>>16))
38 93 equemene
#define MWC ((znew<<16)+wnew )
39 93 equemene
#define MWCfp MWC * 2.328306435454494e-10f
40 93 equemene

41 93 equemene
__kernel void MainLoop(__global int *s,float J,float B,float T,uint size,
42 93 equemene
                       uint iterations,uint seed_w,uint seed_z)
43 93 equemene
{
44 93 equemene
   uint z=seed_z;
45 93 equemene
   uint w=seed_w;
46 93 equemene

47 93 equemene
   for (uint i=0;i<iterations;i++) {
48 93 equemene

49 93 equemene
      uint x=(uint)(MWC%size) ;
50 93 equemene
      uint y=(uint)(MWC%size) ;
51 93 equemene

52 93 equemene
      int p=s[x+size*y];
53 93 equemene

54 93 equemene
      int d=s[x+size*((y+1)%size)];
55 93 equemene
      int u=s[x+size*((y-1)%size)];
56 93 equemene
      int l=s[((x-1)%size)+size*y];
57 93 equemene
      int r=s[((x+1)%size)+size*y];
58 93 equemene

59 93 equemene
      float DeltaE=p*(2.0f*J*(u+d+l+r)+B);
60 93 equemene

61 93 equemene
      int factor=((DeltaE < 0.0f) || (MWCfp < exp(-DeltaE/T))) ? -1:1;
62 93 equemene
      s[x%size+size*(y%size)] = factor*p;
63 93 equemene
      // barrier(CLK_GLOBAL_MEM_FENCE);
64 93 equemene
   }
65 93 equemene
   barrier(CLK_GLOBAL_MEM_FENCE);
66 93 equemene

67 93 equemene
}
68 93 equemene
"""
69 93 equemene
70 93 equemene
def ImageOutput(sigma,prefix):
71 93 equemene
72 93 equemene
        Max=sigma.max()
73 93 equemene
        Min=sigma.min()
74 93 equemene
75 93 equemene
        # Normalize value as 8bits Integer
76 93 equemene
        SigmaInt=(255*(sigma-Min)/(Max-Min)).astype('uint8')
77 93 equemene
        image = Image.fromarray(SigmaInt)
78 93 equemene
        image.save("%s.jpg" % prefix)
79 93 equemene
80 93 equemene
def Metropolis(sigma,J,B,T,iterations,Device):
81 93 equemene
82 93 equemene
        # Initialisation des variables en les CASTant correctement
83 93 equemene
84 93 equemene
        # Je detecte un peripherique GPU dans la liste des peripheriques
85 93 equemene
    Id=1
86 93 equemene
    HasXPU=False
87 93 equemene
    for platform in cl.get_platforms():
88 93 equemene
        for device in platform.get_devices():
89 93 equemene
            if Id==Device:
90 93 equemene
                XPU=device
91 93 equemene
                print "CPU/GPU selected: ",device.name.lstrip()
92 93 equemene
                HasXPU=True
93 93 equemene
            Id+=1
94 93 equemene
95 93 equemene
    if HasXPU==False:
96 93 equemene
        print "No XPU #%i found in all of %i devices, sorry..." % (Device,Id-1)
97 93 equemene
        sys.exit()
98 93 equemene
99 93 equemene
    # Je cree le contexte et la queue pour son execution
100 93 equemene
    ctx = cl.Context([XPU])
101 93 equemene
    queue = cl.CommandQueue(ctx,
102 93 equemene
        properties=cl.command_queue_properties.PROFILING_ENABLE)
103 93 equemene
104 93 equemene
        # Je recupere les flag possibles pour les buffers
105 93 equemene
    mf = cl.mem_flags
106 93 equemene
107 93 equemene
    sigmaCL = cl.Buffer(ctx, mf.WRITE_ONLY|mf.COPY_HOST_PTR,hostbuf=sigma)
108 93 equemene
109 93 equemene
    MetropolisCL = cl.Program(ctx,KERNEL_CODE).build(
110 93 equemene
        options = "-cl-mad-enable -cl-fast-relaxed-math")
111 93 equemene
112 93 equemene
    i=0
113 93 equemene
    step=STEP
114 93 equemene
    duration=0.
115 93 equemene
116 93 equemene
    while (step*i < iterations):
117 93 equemene
        # Call OpenCL kernel
118 93 equemene
        # (1,) is global work size (only 1 work size)
119 93 equemene
        # (1,) is local work size
120 93 equemene
        # sigmaCL is lattice translated in CL format
121 93 equemene
        # step is number of iterations
122 93 equemene
123 93 equemene
        start_time=time.time()
124 93 equemene
        CLLaunch=MetropolisCL.MainLoop(queue,(1,),None,
125 93 equemene
                                                sigmaCL,
126 93 equemene
                                                numpy.float32(J),numpy.float32(B),
127 93 equemene
                                                numpy.float32(T),
128 93 equemene
                                                numpy.uint32(sigma.shape[0]),
129 93 equemene
                                                numpy.uint32(step),
130 93 equemene
                                                numpy.uint32(nprnd(2**32)),
131 93 equemene
                                                numpy.uint32(nprnd(2**32)))
132 93 equemene
        CLLaunch.wait()
133 93 equemene
        # Does not seem to work under AMD/ATI
134 93 equemene
        # elapsed = 1e-9*(CLLaunch.profile.end - CLLaunch.profile.start)
135 93 equemene
        elapsed = time.time()-start_time
136 93 equemene
        print "Iteration %i with T=%f and %i iterations in %f: " % (i,T,step,elapsed)
137 93 equemene
        if LAPIMAGE:
138 93 equemene
            cl.enqueue_copy(queue, sigma, sigmaCL).wait()
139 93 equemene
            ImageOutput(sigma,"Ising2D_GPU_Global_%i_%1.1f_%.3i_Lap" %
140 93 equemene
                (SIZE,T,i))
141 93 equemene
        i=i+1
142 93 equemene
        duration=duration+elapsed
143 93 equemene
144 93 equemene
        cl.enqueue_copy(queue, sigma, sigmaCL).wait()
145 93 equemene
        sigmaCL.release()
146 93 equemene
147 93 equemene
        return(duration)
148 93 equemene
149 93 equemene
def Magnetization(sigma,M):
150 93 equemene
    return(numpy.sum(sigma)/(sigma.shape[0]*sigma.shape[1]*1.0))
151 93 equemene
152 93 equemene
def Energy(sigma,J,B):
153 93 equemene
    # Copier et caster
154 93 equemene
    E=numpy.copy(sigma).astype(numpy.float32)
155 93 equemene
156 93 equemene
    # Appel par slice
157 93 equemene
    E[1:-1,1:-1]=E[1:-1,1:-1]*(2.0*J*(E[:-2,1:-1]+E[2:,1:-1]+
158 93 equemene
                                          E[1:-1,:-2]+E[1:-1,2:])+B)
159 93 equemene
160 93 equemene
    # Bien nettoyer la peripherie
161 93 equemene
    E[:,0]=0
162 93 equemene
    E[:,-1]=0
163 93 equemene
    E[0,:]=0
164 93 equemene
    E[-1,:]=0
165 93 equemene
166 93 equemene
    Energy=numpy.sum(E)
167 93 equemene
168 93 equemene
    return(Energy/(E.shape[0]*E.shape[1]*1.0))
169 93 equemene
170 93 equemene
def CriticalT(T,E):
171 93 equemene
172 93 equemene
    Epoly=numpy.poly1d(numpy.polyfit(T,E,T.size/3))
173 93 equemene
    dEpoly=numpy.diff(Epoly(T))
174 93 equemene
    dEpoly=numpy.insert(dEpoly,0,0)
175 93 equemene
    return(T[numpy.argmin(dEpoly)])
176 93 equemene
177 93 equemene
def DisplayCurves(T,E,M,J,B):
178 93 equemene
179 93 equemene
    plt.xlabel("Temperature")
180 93 equemene
    plt.ylabel("Energy")
181 93 equemene
182 93 equemene
    Experience,=plt.plot(T,E,label="Energy")
183 93 equemene
184 93 equemene
    plt.legend()
185 93 equemene
    plt.show()
186 93 equemene
187 93 equemene
if __name__=='__main__':
188 93 equemene
189 93 equemene
    # Set defaults values
190 93 equemene
    # Coupling factor
191 93 equemene
    J=1.
192 93 equemene
    # External Magnetic Field is null
193 93 equemene
    B=0.
194 93 equemene
    # Size of Lattice
195 93 equemene
    Size=256
196 93 equemene
    # Default Temperatures (start, end, step)
197 93 equemene
    Tmin=0.1
198 93 equemene
    Tmax=5
199 93 equemene
    Tstep=0.1
200 93 equemene
    # Default Number of Iterations
201 93 equemene
    Iterations=Size*Size
202 93 equemene
    # Default Device is first
203 93 equemene
    Device=1
204 93 equemene
205 93 equemene
    # Curves is True to print the curves
206 93 equemene
    Curves=False
207 93 equemene
208 93 equemene
    OCL_vendor={}
209 93 equemene
    OCL_type={}
210 93 equemene
    OCL_description={}
211 93 equemene
212 93 equemene
    try:
213 93 equemene
        import pyopencl as cl
214 93 equemene
215 93 equemene
        print "\nHere are available OpenCL devices:"
216 93 equemene
        Id=1
217 93 equemene
        for platform in cl.get_platforms():
218 93 equemene
            for device in platform.get_devices():
219 93 equemene
                OCL_vendor[Id]=platform.vendor.lstrip().rstrip()
220 93 equemene
                OCL_type[Id]=cl.device_type.to_string(device.type)
221 93 equemene
                OCL_description[Id]=device.name.lstrip().rstrip()
222 93 equemene
                print "* Device #%i from %s of type %s : %s" % (Id,OCL_vendor[Id],OCL_type[Id],OCL_description[Id])
223 93 equemene
                Id=Id+1
224 93 equemene
        OCL_MaxDevice=Id-1
225 93 equemene
        print
226 93 equemene
227 93 equemene
    except ImportError:
228 93 equemene
        print "Your platform does not seem to support OpenCL"
229 93 equemene
        sys.exit(0)
230 93 equemene
231 93 equemene
    try:
232 93 equemene
        opts, args = getopt.getopt(sys.argv[1:],"hcj:b:z:i:s:e:p:d:",["coupling=","magneticfield=","size=","iterations=","tempstart=","tempend=","tempstep=","units",'device='])
233 93 equemene
    except getopt.GetoptError:
234 93 equemene
        print '%s -d <Device Id> -j <Coupling Factor> -b <Magnetic Field> -z <Size of Square Lattice> -i <Iterations> -s <Minimum Temperature> -e <Maximum Temperature> -p <steP Temperature> -c (Print Curves)' % sys.argv[0]
235 93 equemene
        sys.exit(2)
236 93 equemene
237 93 equemene
    for opt, arg in opts:
238 93 equemene
        if opt == '-h':
239 93 equemene
            print '%s -d <Device Id> -j <Coupling Factor> -b <Magnetic Field> -z <Size of Square Lattice> -i <Iterations> -s <Minimum Temperature> -e <Maximum Temperature> -p <steP Temperature> -c (Print Curves)' % sys.argv[0]
240 93 equemene
            sys.exit()
241 93 equemene
        elif opt == '-c':
242 93 equemene
            Curves=True
243 93 equemene
        elif opt in ("-d", "--device"):
244 93 equemene
            Device = int(arg)
245 93 equemene
            if Device>OCL_MaxDevice:
246 93 equemene
                "Device #%s seems not to be available !"
247 93 equemene
                sys.exit()
248 93 equemene
        elif opt in ("-j", "--coupling"):
249 93 equemene
            J = float(arg)
250 93 equemene
        elif opt in ("-b", "--magneticfield"):
251 93 equemene
            B = float(arg)
252 93 equemene
        elif opt in ("-s", "--tempmin"):
253 93 equemene
            Tmin = float(arg)
254 93 equemene
        elif opt in ("-e", "--tempmax"):
255 93 equemene
            Tmax = arg
256 93 equemene
        elif opt in ("-p", "--tempstep"):
257 93 equemene
            Tstep = numpy.uint32(arg)
258 93 equemene
        elif opt in ("-i", "--iterations"):
259 93 equemene
            Iterations = int(arg)
260 93 equemene
        elif opt in ("-z", "--size"):
261 93 equemene
            Size = int(arg)
262 93 equemene
263 93 equemene
    print "Here are parameters of simulation:"
264 93 equemene
    print "* Device selected #%s: %s of type %s from %s" % (Device,OCL_description[Device],OCL_type[Device],OCL_vendor[Device])
265 93 equemene
    print "* Coupling Factor J : %s" % J
266 93 equemene
    print "* Magnetic Field B :  %s" % B
267 93 equemene
    print "* Size of lattice : %sx%s" % (Size,Size)
268 93 equemene
    print "* Iterations : %s" % Iterations
269 93 equemene
    print "* Temperatures from %s to %s by %s" % (Tmin,Tmax,Tstep)
270 93 equemene
271 93 equemene
    LAPIMAGE=False
272 93 equemene
273 93 equemene
    if Iterations<STEP:
274 93 equemene
        STEP=Iterations
275 93 equemene
276 93 equemene
    sigmaIn=numpy.where(numpy.random.randn(Size,Size)>0,1,-1).astype        (numpy.int32)
277 93 equemene
278 93 equemene
    ImageOutput(sigmaIn,"Ising2D_GPU_Global_%i_Initial" % (Size))
279 93 equemene
280 93 equemene
    Trange=numpy.arange(Tmin,Tmax+Tstep,Tstep)
281 93 equemene
282 93 equemene
    E=[]
283 93 equemene
    M=[]
284 93 equemene
285 93 equemene
    for T in Trange:
286 93 equemene
             sigma=numpy.copy(sigmaIn)
287 93 equemene
            duration=Metropolis(sigma,J,B,T,Iterations,Device)
288 93 equemene
            E=numpy.append(E,Energy(sigma,J,B))
289 93 equemene
            M=numpy.append(M,Magnetization(sigma,B))
290 93 equemene
            ImageOutput(sigma,"Ising2D_GPU_Global_%i_%1.1f_Final" % (Size,T))
291 93 equemene
            print "GPU Time : %f" % (duration)
292 93 equemene
            print "Total Energy at Temperature %f : %f" % (T,E[-1])
293 93 equemene
            print "Total Magnetization at Temperature %f : %f" % (T,M[-1])
294 93 equemene
295 93 equemene
    # Save output
296 93 equemene
    numpy.savez("Ising2D_GPU_Global_%i_%.8i" % (Size,Iterations),(Trange,E,M))
297 93 equemene
298 93 equemene
    # Estimate Critical temperature
299 93 equemene
    print "The critical temperature on %ix%i lattice with J=%f, B=%f is %f " % (Size,Size,J,B,CriticalT(Trange,E))
300 93 equemene
301 93 equemene
    if Curves:
302 93 equemene
        DisplayCurves(Trange,E,M,J,B)