cars 1.0.0rc1__cp313-cp313-musllinux_1_2_i686.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.

Potentially problematic release.


This version of cars might be problematic. Click here for more details.

Files changed (202) hide show
  1. cars/__init__.py +74 -0
  2. cars/applications/__init__.py +37 -0
  3. cars/applications/application.py +117 -0
  4. cars/applications/application_constants.py +29 -0
  5. cars/applications/application_template.py +146 -0
  6. cars/applications/auxiliary_filling/__init__.py +29 -0
  7. cars/applications/auxiliary_filling/abstract_auxiliary_filling_app.py +104 -0
  8. cars/applications/auxiliary_filling/auxiliary_filling_algo.py +475 -0
  9. cars/applications/auxiliary_filling/auxiliary_filling_from_sensors_app.py +630 -0
  10. cars/applications/auxiliary_filling/auxiliary_filling_wrappers.py +90 -0
  11. cars/applications/dem_generation/__init__.py +30 -0
  12. cars/applications/dem_generation/abstract_dem_generation_app.py +116 -0
  13. cars/applications/dem_generation/bulldozer_config/base_config.yaml +42 -0
  14. cars/applications/dem_generation/bulldozer_dem_app.py +655 -0
  15. cars/applications/dem_generation/bulldozer_memory.py +55 -0
  16. cars/applications/dem_generation/dem_generation_algo.py +107 -0
  17. cars/applications/dem_generation/dem_generation_constants.py +32 -0
  18. cars/applications/dem_generation/dem_generation_wrappers.py +323 -0
  19. cars/applications/dense_match_filling/__init__.py +30 -0
  20. cars/applications/dense_match_filling/abstract_dense_match_filling_app.py +242 -0
  21. cars/applications/dense_match_filling/fill_disp_algo.py +113 -0
  22. cars/applications/dense_match_filling/fill_disp_constants.py +39 -0
  23. cars/applications/dense_match_filling/fill_disp_wrappers.py +83 -0
  24. cars/applications/dense_match_filling/zero_padding_app.py +302 -0
  25. cars/applications/dense_matching/__init__.py +30 -0
  26. cars/applications/dense_matching/abstract_dense_matching_app.py +261 -0
  27. cars/applications/dense_matching/census_mccnn_sgm_app.py +1460 -0
  28. cars/applications/dense_matching/cpp/__init__.py +0 -0
  29. cars/applications/dense_matching/cpp/dense_matching_cpp.cpython-313-i386-linux-musl.so +0 -0
  30. cars/applications/dense_matching/cpp/dense_matching_cpp.py +94 -0
  31. cars/applications/dense_matching/cpp/includes/dense_matching.hpp +58 -0
  32. cars/applications/dense_matching/cpp/meson.build +9 -0
  33. cars/applications/dense_matching/cpp/src/bindings.cpp +13 -0
  34. cars/applications/dense_matching/cpp/src/dense_matching.cpp +207 -0
  35. cars/applications/dense_matching/dense_matching_algo.py +401 -0
  36. cars/applications/dense_matching/dense_matching_constants.py +89 -0
  37. cars/applications/dense_matching/dense_matching_wrappers.py +951 -0
  38. cars/applications/dense_matching/disparity_grid_algo.py +588 -0
  39. cars/applications/dense_matching/loaders/__init__.py +23 -0
  40. cars/applications/dense_matching/loaders/config_census_sgm_default.json +31 -0
  41. cars/applications/dense_matching/loaders/config_census_sgm_homogeneous.json +30 -0
  42. cars/applications/dense_matching/loaders/config_census_sgm_mountain_and_vegetation.json +30 -0
  43. cars/applications/dense_matching/loaders/config_census_sgm_shadow.json +30 -0
  44. cars/applications/dense_matching/loaders/config_census_sgm_sparse.json +36 -0
  45. cars/applications/dense_matching/loaders/config_census_sgm_urban.json +30 -0
  46. cars/applications/dense_matching/loaders/config_mapping.json +13 -0
  47. cars/applications/dense_matching/loaders/config_mccnn.json +28 -0
  48. cars/applications/dense_matching/loaders/global_land_cover_map.tif +0 -0
  49. cars/applications/dense_matching/loaders/pandora_loader.py +593 -0
  50. cars/applications/dsm_filling/__init__.py +32 -0
  51. cars/applications/dsm_filling/abstract_dsm_filling_app.py +101 -0
  52. cars/applications/dsm_filling/border_interpolation_app.py +270 -0
  53. cars/applications/dsm_filling/bulldozer_config/base_config.yaml +44 -0
  54. cars/applications/dsm_filling/bulldozer_filling_app.py +279 -0
  55. cars/applications/dsm_filling/exogenous_filling_app.py +333 -0
  56. cars/applications/grid_generation/__init__.py +30 -0
  57. cars/applications/grid_generation/abstract_grid_generation_app.py +142 -0
  58. cars/applications/grid_generation/epipolar_grid_generation_app.py +327 -0
  59. cars/applications/grid_generation/grid_correction_app.py +496 -0
  60. cars/applications/grid_generation/grid_generation_algo.py +388 -0
  61. cars/applications/grid_generation/grid_generation_constants.py +46 -0
  62. cars/applications/grid_generation/transform_grid.py +88 -0
  63. cars/applications/ground_truth_reprojection/__init__.py +30 -0
  64. cars/applications/ground_truth_reprojection/abstract_ground_truth_reprojection_app.py +137 -0
  65. cars/applications/ground_truth_reprojection/direct_localization_app.py +629 -0
  66. cars/applications/ground_truth_reprojection/ground_truth_reprojection_algo.py +275 -0
  67. cars/applications/point_cloud_outlier_removal/__init__.py +30 -0
  68. cars/applications/point_cloud_outlier_removal/abstract_outlier_removal_app.py +385 -0
  69. cars/applications/point_cloud_outlier_removal/outlier_removal_algo.py +392 -0
  70. cars/applications/point_cloud_outlier_removal/outlier_removal_constants.py +43 -0
  71. cars/applications/point_cloud_outlier_removal/small_components_app.py +527 -0
  72. cars/applications/point_cloud_outlier_removal/statistical_app.py +531 -0
  73. cars/applications/rasterization/__init__.py +30 -0
  74. cars/applications/rasterization/abstract_pc_rasterization_app.py +183 -0
  75. cars/applications/rasterization/rasterization_algo.py +534 -0
  76. cars/applications/rasterization/rasterization_constants.py +38 -0
  77. cars/applications/rasterization/rasterization_wrappers.py +634 -0
  78. cars/applications/rasterization/simple_gaussian_app.py +1152 -0
  79. cars/applications/resampling/__init__.py +28 -0
  80. cars/applications/resampling/abstract_resampling_app.py +187 -0
  81. cars/applications/resampling/bicubic_resampling_app.py +762 -0
  82. cars/applications/resampling/resampling_algo.py +614 -0
  83. cars/applications/resampling/resampling_constants.py +36 -0
  84. cars/applications/resampling/resampling_wrappers.py +309 -0
  85. cars/applications/sparse_matching/__init__.py +30 -0
  86. cars/applications/sparse_matching/abstract_sparse_matching_app.py +498 -0
  87. cars/applications/sparse_matching/sift_app.py +735 -0
  88. cars/applications/sparse_matching/sparse_matching_algo.py +360 -0
  89. cars/applications/sparse_matching/sparse_matching_constants.py +68 -0
  90. cars/applications/sparse_matching/sparse_matching_wrappers.py +238 -0
  91. cars/applications/triangulation/__init__.py +32 -0
  92. cars/applications/triangulation/abstract_triangulation_app.py +227 -0
  93. cars/applications/triangulation/line_of_sight_intersection_app.py +1243 -0
  94. cars/applications/triangulation/pc_transform.py +552 -0
  95. cars/applications/triangulation/triangulation_algo.py +371 -0
  96. cars/applications/triangulation/triangulation_constants.py +38 -0
  97. cars/applications/triangulation/triangulation_wrappers.py +259 -0
  98. cars/bundleadjustment.py +757 -0
  99. cars/cars.py +177 -0
  100. cars/conf/__init__.py +23 -0
  101. cars/conf/geoid/egm96.grd +0 -0
  102. cars/conf/geoid/egm96.grd.hdr +15 -0
  103. cars/conf/input_parameters.py +156 -0
  104. cars/conf/mask_cst.py +35 -0
  105. cars/core/__init__.py +23 -0
  106. cars/core/cars_logging.py +402 -0
  107. cars/core/constants.py +191 -0
  108. cars/core/constants_disparity.py +50 -0
  109. cars/core/datasets.py +140 -0
  110. cars/core/geometry/__init__.py +27 -0
  111. cars/core/geometry/abstract_geometry.py +1119 -0
  112. cars/core/geometry/shareloc_geometry.py +598 -0
  113. cars/core/inputs.py +568 -0
  114. cars/core/outputs.py +176 -0
  115. cars/core/preprocessing.py +722 -0
  116. cars/core/projection.py +843 -0
  117. cars/core/roi_tools.py +215 -0
  118. cars/core/tiling.py +774 -0
  119. cars/core/utils.py +164 -0
  120. cars/data_structures/__init__.py +23 -0
  121. cars/data_structures/cars_dataset.py +1541 -0
  122. cars/data_structures/cars_dict.py +74 -0
  123. cars/data_structures/corresponding_tiles_tools.py +186 -0
  124. cars/data_structures/dataframe_converter.py +185 -0
  125. cars/data_structures/format_transformation.py +297 -0
  126. cars/devibrate.py +689 -0
  127. cars/extractroi.py +264 -0
  128. cars/orchestrator/__init__.py +23 -0
  129. cars/orchestrator/achievement_tracker.py +125 -0
  130. cars/orchestrator/cluster/__init__.py +37 -0
  131. cars/orchestrator/cluster/abstract_cluster.py +244 -0
  132. cars/orchestrator/cluster/abstract_dask_cluster.py +375 -0
  133. cars/orchestrator/cluster/dask_cluster_tools.py +103 -0
  134. cars/orchestrator/cluster/dask_config/README.md +94 -0
  135. cars/orchestrator/cluster/dask_config/dask.yaml +21 -0
  136. cars/orchestrator/cluster/dask_config/distributed.yaml +70 -0
  137. cars/orchestrator/cluster/dask_config/jobqueue.yaml +26 -0
  138. cars/orchestrator/cluster/dask_config/reference_confs/dask-schema.yaml +137 -0
  139. cars/orchestrator/cluster/dask_config/reference_confs/dask.yaml +26 -0
  140. cars/orchestrator/cluster/dask_config/reference_confs/distributed-schema.yaml +1009 -0
  141. cars/orchestrator/cluster/dask_config/reference_confs/distributed.yaml +273 -0
  142. cars/orchestrator/cluster/dask_config/reference_confs/jobqueue.yaml +212 -0
  143. cars/orchestrator/cluster/dask_jobqueue_utils.py +204 -0
  144. cars/orchestrator/cluster/local_dask_cluster.py +116 -0
  145. cars/orchestrator/cluster/log_wrapper.py +1075 -0
  146. cars/orchestrator/cluster/mp_cluster/__init__.py +27 -0
  147. cars/orchestrator/cluster/mp_cluster/mp_factorizer.py +212 -0
  148. cars/orchestrator/cluster/mp_cluster/mp_objects.py +535 -0
  149. cars/orchestrator/cluster/mp_cluster/mp_tools.py +93 -0
  150. cars/orchestrator/cluster/mp_cluster/mp_wrapper.py +505 -0
  151. cars/orchestrator/cluster/mp_cluster/multiprocessing_cluster.py +873 -0
  152. cars/orchestrator/cluster/mp_cluster/multiprocessing_profiler.py +399 -0
  153. cars/orchestrator/cluster/pbs_dask_cluster.py +207 -0
  154. cars/orchestrator/cluster/sequential_cluster.py +139 -0
  155. cars/orchestrator/cluster/slurm_dask_cluster.py +234 -0
  156. cars/orchestrator/orchestrator.py +905 -0
  157. cars/orchestrator/orchestrator_constants.py +29 -0
  158. cars/orchestrator/registry/__init__.py +23 -0
  159. cars/orchestrator/registry/abstract_registry.py +143 -0
  160. cars/orchestrator/registry/compute_registry.py +106 -0
  161. cars/orchestrator/registry/id_generator.py +116 -0
  162. cars/orchestrator/registry/replacer_registry.py +213 -0
  163. cars/orchestrator/registry/saver_registry.py +363 -0
  164. cars/orchestrator/registry/unseen_registry.py +118 -0
  165. cars/orchestrator/tiles_profiler.py +279 -0
  166. cars/pipelines/__init__.py +26 -0
  167. cars/pipelines/conf_resolution/conf_final_resolution.yaml +5 -0
  168. cars/pipelines/conf_resolution/conf_first_resolution.yaml +2 -0
  169. cars/pipelines/conf_resolution/conf_intermediate_resolution.yaml +2 -0
  170. cars/pipelines/default/__init__.py +26 -0
  171. cars/pipelines/default/default_pipeline.py +786 -0
  172. cars/pipelines/parameters/__init__.py +0 -0
  173. cars/pipelines/parameters/advanced_parameters.py +417 -0
  174. cars/pipelines/parameters/advanced_parameters_constants.py +69 -0
  175. cars/pipelines/parameters/application_parameters.py +71 -0
  176. cars/pipelines/parameters/depth_map_inputs.py +0 -0
  177. cars/pipelines/parameters/dsm_inputs.py +918 -0
  178. cars/pipelines/parameters/dsm_inputs_constants.py +25 -0
  179. cars/pipelines/parameters/output_constants.py +52 -0
  180. cars/pipelines/parameters/output_parameters.py +454 -0
  181. cars/pipelines/parameters/sensor_inputs.py +842 -0
  182. cars/pipelines/parameters/sensor_inputs_constants.py +49 -0
  183. cars/pipelines/parameters/sensor_loaders/__init__.py +29 -0
  184. cars/pipelines/parameters/sensor_loaders/basic_classif_loader.py +86 -0
  185. cars/pipelines/parameters/sensor_loaders/basic_image_loader.py +98 -0
  186. cars/pipelines/parameters/sensor_loaders/pivot_classif_loader.py +90 -0
  187. cars/pipelines/parameters/sensor_loaders/pivot_image_loader.py +105 -0
  188. cars/pipelines/parameters/sensor_loaders/sensor_loader.py +93 -0
  189. cars/pipelines/parameters/sensor_loaders/sensor_loader_template.py +71 -0
  190. cars/pipelines/parameters/sensor_loaders/slurp_classif_loader.py +86 -0
  191. cars/pipelines/pipeline.py +119 -0
  192. cars/pipelines/pipeline_constants.py +31 -0
  193. cars/pipelines/pipeline_template.py +139 -0
  194. cars/pipelines/unit/__init__.py +26 -0
  195. cars/pipelines/unit/unit_pipeline.py +2850 -0
  196. cars/starter.py +167 -0
  197. cars-1.0.0rc1.dist-info/METADATA +292 -0
  198. cars-1.0.0rc1.dist-info/RECORD +202 -0
  199. cars-1.0.0rc1.dist-info/WHEEL +5 -0
  200. cars-1.0.0rc1.dist-info/entry_points.txt +8 -0
  201. cars.libs/libgcc_s-1257a076.so.1 +0 -0
  202. cars.libs/libstdc++-0530927c.so.6.0.32 +0 -0
