Multiclass-interface 1.1__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.
- {Multiclass_interface-1.1 → multiclass_interface-1.3}/.gitlab-ci.yml +0 -1
- {Multiclass_interface-1.1 → multiclass_interface-1.3/Multiclass_interface.egg-info}/PKG-INFO +1 -1
- {Multiclass_interface-1.1 → multiclass_interface-1.3}/Multiclass_interface.egg-info/SOURCES.txt +1 -0
- {Multiclass_interface-1.1/Multiclass_interface.egg-info → multiclass_interface-1.3}/PKG-INFO +1 -1
- {Multiclass_interface-1.1 → multiclass_interface-1.3}/multiclass_interface/mpi_interface.py +29 -24
- {Multiclass_interface-1.1 → multiclass_interface-1.3}/multiclass_interface/tests/test_mpi.py +24 -6
- {Multiclass_interface-1.1 → multiclass_interface-1.3}/multiclass_interface/version.py +2 -2
- multiclass_interface-1.3/sequence_diagrams.md +275 -0
- {Multiclass_interface-1.1 → multiclass_interface-1.3}/.gitignore +0 -0
- {Multiclass_interface-1.1 → multiclass_interface-1.3}/LICENSE +0 -0
- {Multiclass_interface-1.1 → multiclass_interface-1.3}/Multiclass_interface.egg-info/dependency_links.txt +0 -0
- {Multiclass_interface-1.1 → multiclass_interface-1.3}/Multiclass_interface.egg-info/requires.txt +0 -0
- {Multiclass_interface-1.1 → multiclass_interface-1.3}/Multiclass_interface.egg-info/top_level.txt +0 -0
- {Multiclass_interface-1.1 → multiclass_interface-1.3}/README.md +0 -0
- {Multiclass_interface-1.1 → multiclass_interface-1.3}/multiclass_interface/__init__.py +0 -0
- {Multiclass_interface-1.1 → multiclass_interface-1.3}/multiclass_interface/multi_object_list.py +0 -0
- {Multiclass_interface-1.1 → multiclass_interface-1.3}/multiclass_interface/multiprocess_interface.py +0 -0
- {Multiclass_interface-1.1 → multiclass_interface-1.3}/multiclass_interface/tests/__init__.py +0 -0
- {Multiclass_interface-1.1 → multiclass_interface-1.3}/multiclass_interface/tests/my_test_cls.py +0 -0
- {Multiclass_interface-1.1 → multiclass_interface-1.3}/multiclass_interface/tests/test_multiclass_list.py +0 -0
- {Multiclass_interface-1.1 → multiclass_interface-1.3}/multiclass_interface/tests/test_multiprocessinterface.py +0 -0
- {Multiclass_interface-1.1 → multiclass_interface-1.3}/pyproject.toml +0 -0
- {Multiclass_interface-1.1 → multiclass_interface-1.3}/setup.cfg +0 -0
|
@@ -13,7 +13,6 @@ test_ubuntu: # name the job what we like
|
|
|
13
13
|
script:
|
|
14
14
|
- pip install -e .[test]
|
|
15
15
|
- pytest --cov-report term-missing:skip-covered --cov=multiclass_interface multiclass_interface/tests
|
|
16
|
-
- pytest --cov-report term-missing:skip-covered --cov=multiclass_interface multiclass_interface/tests
|
|
17
16
|
coverage: '/(?i)total.*? (100(?:\.0+)?\%|[1-9]?\d(?:\.\d+)?\%)$/'
|
|
18
17
|
tags: # only runners with this tag can do the job [3]
|
|
19
18
|
- ci-ubuntu
|
|
@@ -1,27 +1,24 @@
|
|
|
1
1
|
import numpy as np
|
|
2
2
|
import sys
|
|
3
|
-
import os
|
|
4
|
-
import subprocess
|
|
5
3
|
import traceback
|
|
6
4
|
import inspect
|
|
7
|
-
from enum import Enum
|
|
8
5
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
mpi = subprocess.run("python -c 'from mpi4py import MPI'", shell=True,
|
|
15
|
-
check=False, stderr=subprocess.PIPE).returncode == 0
|
|
6
|
+
comm = None
|
|
7
|
+
size = 1
|
|
8
|
+
rank = 0
|
|
9
|
+
name = ""
|
|
10
|
+
main = True
|
|
16
11
|
|
|
17
|
-
|
|
12
|
+
|
|
13
|
+
def activate_mpi():
|
|
14
|
+
global comm, size, rank, name, main
|
|
18
15
|
from mpi4py import MPI
|
|
19
16
|
comm = MPI.COMM_WORLD
|
|
20
17
|
size = MPI.COMM_WORLD.Get_size()
|
|
21
18
|
rank = MPI.COMM_WORLD.Get_rank()
|
|
22
19
|
name = MPI.Get_processor_name()
|
|
23
|
-
|
|
24
|
-
|
|
20
|
+
main = rank == 0
|
|
21
|
+
|
|
25
22
|
|
|
26
23
|
MPIClassInterfaceAttributes = {
|
|
27
24
|
'close',
|
|
@@ -38,6 +35,7 @@ MPIClassInterfaceAttributes = {
|
|
|
38
35
|
|
|
39
36
|
LOOP_UNTIL_CLOSE = True
|
|
40
37
|
TERMINATE_ON_CLOSE = True
|
|
38
|
+
COLLECTIVE_MPI = True
|
|
41
39
|
|
|
42
40
|
|
|
43
41
|
class MPIClassInterface():
|
|
@@ -56,10 +54,9 @@ class MPIClassInterface():
|
|
|
56
54
|
self.object = Dummy()
|
|
57
55
|
self.closed = False
|
|
58
56
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
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:
|
|
63
60
|
self.work_loop()
|
|
64
61
|
|
|
65
62
|
def __enter__(self):
|
|
@@ -136,13 +133,18 @@ class MPIClassInterface():
|
|
|
136
133
|
def __getattribute__(self, name):
|
|
137
134
|
if name in MPIClassInterfaceAttributes:
|
|
138
135
|
return object.__getattribute__(self, name)
|
|
139
|
-
elif rank > 0:
|
|
136
|
+
elif COLLECTIVE_MPI and rank > 0:
|
|
140
137
|
self.work_loop()
|
|
141
138
|
return lambda *args, **kwargs: 1
|
|
139
|
+
elif not self.use_rank[rank]:
|
|
140
|
+
raise ChildProcessError('MPI worker not used')
|
|
142
141
|
|
|
143
142
|
def wrap(*args, **kwargs):
|
|
144
|
-
|
|
145
|
-
|
|
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)
|
|
146
148
|
|
|
147
149
|
if hasattr(getattr(self.object, name), '__call__'):
|
|
148
150
|
return wrap
|
|
@@ -165,11 +167,14 @@ class MPIClassInterface():
|
|
|
165
167
|
|
|
166
168
|
def close(self):
|
|
167
169
|
if not self.closed:
|
|
168
|
-
if
|
|
169
|
-
|
|
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
|
|
170
176
|
else:
|
|
171
|
-
self.
|
|
172
|
-
res = None
|
|
177
|
+
res = self.do_task('close', [], {})
|
|
173
178
|
self.closed = True
|
|
174
179
|
|
|
175
180
|
|
{Multiclass_interface-1.1 → multiclass_interface-1.3}/multiclass_interface/tests/test_mpi.py
RENAMED
|
@@ -42,13 +42,30 @@ 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():
|
|
65
|
+
mpi_interface.activate_mpi()
|
|
66
|
+
|
|
49
67
|
mpi_interface.exit_mpi_on_close = False
|
|
50
|
-
|
|
51
|
-
rank = MPI.COMM_WORLD.Get_rank()
|
|
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
|
|
53
70
|
mpi_interface.TERMINATE_ON_CLOSE = False
|
|
54
71
|
|
|
@@ -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
|
-
|
|
89
|
+
|
|
73
90
|
run(f, mpici)
|
|
74
91
|
|
|
75
92
|
except ChildProcessError:
|
|
76
93
|
pass
|
|
77
|
-
|
|
94
|
+
|
|
95
|
+
run(mpitest_non_collective_mpi)
|
|
78
96
|
|
|
79
97
|
print(f"Rank {rank} Done test_all")
|
|
@@ -0,0 +1,275 @@
|
|
|
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
|
+
|
|
10
|
+
## ThreadClass
|
|
11
|
+
```mermaid
|
|
12
|
+
sequenceDiagram
|
|
13
|
+
participant U as Main
|
|
14
|
+
participant TC as ThreadClass
|
|
15
|
+
|
|
16
|
+
U->>+TC: cls=A
|
|
17
|
+
|
|
18
|
+
create participant Q as IOQueue
|
|
19
|
+
TC->>Q:
|
|
20
|
+
TC->>-U: ~A
|
|
21
|
+
U->>+TC: ~A(*args,**kwargs)
|
|
22
|
+
create participant T as Thread
|
|
23
|
+
TC->>T: A, IOQueue, args, kwargs
|
|
24
|
+
create participant A
|
|
25
|
+
T->>A: __init__(*args, **kwargs)
|
|
26
|
+
T->>+T: Run()
|
|
27
|
+
T->>+Q: get()
|
|
28
|
+
TC->>-U: ~a
|
|
29
|
+
U->>+TC: ~a.f(*args,**kwargs)
|
|
30
|
+
TC->>Q: put(f,args,kwargs)
|
|
31
|
+
|
|
32
|
+
Q->>-T: f,args,kwargs
|
|
33
|
+
T->>+A: f(*args, **kwargs)
|
|
34
|
+
A->>-T: res
|
|
35
|
+
TC->>+Q: get()
|
|
36
|
+
T->>Q: put(res)
|
|
37
|
+
Q->>-TC: res
|
|
38
|
+
TC->>-U: res
|
|
39
|
+
TC->>T: close()
|
|
40
|
+
T->>-T:
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## ProcessClass
|
|
46
|
+
|
|
47
|
+
The `ProcessClass` is similar to the `ThreadClas` except that it uses a seprate Process instead of a Thread.
|
|
48
|
+
This means:
|
|
49
|
+
- More time used to spawn process
|
|
50
|
+
- Changes to `os.environ['LD_LIBRARY_PATH']` are effective in the process
|
|
51
|
+
- Libraries (dll/so) will have their own memory space (important if multiple instances are launched)
|
|
52
|
+
- Multiple processes allows parallel execution
|
|
53
|
+
|
|
54
|
+
## MultiThreadClassInterface
|
|
55
|
+
|
|
56
|
+
```mermaid
|
|
57
|
+
sequenceDiagram
|
|
58
|
+
participant U as Main
|
|
59
|
+
participant TC as MultiThreadClassInterface
|
|
60
|
+
|
|
61
|
+
U->>+TC: cls=A, [args1,args2])
|
|
62
|
+
|
|
63
|
+
create participant Q1 as IOQueue1
|
|
64
|
+
TC->>Q1:
|
|
65
|
+
create participant T1 as Thread1
|
|
66
|
+
TC->>T1: A, IOQueue1, args1
|
|
67
|
+
create participant A1
|
|
68
|
+
T1->>A1: __init__(*args1)
|
|
69
|
+
T1->>+T1: Run()
|
|
70
|
+
T1->>+Q1: get()
|
|
71
|
+
|
|
72
|
+
create participant Q2 as IOQueue2
|
|
73
|
+
TC->>Q2:
|
|
74
|
+
create participant T2 as Thread2
|
|
75
|
+
TC->>T2: A, IOQueue2, args2
|
|
76
|
+
create participant A2
|
|
77
|
+
T2->>A2: __init__(*args2)
|
|
78
|
+
T2->>+T2: Run()
|
|
79
|
+
T2->>+Q2: get()
|
|
80
|
+
|
|
81
|
+
TC->>-U: ~a
|
|
82
|
+
U->>+TC: ~a.f(*args,**kwargs)
|
|
83
|
+
TC->>Q1: put(f,args,kwargs)
|
|
84
|
+
TC->>Q2: put(f,args,kwargs)
|
|
85
|
+
|
|
86
|
+
Q1->>-T1: f,args,kwargs
|
|
87
|
+
Q2->>-T2: f,args,kwargs
|
|
88
|
+
T1->>+A1: f(*args, **kwargs)
|
|
89
|
+
T2->>+A2: f(*args, **kwargs)
|
|
90
|
+
A1->>-T1: res1
|
|
91
|
+
A2->>-T2: res2
|
|
92
|
+
TC->>+Q1: get()
|
|
93
|
+
T1->>Q1: put(res)
|
|
94
|
+
T2->>Q2: put(res)
|
|
95
|
+
Q1->>-TC: res1
|
|
96
|
+
TC->>+Q2: get()
|
|
97
|
+
Q2->>-TC: res2
|
|
98
|
+
TC->>-U: [res1,res2]
|
|
99
|
+
|
|
100
|
+
TC->>T1: close()
|
|
101
|
+
T1->>-T1:
|
|
102
|
+
TC->>T2: close()
|
|
103
|
+
T2->>-T2:
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
## MultiProcessClassInterface
|
|
108
|
+
|
|
109
|
+
The `MultiProcessClassInterface` is similar to the `MultiThreadClassInterfaces` except that it uses a seprate processes instead of a threads.
|
|
110
|
+
This means:
|
|
111
|
+
- More time used to spawn processes
|
|
112
|
+
- Changes to `os.environ['LD_LIBRARY_PATH']` are effective in the processes
|
|
113
|
+
- Libraries (dll/so) executed in the processes will their own individual memory space (changes to a variable in one dll does not affect the others)
|
|
114
|
+
- Parallel execution of class functions
|
|
115
|
+
|
|
116
|
+
## MPIClassInterface
|
|
117
|
+
```mermaid
|
|
118
|
+
sequenceDiagram
|
|
119
|
+
actor U as User
|
|
120
|
+
|
|
121
|
+
participant MPI0 as MPI,rank0<br>MPIClassInterface
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
MPI0->>+MPI0: cls=A, [(args0),(args1)]
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
create participant A0
|
|
128
|
+
MPI0->>+A0: args0
|
|
129
|
+
MPI0->>-U: ~a
|
|
130
|
+
participant MPI1 as MPI,rank1<br>MPIClassInterface
|
|
131
|
+
MPI1->>+MPI1: cls=A, [(args0),(args1)]
|
|
132
|
+
create participant A1
|
|
133
|
+
MPI1->>A1: args1
|
|
134
|
+
participant MPI2 as MPI,rank2<br>MPIClassInterface
|
|
135
|
+
MPI2->>MPI2: cls=A, [(args0),(args1)]
|
|
136
|
+
MPI1->>-U:
|
|
137
|
+
MPI2->>U:
|
|
138
|
+
|
|
139
|
+
U->>+MPI0:~a.f([args0,args1])
|
|
140
|
+
MPI0->>+MPI0: run_task()
|
|
141
|
+
MPI1->>+MPI1: work_loop
|
|
142
|
+
MPI2->>+MPI2: work_loop
|
|
143
|
+
|
|
144
|
+
rect rgb(191, 223, 255)
|
|
145
|
+
note right of MPI0: Scatter
|
|
146
|
+
MPI0->>MPI0: f,args0
|
|
147
|
+
MPI0->>MPI1: f,args1
|
|
148
|
+
MPI0->>MPI2: "skip",[]
|
|
149
|
+
end
|
|
150
|
+
MPI0->>+A0: f(args0)
|
|
151
|
+
MPI1->>+A1: f(args1)
|
|
152
|
+
A0->>-MPI0: res0
|
|
153
|
+
A1->>-MPI1: res1
|
|
154
|
+
|
|
155
|
+
rect rgb(191, 223, 255)
|
|
156
|
+
note right of MPI0: Gather
|
|
157
|
+
MPI0->>MPI0: res0
|
|
158
|
+
MPI1->>MPI0: res1
|
|
159
|
+
MPI2->>MPI0: None
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
MPI0->>-U: [res1,res2]
|
|
164
|
+
|
|
165
|
+
U->>+MPI0:~a.close()
|
|
166
|
+
MPI0->>+MPI0: run_task()
|
|
167
|
+
rect rgb(191, 223, 255)
|
|
168
|
+
note right of MPI0: Scatter
|
|
169
|
+
MPI0->>MPI0: close
|
|
170
|
+
MPI0->>MPI1: close
|
|
171
|
+
MPI0->>MPI2: close
|
|
172
|
+
end
|
|
173
|
+
MPI0->>-MPI0:
|
|
174
|
+
MPI1->>-MPI1:
|
|
175
|
+
MPI2->>-MPI2:
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
## MPIClassInterface(LOOP_UNTIL_CLOSE=False)
|
|
179
|
+
|
|
180
|
+
Setting `mpi_interface.LOOP_UNTIL_CLOSE=False` results in the following workflow
|
|
181
|
+
|
|
182
|
+
```mermaid
|
|
183
|
+
sequenceDiagram
|
|
184
|
+
actor U as User
|
|
185
|
+
|
|
186
|
+
participant MPI0 as MPI,rank0<br>MPIClassInterface
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
MPI0->>+MPI0: cls=A, [(args0),(args1)]
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
create participant A0
|
|
193
|
+
MPI0->>+A0: args0
|
|
194
|
+
MPI0->>-U: ~a
|
|
195
|
+
participant MPI1 as MPI,rank1<br>MPIClassInterface
|
|
196
|
+
MPI1->>+MPI1: cls=A, [(args0),(args1)]
|
|
197
|
+
create participant A1
|
|
198
|
+
MPI1->>A1: args1
|
|
199
|
+
participant MPI2 as MPI,rank2<br>MPIClassInterface
|
|
200
|
+
MPI2->>MPI2: cls=A, [(args0),(args1)]
|
|
201
|
+
MPI1->>-U:
|
|
202
|
+
MPI2->>U:
|
|
203
|
+
|
|
204
|
+
U->>+MPI0:~a.f([args0,args1])
|
|
205
|
+
MPI0->>+MPI0: run_task()
|
|
206
|
+
MPI1->>+MPI1: work_loop
|
|
207
|
+
MPI2->>+MPI2: work_loop
|
|
208
|
+
MPI2->>-MPI2:
|
|
209
|
+
MPI2->>U:
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
rect rgb(191, 223, 255)
|
|
213
|
+
note right of MPI0: Scatter
|
|
214
|
+
MPI0->>MPI0: f,args0
|
|
215
|
+
MPI0->>MPI1: f,args1
|
|
216
|
+
MPI0->>MPI2: "skip",[]
|
|
217
|
+
end
|
|
218
|
+
MPI0->>+A0: f(args0)
|
|
219
|
+
MPI1->>+A1: f(args1)
|
|
220
|
+
A0->>-MPI0: res0
|
|
221
|
+
A1->>-MPI1: res1
|
|
222
|
+
MPI1->>-MPI1:
|
|
223
|
+
MPI1->>U:
|
|
224
|
+
|
|
225
|
+
rect rgb(191, 223, 255)
|
|
226
|
+
note right of MPI0: Gather
|
|
227
|
+
MPI0->>MPI0: res0
|
|
228
|
+
MPI1->>MPI0: res1
|
|
229
|
+
MPI2->>MPI0: None
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
MPI0->>-U: [res1,res2]
|
|
234
|
+
|
|
235
|
+
```
|
|
236
|
+
|
|
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
|
+
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{Multiclass_interface-1.1 → multiclass_interface-1.3}/Multiclass_interface.egg-info/requires.txt
RENAMED
|
File without changes
|
{Multiclass_interface-1.1 → multiclass_interface-1.3}/Multiclass_interface.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{Multiclass_interface-1.1 → multiclass_interface-1.3}/multiclass_interface/multi_object_list.py
RENAMED
|
File without changes
|
{Multiclass_interface-1.1 → multiclass_interface-1.3}/multiclass_interface/multiprocess_interface.py
RENAMED
|
File without changes
|
{Multiclass_interface-1.1 → multiclass_interface-1.3}/multiclass_interface/tests/__init__.py
RENAMED
|
File without changes
|
{Multiclass_interface-1.1 → multiclass_interface-1.3}/multiclass_interface/tests/my_test_cls.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|