Arcane  v3.14.10.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
SpecificMemoryCopyList.h
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2023 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/* SpecificMemoryCopyList.h (C) 2000-2023 */
9/* */
10/* Classe template pour gérer des fonctions spécialisées de copie mémoire. */
11/*---------------------------------------------------------------------------*/
12#ifndef ARCANE_UTILS_INTERNAL_SPECIFICMEMORYCOPYLIST_H
13#define ARCANE_UTILS_INTERNAL_SPECIFICMEMORYCOPYLIST_H
14/*---------------------------------------------------------------------------*/
15/*---------------------------------------------------------------------------*/
16
17#include "arcane/utils/String.h"
18#include "arcane/utils/ArrayExtentsValue.h"
19#include "arcane/utils/FatalErrorException.h"
20
21#include <atomic>
22
23/*---------------------------------------------------------------------------*/
24/*---------------------------------------------------------------------------*/
25
26namespace Arcane::impl
27{
28
29/*---------------------------------------------------------------------------*/
30/*---------------------------------------------------------------------------*/
34class ARCANE_UTILS_EXPORT IndexedMemoryCopyArgs
35{
36 public:
37
39
40 public:
41
44 : m_indexes(indexes)
45 , m_source(source)
46 , m_destination(destination)
47 , m_queue(run_queue)
48 {}
49
50 public:
51
52 SmallSpan<const Int32> m_indexes;
53 Span<const std::byte> m_source;
54 Span<std::byte> m_destination;
55 RunQueue* m_queue = nullptr;
56};
57
58/*---------------------------------------------------------------------------*/
59/*---------------------------------------------------------------------------*/
64class ARCANE_UTILS_EXPORT IndexedMultiMemoryCopyArgs
65{
66 public:
67
71 Span<std::byte> destination,
73 : m_indexes(indexes)
74 , m_const_multi_memory(multi_memory)
75 , m_destination_buffer(destination)
76 , m_queue(run_queue)
77 {}
78
84 : m_indexes(indexes)
85 , m_multi_memory(multi_memory)
86 , m_source_buffer(source)
87 , m_queue(run_queue)
88 {}
89
90 public:
91
92 SmallSpan<const Int32> m_indexes;
93 SmallSpan<const Span<const std::byte>> m_const_multi_memory;
94 SmallSpan<Span<std::byte>> m_multi_memory;
95 Span<const std::byte> m_source_buffer;
96 Span<std::byte> m_destination_buffer;
97 RunQueue* m_queue = nullptr;
98};
99
100/*---------------------------------------------------------------------------*/
101/*---------------------------------------------------------------------------*/
105class ARCANE_UTILS_EXPORT ISpecificMemoryCopy
106{
107 public:
108
109 virtual ~ISpecificMemoryCopy() = default;
110
111 public:
112
113 virtual void copyFrom(const IndexedMemoryCopyArgs& args) = 0;
114 virtual void copyTo(const IndexedMemoryCopyArgs& args) = 0;
115 virtual void fill(const IndexedMemoryCopyArgs& args) = 0;
116 virtual void copyFrom(const IndexedMultiMemoryCopyArgs&) = 0;
117 virtual void copyTo(const IndexedMultiMemoryCopyArgs&) = 0;
118 virtual void fill(const IndexedMultiMemoryCopyArgs& args) = 0;
119 virtual Int32 datatypeSize() const = 0;
120};
121
122/*---------------------------------------------------------------------------*/
123/*---------------------------------------------------------------------------*/
127class ARCANE_UTILS_EXPORT ISpecificMemoryCopyList
128{
129 public:
130
137 static void setDefaultCopyListIfNotSet(ISpecificMemoryCopyList* ptr);
138
139 public:
140
141 virtual void copyTo(Int32 datatype_size, const IndexedMemoryCopyArgs& args) = 0;
142 virtual void copyFrom(Int32 datatype_size, const IndexedMemoryCopyArgs& args) = 0;
143 virtual void fill(Int32 datatype_size, const IndexedMemoryCopyArgs& args) = 0;
144 virtual void copyTo(Int32 datatype_size, const IndexedMultiMemoryCopyArgs& args) = 0;
145 virtual void copyFrom(Int32 datatype_size, const IndexedMultiMemoryCopyArgs& args) = 0;
146 virtual void fill(Int32 datatype_size, const IndexedMultiMemoryCopyArgs& args) = 0;
147};
148
149/*---------------------------------------------------------------------------*/
150/*---------------------------------------------------------------------------*/
159template <typename Traits>
162{
163 public:
164
165 using InterfaceType = typename Traits::InterfaceType;
166 template <typename DataType, typename Extent> using SpecificType = typename Traits::template SpecificType<DataType, Extent>;
167 using RefType = typename Traits::RefType;
168
169 public:
170
171 static constexpr Int32 NB_COPIER = 128;
172
173 public:
174
176 {
177 m_copier.fill(nullptr);
178
179 m_copier[1] = &m_s1;
180 m_copier[2] = &m_s2;
181 m_copier[3] = &m_s3;
182 m_copier[4] = &m_s4;
183 m_copier[5] = &m_s5;
184 m_copier[6] = &m_s6;
185 m_copier[7] = &m_s7;
186 m_copier[8] = &m_s8;
187 m_copier[9] = &m_s9;
188 m_copier[10] = &m_s10;
189
190 m_copier[12] = &m_s12;
191 m_copier[16] = &m_s16;
192 m_copier[24] = &m_s24;
193 m_copier[32] = &m_s32;
194 m_copier[40] = &m_s40;
195 m_copier[48] = &m_s48;
196 m_copier[56] = &m_s56;
197 m_copier[64] = &m_s64;
198 m_copier[72] = &m_s72;
199 }
200
201 public:
202
203 void printStats()
204 {
205 std::cout << "SpecificMemory::nb_specialized=" << m_nb_specialized
206 << " nb_generic=" << m_nb_generic << "\n";
207 }
208
209 void checkValid()
210 {
211 // Vérifie que les taille sont correctes
212 for (Int32 i = 0; i < NB_COPIER; ++i) {
213 auto* x = m_copier[i];
214 if (x && (x->datatypeSize() != i))
215 ARCANE_FATAL("Incoherent datatype size v={0} expected={1}", x->datatypeSize(), i);
216 }
217 }
218
219 private:
220
221 RefType _copier(Int32 v)
222 {
223 if (v < 0)
224 ARCANE_FATAL("Bad value {0} for datasize", v);
225
226 InterfaceType* x = nullptr;
227 if (v < NB_COPIER)
228 x = m_copier[v];
229 if (x) {
230 if (x->datatypeSize() != v)
231 ARCANE_FATAL("Incoherent datatype size v={0} expected={1}", x->datatypeSize(), v);
232 ++m_nb_specialized;
233 }
234 else
235 ++m_nb_generic;
236 return RefType(x, v);
237 }
238
239 public:
240
241 void copyTo(Int32 datatype_size, const IndexedMemoryCopyArgs& args) override
242 {
243 auto c = _copier(datatype_size);
244 c.copyTo(args);
245 }
246 void copyTo(Int32 datatype_size, const IndexedMultiMemoryCopyArgs& args) override
247 {
248 auto c = _copier(datatype_size);
249 c.copyTo(args);
250 }
251 void copyFrom(Int32 datatype_size, const IndexedMemoryCopyArgs& args) override
252 {
253 auto c = _copier(datatype_size);
254 c.copyFrom(args);
255 }
256 void copyFrom(Int32 datatype_size, const IndexedMultiMemoryCopyArgs& args) override
257 {
258 auto c = _copier(datatype_size);
259 c.copyFrom(args);
260 }
261 void fill(Int32 datatype_size, const IndexedMemoryCopyArgs& args) override
262 {
263 auto c = _copier(datatype_size);
264 c.fill(args);
265 }
266 void fill(Int32 datatype_size, const IndexedMultiMemoryCopyArgs& args) override
267 {
268 auto c = _copier(datatype_size);
269 c.fill(args);
270 }
271
272 private:
273
285
294
295 std::array<InterfaceType*, NB_COPIER> m_copier;
296 std::atomic<Int32> m_nb_specialized = 0;
297 std::atomic<Int32> m_nb_generic = 0;
298};
299
300/*---------------------------------------------------------------------------*/
301/*---------------------------------------------------------------------------*/
302
303template <typename DataType, typename Extent>
305: public ISpecificMemoryCopy
306{
307 static Int32 typeSize() { return static_cast<Int32>(sizeof(DataType)); }
308
309 public:
310
311 Int32 datatypeSize() const override { return m_extent.v * typeSize(); }
312
313 public:
314
315 Extent m_extent;
316
317 protected:
318
319 static Span<const DataType> _toTrueType(Span<const std::byte> a)
320 {
321 return { reinterpret_cast<const DataType*>(a.data()), a.size() / typeSize() };
322 }
323 static Span<DataType> _toTrueType(Span<std::byte> a)
324 {
325 return { reinterpret_cast<DataType*>(a.data()), a.size() / typeSize() };
326 }
327};
328
329/*---------------------------------------------------------------------------*/
330/*---------------------------------------------------------------------------*/
331
332template <typename DataType, typename Extent>
334: public SpecificMemoryCopyBase<DataType, Extent>
335{
337 using BaseClass::_toTrueType;
338
339 public:
340
341 using BaseClass::m_extent;
342
343 public:
344
345 void copyFrom(const IndexedMemoryCopyArgs& args) override
346 {
347 _copyFrom(args.m_indexes, _toTrueType(args.m_source), _toTrueType(args.m_destination));
348 }
349 void copyTo(const IndexedMemoryCopyArgs& args) override
350 {
351 _copyTo(args.m_indexes, _toTrueType(args.m_source), _toTrueType(args.m_destination));
352 }
353 void fill(const IndexedMemoryCopyArgs& args) override
354 {
355 _fill(args.m_indexes, _toTrueType(args.m_source), _toTrueType(args.m_destination));
356 }
357 void copyFrom(const IndexedMultiMemoryCopyArgs& args) override
358 {
359 _copyFrom(args.m_indexes, args.m_multi_memory, _toTrueType(args.m_source_buffer));
360 }
361 void copyTo(const IndexedMultiMemoryCopyArgs& args) override
362 {
363 _copyTo(args.m_indexes, args.m_const_multi_memory, _toTrueType(args.m_destination_buffer));
364 }
365 void fill(const IndexedMultiMemoryCopyArgs& args) override
366 {
367 _fill(args.m_indexes, args.m_multi_memory, _toTrueType(args.m_source_buffer));
368 }
369
370 public:
371
372 void _copyFrom(SmallSpan<const Int32> indexes, Span<const DataType> source,
373 Span<DataType> destination)
374 {
375 ARCANE_CHECK_POINTER(indexes.data());
376 ARCANE_CHECK_POINTER(source.data());
377 ARCANE_CHECK_POINTER(destination.data());
378
379 Int32 nb_index = indexes.size();
380 for (Int32 i = 0; i < nb_index; ++i) {
381 Int64 z_index = (Int64)i * m_extent.v;
382 Int64 zci = (Int64)(indexes[i]) * m_extent.v;
383 for (Int32 z = 0, n = m_extent.v; z < n; ++z)
384 destination[z_index + z] = source[zci + z];
385 }
386 }
389 {
390 ARCANE_CHECK_POINTER(indexes.data());
391 ARCANE_CHECK_POINTER(source.data());
393
394 const Int32 value_size = indexes.size() / 2;
395 for (Int32 i = 0; i < value_size; ++i) {
396 Int32 index0 = indexes[i * 2];
397 Int32 index1 = indexes[(i * 2) + 1];
399 auto* orig_view_data = reinterpret_cast<DataType*>(orig_view_bytes.data());
400 // Utilise un span pour tester les débordements de tableau mais on
401 // pourrait directement utiliser 'orig_view_data' pour plus de performances
402 Span<DataType> orig_view = { orig_view_data, orig_view_bytes.size() / (Int64)sizeof(DataType) };
403 Int64 zci = ((Int64)(index1)) * m_extent.v;
404 Int64 z_index = (Int64)i * m_extent.v;
405 for (Int32 z = 0, n = m_extent.v; z < n; ++z)
406 orig_view[zci + z] = source[z_index + z];
407 }
408 }
409
416 Span<DataType> destination)
417 {
418 ARCANE_CHECK_POINTER(source.data());
419 ARCANE_CHECK_POINTER(destination.data());
420
421 // Si \a indexes est vide, cela signifie qu'on copie toutes les valeurs
422 Int32 nb_index = indexes.size();
423 if (nb_index == 0) {
424 Int64 nb_value = destination.size() / m_extent.v;
425 for (Int64 i = 0; i < nb_value; ++i) {
426 Int64 zci = i * m_extent.v;
427 for (Int32 z = 0, n = m_extent.v; z < n; ++z)
428 destination[zci + z] = source[z];
429 }
430 }
431 else {
432 ARCANE_CHECK_POINTER(indexes.data());
433 for (Int32 i = 0; i < nb_index; ++i) {
434 Int64 zci = (Int64)(indexes[i]) * m_extent.v;
435 for (Int32 z = 0, n = m_extent.v; z < n; ++z)
436 destination[zci + z] = source[z];
437 }
438 }
439 }
440
443 {
444 ARCANE_CHECK_POINTER(source.data());
446
447 const Int32 nb_index = indexes.size() / 2;
448 if (nb_index == 0) {
449 // Remplit toutes les valeurs du tableau avec la source.
450 const Int32 nb_dim1 = multi_views.size();
451 for (Int32 zz = 0; zz < nb_dim1; ++zz) {
453 Int64 nb_value = orig_view_bytes.size() / ((Int64)sizeof(DataType) * m_extent.v);
454 auto* orig_view_data = reinterpret_cast<DataType*>(orig_view_bytes.data());
456 for (Int64 i = 0; i < nb_value; i += m_extent.v) {
457 // Utilise un span pour tester les débordements de tableau mais on
458 // pourrait directement utiliser 'orig_view_data' pour plus de performances
459 for (Int32 z = 0, n = m_extent.v; z < n; ++z)
460 orig_view[i + z] = source[z];
461 }
462 }
463 }
464 else {
465 ARCANE_CHECK_POINTER(indexes.data());
466 for (Int32 i = 0; i < nb_index; ++i) {
467 Int32 index0 = indexes[i * 2];
468 Int32 index1 = indexes[(i * 2) + 1];
469 Span<std::byte> orig_view_bytes = multi_views[index0];
470 auto* orig_view_data = reinterpret_cast<DataType*>(orig_view_bytes.data());
471 // Utilise un span pour tester les débordements de tableau mais on
472 // pourrait directement utiliser 'orig_view_data' pour plus de performances
473 Span<DataType> orig_view = { orig_view_data, orig_view_bytes.size() / (Int64)sizeof(DataType) };
474 Int64 zci = ((Int64)(index1)) * m_extent.v;
475 for (Int32 z = 0, n = m_extent.v; z < n; ++z)
476 orig_view[zci + z] = source[z];
477 }
478 }
479 }
480
481 void _copyTo(SmallSpan<const Int32> indexes, Span<const DataType> source,
482 Span<DataType> destination)
483 {
484 ARCANE_CHECK_POINTER(indexes.data());
485 ARCANE_CHECK_POINTER(source.data());
486 ARCANE_CHECK_POINTER(destination.data());
487
488 Int32 nb_index = indexes.size();
489
490 for (Int32 i = 0; i < nb_index; ++i) {
491 Int64 z_index = (Int64)i * m_extent.v;
492 Int64 zci = (Int64)(indexes[i]) * m_extent.v;
493 for (Int32 z = 0, n = m_extent.v; z < n; ++z)
494 destination[zci + z] = source[z_index + z];
495 }
496 }
497
498 void _copyTo(SmallSpan<const Int32> indexes, SmallSpan<const Span<const std::byte>> multi_views,
499 Span<DataType> destination)
500 {
501 ARCANE_CHECK_POINTER(indexes.data());
502 ARCANE_CHECK_POINTER(destination.data());
503 ARCANE_CHECK_POINTER(multi_views.data());
504
505 const Int32 value_size = indexes.size() / 2;
506 for (Int32 i = 0; i < value_size; ++i) {
507 Int32 index0 = indexes[i * 2];
508 Int32 index1 = indexes[(i * 2) + 1];
509 Span<const std::byte> orig_view_bytes = multi_views[index0];
510 auto* orig_view_data = reinterpret_cast<const DataType*>(orig_view_bytes.data());
511 // Utilise un span pour tester les débordements de tableau mais on
512 // pourrait directement utiliser 'orig_view_data' pour plus de performances
513 Span<const DataType> orig_view = { orig_view_data, orig_view_bytes.size() / (Int64)sizeof(DataType) };
514 Int64 zci = ((Int64)(index1)) * m_extent.v;
515 Int64 z_index = (Int64)i * m_extent.v;
516 for (Int32 z = 0, n = m_extent.v; z < n; ++z)
517 destination[z_index + z] = orig_view[zci + z];
518 }
519 }
520};
521
522/*---------------------------------------------------------------------------*/
523/*---------------------------------------------------------------------------*/
524
525template <typename Traits>
527{
528 template <typename DataType, typename Extent> using SpecificType = typename Traits::template SpecificType<DataType, Extent>;
529
530 public:
531
533 : m_specialized_copier(specialized_copier)
534 , m_used_copier(specialized_copier)
535 {
536 m_generic_copier.m_extent.v = datatype_size;
537 if (!m_used_copier)
538 m_used_copier = &m_generic_copier;
539 }
540
541 void copyFrom(const IndexedMemoryCopyArgs& args)
542 {
543 m_used_copier->copyFrom(args);
544 }
545
546 void copyTo(const IndexedMemoryCopyArgs& args)
547 {
548 m_used_copier->copyTo(args);
549 }
550
551 void fill(const IndexedMemoryCopyArgs& args)
552 {
553 m_used_copier->fill(args);
554 }
555
556 void copyFrom(const IndexedMultiMemoryCopyArgs& args)
557 {
558 m_used_copier->copyFrom(args);
559 }
560
561 void copyTo(const IndexedMultiMemoryCopyArgs& args)
562 {
563 m_used_copier->copyTo(args);
564 }
565
566 void fill(const IndexedMultiMemoryCopyArgs& args)
567 {
568 m_used_copier->fill(args);
569 }
570
571 private:
572
573 ISpecificMemoryCopy* m_specialized_copier = nullptr;
575 ISpecificMemoryCopy* m_used_copier = nullptr;
576};
577
578/*---------------------------------------------------------------------------*/
579/*---------------------------------------------------------------------------*/
580
581} // namespace Arcane::impl
582
583/*---------------------------------------------------------------------------*/
584/*---------------------------------------------------------------------------*/
585
586#endif
#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.
File d'exécution pour un accélérateur.
Lecteur des fichiers de maillage via la bibliothèque LIMA.
Definition Lima.cc:120
Interface d'une liste d'instances de ISpecificMemoryCopy spécialisées.
Interface d'un copieur mémoire spécialisé pour une taille de donnée.
Arguments pour une copie de certains indices entre deux zones mémoire.
Arguments pour une copie de certains indices vers/depuis une zone mémoire multiple.
IndexedMultiMemoryCopyArgs(SmallSpan< const Int32 > indexes, SmallSpan< Span< std::byte > > multi_memory, Span< const std::byte > source, RunQueue *run_queue)
Constructor pour copyFrom.
IndexedMultiMemoryCopyArgs(SmallSpan< const Int32 > indexes, SmallSpan< const Span< const std::byte > > multi_memory, Span< std::byte > destination, RunQueue *run_queue)
Constructeur pour copyTo.
Liste d'instances de ISpecificMemoryCopy spécialisées.
void _fill(SmallSpan< const Int32 > indexes, Span< const DataType > source, Span< DataType > destination)
Remplit les valeurs d'indices spécifiés par indexes.
Vue d'un tableau d'éléments de type T.
Definition Span.h:670