Multiclass-interface 1.2__tar.gz → 1.3__tar.gz

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.
Files changed (23) hide show
  1. {multiclass_interface-1.2 → multiclass_interface-1.3/Multiclass_interface.egg-info}/PKG-INFO +1 -1
  2. {multiclass_interface-1.2/Multiclass_interface.egg-info → multiclass_interface-1.3}/PKG-INFO +1 -1
  3. {multiclass_interface-1.2 → multiclass_interface-1.3}/multiclass_interface/mpi_interface.py +19 -11
  4. {multiclass_interface-1.2 → multiclass_interface-1.3}/multiclass_interface/tests/test_mpi.py +22 -4
  5. {multiclass_interface-1.2 → multiclass_interface-1.3}/multiclass_interface/version.py +2 -2
  6. {multiclass_interface-1.2 → multiclass_interface-1.3}/sequence_diagrams.md +49 -2
  7. {multiclass_interface-1.2 → multiclass_interface-1.3}/.gitignore +0 -0
  8. {multiclass_interface-1.2 → multiclass_interface-1.3}/.gitlab-ci.yml +0 -0
  9. {multiclass_interface-1.2 → multiclass_interface-1.3}/LICENSE +0 -0
  10. {multiclass_interface-1.2 → multiclass_interface-1.3}/Multiclass_interface.egg-info/SOURCES.txt +0 -0
  11. {multiclass_interface-1.2 → multiclass_interface-1.3}/Multiclass_interface.egg-info/dependency_links.txt +0 -0
  12. {multiclass_interface-1.2 → multiclass_interface-1.3}/Multiclass_interface.egg-info/requires.txt +0 -0
  13. {multiclass_interface-1.2 → multiclass_interface-1.3}/Multiclass_interface.egg-info/top_level.txt +0 -0
  14. {multiclass_interface-1.2 → multiclass_interface-1.3}/README.md +0 -0
  15. {multiclass_interface-1.2 → multiclass_interface-1.3}/multiclass_interface/__init__.py +0 -0
  16. {multiclass_interface-1.2 → multiclass_interface-1.3}/multiclass_interface/multi_object_list.py +0 -0
  17. {multiclass_interface-1.2 → multiclass_interface-1.3}/multiclass_interface/multiprocess_interface.py +0 -0
  18. {multiclass_interface-1.2 → multiclass_interface-1.3}/multiclass_interface/tests/__init__.py +0 -0
  19. {multiclass_interface-1.2 → multiclass_interface-1.3}/multiclass_interface/tests/my_test_cls.py +0 -0
  20. {multiclass_interface-1.2 → multiclass_interface-1.3}/multiclass_interface/tests/test_multiclass_list.py +0 -0
  21. {multiclass_interface-1.2 → multiclass_interface-1.3}/multiclass_interface/tests/test_multiprocessinterface.py +0 -0
  22. {multiclass_interface-1.2 → multiclass_interface-1.3}/pyproject.toml +0 -0
  23. {multiclass_interface-1.2 → multiclass_interface-1.3}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: Multiclass_interface
