14#include "arcane/materials/internal/IncrementalComponentModifier.h"
16#include "arcane/utils/ITraceMng.h"
17#include "arcane/utils/FunctorUtils.h"
18#include "arcane/utils/ValueConvert.h"
20#include "arcane/core/IItemFamily.h"
21#include "arcane/core/materials/IMeshMaterialVariable.h"
23#include "arcane/materials/internal/MeshMaterialMng.h"
24#include "arcane/materials/internal/ConstituentConnectivityList.h"
25#include "arcane/materials/internal/AllEnvData.h"
27#include "arcane/accelerator/core/ProfileRegion.h"
38IncrementalComponentModifier::
39IncrementalComponentModifier(AllEnvData* all_env_data,
const RunQueue& queue)
40: TraceAccessor(all_env_data->traceMng())
41, m_all_env_data(all_env_data)
42, m_material_mng(all_env_data->m_material_mng)
43, m_work_info(queue.allocationOptions(), queue.memoryRessource())
49 if (
auto v = Convert::Type<Int32>::tryParseFromEnvironment(
"ARCANE_USE_GENERIC_COPY_BETWEEN_PURE_AND_PARTIAL",
true)) {
50 m_use_generic_copy_between_pure_and_partial = v.value();
55 if (queue.executionPolicy() != Accelerator::eExecutionPolicy::Sequential)
56 m_use_generic_copy_between_pure_and_partial = 2;
58 if (
auto v = Convert::Type<Int32>::tryParseFromEnvironment(
"ARCANE_FORCE_MULTIPLE_COMMAND_FOR_MATERIAL_RESIZE",
true)) {
59 m_force_multiple_command_for_resize = (v.value());
60 info() <<
"Force using multiple command for resize = " << m_force_multiple_command_for_resize;
67void IncrementalComponentModifier::
68initialize(
bool is_debug)
70 m_is_debug = is_debug;
71 Int32 max_local_id = m_material_mng->mesh()->cellFamily()->maxLocalId();
72 Int32 nb_mat = m_material_mng->materials().size();
73 Int32 nb_env = m_material_mng->environments().size();
74 m_work_info.initialize(max_local_id, nb_mat, nb_env, m_queue);
75 m_work_info.is_verbose = is_debug || (traceMng()->verbosityLevel() >= 5);
81void IncrementalComponentModifier::
101void IncrementalComponentModifier::
102_switchCellsForMaterials(
const MeshMaterial* modified_mat,
103 SmallSpan<const Int32> ids)
105 const bool is_add = m_work_info.isAdd();
106 const bool is_device = m_queue.isAcceleratorPolicy();
107 SmallSpan<const bool> is_materials_modified = m_work_info.m_is_materials_modified.view(
false);
109 for (MeshEnvironment* true_env : m_material_mng->trueEnvironments()) {
110 for (MeshMaterial* mat : true_env->trueMaterials()) {
112 if (mat == modified_mat)
115 if (!is_materials_modified[mat->id()])
119 m_work_info.pure_local_ids.clearHost();
120 m_work_info.partial_indexes.clearHost();
123 MeshMaterialVariableIndexer* indexer = mat->variableIndexer();
125 info(4) <<
"MatTransformCells is_add?=" << is_add <<
" indexer=" << indexer->name()
126 <<
" mat_id=" << mat->id();
128 Int32 nb_transformed = _computeCellsToTransformForMaterial(mat, ids);
129 info(4) <<
"nb_transformed=" << nb_transformed;
130 if (nb_transformed == 0)
132 indexer->transformCells(m_work_info, m_queue,
false);
133 _resetTransformedCells(ids);
135 auto pure_local_ids = m_work_info.pure_local_ids.view(is_device);
136 auto partial_indexes = m_work_info.partial_indexes.view(is_device);
138 Int32 nb_pure = pure_local_ids.size();
139 Int32 nb_partial = partial_indexes.size();
140 info(4) <<
"NB_MAT_TRANSFORM pure=" << nb_pure
141 <<
" partial=" << nb_partial <<
" name=" << mat->name()
142 <<
" is_device?=" << is_device
143 <<
" is_modified?=" << is_materials_modified[mat->id()];
145 CopyBetweenPartialAndGlobalArgs args(indexer->index(), pure_local_ids,
147 m_do_copy_between_partial_and_pure,
150 _copyBetweenPartialsAndGlobals(args);
170void IncrementalComponentModifier::
171_switchCellsForEnvironments(
const IMeshEnvironment* modified_env,
172 SmallSpan<const Int32> ids)
174 const bool is_add = m_work_info.isAdd();
175 const bool is_device = m_queue.isAcceleratorPolicy();
176 SmallSpan<const bool> is_environments_modified = m_work_info.m_is_environments_modified.view(
false);
182 const bool is_copy = is_add || !(m_material_mng->isUseMaterialValueWhenRemovingPartialValue());
184 Int32 nb_transformed = _computeCellsToTransformForEnvironments(ids);
185 info(4) <<
"Compute Cells for environments nb_transformed=" << nb_transformed;
186 if (nb_transformed == 0)
189 for (
const MeshEnvironment* env : m_material_mng->trueEnvironments()) {
191 if (env == modified_env)
194 if (env->isMonoMaterial())
197 const Int32 env_id = env->id();
199 if (!is_environments_modified[env_id])
203 m_work_info.pure_local_ids.clearHost();
204 m_work_info.partial_indexes.clearHost();
207 MeshMaterialVariableIndexer* indexer = env->variableIndexer();
209 info(4) <<
"EnvTransformCells is_add?=" << is_add
210 <<
" env_id=" << env_id
211 <<
" indexer=" << indexer->name() <<
" nb_item=" << ids.size();
213 indexer->transformCells(m_work_info, m_queue,
true);
215 SmallSpan<const Int32> pure_local_ids = m_work_info.pure_local_ids.view(is_device);
216 SmallSpan<const Int32> partial_indexes = m_work_info.partial_indexes.view(is_device);
217 const Int32 nb_pure = pure_local_ids.size();
219 info(4) <<
"NB_ENV_TRANSFORM nb_pure=" << nb_pure <<
" name=" << env->name()
220 <<
" is_modified=" << is_environments_modified[env_id];
223 CopyBetweenPartialAndGlobalArgs copy_args(indexer->index(), pure_local_ids,
225 m_do_copy_between_partial_and_pure, is_add,
227 _copyBetweenPartialsAndGlobals(copy_args);
231 _resetTransformedCells(ids);
240Int32 IncrementalComponentModifier::
241_computeCellsToTransformForMaterial(
const MeshMaterial* mat, SmallSpan<const Int32> ids)
243 const MeshEnvironment* env = mat->trueEnvironment();
244 const Int16 env_id = env->componentId();
245 bool is_add = m_work_info.isAdd();
247 ConstituentConnectivityList* connectivity = m_all_env_data->componentConnectivityList();
248 SmallSpan<bool> transformed_cells = m_work_info.transformedCells();
249 return connectivity->fillCellsToTransform(ids, env_id, transformed_cells, is_add, m_queue);
268void IncrementalComponentModifier::
269_removeItemsFromEnvironment(MeshEnvironment* env, MeshMaterial* mat,
270 SmallSpan<const Int32> local_ids,
bool update_env_indexer)
272 info(4) <<
"MeshEnvironment::removeItemsDirect mat=" << mat->name();
274 Int32 nb_to_remove = local_ids.size();
277 env->addToTotalNbCellMat(-nb_to_remove);
279 mat->variableIndexer()->endUpdateRemove(m_work_info, nb_to_remove, m_queue);
281 if (update_env_indexer) {
286 env->variableIndexer()->endUpdateRemove(m_work_info, nb_to_remove, m_queue);
301void IncrementalComponentModifier::
302_addItemsToEnvironment(MeshEnvironment* env, MeshMaterial* mat,
303 SmallSpan<const Int32> local_ids,
bool update_env_indexer)
305 info(4) <<
"MeshEnvironment::addItemsDirect"
306 <<
" mat=" << mat->name();
308 MeshMaterialVariableIndexer* var_indexer = mat->variableIndexer();
309 const Int32 nb_to_add = local_ids.size();
312 env->addToTotalNbCellMat(nb_to_add);
314 const Int16 env_id = env->componentId();
315 m_work_info.m_cells_is_partial.resize(nb_to_add);
316 ConstituentConnectivityList* connectivity = m_all_env_data->componentConnectivityList();
317 connectivity->fillCellsIsPartial(local_ids, env_id, m_work_info.m_cells_is_partial.to1DSmallSpan(), m_queue);
319 _addItemsToIndexer(var_indexer, local_ids);
321 if (update_env_indexer) {
326 _addItemsToIndexer(env->variableIndexer(), local_ids);
333void IncrementalComponentModifier::
334_addItemsToIndexer(MeshMaterialVariableIndexer* var_indexer,
335 SmallSpan<const Int32> local_ids)
338 ComponentItemListBuilder& list_builder = m_work_info.list_builder;
339 list_builder.setIndexer(var_indexer);
341 const Int32 nb_id = local_ids.size();
342 list_builder.preAllocate(nb_id);
344 _computeItemsToAdd(list_builder, local_ids);
346 if (traceMng()->verbosityLevel() >= 5)
347 info() <<
"ADD_MATITEM_TO_INDEXER component=" << var_indexer->name()
348 <<
" nb_pure=" << list_builder.pureIndexes().size()
349 <<
" nb_partial=" << list_builder.partialIndexes().size()
350 <<
"\n pure=(" << list_builder.pureIndexes() <<
")"
351 <<
"\n partial=(" << list_builder.partialIndexes() <<
")";
356 var_indexer->endUpdateAdd(list_builder, m_queue);
359 _resizeVariablesIndexer(var_indexer->index());
363 if (m_do_init_new_items) {
364 IMeshMaterialMng* mm = m_material_mng;
365 bool init_with_zero = mm->isDataInitialisationWithZero();
367 Accelerator::ProfileRegion ps(m_queue,
"InitializeNewItems", 0xFFFF00);
369 SmallSpan<Int32> partial_indexes = list_builder.partialIndexes();
370 if (init_with_zero) {
371 RunQueue::ScopedAsync sc(&m_queue);
372 InitializeWithZeroArgs init_args(var_indexer->index(), partial_indexes, m_queue);
374 bool do_one_command = (m_use_generic_copy_between_pure_and_partial == 2);
375 UniqueArray<CopyBetweenDataInfo>& copy_data = m_work_info.m_host_variables_copy_data;
376 if (do_one_command) {
378 copy_data.reserve(m_material_mng->nbVariable());
379 init_args.m_copy_data = ©_data;
382 auto func_zero = [&](IMeshMaterialVariable* mv) {
383 mv->_internalApi()->initializeNewItemsWithZero(init_args);
385 functor::apply(mm, &IMeshMaterialMng::visitVariables, func_zero);
387 if (do_one_command) {
388 MDSpan<CopyBetweenDataInfo, MDDim1> x(copy_data.data(), MDIndex<1>(copy_data.size()));
389 m_work_info.m_variables_copy_data.copy(x, &m_queue);
390 _applyInitializeWithZero(init_args);
395 SmallSpan<Int32> partial_local_ids = list_builder.partialLocalIds();
397 CopyBetweenPartialAndGlobalArgs args(var_indexer->index(), partial_local_ids,
398 partial_indexes,
true,
true, m_queue);
399 _copyBetweenPartialsAndGlobals(args);
410void IncrementalComponentModifier::
411_resizeVariablesIndexer(Int32 var_index)
413 Accelerator::ProfileRegion ps(m_queue,
"ResizeVariableIndexer", 0xFF00FF);
414 ResizeVariableIndexerArgs resize_args(var_index, m_queue);
418 bool do_one_command = (m_use_generic_copy_between_pure_and_partial == 2);
420 if (m_force_multiple_command_for_resize)
421 do_one_command =
false;
423 UniqueArray<CopyBetweenDataInfo>& copy_data = m_work_info.m_host_variables_copy_data;
424 if (do_one_command) {
426 copy_data.reserve(m_material_mng->nbVariable());
427 resize_args.m_copy_data = ©_data;
430 if (m_force_multiple_command_for_resize) {
436 auto func2 = [&](IMeshMaterialVariable* mv) {
437 Accelerator::ProfileRegion ps2(m_queue, String(
"Resize_") + mv->name());
438 auto* mvi = mv->_internalApi();
439 mvi->resizeForIndexer(resize_args);
442 functor::apply(m_material_mng, &MeshMaterialMng::visitVariables, func2);
445 RunQueue::ScopedAsync sc(&m_queue);
446 auto func1 = [&](IMeshMaterialVariable* mv) {
447 auto* mvi = mv->_internalApi();
448 mvi->resizeForIndexer(resize_args);
450 functor::apply(m_material_mng, &MeshMaterialMng::visitVariables, func1);
453 if (do_one_command) {
455 MDSpan<CopyBetweenDataInfo, MDDim1> x(copy_data.data(), MDIndex<1>(copy_data.size()));
456 m_work_info.m_variables_copy_data.copy(x, &m_queue);
457 _applyCopyVariableViews(m_queue);
473void IncrementalComponentModifier::
474_copyBetweenPartialsAndGlobals(
const CopyBetweenPartialAndGlobalArgs& args)
476 if (args.m_local_ids.empty())
478 const bool do_copy = args.m_do_copy_between_partial_and_pure;
479 const bool is_add_operation = args.m_is_global_to_partial;
480 RunQueue queue(args.m_queue);
481 RunQueue::ScopedAsync sc(&queue);
487 Accelerator::RunQueuePool& queue_pool = m_material_mng->_internalApi()->asyncRunQueuePool();
490 if (is_add_operation) {
491 _resizeVariablesIndexer(args.m_var_index);
495 bool do_one_command = (m_use_generic_copy_between_pure_and_partial == 2);
496 UniqueArray<CopyBetweenDataInfo>& copy_data = m_work_info.m_host_variables_copy_data;
498 copy_data.reserve(m_material_mng->nbVariable());
501 CopyBetweenPartialAndGlobalArgs args2(args);
502 args2.m_use_generic_copy = (m_use_generic_copy_between_pure_and_partial >= 1);
504 args2.m_copy_data = ©_data;
505 auto func2 = [&](IMeshMaterialVariable* mv) {
506 auto* mvi = mv->_internalApi();
508 args2.m_queue = queue_pool[index];
509 mvi->copyBetweenPartialAndGlobal(args2);
512 functor::apply(m_material_mng, &MeshMaterialMng::visitVariables, func2);
513 if (do_one_command) {
515 MDSpan<CopyBetweenDataInfo, MDDim1> x(copy_data.data(), MDIndex<1>(copy_data.size()));
516 m_work_info.m_variables_copy_data.copy(x, &queue);
517 _applyCopyBetweenPartialsAndGlobals(args2, queue);
520 queue_pool.barrier();
Always enables tracing in Arcane parts concerning materials.