Multiclass-interface 1.2__py3-none-any.whl → 1.4__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: Multiclass_interface
3
- Version: 1.2
3
+ Version: 1.4
4
4
  Summary: Multiclass interface
5
5
  Author-email: "Mads M. Pedersen" <mmpe@dtu.dk>
6
6
  Project-URL: Homepage, https://gitlab.windenergy.dtu.dk/DYNAMIKS/multiclass_interface
@@ -1,15 +1,15 @@
1
1
  multiclass_interface/__init__.py,sha256=1kI9Vxsap_8eap6kldNHhIWLEVBT2DLWl2UbTOTnVN0,114
2
- multiclass_interface/mpi_interface.py,sha256=CJCKbRQnE8jDndwjzlIy-0VKplsd4c0IUeT-oXbtbOY,5716
2
+ multiclass_interface/mpi_interface.py,sha256=K9onnnfhEOwD6vpZBSJ8YOpeT1f75e7Bv2zIGLzaTKI,6584
3
3
  multiclass_interface/multi_object_list.py,sha256=GmLKWUsu9Vf3Qcy7SlhxqPW_yDw2pzo2EFkkF8R94Dg,2022
4
4
  multiclass_interface/multiprocess_interface.py,sha256=S0gO9u4mQrbhpxarKMD0i7M35EVC9vaKjp3Ls4Y26KU,8169
5
- multiclass_interface/version.py,sha256=ygh-DNoh7nLBcVxwMCbHzWEyaJaMAEWs6Q04Ah2QTz0,406
5
+ multiclass_interface/version.py,sha256=mcG9KdSEcflCnNa2c534AT_PBr7fzMNm38O1LvPiEzE,406
6
6
  multiclass_interface/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
7
  multiclass_interface/tests/my_test_cls.py,sha256=KDcM0zcwwFAcXJhHdl0KHd45MaqHvR8mxHdoUqmbC_E,826
8
- multiclass_interface/tests/test_mpi.py,sha256=aDIvB3o5MNHfkLxCiTl-crIDXyLYbFt9hpRZlop3i7I,2408
8
+ multiclass_interface/tests/test_mpi.py,sha256=owgXwmZCBVO5OuvfLMw8CfBwf1-AnkUzEMf-K8w_mvc,2826
9
9
  multiclass_interface/tests/test_multiclass_list.py,sha256=W7w5wiA3-_wgL9lOCRDsCijikJiHVrp5RqBYwJzWxp4,515
10
10
  multiclass_interface/tests/test_multiprocessinterface.py,sha256=u2BVzoq7YB7L4jwKiveyQheCgQ2O7CGg5nQl9M1rTzM,3165
11
- Multiclass_interface-1.2.dist-info/LICENSE,sha256=oApPkWzMlqIJF9EOB2gV6yvdsm6a2-AW94wuayHIz70,1094
12
- Multiclass_interface-1.2.dist-info/METADATA,sha256=HVPvQX8xwZMqsF8wQjK3JPLjLOj5Uv6B3G35Z1pgSSo,1580
13
- Multiclass_interface-1.2.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
14
- Multiclass_interface-1.2.dist-info/top_level.txt,sha256=LOL3xjSUkjW6thjDr0IMvgkitnbsNokahxl-HjgOJG4,21
15
- Multiclass_interface-1.2.dist-info/RECORD,,
11
+ Multiclass_interface-1.4.dist-info/LICENSE,sha256=oApPkWzMlqIJF9EOB2gV6yvdsm6a2-AW94wuayHIz70,1094
12
+ Multiclass_interface-1.4.dist-info/METADATA,sha256=zcvMytoazf3k0-iUIE8Lx00pF8VeCD64jgHI09kefUI,1580
13
+ Multiclass_interface-1.4.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
14
+ Multiclass_interface-1.4.dist-info/top_level.txt,sha256=LOL3xjSUkjW6thjDr0IMvgkitnbsNokahxl-HjgOJG4,21
15
+ Multiclass_interface-1.4.dist-info/RECORD,,
@@ -7,17 +7,20 @@ comm = None
7
7
  size = 1
8
8
  rank = 0
9
9
  name = ""
10
- main = True
10
+ mpi = False
11
11
 
12
12
 
13
- def activate_mpi():
14
- global comm, size, rank, name, main
13
+ def activate_mpi(collective_mpi=True, loop_until_close=True, terminate_on_close=True):
14
+ global comm, size, rank, name, mpi, LOOP_UNTIL_CLOSE, TERMINATE_ON_CLOSE, COLLECTIVE_MPI
15
15
  from mpi4py import MPI
16
16
  comm = MPI.COMM_WORLD
17
17
  size = MPI.COMM_WORLD.Get_size()
18
18
  rank = MPI.COMM_WORLD.Get_rank()
19
19
  name = MPI.Get_processor_name()
20
- main = rank == 0
20
+ mpi = True
21
+ COLLECTIVE_MPI = collective_mpi
22
+ LOOP_UNTIL_CLOSE = loop_until_close
23
+ TERMINATE_ON_CLOSE = terminate_on_close
21
24
 
22
25
 