3
- Version: 1.2
3
+ Version: 1.3
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,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: Multiclass_interface
3
- Version: 1.2
3
+ Version: 1.3
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
@@ -35,6 +35,7 @@ MPIClassInterfaceAttributes = {
35
35
 
36
36
  LOOP_UNTIL_CLOSE = True
37
37
  TERMINATE_ON_CLOSE = True
38
+ COLLECTIVE_MPI = True
38
39
 
39
40
 
40
41
  class MPIClassInterface():
@@ -53,10 +54,9 @@ class MPIClassInterface():
53
54
  self.object = Dummy()
54
55
  self.closed = False
55
56
 
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:
57
+ self.use_rank = np.array([True] * size)
58
+ self.use_rank[len(args_lst):] = False
59
+ if rank > 0 and COLLECTIVE_MPI and LOOP_UNTIL_CLOSE:
60
60
  self.work_loop()
61
61
 
62
62
  def __enter__(self):
@@ -133,13 +133,18 @@ class MPIClassInterface():
133
133
  def __getattribute__(self, name):
134
134
  if name in MPIClassInterfaceAttributes:
135
135
  return object.__getattribute__(self, name)
136
- elif rank > 0:
136
+ elif COLLECTIVE_MPI and rank > 0:
137
137
  self.work_loop()
138
138
  return lambda *args, **kwargs: 1
139
+ elif not self.use_rank[rank]:
140
+ raise ChildProcessError('MPI worker not used')
139
141
 
140
142
  def wrap(*args, **kwargs):
141
- inp = [self.get_input(name, i, args, kwargs) for i in range(size)]
142
- return self.run_task(inp)
143
+ if COLLECTIVE_MPI:
144
+ inp = [self.get_input(name, i, args, kwargs) for i in range(size)]
145
+ return self.run_task(inp)
146
+ else:
147
+ return self.do_task(name, args, kwargs)
143
148
 
144
149
  if hasattr(getattr(self.object, name), '__call__'):
145
150
  return wrap
@@ -162,11 +167,14 @@ class MPIClassInterface():
162
167
 
163
168
  def close(self):
164
169
  if not self.closed:
165
- if rank == 0:
166
- res = self.run_task([('close', [], {}) for _ in range(size)])
170
+ if COLLECTIVE_MPI:
171
+ if rank == 0:
172
+ res = self.run_task([('close', [], {}) for _ in range(size)])
173
+ else:
174
+ self.work_loop()
175
+ res = None
167
176
  else:
168
- self.work_loop()
169
- res = None
177
+ res = self.do_task('close', [], {})
170
178
  self.closed = True
171
179
 
172
180
 
@@ -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.3'
16
+ __version_tuple__ = version_tuple = (1, 3)
@@ -1,3 +1,12 @@
1
+ # Sequence diagrams
2
+ - [ThreadClass](#threadclass)
3
+ - [ProcessClass](#processclass)
4
+ - [MultiThreadClassInterface](#multithreadclassinterface)
5
+ - [MultiProcessClassInterface](#multiprocessclassinterface)
6
+ - [MPIClassInterface](#mpiclassinterface)
7
+ - [MPIClassInterface(LOOP_UNTIL_CLOSE=False)](#mpiclassinterfaceloop_until_closefalse)
8
+ - [MPIClassInterface(COLLECTIVE_MPI=False)](#mpiclassinterfacecollective_mpifalse)
9
+
1
10
  ## ThreadClass
2
11
  ```mermaid
3
12
  sequenceDiagram
@@ -42,7 +51,7 @@ This means:
42
51
  - Libraries (dll/so) will have their own memory space (important if multiple instances are launched)
43
52
  - Multiple processes allows parallel execution
44
53
 
45
- ## MultiProcessClassInterface
54
+ ## MultiThreadClassInterface
46
55
 
47
56
  ```mermaid
48
57
  sequenceDiagram
@@ -166,7 +175,7 @@ sequenceDiagram
166
175
  MPI2->>-MPI2:
167
176
  ```
168
177
 
169
- ## MPIClassInterface
178
+ ## MPIClassInterface(LOOP_UNTIL_CLOSE=False)
170
179
 
171
180
  Setting `mpi_interface.LOOP_UNTIL_CLOSE=False` results in the following workflow
172
181
 
@@ -226,3 +235,41 @@ sequenceDiagram
226
235
  ```
227
236
 
228
237
 
238
+ ## MPIClassInterface(COLLECTIVE_MPI=False)
239
+ Setting `mpi_interface.COLLECTIVE_MPI=False` results in the following workflow
240
+
241
+ ```mermaid
242
+ sequenceDiagram
243
+
244
+ participant MPI0 as MPI,rank0<br>MPIClassInterface
245
+
246
+
247
+ MPI0->>+MPI0: cls=A, [(args0),(args1)]
248
+
249
+
250
+ create participant A0
251
+ MPI0->>+A0: args0
252
+
253
+ participant MPI1 as MPI,rank1<br>MPIClassInterface
254
+ MPI1->>+MPI1: cls=A, [(args0),(args1)]
255
+ create participant A1
256
+ MPI1->>A1: args1
257
+ participant MPI2 as MPI,rank2<br>MPIClassInterface
258
+ MPI2->>MPI2: cls=A, [(args0),(args1)]
259
+
260
+ MPI0->>+MPI0:~a.f([args0,args1])
261
+ MPI1->>+MPI1:~a.f([args0,args1])
262
+ MPI2->>+MPI2:~a.f([args0,args1])
263
+
264
+
265
+ MPI0->>+A0: f(args0)
266
+ MPI1->>+A1: f(args1)
267
+ MPI2->>-MPI2: ChildProcessError
268
+ A0->>-MPI0: res0
269
+ A1->>-MPI1: res1
270
+
271
+ MPI0->>-MPI0: res0
272
+ MPI1->>-MPI1: res1
273
+
274
+ ```
275
+