Arcane  v3.14.10.0
Documentation utilisateur
Chargement...
Recherche...
Aucune correspondance
IncrementalComponentModifier_Accelerator.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2024 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com)
4// See the top-level COPYRIGHT file for details.
5// SPDX-License-Identifier: Apache-2.0
6//-----------------------------------------------------------------------------
7/*---------------------------------------------------------------------------*/
8/* IncrementalComponentModifier_Accelerator.cc (C) 2000-2024 */
9/* */
10/* Modification incrémentale des constituants. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/materials/internal/IncrementalComponentModifier.h"
15
16#include "arcane/utils/ITraceMng.h"
17#include "arcane/utils/FunctorUtils.h"
18
19#include "arcane/core/internal/ItemGroupImplInternal.h"
20#include "arcane/core/materials/IMeshMaterialVariable.h"
21
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"
26
28#include "arcane/accelerator/Filter.h"
30#include "arcane/accelerator/core/ProfileRegion.h"
31
32/*---------------------------------------------------------------------------*/
33/*---------------------------------------------------------------------------*/
34
35namespace Arcane::Materials
36{
37
38/*---------------------------------------------------------------------------*/
39/*---------------------------------------------------------------------------*/
40
41void IncrementalComponentModifier::
42apply(MaterialModifierOperation* operation)
43{
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);
49
50 IMeshMaterial* mat = operation->material();
51 SmallSpan<const Int32> orig_ids = operation->ids();
52 SmallSpan<const Int32> ids = orig_ids;
53
54 auto* true_mat = ARCANE_CHECK_POINTER(dynamic_cast<MeshMaterial*>(mat));
55
56 const IMeshEnvironment* env = mat->environment();
57 MeshEnvironment* true_env = true_mat->trueEnvironment();
58 const Integer nb_mat = env->nbMaterial();
59
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();
63
64 ConstituentConnectivityList* connectivity = m_all_env_data->componentConnectivityList();
65 const bool check_if_present = !m_queue.isAcceleratorPolicy();
66
67 const bool is_device = m_queue.isAcceleratorPolicy();
68
69 // Remplit les tableaux indiquants si un constituant est concerné par
70 // la modification en cours. Si ce n'est pas le cas, on pourra éviter de le tester
71 // dans la boucle des constituants.
72 {
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);
77
78 {
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);
82 if (m_is_debug)
83 connectivity->printConstituents(orig_ids);
84 }
85 {
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;
89 }
90 }
91
92 if (nb_mat != 1) {
93
94 // S'il est possible d'avoir plusieurs matériaux par milieu, il faut gérer
95 // pour chaque maille si le milieu évolue suite à l'ajout/suppression de matériau.
96 // Les deux cas sont :
97 // - en cas d'ajout, le milieu évolue pour une maille s'il n'y avait pas
98 // de matériau avant. Dans ce cas le milieu est ajouté à la maille.
99 // - en cas de suppression, le milieu évolue dans la maille s'il y avait
100 // 1 seul matériau avant. Dans ce cas le milieu est supprimé de la maille.
101
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;
112
113 connectivity->fillCellsNbMaterial(ids, env_id, cells_current_nb_material.view(), m_queue);
114
115 {
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();
120 {
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;
124 };
125 auto setter_lambda = [=] ARCCORE_HOST_DEVICE(Int32 input_index, Int32 output_index) {
126 cells_unchanged_in_env_view[output_index] = ids[input_index];
127 };
128 filterer.applyWithIndex(nb_id, select_lambda, setter_lambda, A_FUNCINFO);
129 cells_unchanged_in_env.resize(filterer.nbOutputElement());
130 }
131 {
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;
135 };
136 auto setter_lambda = [=] ARCCORE_HOST_DEVICE(Int32 input_index, Int32 output_index) {
137 cells_changed_in_env_view[output_index] = ids[input_index];
138 };
139 filterer.applyWithIndex(nb_id, select_lambda, setter_lambda, A_FUNCINFO);
140 cells_changed_in_env.resize(filterer.nbOutputElement());
141 }
142 }
143
144 Integer nb_unchanged_in_env = cells_unchanged_in_env.size();
145 info(4) << "Cells unchanged in environment n=" << nb_unchanged_in_env;
146
147 Int16 mat_id = true_mat->componentId();
148 if (is_add) {
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);
152 }
153 else {
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);
159 }
160
161 // Prend pour \a ids uniquement la liste des mailles
162 // qui n'appartenaient pas encore au milieu dans lequel on
163 // ajoute le matériau.
164 ids = cells_changed_in_env.view();
165 }
166
167 // Met à jour le nombre de milieux et de matériaux de chaque maille.
168 // NOTE: il faut d'abord faire l'opération sur les milieux avant
169 // les matériaux.
170 {
171 Int16 env_id = true_env->componentId();
172 Int16 mat_id = true_mat->componentId();
173 if (is_add) {
174 connectivity->addCellsToEnvironment(env_id, ids, m_queue);
175 connectivity->addCellsToMaterial(mat_id, ids, m_queue);
176 }
177 else {
178 connectivity->removeCellsToEnvironment(env_id, ids, m_queue);
179 connectivity->removeCellsToMaterial(mat_id, ids, m_queue);
180 }
181 }
182
183 // Comme on a ajouté/supprimé des mailles matériau dans le milieu,
184 // il faut transformer les mailles pures en mailles partielles (en cas
185 // d'ajout) ou les mailles partielles en mailles pures (en cas de
186 // suppression).
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);
191
192 // Si je suis mono-mat, alors mat->cells()<=>env->cells() et il ne faut
193 // mettre à jour que l'un des deux groupes.
194 bool need_update_env = (nb_mat != 1);
195
196 if (is_add) {
197 mat->cells().addItems(ids.smallView(), check_if_present);
198 if (need_update_env)
199 env->cells().addItems(ids.smallView(), check_if_present);
200 _addItemsToEnvironment(true_env, true_mat, ids, need_update_env);
201 }
202 else {
203 flagRemovedCells(ids, true);
204 _removeItemsInGroup(mat->cells(), ids);
205 if (need_update_env)
206 _removeItemsInGroup(env->cells(), ids);
207 _removeItemsFromEnvironment(true_env, true_mat, ids, need_update_env);
208 // Remet \a removed_local_ids_filter à la valeur initiale pour les prochaines opérations
209 flagRemovedCells(ids, false);
210 }
211}
212
213/*---------------------------------------------------------------------------*/
214/*---------------------------------------------------------------------------*/
215/*!
216 * \brief Calcule les mailles à transformer lorsqu'on modifie les mailles
217 * d'un milieu.
218 */
219Int32 IncrementalComponentModifier::
220_computeCellsToTransformForEnvironments(SmallSpan<const Int32> ids)
221{
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();
226
227 const Int32 n = ids.size();
228 auto command = makeCommand(m_queue);
229 Accelerator::ReducerSum2<Int32> sum_transformed(command);
230 command << RUNCOMMAND_LOOP1(iter, n, sum_transformed)
231 {
232 auto [i] = iter();
233 Int32 lid = ids[i];
234 bool do_transform = false;
235 // En cas d'ajout, on passe de pure à partiel s'il y a plusieurs milieux.
236 // En cas de suppression, on passe de partiel à pure si on est le seul milieu.
237 if (is_add)
238 do_transform = cells_nb_env[lid] > 1;
239 else
240 do_transform = cells_nb_env[lid] == 1;
241 if (do_transform) {
242 transformed_cells[lid] = do_transform;
243 sum_transformed.combine(1);
244 }
245 };
246 Int32 total_transformed = sum_transformed.reducedValue();
247 return total_transformed;
248}
249
250/*---------------------------------------------------------------------------*/
251/*---------------------------------------------------------------------------*/
252
253void IncrementalComponentModifier::
254_computeItemsToAdd(ComponentItemListBuilder& list_builder, SmallSpan<const Int32> local_ids)
255{
256 SmallSpan<const bool> cells_is_partial = m_work_info.m_cells_is_partial;
257
258 Accelerator::GenericFilterer filterer(m_queue);
259
260 MeshMaterialVariableIndexer* var_indexer = list_builder.indexer();
261
262 const Int32 nb_id = local_ids.size();
263
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();
270
271 // TODO: pour l'instant on remplit en deux fois mais il serait
272 // possible de le faire en une seule fois en utilisation l'algorithme de Partition.
273 // Il faudrait alors inverser les éléments de la deuxième liste pour avoir
274 // le même ordre de parcours qu'avant le passage sur accélérateur.
275
276 // Remplit la liste des mailles pures
277 {
278 auto select_lambda = [=] ARCCORE_HOST_DEVICE(Int32 index) -> bool {
279 return !cells_is_partial[index];
280 };
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;
284 };
285 filterer.applyWithIndex(nb_id, select_lambda, setter_lambda, A_FUNCINFO);
286 nb_pure_added = filterer.nbOutputElement();
287 }
288 // Remplit la liste des mailles partielles
289 {
290 auto select_lambda = [=] ARCCORE_HOST_DEVICE(Int32 index) -> bool {
291 return cells_is_partial[index];
292 };
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;
297 };
298 filterer.applyWithIndex(nb_id, select_lambda, setter_lambda, A_FUNCINFO);
299 nb_partial_added = filterer.nbOutputElement();
300 }
301
302 list_builder.resize(nb_pure_added, nb_partial_added);
303}
304
305/*---------------------------------------------------------------------------*/
306/*---------------------------------------------------------------------------*/
307
308void IncrementalComponentModifier::
309flagRemovedCells(SmallSpan<const Int32> local_ids, bool value_to_set)
310{
311 const Int32 nb_item = local_ids.size();
312 SmallSpan<bool> removed_cells = m_work_info.removedCells();
313 auto command = makeCommand(m_queue);
314
315 ARCANE_CHECK_ACCESSIBLE_POINTER(m_queue, local_ids.data());
316 ARCANE_CHECK_ACCESSIBLE_POINTER(m_queue, removed_cells.data());
317
318 command << RUNCOMMAND_LOOP1(iter, nb_item)
319 {
320 auto [i] = iter();
321 removed_cells[local_ids[i]] = value_to_set;
322 };
323}
324
325/*---------------------------------------------------------------------------*/
326/*---------------------------------------------------------------------------*/
327
328void IncrementalComponentModifier::
329_resetTransformedCells(SmallSpan<const Int32> local_ids)
330{
331 const Int32 nb_item = local_ids.size();
332 auto command = makeCommand(m_queue);
333 SmallSpan<bool> transformed_cells = m_work_info.transformedCells();
334 command << RUNCOMMAND_LOOP1(iter, nb_item)
335 {
336 auto [i] = iter();
337 Int32 lid = local_ids[i];
338 transformed_cells[lid] = false;
339 };
340}
341
342/*---------------------------------------------------------------------------*/
343/*---------------------------------------------------------------------------*/
344
345void IncrementalComponentModifier::
346_removeItemsInGroup(ItemGroup cells, SmallSpan<const Int32> removed_ids)
347{
348 const Int32 nb_removed = removed_ids.size();
349 if (nb_removed == 0)
350 return;
351
352 const bool do_old = false;
353 if (do_old) {
354 cells.removeItems(removed_ids.smallView(), false);
355 }
356 else {
357 // Filtre les entités du groupe \a cells en considérant que
358 // m_work_info.removedCells() vaut vrai pour les mailles qui
359 // doivent être supprimées.
360 ItemGroupImplInternal* impl_internal = cells._internalApi();
361 SmallSpan<Int32> items_local_id(impl_internal->itemsLocalId());
362
363 // Lors de l'application du filtre, le tableau d'entrée et de sortie
364 // est le même (c'est normalement supporté par le GenericFilterer).
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];
371 };
372 filterer.applyIf(input_ids, output_ids_view, select_filter, A_FUNCINFO);
373
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);
380 }
381}
382
383/*---------------------------------------------------------------------------*/
384/*---------------------------------------------------------------------------*/
385/*!
386 * \brief Effectue la copie entre les valeurs partielles et globales.
387 *
388 * Cette méthode permet de faire la copie en utilisant une seule RunCommand.
389 */
390void IncrementalComponentModifier::
391_applyCopyBetweenPartialsAndGlobals(const CopyBetweenPartialAndGlobalArgs& args, RunQueue& queue)
392{
393 ARCANE_CHECK_POINTER(args.m_copy_data);
394
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;
398
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);
406
407 const Int32 nb_copy = copy_data.size();
408
409 for (Int32 i = 0; i < nb_copy; ++i) {
410 ARCANE_CHECK_ACCESSIBLE_POINTER(queue, host_copy_data[i].m_output.data());
411 ARCANE_CHECK_ACCESSIBLE_POINTER(queue, host_copy_data[i].m_input.data());
412 }
413 ARCANE_CHECK_ACCESSIBLE_POINTER(queue, input_indexes.data());
414 ARCANE_CHECK_ACCESSIBLE_POINTER(queue, output_indexes.data());
415
416 // TODO: Gérer la copie de manière à pouvoir utiliser la coalescence
417 // TODO: Faire des spécialisations si le dim2_size est de 4 ou 8
418 // (voire un multiple) pour éviter la boucle interne.
419 auto command = makeCommand(queue);
420 command << RUNCOMMAND_LOOP2(iter, nb_copy, nb_value)
421 {
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];
430 };
431}
432
433/*---------------------------------------------------------------------------*/
434/*---------------------------------------------------------------------------*/
435
436void IncrementalComponentModifier::
437_applyInitializeWithZero(const InitializeWithZeroArgs& args)
438{
439 ARCANE_CHECK_POINTER(args.m_copy_data);
440
441 const RunQueue& queue = args.m_queue;
442 auto output_indexes = args.m_indexes_in_multiple;
443
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();
448
449 for (Int32 i = 0; i < nb_copy; ++i) {
450 ARCANE_CHECK_ACCESSIBLE_POINTER(queue, host_copy_data[i].m_output.data());
451 }
452 ARCANE_CHECK_ACCESSIBLE_POINTER(queue, output_indexes.data());
453
454 // TODO: Gérer la copie de manière à pouvoir utiliser la coalescence
455 // TODO: Faire des spécialisations si le dim2_size est de 4 ou 8
456 // (voire un multiple) pour éviter la boucle interne.
457 auto command = makeCommand(queue);
458 command << RUNCOMMAND_LOOP2(iter, nb_copy, nb_value)
459 {
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] = {};
466 };
467}
468
469/*---------------------------------------------------------------------------*/
470/*---------------------------------------------------------------------------*/
471/*!
472 * \brief Effectue la copie des vues pour les variables.
473 *
474 * Cette méthode permet de faire en une seule RunCommand les copies entre
475 * les vues CPU et accélérateurs des variables
476 */
477void IncrementalComponentModifier::
478_applyCopyVariableViews(RunQueue& queue)
479{
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());
482
483 const Int32 nb_copy = host_copy_data.size();
484 if (nb_copy == 0)
485 return;
486
487 // Suppose que toutes les vues ont les mêmes tailles.
488 // C'est le cas car les vues sont composées de 'ArrayView<>' et 'Array2View' et ces
489 // deux classes ont la même taille.
490 // TODO: il serait préférable de prendre le max des tailles et dans la commande
491 // de ne faire la copie que si on ne dépasse pas la taille.
492 Int32 nb_value = host_copy_data[0].m_input.size();
493
494 for (Int32 i = 0; i < nb_copy; ++i) {
495 const CopyBetweenDataInfo& h = host_copy_data[i];
496 ARCANE_CHECK_ACCESSIBLE_POINTER(queue, h.m_output.data());
497 ARCANE_CHECK_ACCESSIBLE_POINTER(queue, h.m_input.data());
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);
500 }
501
502 auto command = makeCommand(queue);
503 command << RUNCOMMAND_LOOP2(iter, nb_copy, nb_value)
504 {
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];
509 };
510}
511
512/*---------------------------------------------------------------------------*/
513/*---------------------------------------------------------------------------*/
514
515} // End namespace Arcane::Materials
516
517/*---------------------------------------------------------------------------*/
518/*---------------------------------------------------------------------------*/
#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.