9
9
# Import packages
10
10
from multiprocessing import Process , Pool , cpu_count , pool
11
11
from traceback import format_exception
12
+ import os
12
13
import sys
13
14
14
15
import numpy as np
15
16
from copy import deepcopy
16
17
from ..engine import MapNode
17
18
from ...utils .misc import str2bool
18
- import psutil
19
19
from ... import logging
20
20
import semaphore_singleton
21
21
from .base import (DistributedPluginBase , report_crash )
@@ -78,6 +78,34 @@ def release_lock(args):
78
78
semaphore_singleton .semaphore .release ()
79
79
80
80
81
+ # Get total system RAM
82
+ def get_system_total_memory_gb ():
83
+ """Function to get the total RAM of the running system in GB
84
+ """
85
+
86
+ # Import packages
87
+ import os
88
+ import sys
89
+
90
+ # Get memory
91
+ if 'linux' in sys .platform :
92
+ with open ('/proc/meminfo' , 'r' ) as f_in :
93
+ meminfo_lines = f_in .readlines ()
94
+ mem_total_line = [line for line in meminfo_lines \
95
+ if 'MemTotal' in line ][0 ]
96
+ mem_total = float (mem_total_line .split ()[1 ])
97
+ memory_gb = mem_total / (1024.0 ** 2 )
98
+ elif 'darwin' in sys .platform :
99
+ mem_str = os .popen ('sysctl hw.memsize' ).read ().strip ().split (' ' )[- 1 ]
100
+ memory_gb = float (mem_str )/ (1024.0 ** 3 )
101
+ else :
102
+ err_msg = 'System platform: %s is not supported'
103
+ raise Exception (err_msg )
104
+
105
+ # Return memory
106
+ return memory_gb
107
+
108
+
81
109
class MultiProcPlugin (DistributedPluginBase ):
82
110
"""Execute workflow with multiprocessing, not sending more jobs at once
83
111
than the system can support.
@@ -102,22 +130,24 @@ class MultiProcPlugin(DistributedPluginBase):
102
130
"""
103
131
104
132
def __init__ (self , plugin_args = None ):
133
+ # Init variables and instance attributes
105
134
super (MultiProcPlugin , self ).__init__ (plugin_args = plugin_args )
106
135
self ._taskresult = {}
107
136
self ._taskid = 0
108
137
non_daemon = True
109
138
self .plugin_args = plugin_args
110
139
self .processors = cpu_count ()
111
- memory = psutil .virtual_memory ()
112
- self .memory = float (memory .total ) / (1024.0 ** 3 )
140
+ self .memory_gb = get_system_total_memory_gb ()
141
+
142
+ # Check plugin args
113
143
if self .plugin_args :
114
144
if 'non_daemon' in self .plugin_args :
115
145
non_daemon = plugin_args ['non_daemon' ]
116
146
if 'n_procs' in self .plugin_args :
117
147
self .processors = self .plugin_args ['n_procs' ]
118
148
if 'memory' in self .plugin_args :
119
149
self .memory = self .plugin_args ['memory' ]
120
-
150
+ # Instantiate different thread pools for non-daemon processes
121
151
if non_daemon :
122
152
# run the execution using the non-daemon pool subclass
123
153
self .pool = NonDaemonPool (processes = self .processors )
@@ -172,40 +202,39 @@ def _send_procs_to_workers(self, updatehash=False, graph=None):
172
202
jobids = np .flatnonzero ((self .proc_pending == True ) & \
173
203
(self .depidx .sum (axis = 0 ) == 0 ).__array__ ())
174
204
175
- #check available system resources by summing all threads and memory used
176
- busy_memory = 0
205
+ # Check available system resources by summing all threads and memory used
206
+ busy_memory_gb = 0
177
207
busy_processors = 0
178
208
for jobid in jobids :
179
- busy_memory += self .procs [jobid ]._interface .estimated_memory_gb
209
+ busy_memory_gb += self .procs [jobid ]._interface .estimated_memory_gb
180
210
busy_processors += self .procs [jobid ]._interface .num_threads
181
211
182
- free_memory = self .memory - busy_memory
212
+ free_memory_gb = self .memory_gb - busy_memory_gb
183
213
free_processors = self .processors - busy_processors
184
214
185
215
186
- #check all jobs without dependency not run
216
+ # Check all jobs without dependency not run
187
217
jobids = np .flatnonzero ((self .proc_done == False ) & \
188
218
(self .depidx .sum (axis = 0 ) == 0 ).__array__ ())
189
219
190
220
191
- #sort jobs ready to run first by memory and then by number of threads
192
- #The most resource consuming jobs run first
221
+ # Sort jobs ready to run first by memory and then by number of threads
222
+ # The most resource consuming jobs run first
193
223
jobids = sorted (jobids ,
194
224
key = lambda item : (self .procs [item ]._interface .estimated_memory_gb ,
195
225
self .procs [item ]._interface .num_threads ))
196
226
197
227
logger .debug ('Free memory (GB): %d, Free processors: %d' ,
198
- free_memory , free_processors )
199
-
228
+ free_memory_gb , free_processors )
200
229
201
- #while have enough memory and processors for first job
202
- #submit first job on the list
230
+ # While have enough memory and processors for first job
231
+ # Submit first job on the list
203
232
for jobid in jobids :
204
233
logger .debug ('Next Job: %d, memory (GB): %d, threads: %d' \
205
234
% (jobid , self .procs [jobid ]._interface .estimated_memory_gb ,
206
235
self .procs [jobid ]._interface .num_threads ))
207
236
208
- if self .procs [jobid ]._interface .estimated_memory_gb <= free_memory and \
237
+ if self .procs [jobid ]._interface .estimated_memory_gb <= free_memory_gb and \
209
238
self .procs [jobid ]._interface .num_threads <= free_processors :
210
239
logger .info ('Executing: %s ID: %d' % (self .procs [jobid ]._id , jobid ))
211
240
executing_now .append (self .procs [jobid ])
@@ -226,7 +255,7 @@ def _send_procs_to_workers(self, updatehash=False, graph=None):
226
255
self .proc_done [jobid ] = True
227
256
self .proc_pending [jobid ] = True
228
257
229
- free_memory -= self .procs [jobid ]._interface .estimated_memory_gb
258
+ free_memory_gb -= self .procs [jobid ]._interface .estimated_memory_gb
230
259
free_processors -= self .procs [jobid ]._interface .num_threads
231
260
232
261
# Send job to task manager and add to pending tasks
0 commit comments