Python in knjižnice
Zdaj, ko znamo graditi enostavne vsebnike, je čas, da pripravimo vsebnike, ki jih bomo zaganjali na računskih vozliščih superračunalnika. Pogledali si bomo, kako v vsebniku zaženemo:
- program, ki se izvaja na jedrih centralne procesne enote,
- program, ki uporablja grafično procesno enoto in
- program, ki se hkrati izvaja na več vozliščih.
Program, ki ga bomo uporabljali na delavnici, računa Mandelbrotovo množico. Napisan je v programskem jeziku Python. Osnovi program bomo po potrebi sproti nadgrajevali s podporo za izbrano tehnologijo in z njim preverjali delovanje vsebnika.
Mandelbrotova množica
Mandelbrotovo množico sestavlja množica točk c v kompleksni ravnini, za katere zaporedje kompleksnih vrednosti z(i+1) = z(i) * z(i) + c, z začetno vrednostjo z(0) = 0, ne divergira.
Mandelbrotovo množico rišemo s črno barvo, točke zunaj množice pa pobarvamo glede na število iteracij, po katerih smo zaznali divergenco zaporedja.
Opazimo samopodobnost in zapleten rob, ki se ob povečavi ne poenostavi. Ti lastnosti Mandelbrotovo množico uvrščata med fraktale.
Program za izris Mandelbrotove množice
Osnovna verzija programa in nekaj konfiguracijskih datotek:
Koda programa mandelbrot-seq.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112 | #!/usr/bin/env python3
####################################################################################
# #
# single-core implementation of the Mandelbrot set #
# #
####################################################################################
# import required libraries
import time, os
import argparse, configparser
import numpy as np
from PIL import Image
from numba import jit, prange
# mandelbrot_colors computes pixel colors in the image
# real_min, real_max, imag_min, imag_max: bounds of the complex plane
# iters_max: the maximum number of iterations
# image: a reference to a memory location of the image
@jit(nopython = True, parallel = False, cache = True)
def mandelbrot_colors(real_min, real_max, imag_min, imag_max, iters_max, image):
# image size in pixels
width = image.shape[1]
height = image.shape[0]
# pixel size in complex plane
real_step = (real_max - real_min) / width
imag_step = (imag_max - imag_min) / height
# check convergence of each pixel in the image
for y in prange(0, height):
for x in prange(0, width):
# a point in a complex plane corrsponding to the pixel (x, y)
real = real_min + real_step * x
imag = imag_min + imag_step * y
c = complex(real, imag)
# check for convergence
z = complex(0, 0)
iters = 0
while abs(z) <= 2 and iters < iters_max:
z = z*z + c
iters += 1
# color pixel in HSV scheme
image[y, x] = (iters % 256, 255, 255 * (iters < iters_max))
# end mandelbrot_colors
# mandelbrot creates an image array of the Mandelbrot set
# real_min, real_max, imag_min, imag_max: bounds of the complex plane
# iters_max: the maximum number of iterations
# width, height: size of the final image
def mandelbrot(real_min, real_max, imag_min, imag_max, iters_max, width, height):
# allocate image array
image = np.zeros((height, width, 3), dtype = np.uint8)
# process image
mandelbrot_colors(real_min, real_max, imag_min, imag_max, iters_max, image)
# return image array
return image
# end mandelbrot
# main routine
def main():
# parse arguments
ap = argparse.ArgumentParser()
ap.add_argument('--config', type = str, default = '', help = 'config file')
args = vars(ap.parse_args())
config_file = args['config']
# parse config file
config = configparser.ConfigParser()
if os.path.isfile(config_file):
config.read(config_file)
real_min = config.getfloat('AREA', 'real_min', fallback = -2.5)
real_max = config.getfloat('AREA', 'real_max', fallback = +1.5)
imag_min = config.getfloat('AREA', 'imag_min', fallback = -1.125)
imag_max = config.getfloat('AREA', 'imag_max', fallback = +1.125)
iters_max = config.getint('ITERATIONS', 'max', fallback = 256)
width = config.getint('IMAGE', 'width', fallback = 3840)
height = config.getint('IMAGE', 'height', fallback = 2160)
name = config.get('IMAGE', 'name', fallback = 'mandelbrot.jpg')
# main processing
t = time.time()
image = mandelbrot(real_min, real_max, imag_min, imag_max, iters_max, width, height)
t = time.time() - t
# save image
Image.fromarray(image, mode='HSV').convert('RGB').save(name)
# printout
print('SEQ: size:', (width, height), 'iterations:', iters_max, 'time:', round(t, 3), "s")
# end main
# invoke the main routine, when this is the main script
if __name__ == "__main__":
main()
|
Izvorna datoteka: mandelbrot-seq.py
Konfiguracijska datoteka default.conf
1
2
3
4
5
6
7
8
9
10
11
12
13 | [AREA]
real_min = -2.5
real_max = +1.5
imag_min = -1.125
imag_max = +1.125
[ITERATIONS]
max = 256
[IMAGE]
width = 3840
height = 2160
name = mandelbrot.jpg
|
Izvorna datoteka: default.conf
Konfiguracijska datoteka detail-1.conf
1
2
3
4
5
6
7
8
9
10
11
12
13 | [AREA]
real_min = -1.14183
real_max = -0.60999
imag_min = 0.05506
imag_max = 0.35422
[ITERATIONS]
max = 256
[IMAGE]
width = 3840
height = 2160
name = mandelbrot-1.jpg
|
Izvorna datoteka: detail-1.conf
Konfiguracijska datoteka detail-2.conf
1
2
3
4
5
6
7
8
9
10
11
12
13 | [AREA]
real_min = -0.7856455
real_max = -0.7340665
imag_min = -0.140053594
imag_max = -0.111040406
[ITERATIONS]
max = 256
[IMAGE]
width = 3840
height = 2160
name = mandelbrot-2.jpg
|
Izvorna datoteka: detail-2.conf
Konfiguracijska datoteka detail-3.conf
1
2
3
4
5
6
7
8
9
10
11
12
13 | [AREA]
real_min = -0.751085
real_max = -0.734975
imag_min = 0.121902063
imag_max = 0.130963938
[ITERATIONS]
max = 256
[IMAGE]
width = 3840
height = 2160
name = mandelbrot-3.jpg
|
Izvorna datoteka: detail-3.conf
Osnovni program vključuje tri funkcije:
- V funkciji
main
(vrstice od 74 do 107) iz konfiguracijske datoteke preberemo parametre izrisa. Če konfiguracijske datoteke ne podamo (stikalo --config
), pripravimo sliko Mandelbrotove množice s privzetimi parametri.
- Funkcija
mandelbrot
(vrstice 56 do 71) pripravi prazno sliko, ki jo funkcija mandelbrot_colors
pobarva.
- Računanje Mandelbrotove množice izvaja funkcija
mandelbrot_colors
(vrstice 19 do 53), ki se sprehodi čez vse slikovne točke in za vsako nastavi barvo, odvisno od konvergence zaporedja.
Bolj, kot podrobnosti programa, je za gradnjo vsebnika pomembno, da
V funkciji mandelbrot_color
uporabimo dve funkciji iz paketa numba
: s prange
zahtevamo vzporedno računanje iteracij v podanem obsegu, z navodilom @jit(nopython=True, parallel = False, cache = True)
pa sprotno prevajanje za eno jedro in shranjevanje prevedene kode za naslednjo uporabo.
Vsebnik za python z nekaj paketi
Pripravimo vsebnik za python s potrebnimi paketi. Za osnovno bomo vzeli vsebnik ubuntu:20.04
- najnovejšo različico z dolgotrajno podporo LTS (angl. Long Term Support) - in vanjo namestili:
- osnovna orodja za prevajanje,
build-essential
,
- knjižnico TBB za večnitenje,
libtbb-dev
,
- programski jezik python,
python3-dev
,
- program
pip
za nameščanje paketov v python, python3-pip
, in
- pakete:
numpy
, Pillow
, tbb
in numba
.
Recept python-scilib.def
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47 | Bootstrap: docker
From: ubuntu:20.04
IncludeCmd: yes
%setup
%files
%environment
export LC_ALL=C
%post
export LC_ALL=C
export DEBIAN_FRONTEND=noninteractive
apt -y update
apt -y install build-essential
apt -y install libtbb-dev
apt -y install python3-dev
apt -y install python3-pip
pip3 install numpy
pip3 install Pillow
pip3 install tbb
pip3 install numba
%runscript
%test
python3 --version
python3 -c "import numpy; print('numpy', numpy.__version__)"
python3 -c "import PIL; print('PIL', PIL.__version__)"
python3 -c "import numba; print('numba', numba.__version__)"
%labels
Author uros (dot) lotric (at) fri (dot) uni (dash) lj (dot) si
Container firbec with terminal viewer viu
Version 1.0
Description Workshop advanced supercomputing (Superračunalištvo bolj zares)
%help
Python container with libraries:
numpy: computation
PIL: image manipulation
tbb: thread building blocks
numba: parallel processing with just in time compilation
|
Izvorna datoteka: python-scilib.def.
Preveri svoje znanje
Vaja
Za pripravo recepta in gradnjo vsebnika sledimo navodilom: Vaja 04.