idmtools 0.0.0.dev0__py3-none-any.whl → 0.0.2__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.
- idmtools/__init__.py +27 -8
- idmtools/analysis/__init__.py +5 -0
- idmtools/analysis/add_analyzer.py +89 -0
- idmtools/analysis/analyze_manager.py +490 -0
- idmtools/analysis/csv_analyzer.py +103 -0
- idmtools/analysis/download_analyzer.py +96 -0
- idmtools/analysis/map_worker_entry.py +100 -0
- idmtools/analysis/platform_analysis_bootstrap.py +94 -0
- idmtools/analysis/platform_anaylsis.py +291 -0
- idmtools/analysis/tags_analyzer.py +93 -0
- idmtools/assets/__init__.py +9 -0
- idmtools/assets/asset.py +453 -0
- idmtools/assets/asset_collection.py +514 -0
- idmtools/assets/content_handlers.py +19 -0
- idmtools/assets/errors.py +23 -0
- idmtools/assets/file_list.py +191 -0
- idmtools/builders/__init__.py +11 -0
- idmtools/builders/arm_simulation_builder.py +152 -0
- idmtools/builders/csv_simulation_builder.py +76 -0
- idmtools/builders/simulation_builder.py +348 -0
- idmtools/builders/sweep_arm.py +109 -0
- idmtools/builders/yaml_simulation_builder.py +82 -0
- idmtools/config/__init__.py +7 -0
- idmtools/config/idm_config_parser.py +486 -0
- idmtools/core/__init__.py +10 -0
- idmtools/core/cache_enabled.py +114 -0
- idmtools/core/context.py +68 -0
- idmtools/core/docker_task.py +207 -0
- idmtools/core/enums.py +51 -0
- idmtools/core/exceptions.py +91 -0
- idmtools/core/experiment_factory.py +71 -0
- idmtools/core/id_file.py +70 -0
- idmtools/core/interfaces/__init__.py +5 -0
- idmtools/core/interfaces/entity_container.py +64 -0
- idmtools/core/interfaces/iassets_enabled.py +58 -0
- idmtools/core/interfaces/ientity.py +331 -0
- idmtools/core/interfaces/iitem.py +206 -0
- idmtools/core/interfaces/imetadata_operations.py +89 -0
- idmtools/core/interfaces/inamed_entity.py +17 -0
- idmtools/core/interfaces/irunnable_entity.py +159 -0
- idmtools/core/logging.py +387 -0
- idmtools/core/platform_factory.py +316 -0
- idmtools/core/system_information.py +104 -0
- idmtools/core/task_factory.py +145 -0
- idmtools/entities/__init__.py +10 -0
- idmtools/entities/command_line.py +229 -0
- idmtools/entities/command_task.py +155 -0
- idmtools/entities/experiment.py +787 -0
- idmtools/entities/generic_workitem.py +43 -0
- idmtools/entities/ianalyzer.py +163 -0
- idmtools/entities/iplatform.py +1106 -0
- idmtools/entities/iplatform_default.py +39 -0
- idmtools/entities/iplatform_ops/__init__.py +5 -0
- idmtools/entities/iplatform_ops/iplatform_asset_collection_operations.py +148 -0
- idmtools/entities/iplatform_ops/iplatform_experiment_operations.py +415 -0
- idmtools/entities/iplatform_ops/iplatform_simulation_operations.py +315 -0
- idmtools/entities/iplatform_ops/iplatform_suite_operations.py +322 -0
- idmtools/entities/iplatform_ops/iplatform_workflowitem_operations.py +301 -0
- idmtools/entities/iplatform_ops/utils.py +185 -0
- idmtools/entities/itask.py +316 -0
- idmtools/entities/iworkflow_item.py +167 -0
- idmtools/entities/platform_requirements.py +20 -0
- idmtools/entities/relation_type.py +14 -0
- idmtools/entities/simulation.py +255 -0
- idmtools/entities/suite.py +188 -0
- idmtools/entities/task_proxy.py +37 -0
- idmtools/entities/templated_simulation.py +325 -0
- idmtools/frozen/frozen_dict.py +71 -0
- idmtools/frozen/frozen_list.py +66 -0
- idmtools/frozen/frozen_set.py +86 -0
- idmtools/frozen/frozen_tuple.py +18 -0
- idmtools/frozen/frozen_utils.py +179 -0
- idmtools/frozen/ifrozen.py +66 -0
- idmtools/plugins/__init__.py +5 -0
- idmtools/plugins/git_commit.py +117 -0
- idmtools/registry/__init__.py +4 -0
- idmtools/registry/experiment_specification.py +105 -0
- idmtools/registry/functions.py +28 -0
- idmtools/registry/hook_specs.py +132 -0
- idmtools/registry/master_plugin_registry.py +51 -0
- idmtools/registry/platform_specification.py +138 -0
- idmtools/registry/plugin_specification.py +129 -0
- idmtools/registry/task_specification.py +104 -0
- idmtools/registry/utils.py +119 -0
- idmtools/services/__init__.py +5 -0
- idmtools/services/ipersistance_service.py +135 -0
- idmtools/services/platforms.py +13 -0
- idmtools/utils/__init__.py +5 -0
- idmtools/utils/caller.py +24 -0
- idmtools/utils/collections.py +246 -0
- idmtools/utils/command_line.py +45 -0
- idmtools/utils/decorators.py +300 -0
- idmtools/utils/display/__init__.py +22 -0
- idmtools/utils/display/displays.py +181 -0
- idmtools/utils/display/settings.py +25 -0
- idmtools/utils/dropbox_location.py +30 -0
- idmtools/utils/entities.py +127 -0
- idmtools/utils/file.py +72 -0
- idmtools/utils/file_parser.py +151 -0
- idmtools/utils/filter_simulations.py +182 -0
- idmtools/utils/filters/__init__.py +5 -0
- idmtools/utils/filters/asset_filters.py +88 -0
- idmtools/utils/general.py +286 -0
- idmtools/utils/gitrepo.py +336 -0
- idmtools/utils/hashing.py +239 -0
- idmtools/utils/info.py +124 -0
- idmtools/utils/json.py +82 -0
- idmtools/utils/language.py +107 -0
- idmtools/utils/local_os.py +40 -0
- idmtools/utils/time.py +22 -0
- idmtools-0.0.2.dist-info/METADATA +120 -0
- idmtools-0.0.2.dist-info/RECORD +116 -0
- idmtools-0.0.2.dist-info/entry_points.txt +9 -0
- idmtools-0.0.2.dist-info/licenses/LICENSE.TXT +3 -0
- idmtools-0.0.0.dev0.dist-info/METADATA +0 -41
- idmtools-0.0.0.dev0.dist-info/RECORD +0 -5
- {idmtools-0.0.0.dev0.dist-info → idmtools-0.0.2.dist-info}/WHEEL +0 -0
- {idmtools-0.0.0.dev0.dist-info → idmtools-0.0.2.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
"""
|
|
2
|
+
IPlatformWorkflowItemOperations defines workflow item operations interface.
|
|
3
|
+
|
|
4
|
+
Copyright 2021, Bill & Melinda Gates Foundation. All rights reserved.
|
|
5
|
+
"""
|
|
6
|
+
from abc import ABC, abstractmethod
|
|
7
|
+
from dataclasses import dataclass
|
|
8
|
+
from logging import DEBUG
|
|
9
|
+
from typing import Type, Any, List, Tuple, Dict, NoReturn, TYPE_CHECKING
|
|
10
|
+
from idmtools.assets import Asset
|
|
11
|
+
from idmtools.core import CacheEnabled, getLogger
|
|
12
|
+
from idmtools.entities.iplatform_ops.utils import batch_create_items
|
|
13
|
+
from idmtools.entities.iworkflow_item import IWorkflowItem
|
|
14
|
+
from idmtools.registry.functions import FunctionPluginManager
|
|
15
|
+
|
|
16
|
+
if TYPE_CHECKING: # pragma: no cover
|
|
17
|
+
from idmtools.entities.iplatform import IPlatform
|
|
18
|
+
|
|
19
|
+
logger = getLogger(__name__)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@dataclass
|
|
23
|
+
class IPlatformWorkflowItemOperations(CacheEnabled, ABC):
|
|
24
|
+
"""
|
|
25
|
+
IPlatformWorkflowItemOperations defines workflow item operations interface.
|
|
26
|
+
"""
|
|
27
|
+
platform: 'IPlatform' # noqa: F821
|
|
28
|
+
platform_type: Type
|
|
29
|
+
|
|
30
|
+
@abstractmethod
|
|
31
|
+
def get(self, workflow_item_id: str, **kwargs) -> Any:
|
|
32
|
+
"""
|
|
33
|
+
Returns the platform representation of an WorkflowItem.
|
|
34
|
+
|
|
35
|
+
Args:
|
|
36
|
+
workflow_item_id: Item id of WorkflowItems
|
|
37
|
+
**kwargs:
|
|
38
|
+
|
|
39
|
+
Returns:
|
|
40
|
+
Platform Representation of an workflow_item
|
|
41
|
+
"""
|
|
42
|
+
pass
|
|
43
|
+
|
|
44
|
+
def batch_create(self, workflow_items: List[IWorkflowItem], display_progress: bool = True, **kwargs) -> List[Any]:
|
|
45
|
+
"""
|
|
46
|
+
Provides a method to batch create workflow items.
|
|
47
|
+
|
|
48
|
+
Args:
|
|
49
|
+
workflow_items: List of worfklow items to create
|
|
50
|
+
display_progress: Whether to display progress bar
|
|
51
|
+
**kwargs:
|
|
52
|
+
|
|
53
|
+
Returns:
|
|
54
|
+
List of tuples containing the create object and id of item that was created.
|
|
55
|
+
"""
|
|
56
|
+
return batch_create_items(workflow_items, create_func=self.create, display_progress=display_progress,
|
|
57
|
+
progress_description="Creating WorkItems", unit="workitem", **kwargs)
|
|
58
|
+
|
|
59
|
+
def pre_create(self, workflow_item: IWorkflowItem, **kwargs) -> NoReturn:
|
|
60
|
+
"""
|
|
61
|
+
Run the platform/workflow item post creation events.
|
|
62
|
+
|
|
63
|
+
Args:
|
|
64
|
+
workflow_item: IWorkflowItem to run post-creation events
|
|
65
|
+
**kwargs: Optional arguments mainly for extensibility
|
|
66
|
+
|
|
67
|
+
Returns:
|
|
68
|
+
NoReturn
|
|
69
|
+
"""
|
|
70
|
+
if logger.isEnabledFor(DEBUG):
|
|
71
|
+
logger.debug("Calling idmtools_platform_pre_create_item")
|
|
72
|
+
FunctionPluginManager.instance().hook.idmtools_platform_pre_create_item(item=workflow_item, kwargs=kwargs)
|
|
73
|
+
if logger.isEnabledFor(DEBUG):
|
|
74
|
+
logger.debug("Calling pre_creation")
|
|
75
|
+
workflow_item.pre_creation(self.platform)
|
|
76
|
+
|
|
77
|
+
def post_create(self, workflow_item: IWorkflowItem, **kwargs) -> NoReturn:
|
|
78
|
+
"""
|
|
79
|
+
Run the platform/workflow item post creation events.
|
|
80
|
+
|
|
81
|
+
Args:
|
|
82
|
+
workflow_item: IWorkflowItem to run post-creation events
|
|
83
|
+
**kwargs: Optional arguments mainly for extensibility
|
|
84
|
+
|
|
85
|
+
Returns:
|
|
86
|
+
NoReturn
|
|
87
|
+
"""
|
|
88
|
+
if logger.isEnabledFor(DEBUG):
|
|
89
|
+
logger.debug("Calling idmtools_platform_post_create_item hooks")
|
|
90
|
+
FunctionPluginManager.instance().hook.idmtools_platform_post_create_item(item=workflow_item, kwargs=kwargs)
|
|
91
|
+
if logger.isEnabledFor(DEBUG):
|
|
92
|
+
logger.debug("Calling post_creation")
|
|
93
|
+
workflow_item.post_creation(self.platform)
|
|
94
|
+
|
|
95
|
+
def create(self, workflow_item: IWorkflowItem, do_pre: bool = True, do_post: bool = True, **kwargs) -> Any:
|
|
96
|
+
"""
|
|
97
|
+
Creates an workflow item from an IDMTools IWorkflowItem object.
|
|
98
|
+
|
|
99
|
+
Also performs pre-creation and post-creation locally and on platform.
|
|
100
|
+
|
|
101
|
+
Args:
|
|
102
|
+
workflow_item: Suite to create
|
|
103
|
+
do_pre: Perform Pre creation events for item
|
|
104
|
+
do_post: Perform Post creation events for item
|
|
105
|
+
**kwargs: Optional arguments mainly for extensibility
|
|
106
|
+
|
|
107
|
+
Returns:
|
|
108
|
+
Created platform item and the UUID of said item
|
|
109
|
+
"""
|
|
110
|
+
if workflow_item.status is not None:
|
|
111
|
+
return workflow_item._platform_object, workflow_item.uid
|
|
112
|
+
if do_pre:
|
|
113
|
+
if logger.isEnabledFor(DEBUG):
|
|
114
|
+
logger.debug("Calling pre_create")
|
|
115
|
+
self.pre_create(workflow_item, **kwargs)
|
|
116
|
+
if logger.isEnabledFor(DEBUG):
|
|
117
|
+
logger.debug("Calling platform_create")
|
|
118
|
+
ret = self.platform_create(workflow_item, **kwargs)
|
|
119
|
+
workflow_item.platform = self.platform
|
|
120
|
+
if do_post:
|
|
121
|
+
if logger.isEnabledFor(DEBUG):
|
|
122
|
+
logger.debug("Calling post_create")
|
|
123
|
+
self.post_create(workflow_item, **kwargs)
|
|
124
|
+
return ret
|
|
125
|
+
|
|
126
|
+
@abstractmethod
|
|
127
|
+
def platform_create(self, workflow_item: IWorkflowItem, **kwargs) -> Tuple[Any, str]:
|
|
128
|
+
"""
|
|
129
|
+
Creates an workflow_item from an IDMTools workflow_item object.
|
|
130
|
+
|
|
131
|
+
Args:
|
|
132
|
+
workflow_item: WorkflowItem to create
|
|
133
|
+
**kwargs: Optional arguments mainly for extensibility
|
|
134
|
+
|
|
135
|
+
Returns:
|
|
136
|
+
Created platform item and the id of said item
|
|
137
|
+
"""
|
|
138
|
+
pass
|
|
139
|
+
|
|
140
|
+
def pre_run_item(self, workflow_item: IWorkflowItem, **kwargs):
|
|
141
|
+
"""
|
|
142
|
+
Trigger right before commissioning experiment on platform.
|
|
143
|
+
|
|
144
|
+
This ensures that the item is created. It also ensures that the children(simulations) have also been created.
|
|
145
|
+
|
|
146
|
+
Args:
|
|
147
|
+
workflow_item: Experiment to commission
|
|
148
|
+
|
|
149
|
+
Returns:
|
|
150
|
+
None
|
|
151
|
+
"""
|
|
152
|
+
# ensure the item is created before running
|
|
153
|
+
# TODO what status are valid here? Create only?
|
|
154
|
+
if workflow_item.status is None:
|
|
155
|
+
if logger.isEnabledFor(DEBUG):
|
|
156
|
+
logger.debug("Calling create")
|
|
157
|
+
self.create(workflow_item)
|
|
158
|
+
|
|
159
|
+
def post_run_item(self, workflow_item: IWorkflowItem, **kwargs):
|
|
160
|
+
"""
|
|
161
|
+
Trigger right after commissioning workflow item on platform.
|
|
162
|
+
|
|
163
|
+
Args:
|
|
164
|
+
workflow_item: Experiment just commissioned
|
|
165
|
+
|
|
166
|
+
Returns:
|
|
167
|
+
None
|
|
168
|
+
"""
|
|
169
|
+
if logger.isEnabledFor(DEBUG):
|
|
170
|
+
logger.debug("Calling idmtools_platform_post_run hooks")
|
|
171
|
+
FunctionPluginManager.instance().hook.idmtools_platform_post_run(item=workflow_item, kwargs=kwargs)
|
|
172
|
+
|
|
173
|
+
def run_item(self, workflow_item: IWorkflowItem, **kwargs):
|
|
174
|
+
"""
|
|
175
|
+
Called during commissioning of an item. This should create the remote resource.
|
|
176
|
+
|
|
177
|
+
Args:
|
|
178
|
+
workflow_item:
|
|
179
|
+
|
|
180
|
+
Returns:
|
|
181
|
+
None
|
|
182
|
+
"""
|
|
183
|
+
if logger.isEnabledFor(DEBUG):
|
|
184
|
+
logger.debug("Calling pre_run_item")
|
|
185
|
+
self.pre_run_item(workflow_item, **kwargs)
|
|
186
|
+
if logger.isEnabledFor(DEBUG):
|
|
187
|
+
logger.debug("Calling platform_run_item")
|
|
188
|
+
self.platform_run_item(workflow_item, **kwargs)
|
|
189
|
+
if logger.isEnabledFor(DEBUG):
|
|
190
|
+
logger.debug("Calling post_run_item")
|
|
191
|
+
self.post_run_item(workflow_item, **kwargs)
|
|
192
|
+
|
|
193
|
+
@abstractmethod
|
|
194
|
+
def platform_run_item(self, workflow_item: IWorkflowItem, **kwargs):
|
|
195
|
+
"""
|
|
196
|
+
Called during commissioning of an item. This should perform what is needed to commission job on platform.
|
|
197
|
+
|
|
198
|
+
Args:
|
|
199
|
+
workflow_item:
|
|
200
|
+
|
|
201
|
+
Returns:
|
|
202
|
+
None
|
|
203
|
+
"""
|
|
204
|
+
pass
|
|
205
|
+
|
|
206
|
+
@abstractmethod
|
|
207
|
+
def get_parent(self, workflow_item: Any, **kwargs) -> Any:
|
|
208
|
+
"""
|
|
209
|
+
Returns the parent of item. If the platform doesn't support parents, you should throw a TopLevelItem error.
|
|
210
|
+
|
|
211
|
+
Args:
|
|
212
|
+
workflow_item: Workflow item to get parent of
|
|
213
|
+
**kwargs:
|
|
214
|
+
|
|
215
|
+
Returns:
|
|
216
|
+
Parent of Worktflow item
|
|
217
|
+
|
|
218
|
+
Raise:
|
|
219
|
+
TopLevelItem
|
|
220
|
+
"""
|
|
221
|
+
pass
|
|
222
|
+
|
|
223
|
+
@abstractmethod
|
|
224
|
+
def get_children(self, workflow_item: Any, **kwargs) -> List[Any]:
|
|
225
|
+
"""
|
|
226
|
+
Returns the children of an workflow_item object.
|
|
227
|
+
|
|
228
|
+
Args:
|
|
229
|
+
workflow_item: WorkflowItem object
|
|
230
|
+
**kwargs: Optional arguments mainly for extensibility
|
|
231
|
+
|
|
232
|
+
Returns:
|
|
233
|
+
Children of workflow_item object
|
|
234
|
+
"""
|
|
235
|
+
pass
|
|
236
|
+
|
|
237
|
+
def to_entity(self, workflow_item: Any, **kwargs) -> IWorkflowItem:
|
|
238
|
+
"""
|
|
239
|
+
Converts the platform representation of workflow_item to idmtools representation.
|
|
240
|
+
|
|
241
|
+
Args:
|
|
242
|
+
workflow_item:Platform workflow_item object
|
|
243
|
+
|
|
244
|
+
Returns:
|
|
245
|
+
IDMTools workflow_item object
|
|
246
|
+
"""
|
|
247
|
+
return workflow_item
|
|
248
|
+
|
|
249
|
+
@abstractmethod
|
|
250
|
+
def refresh_status(self, workflow_item: IWorkflowItem, **kwargs):
|
|
251
|
+
"""
|
|
252
|
+
Refresh status for workflow item.
|
|
253
|
+
|
|
254
|
+
Args:
|
|
255
|
+
workflow_item: Item to refresh status for
|
|
256
|
+
|
|
257
|
+
Returns:
|
|
258
|
+
None
|
|
259
|
+
"""
|
|
260
|
+
pass
|
|
261
|
+
|
|
262
|
+
@abstractmethod
|
|
263
|
+
def send_assets(self, workflow_item: Any, **kwargs):
|
|
264
|
+
"""
|
|
265
|
+
Send assets for workflow item to platform.
|
|
266
|
+
|
|
267
|
+
Args:
|
|
268
|
+
workflow_item: Item to send assets for
|
|
269
|
+
|
|
270
|
+
Returns:
|
|
271
|
+
None
|
|
272
|
+
"""
|
|
273
|
+
pass
|
|
274
|
+
|
|
275
|
+
@abstractmethod
|
|
276
|
+
def get_assets(self, workflow_item: IWorkflowItem, files: List[str], **kwargs) -> Dict[str, bytearray]:
|
|
277
|
+
"""
|
|
278
|
+
Load assets for workflow item.
|
|
279
|
+
|
|
280
|
+
Args:
|
|
281
|
+
workflow_item: Item
|
|
282
|
+
files: List of files to load
|
|
283
|
+
**kwargs:
|
|
284
|
+
|
|
285
|
+
Returns:
|
|
286
|
+
Dictionary with filename as key and value as binary content
|
|
287
|
+
"""
|
|
288
|
+
pass
|
|
289
|
+
|
|
290
|
+
@abstractmethod
|
|
291
|
+
def list_assets(self, workflow_item: IWorkflowItem, **kwargs) -> List[Asset]:
|
|
292
|
+
"""
|
|
293
|
+
List available assets for a workflow item.
|
|
294
|
+
|
|
295
|
+
Args:
|
|
296
|
+
workflow_item: workflow item to list files for
|
|
297
|
+
|
|
298
|
+
Returns:
|
|
299
|
+
List of filenames
|
|
300
|
+
"""
|
|
301
|
+
pass
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Utils for platform operations.
|
|
3
|
+
|
|
4
|
+
Here we have mostly utilities to handle batch operations which tend to overlap across different item types.
|
|
5
|
+
|
|
6
|
+
Copyright 2021, Bill & Melinda Gates Foundation. All rights reserved.
|
|
7
|
+
"""
|
|
8
|
+
from concurrent.futures import as_completed, Future
|
|
9
|
+
from concurrent.futures.process import ProcessPoolExecutor
|
|
10
|
+
from concurrent.futures.thread import ThreadPoolExecutor
|
|
11
|
+
from functools import partial
|
|
12
|
+
from logging import getLogger, DEBUG
|
|
13
|
+
from os import cpu_count
|
|
14
|
+
from typing import List, Union, Generator, Iterable, Callable, Any
|
|
15
|
+
from more_itertools import chunked
|
|
16
|
+
from idmtools.core import EntityContainer
|
|
17
|
+
from idmtools.entities.templated_simulation import TemplatedSimulations
|
|
18
|
+
|
|
19
|
+
logger = getLogger(__name__)
|
|
20
|
+
user_logger = getLogger('user')
|
|
21
|
+
# Global executor
|
|
22
|
+
EXECUTOR = None
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def batch_items(items: Union[Iterable, Generator], batch_size=16):
|
|
26
|
+
"""
|
|
27
|
+
Batch items.
|
|
28
|
+
|
|
29
|
+
Args:
|
|
30
|
+
items: Items to batch
|
|
31
|
+
batch_size: Size of the batch
|
|
32
|
+
|
|
33
|
+
Returns:
|
|
34
|
+
Generator
|
|
35
|
+
|
|
36
|
+
Raises:
|
|
37
|
+
StopIteration
|
|
38
|
+
"""
|
|
39
|
+
for item_chunk in chunked(items, batch_size):
|
|
40
|
+
logger.info('created chunk')
|
|
41
|
+
yield item_chunk
|
|
42
|
+
raise StopIteration
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def item_batch_worker_thread(create_func: Callable, items: Union[List], **kwargs) -> List:
|
|
46
|
+
"""
|
|
47
|
+
Default batch worker thread function. It just calls create on each item.
|
|
48
|
+
|
|
49
|
+
Args:
|
|
50
|
+
create_func: Create function for item
|
|
51
|
+
items: Items to create
|
|
52
|
+
|
|
53
|
+
Returns:
|
|
54
|
+
List of items created
|
|
55
|
+
"""
|
|
56
|
+
if logger.isEnabledFor(DEBUG):
|
|
57
|
+
logger.debug(f'Create {len(items)}')
|
|
58
|
+
|
|
59
|
+
ret = []
|
|
60
|
+
for item in items:
|
|
61
|
+
ret.append(create_func(item, **kwargs))
|
|
62
|
+
|
|
63
|
+
return ret
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def batch_create_items(items: Union[Iterable, Generator], batch_worker_thread_func: Callable[[List], List] = None,
|
|
67
|
+
create_func: Callable[..., Any] = None, display_progress: bool = True,
|
|
68
|
+
progress_description: str = "Commissioning items", unit: str = None, **kwargs):
|
|
69
|
+
"""
|
|
70
|
+
Batch create items. You must specify either batch_worker_thread_func or create_func.
|
|
71
|
+
|
|
72
|
+
Args:
|
|
73
|
+
items: Items to create
|
|
74
|
+
batch_worker_thread_func: Optional Function to execute. Should take a list and return a list
|
|
75
|
+
create_func: Optional Create function
|
|
76
|
+
display_progress: Enable progress bar
|
|
77
|
+
progress_description: Description to show in progress bar
|
|
78
|
+
unit: Unit for progress bar
|
|
79
|
+
**kwargs:
|
|
80
|
+
|
|
81
|
+
Returns:
|
|
82
|
+
Batches crated results
|
|
83
|
+
"""
|
|
84
|
+
global EXECUTOR
|
|
85
|
+
from idmtools.config import IdmConfigParser
|
|
86
|
+
from idmtools.utils.collections import ExperimentParentIterator
|
|
87
|
+
|
|
88
|
+
max_workers = kwargs.get('max_workers', None)
|
|
89
|
+
|
|
90
|
+
# Consider values from the block that Platform uses
|
|
91
|
+
_batch_size = int(IdmConfigParser.get_option(None, "batch_size", fallback=16))
|
|
92
|
+
|
|
93
|
+
batch_size = kwargs.get('batch_size', None)
|
|
94
|
+
if batch_size is not None:
|
|
95
|
+
_batch_size = batch_size
|
|
96
|
+
|
|
97
|
+
if display_progress and not IdmConfigParser.is_progress_bar_disabled():
|
|
98
|
+
from tqdm import tqdm
|
|
99
|
+
extra_args = dict(unit=unit) if unit else dict()
|
|
100
|
+
prog = tqdm(desc="Initializing objects for creation", **extra_args)
|
|
101
|
+
else:
|
|
102
|
+
prog = None
|
|
103
|
+
|
|
104
|
+
if EXECUTOR is None:
|
|
105
|
+
_workers_per_cpu = IdmConfigParser.get_option(None, "workers_per_cpu", fallback=None)
|
|
106
|
+
if _workers_per_cpu:
|
|
107
|
+
_max_workers = int(_workers_per_cpu) * cpu_count()
|
|
108
|
+
if logger.isEnabledFor(DEBUG):
|
|
109
|
+
logger.debug(f"workers set by cpu: {_workers_per_cpu} * {cpu_count()}")
|
|
110
|
+
else:
|
|
111
|
+
_max_workers = int(IdmConfigParser.get_option(None, "max_workers", fallback=16))
|
|
112
|
+
|
|
113
|
+
if max_workers is not None:
|
|
114
|
+
_max_workers = max_workers
|
|
115
|
+
|
|
116
|
+
logger.info(f'Creating {_max_workers} Platform Workers')
|
|
117
|
+
default_pool_executor = IdmConfigParser.get_option(None, "default_pool_executor", fallback="thread").lower()
|
|
118
|
+
if default_pool_executor == "process":
|
|
119
|
+
EXECUTOR = ProcessPoolExecutor(max_workers=_max_workers)
|
|
120
|
+
else:
|
|
121
|
+
EXECUTOR = ThreadPoolExecutor(max_workers=_max_workers)
|
|
122
|
+
|
|
123
|
+
if batch_worker_thread_func is None:
|
|
124
|
+
|
|
125
|
+
if create_func is None:
|
|
126
|
+
raise ValueError("You must provide either an item create callback or a item batch worker thread callback to"
|
|
127
|
+
" perform batches")
|
|
128
|
+
batch_worker_thread_func = partial(item_batch_worker_thread, create_func, **kwargs)
|
|
129
|
+
if logger.isEnabledFor(DEBUG):
|
|
130
|
+
logger.debug(f'Batching creation by {_batch_size}')
|
|
131
|
+
|
|
132
|
+
futures = []
|
|
133
|
+
|
|
134
|
+
total = 0
|
|
135
|
+
parent = None
|
|
136
|
+
if isinstance(items, ExperimentParentIterator) and isinstance(items.items, TemplatedSimulations):
|
|
137
|
+
parent = items.parent
|
|
138
|
+
i = items.items.simulations().generator
|
|
139
|
+
elif isinstance(items, ExperimentParentIterator) and isinstance(items.items, EntityContainer):
|
|
140
|
+
parent = items.parent
|
|
141
|
+
i = items.items
|
|
142
|
+
else:
|
|
143
|
+
i = items
|
|
144
|
+
if display_progress and not IdmConfigParser.is_progress_bar_disabled() and hasattr(items, '__len__'):
|
|
145
|
+
prog.total = len(items)
|
|
146
|
+
for chunk in chunked(i, _batch_size):
|
|
147
|
+
total += len(chunk)
|
|
148
|
+
if parent:
|
|
149
|
+
for c in chunk:
|
|
150
|
+
c.parent = parent
|
|
151
|
+
if logger.isEnabledFor(DEBUG):
|
|
152
|
+
logger.debug(f"Submitting chunk: {len(chunk)}")
|
|
153
|
+
if display_progress and not IdmConfigParser.is_progress_bar_disabled():
|
|
154
|
+
prog.update(len(chunk))
|
|
155
|
+
futures.append(EXECUTOR.submit(batch_worker_thread_func, chunk))
|
|
156
|
+
|
|
157
|
+
results = []
|
|
158
|
+
if display_progress and not IdmConfigParser.is_progress_bar_disabled():
|
|
159
|
+
prog.set_description(progress_description)
|
|
160
|
+
prog.reset(total)
|
|
161
|
+
results = show_progress_of_batch(prog, futures)
|
|
162
|
+
else:
|
|
163
|
+
for future in futures:
|
|
164
|
+
results.extend(future.result())
|
|
165
|
+
|
|
166
|
+
return results
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
def show_progress_of_batch(progress_bar: 'tqdm', futures: List[Future]) -> List: # noqa: F821
|
|
170
|
+
"""
|
|
171
|
+
Show progress bar for batch.
|
|
172
|
+
|
|
173
|
+
Args:
|
|
174
|
+
progress_bar: Progress bar
|
|
175
|
+
futures: List of futures that are still running/queued
|
|
176
|
+
|
|
177
|
+
Returns:
|
|
178
|
+
Returns results
|
|
179
|
+
"""
|
|
180
|
+
results = []
|
|
181
|
+
for future in as_completed(futures):
|
|
182
|
+
result = future.result()
|
|
183
|
+
progress_bar.update(len(result))
|
|
184
|
+
results.extend(future.result())
|
|
185
|
+
return results
|