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.
- {Multiclass_interface-1.2.dist-info → Multiclass_interface-1.4.dist-info}/METADATA +1 -1
- {Multiclass_interface-1.2.dist-info → Multiclass_interface-1.4.dist-info}/RECORD +8 -8
- multiclass_interface/mpi_interface.py +28 -17
- multiclass_interface/tests/test_mpi.py +22 -4
- multiclass_interface/version.py +2 -2
- {Multiclass_interface-1.2.dist-info → Multiclass_interface-1.4.dist-info}/LICENSE +0 -0
- {Multiclass_interface-1.2.dist-info → Multiclass_interface-1.4.dist-info}/WHEEL +0 -0
- {Multiclass_interface-1.2.dist-info → Multiclass_interface-1.4.dist-info}/top_level.txt +0 -0
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
multiclass_interface/__init__.py,sha256=1kI9Vxsap_8eap6kldNHhIWLEVBT2DLWl2UbTOTnVN0,114
|
|
2
|
-
multiclass_interface/mpi_interface.py,sha256=
|
|
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=
|
|
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=
|
|
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.
|
|
12
|
-
Multiclass_interface-1.
|
|
13
|
-
Multiclass_interface-1.
|
|
14
|
-
Multiclass_interface-1.
|
|
15
|
-
Multiclass_interface-1.
|
|
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
|
-
|
|
10
|
+
mpi = False
|
|
11
11
|
|
|
12
12
|
|
|
13
|
-
def activate_mpi():
|
|
14
|
-
global comm, size, rank, name,
|
|
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
|
-
|
|
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
|
-
|
|
57
|
-
|
|
58
|
-
|
|
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
|
-
|
|
142
|
-
|
|
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
|
|
166
|
-
|
|
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.
|
|
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
|
-
|
|
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")
|
multiclass_interface/version.py
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|