@@ -0,0 +1,375 @@
1
+ #!/usr/bin/env python
2
+ # coding: utf8
3
+ #
4
+ # Copyright (c) 2020 Centre National d'Etudes Spatiales (CNES).
5
+ #
6
+ # This file is part of CARS
7
+ # (see https://github.com/CNES/cars).
8
+ #
9
+ # Licensed under the Apache License, Version 2.0 (the "License");
10
+ # you may not use this file except in compliance with the License.
11
+ # You may obtain a copy of the License at
12
+ #
13
+ # http://www.apache.org/licenses/LICENSE-2.0
14
+ #
15
+ # Unless required by applicable law or agreed to in writing, software
16
+ # distributed under the License is distributed on an "AS IS" BASIS,
17
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18
+ # See the License for the specific language governing permissions and
19
+ # limitations under the License.
20
+ #
21
+ """
22
+ Contains abstract function for abstract dask Cluster
23
+ """
24
+
25
+ # Standard imports
26
+ import logging
27
+ import os
28
+ import time
29
+
30
+ # Third party imports
31
+ from abc import abstractmethod
32
+
33
+ import dask
34
+ import numpy as np
35
+ import psutil
36
+ import xarray as xr
37
+ import yaml
38
+ from dask.config import global_config as global_dask_config
39
+ from dask.config import set as dask_config_set
40
+ from dask.delayed import Delayed
41
+ from dask.distributed import as_completed
42
+ from dask.sizeof import sizeof as dask_sizeof
43
+ from distributed.diagnostics.plugin import WorkerPlugin
44
+ from distributed.utils import CancelledError
45
+
46
+ from cars.core import cars_logging
47
+
48
+ # CARS imports
49
+ from cars.orchestrator.cluster import abstract_cluster
50
+
51
+
52
+ class AbstractDaskCluster(
53
+ abstract_cluster.AbstractCluster
54
+ ): # pylint: disable=R0902
55
+ """
56
+ AbstractDaskCluster
57
+ """
58
+
59
+ def __init__(self, conf_cluster, out_dir, log_dir, launch_worker=True):
60
+ """
61
+ Init function of AbstractDaskCluster
62
+
63
+ :param conf_cluster: configuration for cluster
64
+
65
+ """
66
+
67
+ print("cluster log_dir", log_dir)
68
+
69
+ # call parent init
70
+ super().__init__(
71
+ conf_cluster, out_dir, log_dir, launch_worker=launch_worker
72
+ )
73
+ # retrieve parameters
74
+ self.nb_workers = self.checked_conf_cluster["nb_workers"]
75
+ self.task_timeout = self.checked_conf_cluster["task_timeout"]
76
+ self.walltime = self.checked_conf_cluster["walltime"]
77
+ self.use_memory_logger = self.checked_conf_cluster["use_memory_logger"]
78
+ self.config_name = self.checked_conf_cluster["config_name"]
79
+ self.profiling = self.checked_conf_cluster["profiling"]
80
+ self.launch_worker = launch_worker
81
+
82
+ self.activate_dashboard = self.checked_conf_cluster[
83
+ "activate_dashboard"
84
+ ]
85
+ self.python = self.checked_conf_cluster["python"]
86
+ if self.checked_conf_cluster["mode"] == "slurm_dask":
87
+ self.account = self.checked_conf_cluster["account"]
88
+ self.qos = self.checked_conf_cluster["qos"]
89
+
90
+ if self.launch_worker:
91
+ # Set DASK CARS specific config
92
+ # TODO: update with adequate configuration through tests
93
+ set_config()
94
+
95
+ # Save dask config used
96
+ save_config(self.out_dir, "dask_config_" + self.config_name)
97
+
98
+ # Create cluster
99
+ self.cluster, self.client = self.start_dask_cluster()
100
+
101
+ # Add plugin to monitor memory of workers
102
+ if self.use_memory_logger:
103
+ plugin = ComputeDSMMemoryLogger(self.out_dir)
104
+ self.client.register_worker_plugin(plugin)
105
+
106
+ @abstractmethod
107
+ def check_conf(self, conf):
108
+ """
109
+ Check configuration
110
+
111
+ :param conf: configuration to check
112
+ :type conf: dict
113
+
114
+ :return: overloaded configuration
115
+ :rtype: dict
116
+
117
+ """
118
+
119
+ @abstractmethod
120
+ def start_dask_cluster(self):
121
+ """
122
+ Start dask cluster
123
+ """
124
+
125
+ def create_task_wrapped(self, func, nout=1):
126
+ """
127
+ Create task
128
+
129
+ :param func: function
130
+ :param nout: number of outputs
131
+ """
132
+ return dask.delayed(
133
+ cars_logging.wrap_logger(func, self.worker_log_dir, self.log_level),
134
+ nout=nout,
135
+ )
136
+
137
+ def get_delayed_type(self):
138
+ """
139
+ Get delayed type
140
+ """
141
+ return Delayed
142
+
143
+ def start_tasks(self, task_list):
144
+ """
145
+ Start all tasks
146
+
147
+ :param task_list: task list
148
+ """
149
+
150
+ return self.client.compute(task_list)
151
+
152
+ def scatter(self, data, broadcast=True):
153
+ """
154
+ Distribute data through workers
155
+
156
+ :param data: task data
157
+ """
158
+ return self.client.scatter(data, broadcast=broadcast)
159
+
160
+ def future_iterator(self, future_list, timeout=None):
161
+ """
162
+ Start all tasks
163
+
164
+ :param future_list: future_list list
165
+ """
166
+
167
+ return DaskFutureIterator(future_list, timeout=timeout)
168
+
169
+
170
+ class DaskFutureIterator:
171
+ """
172
+ iterator on dask futures, similar to as_completed
173
+ Only returns the actual results, delete the future after usage
174
+ """
175
+
176
+ def __init__(self, future_list, timeout=None): # pylint: disable=W0613
177
+ # TODO: python 3.9: add timeout=timeout as parameter
178
+ self.dask_a_c = as_completed(future_list, with_results=True)
179
+ self.prev = None
180
+
181
+ def __iter__(self):
182
+ return self
183
+
184
+ def __next__(self):
185
+ try:
186
+ fut, res = self.dask_a_c.__next__()
187
+ except StopIteration as exception:
188
+ if self.prev is not None:
189
+ self.prev.cancel()
190
+ self.prev = None
191
+ raise exception
192
+ except dask.distributed.TimeoutError as exception:
193
+ raise TimeoutError("No tasks available") from exception
194
+ # release previous future
195
+ if self.prev is not None:
196
+ self.prev.cancel()
197
+ # store current future
198
+ self.prev = fut
199
+
200
+ if isinstance(res, CancelledError):
201
+ raise RuntimeError("CancelError from worker {}".format(res))
202
+ return res
203
+
204
+
205
+ def set_config():
206
+ """
207
+ Set particular DASK config such as:
208
+ - scheduler
209
+ """
210
+ # TODO: export API to prepare.run and compute_dsm.run() to set scheduler
211
+ # example mode debug: dask_config_set(scheduler='single-threaded')
212
+ # example mode multithread: dask_config_set(scheduler='threads')
213
+ # Here set Multiprocess mode instead multithread because of GIL blocking
214
+ dask_config_set(scheduler="processes")
215
+
216
+
217
+ def save_config(output_dir: str, file_name: str):
218
+ """
219
+ Save DASK global config
220
+
221
+ :param output_dir: output directory path
222
+ :param file_name: output file name
223
+
224
+ """
225
+ logging.info(
226
+ "Save DASK global merged config for debug "
227
+ "(1: $DASK_DIR if exists, 2: ~/.config/dask/, ... ) "
228
+ )
229
+ # write global merged DASK config in YAML
230
+ write_yaml_config(global_dask_config, output_dir, file_name)
231
+
232
+
233
+ def write_yaml_config(yaml_config: dict, output_dir: str, file_name: str):
234
+ """
235
+ Writes a YAML config to disk.
236
+ TODO: put in global file if needed elsewhere than DASK conf save.
237
+
238
+ :param yaml_config: YAML config to write
239
+ :param output_dir: output directory path
240
+ :param file_name: output file name
241
+ """
242
+ # file path where to store the dask config
243
+ yaml_config_path = os.path.join(output_dir, file_name + ".yaml")
244
+ with open(yaml_config_path, "w", encoding="utf-8") as yaml_config_file:
245
+ yaml.dump(yaml_config, yaml_config_file)
246
+
247
+
248
+ @dask_sizeof.register_lazy("xarray")
249
+ def register_xarray():
250
+ """
251
+ Add hook to dask so it correctly estimates memory used by xarray
252
+ """
253
+
254
+ @dask_sizeof.register(xr.DataArray)
255
+ # pylint: disable=unused-variable
256
+ def sizeof_xarray_dataarray(xarr):
257
+ """
258
+ Inner function for total size of xarray_dataarray
259
+ """
260
+ total_size = dask_sizeof(xarr.values)
261
+ for __, carray in xarr.coords.items():
262
+ total_size += dask_sizeof(carray.values)
263
+ total_size += dask_sizeof(xarr.attrs)
264
+ return total_size
265
+
266
+ @dask_sizeof.register(xr.Dataset)
267
+ # pylint: disable=unused-variable
268
+ def sizeof_xarray_dataset(xdat):
269
+ """
270
+ Inner function for total size of xarray_dataset
271
+ """
272
+ total_size = 0
273
+ for __, varray in xdat.data_vars.items():
274
+ total_size += dask_sizeof(varray.values)
275
+ for __, carray in xdat.coords.items():
276
+ total_size += dask_sizeof(carray)
277
+ total_size += dask_sizeof(xdat.attrs)
278
+ return total_size
279
+
280
+
281
+ class ComputeDSMMemoryLogger(WorkerPlugin):
282
+ """A subclass of WorkerPlugin dedicated to monitoring workers memory
283
+
284
+ This plugin enables two things:
285
+
286
+ - Additional dask log traces (for each worker internal state change):
287
+
288
+ - amount of tasks
289
+ - associated memory
290
+ - A numpy data file with memory metrics and timing
291
+ """
292
+
293
+ def __init__(self, outdir):
294
+ """
295
+ Constructor
296
+ :param outdir: output directory
297
+ :type outdir: string
298
+ """
299
+ self.outdir = outdir
300
+
301
+ def setup(self, worker):
302
+ """
303
+ Associate plugin with a worker
304
+ :param worker: The worker to associate the plugin with
305
+ """
306
+ # Pylint Exception : Inherited attributes outside __init__
307
+ # pylint: disable=attribute-defined-outside-init
308
+ self.worker = worker
309
+ self.name = worker.name
310
+ # Measure plugin registration time
311
+ self.start_time = time.time()
312
+ # Data will hold the memory traces as numpy array
313
+ self.data = [[0, 0, 0, 0]]
314
+
315
+ def transition(self, key, start, finish, **kwargs):
316
+ """
317
+ Callback when worker changes internal state
318
+ """
319
+ # TODO Pylint Exception : Inherited attributes outside __init__
320
+ # pylint: disable=attribute-defined-outside-init
321
+
322
+ # Define cumulants
323
+ total_in_memory = 0
324
+ total_nbytes = 0
325
+
326
+ # Measure elapsed time for the state change
327
+ elapsed_time = time.time() - self.start_time
328
+
329
+ # Walk the worker known memory
330
+ for task_key in self.worker.state.tasks.keys():
331
+ task_size = self.worker.state.tasks[task_key].get_nbytes()
332
+
333
+ total_in_memory += task_size
334
+ total_nbytes += 1
335
+
336
+ # Use psutil to capture python process memory as well
337
+ process = psutil.Process(os.getpid())
338
+ process_memory = process.memory_info().rss
339
+
340
+ # Update data records
341
+ self.data = np.concatenate(
342
+ (
343
+ self.data,
344
+ np.array(
345
+ [
346
+ [
347
+ elapsed_time,
348
+ total_in_memory,
349
+ total_nbytes,
350
+ process_memory,
351
+ ]
352
+ ]
353
+ ),
354
+ )
355
+ )
356
+ # Convert nbytes size for logger
357
+ total_nbytes = float(total_nbytes) / 1000000
358
+ process_memory = float(process_memory) / 1000000
359
+
360
+ # Log memory state
361
+ logging.info(
362
+ "Memory report: data created = {} ({} Mb), "
363
+ "python process memory = {} Mb".format(
364
+ total_in_memory,
365
+ total_nbytes,
366
+ process_memory,
367
+ )
368
+ )
369
+
370
+ # Save data records in npy file
371
+ # TODO: Save only every x seconds ?
372
+ file = os.path.join(
373
+ self.outdir, "dask_log", "memory_" + repr(self.name) + ".npy"
374
+ )
375
+ np.save(file, self.data)
@@ -0,0 +1,103 @@
1
+ #!/usr/bin/env python
2
+ # coding: utf8
3
+ #
4
+ # Copyright (c) 2020 Centre National d'Etudes Spatiales (CNES).
5
+ #
6
+ # This file is part of CARS
7
+ # (see https://github.com/CNES/cars).
8
+ #
9
+ # Licensed under the Apache License, Version 2.0 (the "License");
10
+ # you may not use this file except in compliance with the License.
11
+ # You may obtain a copy of the License at
12
+ #
13
+ # http://www.apache.org/licenses/LICENSE-2.0
14
+ #
15
+ # Unless required by applicable law or agreed to in writing, software
16
+ # distributed under the License is distributed on an "AS IS" BASIS,
17
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18
+ # See the License for the specific language governing permissions and
19
+ # limitations under the License.
20
+ #
21
+ """
22
+ Contains functions cluster conf checker
23
+ """
24
+ import time
25
+
26
+ from json_checker import And, Checker, Or
27
+
28
+
29
+ def create_checker_schema(conf):
30
+ """
31
+ Create checker shema that it can be overloaded
32
+
33
+ :param conf: configuration to check
34
+ :type conf: dict
35
+
36
+ :return: overloaded configuration
37
+ :rtype: dict
38
+
39
+ """
40
+
41
+ # init conf
42
+ if conf is not None:
43
+ overloaded_conf = conf.copy()
44
+ else:
45
+ conf = {}
46
+ overloaded_conf = {}
47
+
48
+ # Overload conf
49
+ overloaded_conf["mode"] = conf.get("mode", "unknowed_dask")
50
+ overloaded_conf["use_memory_logger"] = conf.get("use_memory_logger", False)
51
+ overloaded_conf["nb_workers"] = conf.get("nb_workers", 2)
52
+ overloaded_conf["task_timeout"] = conf.get("task_timeout", 600)
53
+ overloaded_conf["max_ram_per_worker"] = conf.get("max_ram_per_worker", 2000)
54
+ overloaded_conf["walltime"] = conf.get("walltime", "00:59:00")
55
+ overloaded_conf["config_name"] = conf.get("config_name", "unknown")
56
+ overloaded_conf["activate_dashboard"] = conf.get(
57
+ "activate_dashboard", False
58
+ )
59
+ overloaded_conf["python"] = conf.get("python", None)
60
+ overloaded_conf["profiling"] = conf.get("profiling", {})
61
+
62
+ cluster_schema = {
63
+ "mode": str,
64
+ "use_memory_logger": bool,
65
+ "nb_workers": And(int, lambda x: x > 0),
66
+ "task_timeout": And(int, lambda x: x > 0),
67
+ "max_ram_per_worker": And(Or(float, int), lambda x: x > 0),
68
+ "walltime": str,
69
+ "config_name": str,
70
+ "activate_dashboard": bool,
71
+ "profiling": dict,
72
+ "python": Or(None, str),
73
+ }
74
+
75
+ return overloaded_conf, cluster_schema
76
+
77
+
78
+ def check_configuration(overloaded_conf, cluster_schema):
79
+ """
80
+ Check configuration from overload conf and cluster schema
81
+
82
+
83
+ :param conf: overloaded_conf to check
84
+ :type conf: dict
85
+ :param conf: cluster_schema checking rules
86
+ :type conf: dict
87
+
88
+ :return: overloaded configuration
89
+ :rtype: dict
90
+
91
+ """
92
+ # Check conf
93
+ checker = Checker(cluster_schema)
94
+ checker.validate(overloaded_conf)
95
+
96
+ # Check walltime format
97
+ walltime = overloaded_conf["walltime"]
98
+ try:
99
+ time.strptime(walltime, "%H:%M:%S")
100
+ except ValueError as err:
101
+ raise ValueError("Walltime should be formatted as HH:MM:SS") from err
102
+
103
+ return overloaded_conf
@@ -0,0 +1,94 @@
1
+ # CARS Dask configuration
2
+
3
+ This file contains the description of DASK configuration used with CARS
4
+
5
+ This configuration is split into 3 files:
6
+ - [dask.yaml](./dask.yaml) : basic DASK configuration
7
+ - [distributed.yaml](./distributed.yaml) : configuration of DASK distributed : scheduler and workers
8
+ - [jobqueue.yaml](./jobqueue.yaml) : configuration of DASK and PBS cluster interface
9
+
10
+
11
+ ## dask.yaml configuration
12
+
13
+
14
+ | Option | CARS value | Default Dask value | Comments |
15
+ | ------- | ----------- | ------------------- | -------- |
16
+ | temporary-directory | null | None = null | Default: tmpdir = dask-worker-space local |
17
+ | dataframe:shuffle-compression| null | None = null | Default: no compression . TODO: test if gain |
18
+ | array:svg:size | 120 | 120 | Default. |
19
+ | array:slicing:split-large-chunks| null | None = null | Default. TODO: set to true if too much warnings. Test if adds perfomance issues |
20
+ | optimization:fuse:active| **true** | None = null | **Activated** TODO: test impact on configuration activation |
21
+ | optimization:fuse:ave-width| 1| 1 | Default. **TODO : to test/adapt limit of width= num_nodes/height** |
22
+ | optimization:fuse:max-width| null| None = null | Default : depends on de ave-width. 1.5 + ave_width * log(ave_width + 1) |
23
+ | optimization:fuse:max-height| .inf | inf | Default : No max limitation. All possibilities. |
24
+ | optimization:fuse:max-depth-new-edges| null|None = null | Default : depends on ave-width. ave_width * 1.5 |
25
+ | optimization:fuse:subgraphs| null | None = null | Default: Let optimizer choose. TODO: test?|
26
+ | optimization:fuse:rename-keys| true | true | Default. TODO: test ?|
27
+
28
+ ## Configuration distributed.yaml
29
+
30
+
31
+ | Option | CARS value | Default Dask value | Comments |
32
+ | ------- | ----------- | ------------------- | -------- |
33
+ | version | **2** | NA| Not defined in documentation | Default in example. TODO: keep ? why specify ? no documentation... |
34
+ | logging:distributed| **info** | info | DASK distributed log level. *Adapt depending the output loglevel. Set to debug for mac level* |
35
+ | logging:distributed.client| warning | warning | See for Client, adapt of refined analysis |
36
+ | logging:distributed.worker| debug | not set | Default. For more workers infors : uncomment.|
37
+ | logging:bokeh | **critical** | error ? | Log limitation on warnings / errors polluting output. |
38
+ | logging:tornado | **critical** | warning ? | Duplicate in output configuration . To test in dask.yaml. Link with http://stackoverflow.com/questions/21234772/python-tornado-disable-logging-to-stderr ?. The idea is to delete tornado messages, but does not talk about dask conf|
39
+ | logging:tornado.application | **error** | ? | dig for more performance analysis of tornado (cf timeout TCP ...), We need to upgrade tornato loglevel. TODO |
40
+ | scheduler:blocked-handlers| [] | [] | Default. |
41
+ | scheduler:allowed-failures| **10** | 3 | Augmented for some failed cases. TODO: lower this value |
42
+ | scheduler:bandwidth| **100000** | 100000000 | Tested values, set lower : 100mbps vs 100G ? estimated flow. enough ? TODO: analyse the use of this parameter. |
43
+ | scheduler:transition-log-length| 100000 | 100000 | Default. Unit? TODO: Storage size in spinning logs. Seems ok if memory doent freeze |
44
+ | scheduler:work-stealing| True | True | Default. load balancing of workers tasks. TODO: Could be dangerous for stability, working with images |
45
+ | worker:blocked-handlers| [] | [] | Default |
46
+ | :worker:multiprocessing-method| **forkserver** | spawn | Tested modification. TODO: see the gain with forkserver. Perf vs stability ... spawn vs fork vs forkserver. Seems ok with forkserver as intermediate solution but maybe not that slow with spawn, ans more stable, with software stacked on each multiprocessed worker. |
47
+ | worker:connections:outgoing et incoming| 50 and **50** | 50 and 10 | Default for outgoing. Modified to 50 for incoming. TODO: Precise analysis of conections, current connections. Beware not to saturate. |
48
+ | worker:validate| **true** | false | Augmentation for debug Default. TODO: see impact? |
49
+ | worker:lifetime:restart | **True** | False | Commented. TODO: to test. What is deadline ? See lifetime utilisation. "Lifetime was intended to provide a mechanism for a periodic reset of workers, such as might be useful when dealing with libraries that might leak memory and so benefit from cycling worker processes. It is orthogonal to adaptive." mrocklin https://github.com/dask/distributed/issues/3141 . Does lifetime as to be set the same as walltime ? |
50
+ | worker:lifetime:duration| null | None=null | Default. |
51
+ | worker:lifetime:stagger| 0 | 0 | Default. |
52
+ | worker:profile:interval| 10 ms | 10ms | Default. |
53
+ | worker:profile:cycle| 1000 ms | 1000ms | Default. |
54
+ | worker:memory:target| 0.60 | 0.6 | Default. |
55
+ | worker:memory:spill| 0.70 | 0.7 | Default. |
56
+ | worker:memory:pause| 0.80 | 0.8 | Default. |
57
+ | worker:memory:terminate| 0.95 | 0.95 | Default. |
58
+ | comm:retry:count| **10** | 0 | Tested for stability improvement. TODO: Default: 0 should not change that. For now we keep it to 10. May be lower comminuration issue between workers |
59
+ | comm:compression| auto | auto | Default. |
60
+ | comm:default-scheme| tcp | tcp | Default. |
61
+ | comm:socket-backlog| 2048 | 2048 | Default. TODO: not sufficient ? |
62
+ | comm:timeouts:connects| **60s** | 10s | Augmentation of value following done tests. TODO: issues before. Do not touch it ... |
63
+ | comm:timeouts:tcp| **120s** | 30s | Augmentation of value following done tests. TODO: issues before. Do not touch it ... |
64
+ | comm:require-encryption| **False** | None=null | Deactivated. No need |
65
+ | dashboard:export-tool| False | False | Default |
66
+ | admin:tick:interval | 20 ms | 20 ms | Default. |
67
+ | admin:tick:limit| **1s** | 3s | TODO: test it : default 3s, keep 1s ? |
68
+ | admin:log-format| %(asctime)s :: %(name)s - %(levelname)s - %(message)s' | %(name)s - %(levelname)s - %(message)s | default ok |
69
+ | admin:pdb-on-err| False| False | Default. TODO test : set to true for debug. |
70
+
71
+ ## Configuration jobqueue.yaml
72
+
73
+ The main configuration is done with [dask usage in CARS](https://github.com/CNES/cars/blob/master/cars/orchestrator/cluster/pbs_dask_cluster.py)
74
+
75
+ But also in documented file [jobqueue.yaml](./jobqueue.yaml) if not overloaded in CARS.
76
+ [Jobqueue documentation](https://jobqueue.dask.org/en/latest/configuration.html)
77
+
78
+ ## Official configurations :
79
+
80
+ Reference dask configuration of dask projects are stored in [reference_confs](./reference_confs/)
81
+
82
+ ### Dask
83
+
84
+ - default: https://raw.githubusercontent.com/dask/dask/main/dask/dask.yaml
85
+ - schema: https://raw.githubusercontent.com/dask/dask/main/dask/dask-schema.yaml
86
+
87
+ ### Distributed
88
+
89
+ - default: https://raw.githubusercontent.com/dask/distributed/main/distributed/distributed.yaml
90
+ - schema: https://raw.githubusercontent.com/dask/distributed/main/distributed/distributed-schema.yaml
91
+
92
+ ### Jobqueue
93
+
94
+ - default: https://raw.githubusercontent.com/dask/dask-jobqueue/main/dask_jobqueue/jobqueue.yaml
@@ -0,0 +1,21 @@
1
+ temporary-directory: null # Directory for local disk like /tmp, /scratch, or /local. null -> local dask-worker-space directory.
2
+
3
+ dataframe:
4
+ shuffle:
5
+ compression: null # compression for on disk-shuffling. Partd supports ZLib, BZ2, SNAPPY, BLOSC
6
+
7
+ array:
8
+ svg:
9
+ size: 120 # pixels for jupyter notebook array rendering
10
+ slicing:
11
+ split-large-chunks: null # How to handle large output chunks in slicing. Warns by default.
12
+
13
+ optimization:
14
+ fuse: # Options for Dask's task fusion optimizations
15
+ active: true
16
+ ave-width: 1 # Upper limit for width, where width = num_nodes / height
17
+ max-width: null # 1.5 + ave_width * log(ave_width + 1)
18
+ max-height: .inf # Fuse all possibilities
19
+ max-depth-new-edges: null # ave_width * 1.5
20
+ subgraphs: null # true for dask.dataframe, false for everything else. Set to null to let the default optimizer of individual dask collections decide.
21
+ rename-keys: true # Set to true to rename the fused keys with `default_fused_keys_renamer`. Can be costly.
@@ -0,0 +1,70 @@
1
+ distributed:
2
+ version: 2
3
+ logging: # Logging dask distributed module conf
4
+ distributed: warning
5
+ distributed.client: warning
6
+ distributed.worker: warning
7
+ distributed.scheduler: warning
8
+ distributed.nanny: warning
9
+ distributed.core: warning
10
+ bokeh: critical
11
+ # http://stackoverflow.com/questions/21234772/python-tornado-disable-logging-to-stderr
12
+ tornado: critical
13
+ tornado.application: error
14
+
15
+ scheduler:
16
+ blocked-handlers: [] # message operation list to block from scheduler to worker
17
+ allowed-failures: 10 # number of retries before a task is considered bad
18
+ bandwidth: 100000000 # 100 MB/s estimated worker-worker bandwidth
19
+ work-stealing: True # workers should steal tasks from each other
20
+
21
+ worker:
22
+ blocked-handlers: [] # message operation list to block from scheduler to worker
23
+ multiprocessing-method: forkserver # can be fork, spawn or forkserver multiprocessing method
24
+ connections: # Maximum concurrent connections for data
25
+ outgoing: 50 # This helps to control network saturation
26
+ incoming: 50
27
+ validate: True # Check worker state at every step for debugging
28
+ lifetime:
29
+ duration: null
30
+ stagger: 0 # Random amount of time by which to stagger lifetime. Avoid kill at the same lifetime
31
+ restart: False # Do we ressurrect the worker after the lifetime deadline?
32
+ profile:
33
+ interval: 10ms # Time between statistical profiling queries
34
+ cycle: 1000ms # Time between starting new profile
35
+ memory:
36
+ target: False # target fraction to stay below
37
+ spill: False # fraction at which we spill to disk
38
+ pause: False # fraction at which we pause worker threads
39
+ terminate: False # fraction at which we terminate the worker
40
+ comm:
41
+ retry: # some operations (such as gathering data) are subject to re-tries with the below parameters
42
+ count: 10 # the maximum retry attempts. 0 disables re-trying.
43
+ compression: auto # Compression for communication; Default: auto
44
+ default-scheme: tcp # default scheme (can be tls for secure comm)
45
+ socket-backlog: 2048 # default value, must be large enough for data between workers
46
+
47
+ timeouts:
48
+ connect: 60s # time before connecting fails (default: 10s)
49
+ tcp: 120s # time before calling an unresponsive connection dead (default: 30s)
50
+
51
+ require-encryption: False # Whether to require encryption on non-local comms
52
+
53
+ ###################
54
+ # Bokeh dashboard #
55
+ ###################
56
+
57
+ dashboard:
58
+ export-tool: False # Deactivate bokeh dashboard for performance
59
+
60
+ ##################
61
+ # Administrative #
62
+ ##################
63
+
64
+ admin:
65
+ tick:
66
+ interval: 20ms # time between event loop health checks
67
+ limit: 1s # time allowed before triggering a warning
68
+ log-format: '%(asctime)s :: %(name)s - %(levelname)s - %(message)s'
69
+ pdb-on-err: False # enter debug mode on scheduling error
70
+ low-level-log-length: 100000 # How long should we keep the transition log in memory (default length 100000 (bytes?))
@@ -0,0 +1,26 @@
1
+ jobqueue:
2
+ pbs:
3
+ name: cars-dask-worker # Name of dask worker (set to PBS JOB NAME)
4
+
5
+ # Dask worker options
6
+ cores: null # Total number of cores per job
7
+ memory: null # Total amount of memory per job
8
+ processes: null # Number of Python processes per job
9
+
10
+ interface: null # Network interface to use like eth0 or ib0
11
+ death-timeout: 3000 # Number of seconds to wait if a worker can not find a scheduler
12
+ local-directory: null # Location of fast local storage like /scratch or $TMPDIR
13
+ extra: [] # Additional arguments to pass to `dask-worker`
14
+
15
+ # PBS resource manager options
16
+ shebang: "#!/usr/bin/env bash" # Path to desired interpreter for your batch submission script.
17
+ queue: null # PBS queue by default. Take the one specified in PBSCluster() first
18
+ project: null # PBS project name in ACCOUNT information
19
+ walltime: '00:59:00' # PBS walltime by default.
20
+ env-extra: [] # PBS environnements to pass to workers
21
+ resource-spec: null # Resource string for PBS cpu and memory by default
22
+ job-extra: [] # ?
23
+ log-directory: null # Log directory by default
24
+
25
+ # Scheduler options
26
+ scheduler-options: {} # Used to pass additional arguments to Dask Scheduler.