1- import AutoParallelizePy
1+ """
2+ Summary: A simple single-core example program
3+ emulating a hypothetical MPI environment consisting
4+ of 32 processes to test and demonstrate the
5+ AutoParallelizePy class:
6+ class domainDecomposeND
7+
8+ Aims: Create a simple 4D array of arbitrary
9+ shape and auto-domain decompose using the
10+ built-in domainDecomposeND class and recover
11+ the original array after decomposition.
12+ """
13+
214import numpy as np
15+ import AutoParallelizePy as APP
16+
17+ # Even though this example isn't MPI-parallelized, we may emulate a
18+ # hypothetical MPI environment assuming there are a total of 32 procs
19+ size = 32
320
4- size = 48
5- axes_limits = [47 ,37 ,1 ,98 ] # aka how many data points are in each dimension
21+ # Create a simple 4D array of random numbers
22+ arrShape = [47 ,37 ,19 ,98 ]
23+ origArr = np .random .uniform (low = - 20 , high = 20 , size = (arrShape ))
24+
25+ # Configure the domain decomposition scheme such that only the first,
26+ # second, and fourth dimensions of this array are parallelized
627parallel_axes = [0 ,1 ,3 ]
7- user_nblocks = [ 3 , 4 , 1 , 4 ]
8- user_nblocks = None
9- domDecompND = AutoParallelizePy . domainDecomposeND ( size , axes_limits , parallel_axes , user_nblocks , False , True , False )
10- a = np . arange ( np . prod ( axes_limits )). reshape ( axes_limits )
11- a1 = np .zeros (axes_limits )
28+ domDecompND = APP . domainDecomposeND ( size , arrShape , parallel_axes )
29+
30+ # Now let's have our hypothetical procs (ranks) each take a slice of
31+ # the data and dump it in a new array to retrieve the original data
32+ testArr = np .zeros (arrShape )
1233for rank in range (size ):
1334 slq0 = domDecompND .slq [0 ][rank ]
1435 elq0 = domDecompND .elq [0 ][rank ]
1839 elq2 = domDecompND .elq [2 ][rank ]
1940 slq3 = domDecompND .slq [3 ][rank ]
2041 elq3 = domDecompND .elq [3 ][rank ]
21- a1 [slq0 :elq0 ,slq1 :elq1 ,slq2 :elq2 ,slq3 :elq3 ] = a [slq0 :elq0 ,slq1 :elq1 ,slq2 :elq2 ,slq3 :elq3 ]
42+ mySubArr = origArr [slq0 :elq0 ,slq1 :elq1 ,slq2 :elq2 ,slq3 :elq3 ]
43+ # Dump the subarray into the test array in the correct block
44+ testArr [slq0 :elq0 ,slq1 :elq1 ,slq2 :elq2 ,slq3 :elq3 ] = mySubArr
2245
46+ # If the domain decomposition scheme is correctly done, testArr
47+ # recovers the original array. Let's check that
48+ print ("*********************************" )
49+ if np .all (origArr == testArr ):
50+ print ("The original data was successfully recovered!" )
51+ else :
52+ print ("Failed!" )
53+ print ("*********************************" )
54+ print ("" )
2355
24- print (np .all (a == a1 ))
56+ # Now let's print the different attributes of the object domDecompND
57+ print ("Assuming the data is N-dimensional and MPI-parallelized across a total number of np cores:" )
58+ print ("-------------------------------------------------------------------" )
59+ print ('\033 [1m' + "domDecompND.nblock" + '\033 [0m' + " gives an N-D array of the number of MPI-blocks in each dimension." )
60+ print ("The product of all the blocks must recover the total number of cores in an MPI scheme." )
61+ print ("In this example we have domDecompND.nblock = " , domDecompND .nblock )
62+ print ("-------------------------------------------------------------------" )
63+ print ('\033 [1m' + "domDecompND.coordinates" + '\033 [0m' + " gives an Nxnp array of all the Cartesian coordinates of the MPI-blocks." )
64+ print ("In this example we have domDecompND.coordinates = " , domDecompND .coordinates )
65+ print ("and hence the coordinates of the MPI-block handled by 27th (rank = 27) processor is:" ,domDecompND .coordinates [:,27 ])
66+ print ("-------------------------------------------------------------------" )
67+ print ('\033 [1m' + "domDecompND.slq" + '\033 [0m' + " gives an Nxnp array of all the datapoint indices that mark the begining of each MPI-block dimension." )
68+ print ("In this example we have domDecompND.slq = " , domDecompND .slq )
69+ print ("and hence the MPI-block belonging to the 27th processor starts at:" ,domDecompND .slq [:,27 ])
70+ print ("-------------------------------------------------------------------" )
71+ print ('\033 [1m' + "domDecompND.elq" + '\033 [0m' + " gives an Nxnp array of all the datapoint indices that mark the end of each MPI-block dimension." )
72+ print ("In this example we have domDecompND.elq = " , domDecompND .elq )
73+ print ("and hence the MPI-block belonging to the 27th processor ends at:" ,domDecompND .elq [:,27 ])
74+ print ("-------------------------------------------------------------------" )
75+ print ('\033 [1m' + "domDecompND.mynq" + '\033 [0m' + " gives an Nxnp array of the total number of gridpoints of each MPI-block dimension." )
76+ print ("Note that we have domDecompND.mynq = domDecompND.elq - domDecompND.slq" )
77+ print ("In this example we have domDecompND.mynq = " , domDecompND .mynq )
78+ print ("and hence the MPI-block belonging to the 27th processor has the following number of gridpoints in each dimension:" ,domDecompND .mynq [:,27 ])
79+ print ("-------------------------------------------------------------------" )
80+ print ('\033 [1m' + "domDecompND.split_sizes" + '\033 [0m' + " gives an array of length np of the total number of gridpoints handled by each processor." )
81+ print ("Note that we have domDecompND.split_sizes == np.prod(domDecompND.mynq, axis=0)" )
82+ print ("In this example we have domDecompND.split_sizes = " , domDecompND .split_sizes )
83+ print ("and hence the 27th processor has the following total number of gridpoints:" ,domDecompND .split_sizes [27 ])
84+ print ("-------------------------------------------------------------------" )
85+ print ('\033 [1m' + "domDecompND.arrShape" + '\033 [0m' + " gives the shape of the array to be MPI-parallelized." )
86+ print ("In this example we have domDecompND.arrShape = " , domDecompND .arrShape )
87+ print ("-------------------------------------------------------------------" )
88+ print ('\033 [1m' + "domDecompND.parallel_axes" + '\033 [0m' + " gives the user's input list of axes/dimensions to be parallelized." )
89+ print ("In this example we have domDecompND.parallel_axes = " , domDecompND .parallel_axes )
90+ print ("-------------------------------------------------------------------" )
91+ print ('\033 [1m' + "domDecompND.n_dim" + '\033 [0m' + " gives the number of dimensions of the raw array." )
92+ print ("In this example we have domDecompND.n_dim = " , domDecompND .n_dim )
93+ print ("-------------------------------------------------------------------" )
94+ print ('\033 [1m' + "domDecompND.n_par_dim" + '\033 [0m' + " gives the number of parallelized dimensions." )
95+ print ("In this example we have domDecompND.n_par_dim = " , domDecompND .n_par_dim )
96+ print ("-------------------------------------------------------------------" )
0 commit comments