23
26
  MPIClassInterfaceAttributes = {
@@ -33,8 +36,9 @@ MPIClassInterfaceAttributes = {
33
36
  'closed'}
34
37
 
35
38
 
36
- LOOP_UNTIL_CLOSE = True
37
- TERMINATE_ON_CLOSE = True
39
+ LOOP_UNTIL_CLOSE = True # MPI workers (rank>0) will enter the work loop and wait for commands from rank 0
40
+ TERMINATE_ON_CLOSE = True # MPI workers (rank>0) will terminate (sys.exit) when the close command is called via rank0
41
+ COLLECTIVE_MPI = True # rank0 acts as a single point of contact (scatters command+arg and gathers results)
38
42
 
39
43
 
40
44
  class MPIClassInterface():
@@ -53,10 +57,9 @@ class MPIClassInterface():
53
57
  self.object = Dummy()
54
58
  self.closed = False
55
59
 
56
- if rank == 0:
57
- self.use_rank = np.array([True] * size)
58
- self.use_rank[len(args_lst):] = False
59
- elif LOOP_UNTIL_CLOSE:
60
+ self.use_rank = np.array([True] * size)
61
+ self.use_rank[len(args_lst):] = False
62
+ if rank > 0 and COLLECTIVE_MPI and LOOP_UNTIL_CLOSE:
60
63
  self.work_loop()
61
64
 
62
65
  def __enter__(self):
@@ -133,13 +136,18 @@ class MPIClassInterface():
133
136
  def __getattribute__(self, name):
134
137
  if name in MPIClassInterfaceAttributes:
135
138
  return object.__getattribute__(self, name)
136
- elif rank > 0:
139
+ elif COLLECTIVE_MPI and rank > 0:
137
140
  self.work_loop()
138
141
  return lambda *args, **kwargs: 1
142
+ elif not self.use_rank[rank]:
143
+ raise ChildProcessError('MPI worker not used')
139
144
 
140
145
  def wrap(*args, **kwargs):
141
- inp = [self.get_input(name, i, args, kwargs) for i in range(size)]
142
- return self.run_task(inp)
146
+ if COLLECTIVE_MPI:
147
+ inp = [self.get_input(name, i, args, kwargs) for i in range(size)]
148
+ return self.run_task(inp)
149
+ else:
150
+ return self.do_task(name, args, kwargs)
143
151
 
144
152
  if hasattr(getattr(self.object, name), '__call__'):
145
153
  return wrap
@@ -162,11 +170,14 @@ class MPIClassInterface():
162
170
 
163
171
  def close(self):
164
172
  if not self.closed:
165
- if rank == 0:
166
- res = self.run_task([('close', [], {}) for _ in range(size)])
173
+ if COLLECTIVE_MPI:
174
+ if rank == 0:
175
+ res = self.run_task([('close', [], {}) for _ in range(size)])
176
+ else:
177
+ self.work_loop()
178
+ res = None
167
179
  else:
168
- self.work_loop()
169
- res = None
180
+ res = self.do_task('close', [], {})
170
181
  self.closed = True
171
182
 
172
183
 
@@ -42,11 +42,28 @@ def mpitest_mpi_ProcessClass():
42
42
  with ProcessClass(MyTest) as cls:
43
43
  myTest = cls(1)
44
44
  assert myTest.get_id() == 1
45
- print("done, test_mpi_ProcessClass")
45
+ print("done, test_mpi_ProcessClass", flush=True)
46
+
47
+
48
+ def mpitest_non_collective_mpi():
49
+ mpi_interface.COLLECTIVE_MPI = False
50
+ rank = mpi_interface.rank
51
+ import time
52
+ N = 3
53
+ with MPIClassInterface(MyTest, [(i + 10,) for i in range(N)]) as m:
54
+
55
+ try:
56
+ assert m.get_id() == rank + 10
57
+ assert rank < N # rank > N will fail with ChildProcessError
58
+ except ChildProcessError:
59
+ pass
60
+
61
+ mpi_interface.COLLECTIVE_MPI = True
46
62
 
47
63
 
48
64
  def mpitest_all():
49
65
  mpi_interface.activate_mpi()
66
+
50
67
  mpi_interface.exit_mpi_on_close = False
51
68
  rank = mpi_interface.rank
52
69
  from multiclass_interface.tests.test_multiprocessinterface import test_attribute, test_missing_attribute, test_execption, test_setattr, test_setattr_method
@@ -67,13 +84,14 @@ def mpitest_all():
67
84
  run(f)
68
85
 
69
86
  try:
70
- with MPIClassInterface(MyTest, [(1,), (2,)]) as mpici:
87
+ with MPIClassInterface(MyTest, [(1,), (2,), (3,)]) as mpici:
71
88
  for f in [test_attribute, test_missing_attribute, test_execption, test_setattr, test_setattr_method]:
72
- break
89
+
73
90
  run(f, mpici)
74
91
 
75
92
  except ChildProcessError:
76
93
  pass
77
- mpi_interface.TERMINATE_ON_CLOSE = True
94
+
95
+ run(mpitest_non_collective_mpi)
78
96
 
79
97
  print(f"Rank {rank} Done test_all")
@@ -12,5 +12,5 @@ __version__: str
12
12
  __version_tuple__: VERSION_TUPLE
13
13
  version_tuple: VERSION_TUPLE
14
14
 
15
- __version__ = version = '1.2'
16
- __version_tuple__ = version_tuple = (1, 2)
15
+ __version__ = version = '1.4'
16
+ __version_tuple__ = version_tuple = (1, 4)