14#include "arcane/materials/internal/IncrementalComponentModifier.h"
16#include "arcane/utils/ITraceMng.h"
17#include "arcane/utils/FunctorUtils.h"
19#include "arcane/core/internal/ItemGroupImplInternal.h"
20#include "arcane/core/materials/IMeshMaterialVariable.h"
22#include "arcane/materials/internal/MeshMaterialMng.h"
23#include "arcane/materials/internal/MaterialModifierOperation.h"
24#include "arcane/materials/internal/ConstituentConnectivityList.h"
25#include "arcane/materials/internal/AllEnvData.h"
28#include "arcane/accelerator/Filter.h"
30#include "arcane/accelerator/core/ProfileRegion.h"
41void IncrementalComponentModifier::
42apply(MaterialModifierOperation* operation)
44 const char* str_add =
"ApplyConstituentOperationAdd";
45 const char* str_remove =
"ApplyConstituentOperationRemove";
46 bool is_add = operation->isAdd();
47 Int32 color = (is_add) ? 0x00FFFF : 0x007FFF;
48 Accelerator::ProfileRegion ps(m_queue, is_add ? str_add : str_remove, color);
50 IMeshMaterial* mat = operation->material();
51 SmallSpan<const Int32> orig_ids = operation->ids();
52 SmallSpan<const Int32> ids = orig_ids;
56 const IMeshEnvironment* env = mat->environment();
57 MeshEnvironment* true_env = true_mat->trueEnvironment();
58 const Integer nb_mat = env->nbMaterial();
60 info(4) <<
"-- ** -- Using optimisation updateMaterialDirect is_add=" << is_add
61 <<
" mat=" << mat->name() <<
" nb_item=" << orig_ids.size()
62 <<
" mat_id=" << mat->id() <<
" env_id=" << env->id();
64 ConstituentConnectivityList* connectivity = m_all_env_data->componentConnectivityList();
65 const bool check_if_present = !m_queue.isAcceleratorPolicy();
67 const bool is_device = m_queue.isAcceleratorPolicy();
73 m_work_info.m_is_materials_modified.fillHost(
false);
74 m_work_info.m_is_environments_modified.fillHost(
false);
75 m_work_info.m_is_materials_modified.sync(is_device);
76 m_work_info.m_is_environments_modified.sync(is_device);
79 auto mat_modifier = m_work_info.m_is_materials_modified.modifier(is_device);
80 auto env_modifier = m_work_info.m_is_environments_modified.modifier(is_device);
81 connectivity->fillModifiedConstituents(orig_ids, mat_modifier.view(), env_modifier.view(), mat->id(), is_add, m_queue);
83 connectivity->printConstituents(orig_ids);
86 auto is_mat_modified = m_work_info.m_is_materials_modified.view(
false);
87 auto is_env_modified = m_work_info.m_is_environments_modified.view(
false);
88 info(4) <<
"ModifiedInfosAfter: mats=" << is_mat_modified <<
" envs=" << is_env_modified;
102 UniqueArray<Int32>& cells_changed_in_env = m_work_info.cells_changed_in_env;
103 UniqueArray<Int32>& cells_unchanged_in_env = m_work_info.cells_unchanged_in_env;
104 UniqueArray<Int16>& cells_current_nb_material = m_work_info.m_cells_current_nb_material;
105 const Int32 nb_id = ids.size();
106 cells_unchanged_in_env.resize(nb_id);
107 cells_changed_in_env.resize(nb_id);
108 cells_current_nb_material.resize(nb_id);
109 const Int32 ref_nb_mat = is_add ? 0 : 1;
110 const Int16 env_id = true_env->componentId();
111 info(4) <<
"Using optimisation updateMaterialDirect is_add?=" << is_add;
113 connectivity->fillCellsNbMaterial(ids, env_id, cells_current_nb_material.view(), m_queue);
116 Accelerator::GenericFilterer filterer(m_queue);
117 SmallSpan<Int32> cells_unchanged_in_env_view = cells_unchanged_in_env.view();
118 SmallSpan<Int32> cells_changed_in_env_view = cells_changed_in_env.view();
119 SmallSpan<const Int16> cells_current_nb_material_view = m_work_info.m_cells_current_nb_material.view();
121 auto select_lambda = [=] ARCCORE_HOST_DEVICE(Int32 index) ->
bool {
122 Int16 current_cell_nb_mat = cells_current_nb_material_view[index];
123 return current_cell_nb_mat != ref_nb_mat;
125 auto setter_lambda = [=] ARCCORE_HOST_DEVICE(Int32 input_index, Int32 output_index) {
126 cells_unchanged_in_env_view[output_index] = ids[input_index];
128 filterer.applyWithIndex(nb_id, select_lambda, setter_lambda, A_FUNCINFO);
129 cells_unchanged_in_env.resize(filterer.nbOutputElement());
132 auto select_lambda = [=] ARCCORE_HOST_DEVICE(Int32 index) ->
bool {
133 Int16 current_cell_nb_mat = cells_current_nb_material_view[index];
134 return current_cell_nb_mat == ref_nb_mat;
136 auto setter_lambda = [=] ARCCORE_HOST_DEVICE(Int32 input_index, Int32 output_index) {
137 cells_changed_in_env_view[output_index] = ids[input_index];
139 filterer.applyWithIndex(nb_id, select_lambda, setter_lambda, A_FUNCINFO);
140 cells_changed_in_env.resize(filterer.nbOutputElement());
144 Integer nb_unchanged_in_env = cells_unchanged_in_env.size();
145 info(4) <<
"Cells unchanged in environment n=" << nb_unchanged_in_env;
147 Int16 mat_id = true_mat->componentId();
149 mat->cells().addItems(cells_unchanged_in_env, check_if_present);
150 connectivity->addCellsToMaterial(mat_id, cells_unchanged_in_env.view(), m_queue);
151 _addItemsToEnvironment(true_env, true_mat, cells_unchanged_in_env.view(),
false);
154 flagRemovedCells(cells_unchanged_in_env,
true);
155 _removeItemsInGroup(mat->cells(), cells_unchanged_in_env);
156 connectivity->removeCellsToMaterial(mat_id, cells_unchanged_in_env.view(), m_queue);
157 _removeItemsFromEnvironment(true_env, true_mat, cells_unchanged_in_env.view(),
false);
158 flagRemovedCells(cells_unchanged_in_env,
false);
164 ids = cells_changed_in_env.view();
171 Int16 env_id = true_env->componentId();
172 Int16 mat_id = true_mat->componentId();
174 connectivity->addCellsToEnvironment(env_id, ids, m_queue);
175 connectivity->addCellsToMaterial(mat_id, ids, m_queue);
178 connectivity->removeCellsToEnvironment(env_id, ids, m_queue);
179 connectivity->removeCellsToMaterial(mat_id, ids, m_queue);
187 info(4) <<
"Transform PartialPure for material name=" << true_mat->name();
188 _switchCellsForMaterials(true_mat, orig_ids);
189 info(4) <<
"Transform PartialPure for environment name=" << env->name();
190 _switchCellsForEnvironments(env, orig_ids);
194 bool need_update_env = (nb_mat != 1);
197 mat->cells().addItems(ids.smallView(), check_if_present);
199 env->cells().addItems(ids.smallView(), check_if_present);
200 _addItemsToEnvironment(true_env, true_mat, ids, need_update_env);
203 flagRemovedCells(ids,
true);
204 _removeItemsInGroup(mat->cells(), ids);
206 _removeItemsInGroup(env->cells(), ids);
207 _removeItemsFromEnvironment(true_env, true_mat, ids, need_update_env);
209 flagRemovedCells(ids,
false);
219Int32 IncrementalComponentModifier::
220_computeCellsToTransformForEnvironments(SmallSpan<const Int32> ids)
222 ConstituentConnectivityList* connectivity = m_all_env_data->componentConnectivityList();
223 ConstArrayView<Int16> cells_nb_env = connectivity->cellsNbEnvironment();
224 const bool is_add = m_work_info.isAdd();
225 SmallSpan<bool> transformed_cells = m_work_info.transformedCells();
227 const Int32 n = ids.size();
229 Accelerator::ReducerSum2<Int32> sum_transformed(command);
234 bool do_transform =
false;
238 do_transform = cells_nb_env[lid] > 1;
240 do_transform = cells_nb_env[lid] == 1;
242 transformed_cells[lid] = do_transform;
243 sum_transformed.combine(1);
246 Int32 total_transformed = sum_transformed.reducedValue();
247 return total_transformed;
253void IncrementalComponentModifier::
254_computeItemsToAdd(ComponentItemListBuilder& list_builder, SmallSpan<const Int32> local_ids)
256 SmallSpan<const bool> cells_is_partial = m_work_info.m_cells_is_partial;
258 Accelerator::GenericFilterer filterer(m_queue);
260 MeshMaterialVariableIndexer* var_indexer = list_builder.indexer();
262 const Int32 nb_id = local_ids.size();
264 SmallSpan<Int32> pure_indexes = list_builder.pureIndexes();
265 SmallSpan<Int32> partial_indexes = list_builder.partialIndexes();
266 SmallSpan<Int32> partial_local_ids = list_builder.partialLocalIds();
267 Int32 nb_pure_added = 0;
268 Int32 nb_partial_added = 0;
269 Int32 index_in_partial = var_indexer->maxIndexInMultipleArray();
278 auto select_lambda = [=] ARCCORE_HOST_DEVICE(Int32 index) ->
bool {
279 return !cells_is_partial[index];
281 auto setter_lambda = [=] ARCCORE_HOST_DEVICE(Int32 input_index, Int32 output_index) {
282 Int32 local_id = local_ids[input_index];
283 pure_indexes[output_index] = local_id;
285 filterer.applyWithIndex(nb_id, select_lambda, setter_lambda, A_FUNCINFO);
286 nb_pure_added = filterer.nbOutputElement();
290 auto select_lambda = [=] ARCCORE_HOST_DEVICE(Int32 index) ->
bool {
291 return cells_is_partial[index];
293 auto setter_lambda = [=] ARCCORE_HOST_DEVICE(Int32 input_index, Int32 output_index) {
294 Int32 local_id = local_ids[input_index];
295 partial_indexes[output_index] = index_in_partial + output_index;
296 partial_local_ids[output_index] = local_id;
298 filterer.applyWithIndex(nb_id, select_lambda, setter_lambda, A_FUNCINFO);
299 nb_partial_added = filterer.nbOutputElement();
302 list_builder.resize(nb_pure_added, nb_partial_added);
308void IncrementalComponentModifier::
309flagRemovedCells(SmallSpan<const Int32> local_ids,
bool value_to_set)
311 const Int32 nb_item = local_ids.size();
312 SmallSpan<bool> removed_cells = m_work_info.removedCells();
321 removed_cells[local_ids[i]] = value_to_set;
328void IncrementalComponentModifier::
329_resetTransformedCells(SmallSpan<const Int32> local_ids)
331 const Int32 nb_item = local_ids.size();
333 SmallSpan<bool> transformed_cells = m_work_info.transformedCells();
337 Int32 lid = local_ids[i];
338 transformed_cells[lid] =
false;
345void IncrementalComponentModifier::
346_removeItemsInGroup(ItemGroup cells, SmallSpan<const Int32> removed_ids)
348 const Int32 nb_removed = removed_ids.size();
352 const bool do_old =
false;
354 cells.removeItems(removed_ids.smallView(),
false);
360 ItemGroupImplInternal* impl_internal = cells._internalApi();
361 SmallSpan<Int32> items_local_id(impl_internal->itemsLocalId());
365 SmallSpan<const Int32> input_ids(items_local_id);
366 SmallSpan<Int32> output_ids_view(items_local_id);
367 SmallSpan<const bool> filtered_cells(m_work_info.removedCells());
368 Accelerator::GenericFilterer filterer(m_queue);
369 auto select_filter = [=] ARCCORE_HOST_DEVICE(Int32 local_id) ->
bool {
370 return !filtered_cells[local_id];
372 filterer.applyIf(input_ids, output_ids_view, select_filter, A_FUNCINFO);
374 Int32 current_nb_item = items_local_id.size();
375 Int32 nb_remaining = filterer.nbOutputElement();
376 if ((nb_remaining + nb_removed) != current_nb_item)
377 ARCANE_FATAL(
"Internal error in removing nb_remaining={0} nb_removed={1} original_size={2}",
378 nb_remaining, nb_removed, current_nb_item);
379 impl_internal->notifyDirectRemoveItems(removed_ids, nb_remaining);
390void IncrementalComponentModifier::
391_applyCopyBetweenPartialsAndGlobals(
const CopyBetweenPartialAndGlobalArgs& args, RunQueue& queue)
395 auto output_indexes = args.m_local_ids;
396 auto input_indexes = args.m_indexes_in_multiple;
397 const bool is_global_to_partial = args.m_is_global_to_partial;
399 if (is_global_to_partial)
400 std::swap(output_indexes, input_indexes);
401 SmallSpan<const CopyBetweenDataInfo> host_copy_data(m_work_info.m_host_variables_copy_data);
402 SmallSpan<const CopyBetweenDataInfo> copy_data(m_work_info.m_variables_copy_data.to1DSmallSpan());
403 const Int32 nb_value = input_indexes.size();
404 if (nb_value != output_indexes.size())
405 ARCANE_FATAL(
"input_indexes ({0}) and output_indexes ({1}) are different", nb_value, output_indexes);
407 const Int32 nb_copy = copy_data.size();
409 for (Int32 i = 0; i < nb_copy; ++i) {
422 auto [icopy, i] = iter();
423 auto input = copy_data[icopy].m_input;
424 auto output = copy_data[icopy].m_output;
425 Int32 dim2_size = copy_data[icopy].m_data_size;
426 Int32 output_base = output_indexes[i] * dim2_size;
427 Int32 input_base = input_indexes[i] * dim2_size;
428 for (Int32 j = 0; j < dim2_size; ++j)
429 output[output_base + j] = input[input_base + j];
436void IncrementalComponentModifier::
437_applyInitializeWithZero(
const InitializeWithZeroArgs& args)
441 const RunQueue& queue = args.m_queue;
442 auto output_indexes = args.m_indexes_in_multiple;
444 SmallSpan<const CopyBetweenDataInfo> host_copy_data(m_work_info.m_host_variables_copy_data);
445 SmallSpan<const CopyBetweenDataInfo> copy_data(m_work_info.m_variables_copy_data.to1DSmallSpan());
446 const Int32 nb_value = output_indexes.size();
447 const Int32 nb_copy = copy_data.size();
449 for (Int32 i = 0; i < nb_copy; ++i) {
460 auto [icopy, i] = iter();
461 auto output = copy_data[icopy].m_output;
462 Int32 dim2_size = copy_data[icopy].m_data_size;
463 Int32 output_base = output_indexes[i] * dim2_size;
464 for (Int32 j = 0; j < dim2_size; ++j)
465 output[output_base + j] = {};
477void IncrementalComponentModifier::
478_applyCopyVariableViews(RunQueue& queue)
480 SmallSpan<const CopyBetweenDataInfo> host_copy_data(m_work_info.m_host_variables_copy_data);
481 SmallSpan<const CopyBetweenDataInfo> copy_data(m_work_info.m_variables_copy_data.to1DSmallSpan());
483 const Int32 nb_copy = host_copy_data.size();
492 Int32 nb_value = host_copy_data[0].m_input.size();
494 for (Int32 i = 0; i < nb_copy; ++i) {
495 const CopyBetweenDataInfo& h = host_copy_data[i];
498 if (h.m_input.size() != nb_value)
499 ARCANE_FATAL(
"Invalid nb_value '{0} i={1} expected={2}", h.m_input.size(), nb_value);
505 auto [icopy, i] = iter();
506 auto input = copy_data[icopy].m_input;
507 auto output = copy_data[icopy].m_output;
508 output[i] = input[i];
#define ARCANE_CHECK_ACCESSIBLE_POINTER(queue_or_runner_or_policy, ptr)
Macro qui vérifie en mode check si ptr est accessible pour une RunQueue ou un Runner.
#define ARCANE_CHECK_POINTER(ptr)
Macro retournant le pointeur ptr s'il est non nul ou lancant une exception s'il est nul.
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
Types et fonctions pour gérer les synchronisations sur les accélérateurs.
Types et macros pour gérer les boucles sur les accélérateurs.
#define RUNCOMMAND_LOOP2(iter_name, x1, x2)
Boucle sur accélérateur.
#define RUNCOMMAND_LOOP1(iter_name, x1,...)
Boucle sur accélérateur avec arguments supplémentaires pour les réductions.
RunCommand makeCommand(const RunQueue &run_queue)
Créé une commande associée à la file run_queue.
Active toujours les traces dans les parties Arcane concernant les matériaux.
Int32 Integer
Type représentant un entier.