source: Sophya/trunk/SophyaProg/Tests/zthr.cc@ 3263

Last change on this file since 3263 was 3263, checked in by ansari, 18 years ago

Ajout nouveaux cas de test avec threads select= arrdl OU arrmf (calcul de type DL sur vecteur OU v2=Sin(v1)) dans zthr.cc , Reza 11/06/2007

File size: 13.3 KB
Line 
1#include "sopnamsp.h"
2#include "zthread.h"
3#include "resusage.h"
4
5#include <iostream>
6#include <vector>
7
8#include "tmatrix.h"
9#include "tvector.h"
10#include "matharr.h"
11#include "tarrinit.h"
12
13#include <stdlib.h>
14#include <stdio.h>
15
16/* -------------------------------------------------
17 Programme de test des classes de threads de SOPHYA
18 SOPHYA::ZThread SOPHYA::ZMutex ...
19 Exemples d'execution
20 csh> time zthr mtx 2 500
21 csh> time zthr arr 2 500
22 csh> time zthr arrdl 2 500
23 csh> time zthr arrmf 2 500
24 csh> time zthr sync 4 1000
25 csh> time zthr syncp 4 1000
26*/
27
28#include <time.h>
29#include <unistd.h>
30
31#include "timing.h"
32#include "ctimer.h"
33
34
35// --- Structure d'argument pour fonction d'execution dans les threads de test
36typedef struct {
37 int_4 thid, NTh;
38 int_4 M, VSz;
39} ztarg;
40
41// --- fonction de test simple avec boucle de sleep
42void funzt(void *arg)
43{
44time_t t0, t1;
45int i;
46
47ztarg * za = (ztarg *)arg;
48
49t0 = time(NULL);
50printf("+++++ funzt(ThId=%d) Entry to funzt (za.M=%d) +++++\n", za->thid, za->M);
51int imax = za->M;
52for(i=0; i<imax; i++)
53 {
54 sleep(3);
55 t1 = time(NULL)-t0;
56 printf("++funzt(ThId=%d) Dt= %d \n", za->thid, (int)t1);
57 }
58
59return;
60}
61
62// --- fonction de test simple avec calcul matriciel (produit de 2 matrices double)
63void mtx_funzt(void *arg)
64{
65 ztarg * za = (ztarg *)arg;
66 cout << ">>>> mtx-funzt(ThId=" << za->thid << ") - Matrix size= " << za->M << endl;
67
68 sa_size_t m = za->M;
69 Matrix a1(m,m), a2(m,m), mxprod;
70 a1 = RandomSequence(RandomSequence::Gaussian, 0., 4.);
71 a2 = RandomSequence(RandomSequence::Gaussian, 0., 3.);
72 char buff[128];
73 sprintf(buff, "mtx-funzt(ThId=%d) EndOfInit", za->thid);
74 PrtTim(buff);
75 mxprod = a1*a2;
76 sprintf(buff, "mtx-funzt(ThId=%d) EndOfMxProd", za->thid);
77 PrtTim(buff);
78 return;
79}
80// --- fonction de test simple avec calcul sur tableaux entier I4
81void arr_funzt(void *arg)
82{
83 ztarg * za = (ztarg *)arg;
84 cout << ">>>> arr-funzt(ThId=" << za->thid << ") - Matrix size= " << za->M << endl;
85
86 sa_size_t m = za->M;
87 TMatrix<int_4> a1(m,m), a2(m,m), ares;
88 a1 = RegularSequence(1.,1.);
89 a2 = RegularSequence(5.,3.);
90 char buff[128];
91 sprintf(buff, "arr-funzt(ThId=%d) EndOfInit", za->thid);
92 PrtTim(buff);
93 // ares = 4*a1*12*a2; correction le 23/05/2007 - * (prod.mtx par erreur)
94 ares = (4*a1)+(12*a2);
95 sprintf(buff, "arr-funzt(ThId=%d) EndOfOper", za->thid);
96 PrtTim(buff);
97 return;
98}
99// --- fonction de test simple avec calcul de type DL sur tableaux double 1D
100void arrdl_funzt(void *arg)
101{
102 ztarg * za = (ztarg *)arg;
103 sa_size_t vsz = za->M*za->M;
104
105 cout << ">>>> arrdl-funzt(ThId=" << za->thid << " VecSz=M*M " << vsz
106 << " V2=DLO4(V1) , NOp ~= 10*vsz=" << 10*vsz << endl;
107
108 TVector<r_8> v1(vsz), v2(vsz);
109 v1 = RegularSequence(1.,0.001);
110 char buff[128];
111 sprintf(buff, "arrdl-funzt(ThId=%d) EndOfInit", za->thid);
112 PrtTim(buff);
113 for(sa_size_t i=0; i<vsz; i++) {
114 double x = v1(i);
115 v2(i) = x*(1+x*(x/2.+x*(x/6.+x*x/24.)));
116 }
117 sprintf(buff, "arrdl-funzt(ThId=%d) EndOfOper", za->thid);
118 PrtTim(buff);
119 return;
120}
121// --- fonction de test simple avec calcul de type fonction mathematique sur tableaux double 1D
122void arrmf_funzt(void *arg)
123{
124 ztarg * za = (ztarg *)arg;
125 sa_size_t vsz = za->M*za->M;
126
127 cout << ">>>> arrmf-funzt(ThId=" << za->thid << " VecSz=M*M " << vsz
128 << " V2=Sin(V1) , NOp ~= 10*vsz=" << 10*vsz << endl;
129
130 TVector<r_8> v1(vsz), v2(vsz);
131 v1 = RegularSequence(1.,0.001);
132 char buff[128];
133 sprintf(buff, "arrmf-funzt(ThId=%d) EndOfInit", za->thid);
134 PrtTim(buff);
135 v2 = Sin(v1);
136
137 sprintf(buff, "arrmf-funzt(ThId=%d) EndOfOper", za->thid);
138 PrtTim(buff);
139 return;
140}
141
142
143// Structure de gestion utilisee par la classe MTVecPool
144typedef struct {
145 bool busy;
146 int stat;
147} St_VecPool;
148
149// -------------------------------------------------------------------
150// Structure de gestion de zones memoire partagee (des vecteurs) entre
151// threads - qui doivent operer successivement sur les vecteurs
152// -------------------------------------------------------------------
153class MTVecPool {
154public:
155 MTVecPool(uint_4 nth, uint_4 vsz, uint_4 nvec)
156 {
157 if (nth > 60) throw ParmError("MTVecPool::MTVecPool() nth > 60");
158 if ((nth < 1) || (vsz < 2))
159 throw ParmError("MTVecPool::MTVecPool() nth<1 OR vsz<2 ");
160 _vmx.SetSize(vsz, nvec);
161 _nth = nth;
162 _vsz = vsz;
163 TVector<int_8> xx(2);
164 for(int k=0; k<nth; k++) _vecp.push_back(xx);
165 cout << "-- MTVecPool(nth=" << nth << ")" << endl;
166 _vmx.Show();
167 }
168 ~MTVecPool() { }
169 // Renvoie un pointeur de vecteur pour thread tid
170 TVector<int_8>* GetVecP(uint_4 tid, uint_4& idx)
171 {
172 if (tid >= _nth) ParmError("MTVecPool::GetVecP() tid > _nth");
173 //DBG cout << "DBG-GetVecP(tid= " << tid << ")" << endl;
174 if (tid == 0) {
175 mex.lock();
176 St_VecPool stv;
177 idx = _vecs.size();
178 _vecp[tid].Share(_vmx.Column(idx));
179 stv.busy = true;
180 stv.stat = 0;
181 _vecs.push_back(stv);
182 mex.unlock();
183 //DBG cout << "DBG-GetVecP(tid= " << tid << ") -> Idx=" << idx << " VecSz=" << &(_vecs[idx].vv) << endl;
184 return (&(_vecp[tid]));
185 }
186 else {
187 mex.lock();
188 bool found = false;
189 while (!found) {
190 for(uint_4 k=0; k<_vecs.size(); k++) {
191 if ( (_vecs[k].stat == tid) && (! _vecs[k].busy) ) {
192 found = true; idx = k;
193 _vecs[k].stat = tid; _vecs[k].busy = true;
194 break;
195 }
196 }
197 if (found) {
198 _vecp[tid].Share(_vmx.Column(idx));
199 mex.unlock();
200 //DBG cout << "DBG-GetVecP(tid= " << tid << ") -> nv=" << hex << rv << dec << endl;
201 return (&(_vecp[tid]));
202 }
203 else {
204 mex.broadcast();
205 mex.wait();
206 }
207 }
208 }
209 }
210 // Renvoie un vecteur pour thread tid
211 TVector<int_8> GetVec(uint_4 tid, uint_4& idx)
212 {
213 if (tid >= _nth) ParmError("MTVecPool::GetVec() tid > _nth");
214 //DBG cout << "DBG-GetVec(tid= " << tid << ")" << endl;
215 if (tid == 0) {
216 mex.lock();
217 St_VecPool stv;
218 idx = _vecs.size();
219 stv.busy = true;
220 stv.stat = 0;
221 _vecs.push_back(stv);
222 mex.unlock();
223 //DBG cout << "DBG-GetVec(tid= " << tid << ") -> Idx=" << idx << " VecSz=" << &(_vecs[idx].vv) << endl;
224 return (_vmx.Column(idx));
225 }
226 else {
227 mex.lock();
228 bool found = false;
229 while (!found) {
230 for(uint_4 k=0; k<_vecs.size(); k++) {
231 if ( (_vecs[k].stat == tid) && (! _vecs[k].busy) ) {
232 found = true; idx = k;
233 _vecs[k].stat = tid; _vecs[k].busy = true;
234 break;
235 }
236 }
237 if (found) {
238 mex.unlock();
239 //DBG cout << "DBG-GetVec(tid= " << tid << ") -> nv=" << hex << rv << dec << endl;
240 return (_vmx.Column(idx));
241 }
242 else {
243 mex.broadcast();
244 mex.wait();
245 }
246 }
247 }
248 }
249
250 // Retourne l'index du vecteur au gestionnaire, qui le marque comme disponible
251 void RetVec(uint_4 idx)
252 {
253 //DBG cout << "DBG-RetVec(idx= " << idx << ")" << endl;
254 ZSync zs(mex, 2);
255 _vecs[idx].busy = false; _vecs[idx].stat++;
256 zs.NOp();
257 }
258
259 // Verifie l'etat memoire de tous les vecteurs et fait des print
260 int Check()
261 {
262 cout << "MTVecPool::Check() NVec=" << _vecs.size() << " VSz="
263 << _vsz << " NThreads=" << _nth << endl;
264 int nerr = 0;
265 int_8 sum = 0;
266 int_8 p2 = 1;
267 int_8 min,max;
268 for(int i=0; i<_nth; i++) { sum += p2; p2 *= 2; }
269 for(uint_4 k=0; k<_vecs.size(); k++) {
270 if ( (_vecs[k].busy) || (_vecs[k].stat != _nth) ) {
271 cout << " Check()/Pb Busy Or Stat for k=" << k << endl;
272 nerr++;
273 }
274 _vmx.Column(k) -= sum;
275 _vmx.Column(k).MinMax(min, max);
276 if ((min!=0) || (max!=0)) {
277 cout << " Check()/Pb vec[k=" << k << "] != (sum=" << sum << ")" << endl;
278 nerr++;
279 }
280 }
281 if (nerr == 0) cout << "MTVecPool::Check() - OK (NErr=0)" << endl;
282 else cout << "MTVecPool::Check() PB NErr=" << nerr << endl;
283 return nerr;
284 }
285
286 // ... variables membres
287 ZMutex mex;
288 uint_4 _vsz;
289 uint_4 _nth;
290 TMatrix<int_8> _vmx;
291 vector< St_VecPool> _vecs;
292 vector< TVector<int_8> > _vecp;
293};
294
295
296static MTVecPool* mtvp = NULL;
297
298// --- fonction de test avec synchronisation entre threads en utilisant pointeur de vecteurs
299void syncp_funzt(void *arg)
300{
301 ztarg * za = (ztarg *)arg;
302 cout << ">>>> syncp_funzt(ThId=" << za->thid << ") - NVec/NLoop= " << za->M << endl;
303
304 if (mtvp == NULL)
305 throw NullPtrError("syncp_funzt: MTVecPool* mtvp = NULL");
306
307 int_4 L = za->M;
308 int_4 VS = za->VSz;
309 int_8 p2 = 1;
310 uint_4 k, ii, tid;
311 tid = za->thid;
312 for(k=0; k<tid; k++) p2 *= 2;
313
314 char buff[128];
315 sprintf(buff, "syncp_funzt(ThId=%d) StarOfLoop", za->thid);
316 PrtTim(buff);
317 uint_4 idx;
318 for(k=0; k<L; k++) {
319 *(mtvp->GetVecP(tid, idx)) += p2;
320 //DBG cout << "DBG-syncp_funzt(tid=" << tid << ", idx=" << idx << endl;
321 mtvp->RetVec(idx);
322 }
323 sprintf(buff, "syncp_funzt(ThId=%d) EndOfLoop", za->thid);
324 PrtTim(buff);
325 return;
326}
327// --- fonction de test avec synchronisation entre threads
328void sync_funzt(void *arg)
329{
330 ztarg * za = (ztarg *)arg;
331 cout << ">>>> sync_funzt(ThId=" << za->thid << ") - NVec/NLoop= " << za->M << endl;
332
333 if (mtvp == NULL)
334 throw NullPtrError("sync_funzt: MTVecPool* mtvp = NULL");
335
336 int_4 L = za->M;
337 int_4 VS = za->VSz;
338 int_8 p2 = 1;
339 uint_4 k, ii, tid;
340 tid = za->thid;
341 for(k=0; k<tid; k++) p2 *= 2;
342
343 char buff[128];
344 sprintf(buff, "sync_funzt(ThId=%d) StarOfLoop", za->thid);
345 PrtTim(buff);
346 uint_4 idx;
347 for(k=0; k<L; k++) {
348 mtvp->GetVec(tid, idx) += p2;
349 //DBG cout << "DBG-sync_funzt(tid=" << tid << ", idx=" << idx << endl;
350 mtvp->RetVec(idx);
351 }
352 sprintf(buff, "sync_funzt(ThId=%d) EndOfLoop", za->thid);
353 PrtTim(buff);
354 return;
355}
356
357class CountLock : public ZMutex {
358 int count;
359public:
360 CountLock() { count = 0; }
361 inline int Count() { lock(); int rc = ++count; unlock(); return(rc);
362 }
363};
364
365
366static int N = 1;
367static int M = 5;
368static int VSZ = 32;
369
370int main(int narg, char *arg[])
371
372{
373
374 if (narg < 4) {
375 cout << " Usage: zthr select N LM [Sz] " << endl;
376 cout << " select= sl -> simple loop with sleep " << endl;
377 cout << " select= mtx -> matrix<r_8> init and multiply mx1*mx2" << endl;
378 cout << " select= arr -> array/matrix<int_4> init and operation c1*a1+c2*a2 " << endl;
379 cout << " select= arrdl -> vectorOpe V2 ~= DLO4(V1), VSz=LM*LM " << endl;
380 cout << " select= arrmf -> vectorOpe V2 = Sin(V1), VSz=LM*LM " << endl;
381 cout << " select= clk -> Mutex lock count " << endl;
382 cout << " select= sync -> Thread synchronisation using ZMutex" << endl;
383 cout << " select= syncp -> Thread synchronisation using ZMutex , Vector pointers" << endl;
384 cout << " N= Number of threads (sl/mtx) or CountLock " << endl;
385 cout << " LM = Loop limit (sl/sync) or Matrix size (mtx) " << endl;
386 cout << " Sz = Vector size for select=sync,syncp (default=32) " << endl;
387 return(1);
388 }
389
390 string sel = arg[1];
391 if ((sel != "sl") && (sel != "mtx") && (sel != "arr") &&
392 (sel != "arrdl") && (sel != "arrmf") &&
393 (sel != "sync") && (sel != "syncp") && (sel != "clk")) {
394 cout << "zthr/erreur argument sel (!= sl / mtx / arr / clk) " << endl;
395 return 2;
396 }
397
398 //-- Decodage arguments
399 N = atoi(arg[2]);
400 M = atoi(arg[3]);
401 if (narg > 4) VSZ = atoi(arg[4]);
402 cout << "zthr/Info: select=" << sel << " N=" << N << " M= " << M
403 << " VSz=" << VSZ << endl;
404
405
406 InitTim();
407 SophyaInit();
408
409 int rc = 0;
410 try {
411 ResourceUsage res(ResourceUsage::RU_All);
412 if ((sel == "mtx") || (sel == "arr") || (sel == "sl") ||
413 (sel == "arrdl") || (sel == "arrmf") ||
414 (sel == "sync") || (sel == "syncp")) {
415 if ( (sel == "sync") || (sel == "syncp")) mtvp = new MTVecPool(N,VSZ,M);
416 vector<ztarg *> vza;
417 vector<ZThread *> vzth;
418 for(int i=0; i<N; i++) {
419 cout << "*****zthr: Creating Thread " << i+1 << " /" << N << endl;
420 ZThread * pzt = new ZThread();
421 ztarg* zap = new ztarg;
422 vzth.push_back(pzt);
423 // ATTENTION : il faut que le thid = 0 ... N-1 (et pas 1)
424 zap->thid = i; zap->M = M;
425 zap->NTh = N; zap->VSz = VSZ;
426 vza.push_back(zap);
427 if (sel == "mtx") pzt->setAction(mtx_funzt, vza[i]);
428 else if (sel == "arr") pzt->setAction(arr_funzt, vza[i]);
429 else if (sel == "arrdl") pzt->setAction(arrdl_funzt, vza[i]);
430 else if (sel == "arrmf") pzt->setAction(arrmf_funzt, vza[i]);
431 else if (sel == "sync") pzt->setAction(sync_funzt, vza[i]);
432 else if (sel == "syncp") pzt->setAction(syncp_funzt, vza[i]);
433 else pzt->setAction(funzt, vza[i]);
434 }
435 cout << "***zthr: Starting threads ... " << endl;
436 PrtTim("***zthr/StarThr");
437 for(int i=0; i<N; i++) vzth[i]->start();
438 sleep(1);
439 cout << "***ResourceUsage before thr[i].join()" << endl;
440 cout << res;
441 cout << "***zthr Joining Threads ..." << endl;
442 for(int i=0; i<N; i++) vzth[i]->join();
443 cout << "***zthr Threads Z1 ... Z" << N << " Finished OK" << endl;
444 cout << " zthr/Resusage: getDataSize() = " << res.getDataSize() << " getStackSize()="
445 << res.getStackSize() << endl;
446 cout << res;
447 for(int i=0; i<N; i++) {
448 delete vzth[i];
449 delete vza[i];
450 }
451 if (mtvp) {
452 Timer tm("MTVecPool::Check()");
453 mtvp->Check();
454 tm.Nop();
455 delete mtvp;
456 }
457 }
458 else {
459 PrtTim("BeginOfCount");
460 CountLock clk;
461 int kk;
462 for(kk=0; kk<atoi(arg[3]); kk++) {
463 clk.Count();
464 }
465 cout << " End CountLock-Test Count= " << clk.Count() << endl;
466 }
467 }
468 catch (PThrowable exc) {
469 cerr << "zthr: catched Exception " << exc.Msg() << endl;
470 rc = 77;
471 }
472 catch (...) {
473 cerr << " catched unknown (...) exception (lpk.cc) " << endl;
474 rc = 78;
475 }
476
477 return(rc);
478
479}
480
481
482
Note: See TracBrowser for help on using the repository browser.