TrioCFD 1.9.8
TrioCFD documentation
Loading...
Searching...
No Matches
Device_test.cpp
1/****************************************************************************
2* Copyright (c) 2025, CEA
3* All rights reserved.
4*
5* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
6* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
7* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
8* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
9*
10* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
11* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
12* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
13*
14*****************************************************************************/
15
16#include <TRUSTTrav.h>
17#include <TRUSTTab_parts.h>
18#include <Device.h>
19#include <string>
20#include <sstream>
21#include <comm_incl.h>
22#include <DeviceMemory.h>
23
24// Device_test: teste intensivement les methodes de l'interface Device.h:
25bool self_tested_ = false;
26void self_test()
27{
28 if (self_tested_)
29 return;
30 else
31 self_tested_ = true;
32 {
33 // local_operations_vect_bis_generic
34 // Cas test unitaire critique:
35 {
36 DoubleTab a(2);
37 a(0) = 1;
38 a(1) = 2;
39 mapToDevice(a);
40 double mp = mp_norme_vect(a);
41 double sol = sqrt(Process::nproc() * 5);
42 if (mp != sol)
43 {
44 Cerr << "What! " << mp << " != " << sol << finl;
45 Cerr
46 << "Weird bug seen during a sum reduction with Kokkos::parallel_reduce for TRUST production build on Cuda 11.6. Fixed with Cuda 12.1 (or before...)."
47 << finl;
48 Cerr << "Update Cuda please !" << finl;
50 }
51 }
52 }
53#ifndef NDEBUG
54 // Test mapToDevice(arr)
55 // Status
56 // Status before Status after Copy ?
57 // DataLocation::HostOnly DataLocation::HostDevice Yes
58 // Host DataLocation::HostDevice Yes
59 // DataLocation::HostDevice DataLocation::HostDevice No
60 // Device Device No
61 {
62 DoubleTab a(10);
63 assert(a.get_data_location() == DataLocation::HostOnly);
64 mapToDevice(a);
65 assert(a.get_data_location() == DataLocation::HostDevice);
66 a[1]=0;
67 assert(a.get_data_location() == DataLocation::Host);
68 mapToDevice(a);
69 assert(a.get_data_location() == DataLocation::HostDevice);
70 }
71
72 {
73 DoubleTab a(10);
74 a = 23;
75 assert(a.get_data_location() == DataLocation::HostOnly);
76 {
77 DoubleTab b;
78 b.ref(a);
79 mapToDevice(b);
80 assert(b.get_data_location() == DataLocation::HostDevice);
81 assert(a.get_data_location() == DataLocation::HostDevice);
82 }
83 }
84
85 int N = 10;
86 // Teste les methodes d'acces sur le device:
87 DoubleTab inco(N);
88 inco = 1;
89 mapToDevice(inco); // copy
90 assert(inco.get_data_location() == DataLocation::HostDevice);
91 assert(inco.ref_count() == 1);
92 {
93 // Exemple 1er operateur
94 DoubleTab a;
95 a.ref(inco); // Doit prendre l'etat de inco
96 assert(a.get_data_location() == DataLocation::HostDevice);
97 assert(a.ref_count() == 2);
98 assert(inco.ref_count() == 2);
99 DoubleTab b(N);
100
101 CDoubleArrView a_v = static_cast<const ArrOfDouble&>(a).view_ro();
102 DoubleArrView b_v = static_cast<ArrOfDouble&>(b).view_wo();
103 Kokkos::parallel_for(N, KOKKOS_LAMBDA(const int i)
104 {
105 b_v[i] = a_v[i];
106 });
107 Kokkos::fence();
108
109 const DoubleTab& const_b = b;
110 const DoubleTab& const_a = a;
111 assert(const_b[5] == const_a[5]);
112 assert(const_b[5] == 1);
113 //assert(b[5] == a[5]); // Argh double& TRUSTArray<double>::operator[](int i) appele pour a et donc repasse sur host
114 // Comment detecter que operator[](int i) est utilise en read ou write ? Possible ? Non, sauf si const utilise.
115 assert(a.get_data_location() == DataLocation::HostDevice);
116 assert(b.get_data_location() == DataLocation::HostDevice);
117 assert(inco.get_data_location() == DataLocation::HostDevice);
118 }
119 assert(inco.get_data_location() == DataLocation::HostDevice);
120 assert(inco.ref_count() == 1);
121 {
122 // Exemple 2eme operateur
123 DoubleTab a;
124 a.ref(inco); // Doit prendre l'etat de inco qui est toujours DataLocation::HostDevice
125 assert(a.get_data_location() == DataLocation::HostDevice);
126 assert(a.ref_count() == 2);
127 assert(inco.ref_count() == 2);
128
129 DoubleTab b(N);
130 CDoubleArrView a_v = static_cast<const ArrOfDouble&>(a).view_ro();
131 DoubleArrView b_v = static_cast<ArrOfDouble&>(b).view_wo();
132 Kokkos::parallel_for(N, KOKKOS_LAMBDA(const int i)
133 {
134 b_v[i] = a_v[i];
135 });
136 Kokkos::fence();
137
138 const DoubleTab& const_b = b;
139 const DoubleTab& const_a = a;
140 assert(const_b[5] == const_a[5]);
141 assert(const_b[5] == 1);
142 assert(a.get_data_location() == DataLocation::HostDevice);
143 assert(b.get_data_location() == DataLocation::HostDevice);
144 }
145 assert(inco.ref_count() == 1);
146
147 // Mise a jour de l'inconnue sur le device:
148 inco += 1;
149 assert(inco.get_data_location() == DataLocation::Device);
150 assert(inco.ref_count() == 1);
151 {
152 // Pas de temps suivant, nouvel operateur:
153 DoubleTab a;
154 a.ref(inco); // Doit prendre l'etat de inco
155 assert(a.get_data_location() == DataLocation::Device);
156 assert(a.ref_count() == 2);
157 assert(inco.ref_count() == 2);
158
159 DoubleTab b(N);
160 CDoubleArrView a_v = static_cast<const ArrOfDouble&>(a).view_ro();
161 DoubleArrView b_v = static_cast<ArrOfDouble&>(b).view_wo();
162 Kokkos::parallel_for(N, KOKKOS_LAMBDA(const int i)
163 {
164 b_v[i] = a_v[i];
165 });
166 Kokkos::fence();
167 const DoubleTab& const_b = b;
168 const DoubleTab& const_a = a;
169 assert(const_b[5] == const_a[5]);
170 assert(const_b[5] == 2);
171 assert(a.get_data_location() == DataLocation::HostDevice);
172 assert(b.get_data_location() == DataLocation::HostDevice);
173 assert(inco.get_data_location() == DataLocation::HostDevice); // Car a ref sur inco
174 }
175 assert(inco.get_data_location() == DataLocation::HostDevice);
176 // Mise a jour de l'inconnue sur le device
177 {
178 inco += 1;
179 assert(inco.get_data_location() == DataLocation::Device);
180
181 DoubleTab a;
182 a.ref(inco); // Doit prendre l'etat de inco
183 assert(a.get_data_location() == DataLocation::Device);
184 assert(a.ref_count() == 2);
185 assert(inco.ref_count() == 2);
186
187 DoubleTab b(N);
188 CDoubleArrView a_v = static_cast<const ArrOfDouble&>(a).view_ro();
189 DoubleArrView b_v = static_cast<ArrOfDouble&>(b).view_wo();
190 Kokkos::parallel_for(N, KOKKOS_LAMBDA(const int i)
191 {
192 b_v[i] = a_v[i];
193 });
194 Kokkos::fence();
195 const DoubleTab& const_b = b;
196 const DoubleTab& const_a = a;
197 assert(const_b[5] == const_a[5]);
198 assert(const_b[5] == 3);
199 assert(a.get_data_location() == DataLocation::HostDevice);
200 assert(b.get_data_location() == DataLocation::HostDevice);
201 assert(inco.get_data_location() == DataLocation::HostDevice);
202 }
203 assert(inco.get_data_location() == DataLocation::HostDevice);
204
205 // Test d'operations ArrOfDouble sur GPU
206 {
207 ArrOfDouble a(10), b(10);
208 a=1;
209 b=2;
210 mapToDevice(a);
211 mapToDevice(b);
212 b+=a; // TRUSTArray& operator+=(const TRUSTArray& y) sur le device
213 b+=3; // TRUSTArray& operator+=(const _TYPE_ dy)
214 b-=2; // TRUSTArray& operator-=(const _TYPE_ dy)
215 b-=a; // TRUSTArray& operator-=(const TRUSTArray& y)
216 // ToDo regler: Multiple definition of 'nvkernel__ZN10TRUST
217 //b*=10; // TRUSTArray& operator*= (const _TYPE_ dy)
218 //b/=2; // TRUSTArray& operator/= (const _TYPE_ dy)
219 assert(a.get_data_location() == DataLocation::HostDevice);
220 assert(b.get_data_location() == DataLocation::Device);
221 const ArrOfDouble& const_b = b;
222 // Operations sur le device:
223 // Retour sur le host pour verifier le resultat
224 copyFromDevice(b);
225 assert(const_b[0] == 3);
226 }
227
228 // Constructeurs sur device:
229 {
230 DoubleTab a(10);
231 allocateOnDevice(a);
232 assert(a.get_data_location() == DataLocation::Device);
233 a = 1; // Sur le device
234 assert(a.get_data_location() == DataLocation::Device);
235 DoubleTab b(a); // b doit etre aussi alloue sur le device et la copie faite sur le device
236 assert(b.get_data_location() == DataLocation::Device);
237 copyFromDevice(b);
238 const ArrOfDouble& const_b = b;
239 assert(const_b[0] == 1);
240 assert(const_b[b.size() - 1] == 1);
241 }
242 {
243 // Copies de tableau:
244 DoubleTab a(10);
245 a=1;
246 mapToDevice(a); // a sur le device
247 DoubleTab b;
248 b = a; // b doit etre aussi alloue/rempli sur le device par copie de a:
249 assert(b.get_data_location() == DataLocation::Device);
250 const ArrOfDouble& const_b = b;
251 copyFromDevice(b);
252 assert(const_b[0] == 1);
253 assert(const_b[b.size() - 1] == 1);
254 }
255 // operator_vect_vect_generic pour DoubleTab::operator+-*/
256 {
257 DoubleTab a(10), b(10);
258 const ArrOfDouble& const_a = a;
259 const ArrOfDouble& const_b = b;
260 a=1;
261 b=10;
262 mapToDevice(a);
263 assert(a.get_data_location() == DataLocation::HostDevice);
264 mapToDevice(b);
265 assert(b.get_data_location() == DataLocation::HostDevice);
266 a=b; // TRUSTArray<_TYPE_>::inject_array(v) faite sur le device (a=10)
267 assert(a.get_data_location() == DataLocation::Device);
268 a+=b; // operator_vect_vect_generic(ADD_) faite sur le device (a=20)
269 assert(a.get_data_location() == DataLocation::Device);
270 b-=a; // operator_vect_vect_generic(SUB_) faite sur le device (b=-10)
271 assert(b.get_data_location() == DataLocation::Device);
272 // Retour sur le host pour verifier les resultats
273 copyFromDevice(a);
274 copyFromDevice(b);
275 assert(a.get_data_location() == DataLocation::HostDevice);
276 assert(b.get_data_location() == DataLocation::HostDevice);
277 assert(const_a[0] == 20);
278 assert(const_a[a.size()-1] == 20);
279 assert(const_b[0] == -10);
280 assert(const_b[b.size()-1] == -10);
281 }
282 // DoubleTrav
283 {
284 DoubleTrav a(10*N);
285 a = 1;
286 mapToDevice(a); // copy
287 assert(a.get_data_location() == DataLocation::HostDevice);
288 assert(a.ref_count() == 1);
290 }
291 // Second DoubleTrav
292 {
294 DoubleTrav a(10*N); // a is initialized to 0 on the device cause previous DoubleTrav was HostDevice !
295 assert(a.get_data_location() == DataLocation::Device);
296 const ArrOfDouble& const_a = a;
297 assert(const_a[0] == 0);
298 }
299 // Constructeur par copie DoubleTab
300 {
301 DoubleTab a(N);
302 a=-1;
303 mapToDevice(a); // Sur le device
304 DoubleTrav b(a); // b doit etre sur le device (=0)
305 assert(b.get_data_location()==DataLocation::Device);
306 b+=1; // Operation doit etre faite sur le device (=1)
307 assert(b.get_data_location()==DataLocation::Device);
308 copyFromDevice(b);
309 const ArrOfDouble& const_b = b;
310 assert(const_b[0] == 1);
311 assert(const_b[b.size()-1] == 1);
312 }
313 // max/min methods
314 {
315 DoubleTab a(3);
316 a(0)=1;
317 a(1)=3;
318 a(2)=-10;
319 mapToDevice(a);
320 // Change sur le host pour test:
321 a.data()[0]=0;
322 a.data()[1]=0;
323 a.data()[2]=0;
324 a.set_data_location(DataLocation::Device);
325 assert(local_max_vect(a)==3);
326 assert(local_min_vect(a)==-10);
327 assert(local_max_abs_vect(a)==10);
328 assert(local_min_abs_vect(a)==1);
329 //assert(local_imax_vect(a)==1);
330 //assert(local_imin_vect(a)==2);
331 assert(a.isDataOnDevice());
332 // On teste sur host les deux methodes imin,imax non portees sur GPU:
333 copyFromDevice(a);
334 assert(a.get_data_location()==DataLocation::HostDevice);
335 assert(local_imax_vect(a)==1);
336 assert(local_imin_vect(a)==2);
337 }
338 // ref_array
339 {
340 DoubleTab a(N);
341 a=1;
342 mapToDevice(a); // Sur le device
343 assert(a.get_data_location()==DataLocation::HostDevice);
344 DoubleTab b;
345 b.ref_array(a);
346 assert(b.get_data_location()==DataLocation::HostDevice); // b doit etre sur le device
347 }
348 // ref_tab/ref_array on a chunk array
349 {
350 DoubleTab a(2*N);
351 a=1;
352 DoubleTab b;
353 b.ref_tab(a, 0, N); // reference partielle sur a
354 mapToDevice(b); // Sur le device
355 assert(b.get_data_location()==DataLocation::HostDevice); // b doit etre sur le device
356 assert(a.get_data_location()==DataLocation::HostDevice); // a doit etre sur le device
357
358 DoubleArrView a_v = static_cast<ArrOfDouble&>(a).view_wo();
359 Kokkos::parallel_for(2*N, KOKKOS_LAMBDA(const int i)
360 {
361 a_v[i] = 2;
362 });
363 Kokkos::fence();
364 // Retour sur le device et verification que a etait completement sur le device:
365 assert(a.get_data_location()==DataLocation::Device);
366 assert(a(0)==2);
367 assert(a.get_data_location()==DataLocation::Host);
368 assert(a(2*N-1)==2);
369 }
370 double * ptr_host;
371 {
372 DoubleTab a(N);
373 a=1;
374 {
375 DoubleTab b;
376 b.ref_array(a);
377 mapToDevice(b); // Sur le device
378 assert(a.data()==b.data());
379 assert(b.get_data_location() == DataLocation::HostDevice);
380 assert(a.get_data_location() == DataLocation::HostDevice); // a est considere sur le device egalement
381 }
382 assert(a.get_data_location() == DataLocation::HostDevice);
383 ptr_host = a.data();
384 assert(isAllocatedOnDevice(ptr_host)); // Verifie que le tableau possede une zone memoire sur le device
385 }
386 assert(!isAllocatedOnDevice(ptr_host)); // Verifie que le tableau ne possede plus une zone memoire sur le device
387 // Test du resize_array_ dans TRUSTArray<_TYPE_, _SIZE_>::resize_array_
388 {
389 DoubleTab a(1);
390 mapToDevice(a);
391 a=1;
392 a.resize(2);
393 a+=1;
394 assert(a.isDataOnDevice());
395 assert(a(0)==2); // Check that after resize data on device is keep
396 assert(a(1)==1); // Check that resize initialize new elements to 0
397 }
398 // ToDo:Comment gerer les DoubleTab_Parts ? Pas facile donc pour le moment
399 // le constructeur par copie fait un copyFromDevice du DoubleTab...
400 /*
401 {
402 DoubleTab pression;
403 mapToDevice(pression);
404 DoubleTab_parts P0P1(pression); // P0P1 Device
405 DoubleTab& P0 = P0P1[0];
406 DoubleTab& P1 = P0P1[1];
407 double moyenne_K = mp_moyenne_vect(P0); // P0 DataLocation::HostDevice mais pas P1 !
408 P1 -= moyenne_K; // Gros pb car P1 toujours sur Device !
409 }
410 */
411 //if (Process::me()==0) std::cerr << ptr_host << std::endl;
412
413 // DoubleTrav copy Constructor:
414 {
415 DoubleTrav b(100);
416 b = 123;
417 mapToDevice(b);
418 DoubleVect b2(b);
419 assert(b2.get_mem_storage() == STORAGE::TEMP_STORAGE);
420 assert(b2.get_data_location() == DataLocation::Device);
421
422 DoubleVect b3(b2);
423 assert(b3.get_mem_storage() == STORAGE::TEMP_STORAGE);
424 assert(b3.get_data_location() == DataLocation::Device);
425 }
426
427 {
428 // Provisoire reproduire le blocage ?
429 //DoubleTab a(10);
430 //allocateOnDevice(a);
431 //allocateOnDevice(a);
432 }
433#endif
434}
435
436
static int nproc()
renvoie le nombre de processeurs dans le groupe courant Voir Comm_Group::nproc() et PE_Groups::curren...
Definition Process.cpp:104
static void exit(int exit_code=-1)
Routine de sortie de TRUST dans une region Kokkos.
Definition Process.cpp:455
DataLocation get_data_location()
Definition TRUSTArray.h:245
int ref_count() const
_TYPE_ * data()
void set_data_location(DataLocation flag)
Definition TRUSTArray.h:247
bool isDataOnDevice() const
virtual void ref(const TRUSTTab &)
Definition TRUSTTab.tpp:308
void ref_array(TRUSTArray< _TYPE_, _SIZE_ > &, _SIZE_ start=0, _SIZE_ sz=-1) override
Definition TRUSTTab.tpp:332
virtual void ref_tab(TRUSTTab &, _SIZE_ start_line=0, _SIZE_ nb_lines=-1)
Definition TRUSTTab.tpp:345
void resize(_SIZE_ n, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
Definition TRUSTTab.tpp:469
_SIZE_ size() const
Definition TRUSTVect.tpp:45
static void printMemoryMap()