~ubuntu-branches/ubuntu/lucid/pdl/lucid

« back to all changes in this revision

Viewing changes to Basic/Core/pdlthread.c

  • Committer: Bazaar Package Importer
  • Author(s): Ben Gertzfield
  • Date: 2002-04-08 18:47:16 UTC
  • Revision ID: james.westby@ubuntu.com-20020408184716-0hf64dc96kin3htp
Tags: upstream-2.3.2
ImportĀ upstreamĀ versionĀ 2.3.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* XXX NOTE THAT IT IS NOT SAFE TO USE ->pdls MEMBER OUTSIDE
 
2
   INITTHREADSTRUCT! */
 
3
 
 
4
#define PDL_CORE      /* For certain ifdefs */
 
5
#include "pdl.h"      /* Data structure declarations */
 
6
#include "pdlcore.h"  /* Core declarations */
 
7
 
 
8
 
 
9
#define MAX2(a,b) if((b)>(a)) a=b;
 
10
 
 
11
#define strndup strndup_mine
 
12
 
 
13
static void *strndup(void *ptr, int size) {
 
14
        if(size == 0) return 0; else
 
15
        {
 
16
        void *newptr = malloc(size);
 
17
        int i;
 
18
        for(i=0; i<size; i++) ((char *)newptr)[i] = ((char *)ptr)[i];
 
19
        return newptr;
 
20
        }
 
21
}
 
22
 
 
23
static void print_iarr(int *iarr, int n) {
 
24
  int i;
 
25
  printf("(");
 
26
  for (i=0;i<n;i++)
 
27
    printf("%s%d",(i?" ":""),iarr[i]);
 
28
  printf(")");
 
29
}
 
30
 
 
31
#define psp printf("%s",spaces)
 
32
void dump_thread(pdl_thread *thread) {
 
33
  int i;
 
34
  char spaces[] = "    ";
 
35
  printf("DUMPTHREAD %d \n",thread);
 
36
  if (0&& thread->einfo) {
 
37
    psp; printf("Funcname: %s\n",thread->einfo->funcname);
 
38
    psp; printf("Paramaters: ");
 
39
    for (i=0;i<thread->einfo->nparamnames;i++)
 
40
      printf("%s ",thread->einfo->paramnames[i]);
 
41
    printf("\n");
 
42
  }
 
43
  psp; printf("Flags: %d, Ndims: %d, Nimplicit: %d, Npdls: %d, Nextra: %d\n",
 
44
         thread->gflags,thread->ndims,thread->nimpl,thread->npdls,thread->nextra);
 
45
 
 
46
  psp; printf("Dims: "); print_iarr(thread->dims,thread->ndims); printf("\n");
 
47
  psp; printf("Inds: "); print_iarr(thread->inds,thread->ndims); printf("\n");
 
48
  psp; printf("Offs: "); print_iarr(thread->offs,thread->ndims); printf("\n");
 
49
  psp; printf("Incs: "); print_iarr(thread->incs,thread->ndims); printf("\n");
 
50
  psp; printf("Realdims: "); print_iarr(thread->realdims,thread->npdls); printf("\n");
 
51
  psp; printf("Pdls: (");
 
52
  for (i=0;i<thread->npdls;i++)
 
53
    printf("%s%d",(i?" ":""),thread->pdls[i]);
 
54
  printf(")\n");
 
55
  psp; printf("Per pdl flags: (");
 
56
  for (i=0;i<thread->npdls;i++)
 
57
    printf("%s%d",(i?" ":""),thread->flags[i]);
 
58
  printf(")\n");
 
59
}
 
60
 
 
61
int *pdl_get_threadoffsp(pdl_thread *thread)
 
62
{
 
63
  if(thread->gflags & PDL_THREAD_MAGICKED) {
 
64
        int thr = pdl_magic_get_thread(thread->pdls[thread->mag_nthpdl]);
 
65
        return thread->offs + thr * thread->npdls;
 
66
  }
 
67
/* The non-multithreaded case: return just the usual offsets */
 
68
  return thread->offs;
 
69
}
 
70
 
 
71
int *pdl_get_threadoffsp_int(pdl_thread *thread, int *nthr)
 
72
{
 
73
  if(thread->gflags & PDL_THREAD_MAGICKED) {
 
74
        int thr = pdl_magic_get_thread(thread->pdls[thread->mag_nthpdl]);
 
75
        *nthr = thr;
 
76
        return thread->offs + thr * thread->npdls;
 
77
  }
 
78
  *nthr = 0;
 
79
/* The non-multithreaded case: return just the usual offsets */
 
80
  return thread->offs;
 
81
}
 
82
 
 
83
void pdl_thread_copy(pdl_thread *from,pdl_thread *to) {
 
84
#ifdef PDL_THREAD_DEBUG
 
85
        to->magicno = from->magicno;
 
86
#endif
 
87
        to->gflags = from->gflags;
 
88
        to->einfo = from->einfo;
 
89
        to->ndims = from->ndims;
 
90
        to->nimpl = from->nimpl;
 
91
        to->npdls = from->npdls;
 
92
        to->inds = strndup(from->inds,sizeof(*to->inds)*to->ndims);
 
93
        to->dims = strndup(from->dims,sizeof(*to->dims)*to->ndims);
 
94
        to->offs = strndup(from->offs,sizeof(*to->offs)*to->npdls);
 
95
        to->incs = strndup(from->incs,sizeof(*to->offs)*to->npdls*to->ndims);
 
96
        to->realdims = from->realdims;
 
97
        to->flags = strndup(from->flags,to->npdls);
 
98
        to->pdls = strndup(from->pdls,sizeof(*to->pdls)*to->npdls); /* XX MEMLEAK */
 
99
        to->mag_nthpdl = from->mag_nth;
 
100
        to->mag_nthpdl = from->mag_nthpdl;
 
101
}
 
102
 
 
103
void pdl_freethreadloop(pdl_thread *thread) {
 
104
        PDLDEBUG_f(printf("Freethreadloop(%d, %d %d %d %d %d %d)\n",
 
105
                thread,
 
106
                thread->inds, thread->dims, thread->offs, thread->incs,
 
107
                thread->flags, thread->pdls);)
 
108
        if(!thread->inds) {return;}
 
109
        free(thread->inds);
 
110
        free(thread->dims);
 
111
        free(thread->offs);
 
112
        free(thread->incs);
 
113
/*      free(thread->realdims); */
 
114
        free(thread->flags);
 
115
        free(thread->pdls);
 
116
        pdl_clearthreadstruct(thread);
 
117
}
 
118
 
 
119
void pdl_clearthreadstruct(pdl_thread *it) {
 
120
        PDLDEBUG_f(printf("Clearthreadloop(%d)\n", it);)
 
121
        it->einfo = 0;it->inds = 0;it->dims = 0;
 
122
        it->ndims = it->nimpl = it->npdls = 0; it->offs = 0;
 
123
        it->pdls = 0;it->incs = 0; it->realdims=0; it->flags=0;
 
124
        it->gflags=0; /* unsets PDL_THREAD_INITIALIZED among others */
 
125
#ifdef PDL_THREAD_DEBUG
 
126
        PDL_THR_CLRMAGIC(it);
 
127
#endif
 
128
}
 
129
 
 
130
/* The assumptions this function makes:
 
131
 *  pdls is dynamic and may go away -> copied
 
132
 *  realdims is static and is NOT copied and NOT freed!!!
 
133
 *  creating is only used inside this routine.
 
134
 *  errorinfo is assumed static.
 
135
 *  usevaffine is assumed static. (uses if exists)
 
136
 *
 
137
 * Only the first thread-magicked pdl is taken into account.
 
138
 */
 
139
void pdl_initthreadstruct(int nobl,
 
140
        pdl **pdls,int *realdims,int *creating,int npdls,
 
141
        pdl_errorinfo *info,pdl_thread *thread, char *flags) {
 
142
        int i; int j;
 
143
        int ndims=0; int nth;
 
144
        int mx;
 
145
        int nids;
 
146
        int nimpl;
 
147
        int nthid;
 
148
 
 
149
        int mydim;
 
150
 
 
151
        int *nthreadids;
 
152
        int nthr = 0; int nthrd;
 
153
 
 
154
        PDLDEBUG_f(printf("Initthreadloop(%d)\n", thread);)
 
155
#ifdef PDL_THREAD_DEBUG
 
156
          /* the following is a fix for a problem in the current core logic
 
157
           * see comments in pdl_make_physical in pdlapi.c
 
158
           * the if clause detects if this thread has previously been initialized
 
159
           * if yes free the stuff that was allocated in the last run
 
160
           * just returning is not! good enough (I tried it)
 
161
           * CS
 
162
           */
 
163
        if (thread->magicno == PDL_THR_MAGICNO && 
 
164
            thread->gflags & PDL_THREAD_INITIALIZED) {
 
165
          PDLDEBUG_f(printf("REINITIALIZING already initialized thread\n");)    
 
166
          PDLDEBUG_f(dump_thread(thread);)      
 
167
          /* return; */ /* try again, should (!?) work */
 
168
          if (thread->inds) free(thread->inds);
 
169
          if (thread->dims) free(thread->dims);
 
170
          if (thread->offs) free(thread->offs);
 
171
          if (thread->incs) free(thread->incs);
 
172
          if (thread->flags) free(thread->flags);
 
173
          if (thread->pdls) free(thread->pdls);
 
174
          PDLDEBUG_f(warn("trying to reinitialize already initialized "
 
175
             "thread (mem-leak!); freeing...");)
 
176
        }
 
177
        PDL_THR_SETMAGIC(thread);
 
178
#endif
 
179
        thread->gflags = 0;
 
180
 
 
181
        thread->npdls = npdls;
 
182
        thread->pdls = strndup(pdls,sizeof(*pdls)*npdls);
 
183
        thread->realdims = realdims;
 
184
        thread->ndims = 0;
 
185
 
 
186
        thread->mag_nth = -1;
 
187
        thread->mag_nthpdl = -1;
 
188
        thread->mag_nthr = -1;
 
189
 
 
190
        nids=0;
 
191
        mx=0;
 
192
/* Find the max. number of threadids */
 
193
        for(j=0; j<npdls; j++) {
 
194
                if(creating[j]) continue;
 
195
                MAX2(nids,pdls[j]->nthreadids);
 
196
                MAX2(mx,pdls[j]->threadids[0] - realdims[j]);
 
197
        }
 
198
        nthreadids = pdl_malloc(sizeof(int)*nids);
 
199
        ndims += mx;  nimpl = mx; thread->nimpl = nimpl;
 
200
        for(j=0; j<npdls; j++) {
 
201
                if(creating[j]) continue;
 
202
                /* Check for magical piddles (parallelized) */
 
203
                if((!nthr) &&
 
204
                  pdls[j]->magic &&
 
205
                  (nthr = pdl_magic_thread_nthreads(pdls[j],&nthrd))) {
 
206
                        thread->mag_nthpdl = j;
 
207
                        thread->mag_nth = nthrd - realdims[j];
 
208
                       thread->mag_nthr = nthr;
 
209
                        if(thread->mag_nth < 0) {
 
210
                                die("Cannot magick non-threaded dims");
 
211
                        }
 
212
                }
 
213
 
 
214
                for(i=0; i<nids; i++) {
 
215
                        mx=0; if(pdls[j]->nthreadids <= nids) {
 
216
                                MAX2(mx,
 
217
                                     pdls[j]->threadids[i+1]
 
218
                                     - pdls[j]->threadids[i]);
 
219
                        }
 
220
                        ndims += mx;
 
221
                        nthreadids[i] = mx;
 
222
                }
 
223
        }
 
224
 
 
225
        if(nthr) {
 
226
                thread->gflags |= PDL_THREAD_MAGICKED;
 
227
        }
 
228
 
 
229
        if(ndims < nobl) { /* If too few, add enough implicit dims */
 
230
                thread->nextra = nobl - ndims;
 
231
                ndims += thread->nextra;
 
232
        } else {
 
233
                thread->nextra = 0;
 
234
        }
 
235
 
 
236
        thread->ndims = ndims;
 
237
        thread->nimpl = nimpl;
 
238
        thread->inds = malloc(sizeof(int) * thread->ndims);
 
239
        thread->dims = malloc(sizeof(int) * thread->ndims);
 
240
        thread->offs = malloc(sizeof(int) * thread->npdls
 
241
                        * (nthr>0 ? nthr : 1));
 
242
        thread->incs = malloc(sizeof(int) * thread->ndims * npdls);
 
243
        thread->flags = malloc(sizeof(char) * npdls);
 
244
        nth=0; /* Index to dimensions */
 
245
 
 
246
        /* populate the per_pdl_flags */
 
247
 
 
248
        for (i=0;i<npdls; i++) {
 
249
          thread->flags[i] = 0;
 
250
          if (PDL_VAFFOK(pdls[i]) && VAFFINE_FLAG_OK(flags,i))
 
251
            thread->flags[i] |= PDL_THREAD_VAFFINE_OK;
 
252
        }
 
253
        flags = thread->flags; /* shortcut for the remainder */
 
254
 
 
255
/* Make implicit inds */
 
256
 
 
257
        for(i=0; i<nimpl; i++) {
 
258
                thread->dims[nth] = 1;
 
259
                for(j=0; j<thread->npdls; j++) {
 
260
                        thread->incs[nth*npdls+j] = 0;
 
261
                        if(creating[j]) continue;
 
262
                        if(thread->pdls[j]->threadids[0]-
 
263
                                        thread->realdims[j] <= i)
 
264
                                continue;
 
265
                        if(pdls[j]->dims[i+realdims[j]] != 1) {
 
266
                                if(thread->dims[nth] != 1) {
 
267
                                        if(thread->dims[nth] !=
 
268
                                                pdls[j]->dims[i+realdims[j]]) {
 
269
                                              pdl_croak_param(info,j,"Mismatched implicit thread dimension %d: should be %d, is %d\n\t",
 
270
                                                        i,
 
271
                                                        thread->dims[nth],
 
272
                                                        pdls[j]->dims[i+thread->realdims[j]]);
 
273
                                        }
 
274
                                } else {
 
275
                                        thread->dims[nth] =
 
276
                                                pdls[j]->dims[i+realdims[j]];
 
277
                                }
 
278
                                thread->incs[nth*npdls+j] =
 
279
                                        PDL_TREPRINC(pdls[j],flags[j],i+realdims[j]);
 
280
                        }
 
281
                }
 
282
                nth++;
 
283
        }
 
284
 
 
285
/* Go through everything again and make the real things */
 
286
 
 
287
        for(nthid=0; nthid<nids; nthid++) {
 
288
        for(i=0; i<nthreadids[nthid]; i++) {
 
289
                thread->dims[nth] = 1;
 
290
                for(j=0; j<thread->npdls; j++) {
 
291
                        thread->incs[nth*npdls+j] = 0;
 
292
                        if(creating[j]) continue;
 
293
                        if(thread->pdls[j]->nthreadids < nthid)
 
294
                                continue;
 
295
                        if(thread->pdls[j]->threadids[nthid+1]-
 
296
                           thread->pdls[j]->threadids[nthid]
 
297
                                        <= i) continue;
 
298
                        mydim = i+thread->pdls[j]->threadids[nthid];
 
299
                        if(pdls[j]->dims[mydim]
 
300
                                        != 1) {
 
301
                                if(thread->dims[nth] != 1) {
 
302
                                        if(thread->dims[nth] !=
 
303
                                                pdls[j]->dims[mydim]) {
 
304
                                                pdl_croak_param(info,j,"Mismatched Implicit thread dimension %d: should be %d, is %d",
 
305
                                                        i,
 
306
                                                        thread->dims[nth],
 
307
                                                        pdls[j]->dims[i+thread->realdims[j]]);
 
308
                                        }
 
309
                                } else {
 
310
                                        thread->dims[nth] =
 
311
                                                pdls[j]->dims[mydim];
 
312
                                }
 
313
                                thread->incs[nth*npdls+j] =
 
314
                                        PDL_TREPRINC(pdls[j],flags[j],mydim);
 
315
                        }
 
316
                }
 
317
                nth++;
 
318
        }
 
319
        }
 
320
 
 
321
 
 
322
/* Make sure that we have the obligatory number of threaddims */
 
323
 
 
324
        for(; nth<ndims; nth++) {
 
325
                thread->dims[nth]=1;
 
326
                for(j=0; j<npdls; j++)
 
327
                        thread->incs[nth*npdls+j] = 0;
 
328
        }
 
329
/* If threading, make the true offsets and dims.. */
 
330
 
 
331
        if(nthr > 0) {
 
332
                int n1 = thread->dims[thread->mag_nth] / nthr;
 
333
                int n2 = thread->dims[thread->mag_nth] % nthr;
 
334
                if(n2) {
 
335
                        die("Cannot magick-thread with non-divisible n!");
 
336
                }
 
337
                thread->dims[thread->mag_nth] = n1;
 
338
        }
 
339
        thread->gflags |= PDL_THREAD_INITIALIZED;
 
340
        PDLDEBUG_f(dump_thread(thread);)        
 
341
}
 
342
 
 
343
void pdl_thread_create_parameter(pdl_thread *thread,int j,int *dims,
 
344
                                 int temp)
 
345
{
 
346
        int i;
 
347
        int td = temp ? 0 : thread->nimpl;
 
348
 
 
349
        if(!temp && thread->nimpl != thread->ndims - thread->nextra) {
 
350
                pdl_croak_param(thread->einfo,j,
 
351
                        "Trying to create parameter while explicitly threading.\
 
352
See the manual for why this is impossible");
 
353
        }
 
354
        pdl_reallocdims(thread->pdls[j], thread->realdims[j] + td);
 
355
        for(i=0; i<thread->realdims[j]; i++)
 
356
                thread->pdls[j]->dims[i] = dims[i];
 
357
        if (!temp)
 
358
          for(i=0; i<thread->nimpl; i++)
 
359
                thread->pdls[j]->dims[i+thread->realdims[j]] =
 
360
                       thread->dims[i] *
 
361
                     ((i == thread->mag_nth && thread->mag_nthr > 0) ?
 
362
                           thread->mag_nthr : 1);
 
363
        thread->pdls[j]->threadids[0] = td + thread->realdims[j];
 
364
        pdl_resize_defaultincs(thread->pdls[j]);
 
365
        for(i=0; i<thread->nimpl; i++) {
 
366
                thread->incs[thread->npdls*i + j] =
 
367
                  temp ? 0 :
 
368
                  PDL_REPRINC(thread->pdls[j],i+thread->realdims[j]);
 
369
        }
 
370
}
 
371
 
 
372
int pdl_startthreadloop(pdl_thread *thread,void (*func)(pdl_trans *),
 
373
                        pdl_trans *t) {
 
374
        int i,j;
 
375
        int *offsp; int nthr;
 
376
        if((thread->gflags & (PDL_THREAD_MAGICKED | PDL_THREAD_MAGICK_BUSY))
 
377
             == PDL_THREAD_MAGICKED) {
 
378
                thread->gflags |= PDL_THREAD_MAGICK_BUSY;
 
379
                if(!func) {
 
380
                        die("NULL FUNCTION WHEN PTHREADING\n");
 
381
                }
 
382
                /* Do the threadloop magically (i.e. in parallel) */
 
383
                pdl_magic_thread_cast(thread->pdls[thread->mag_nthpdl],
 
384
                        func,t);
 
385
                thread->gflags &= ~PDL_THREAD_MAGICK_BUSY;
 
386
                return 1; /* DON'T DO THREADLOOP AGAIN */
 
387
        }
 
388
        for(i=0; i<thread->ndims; i++)
 
389
                thread->inds[i] = 0;
 
390
        offsp = pdl_get_threadoffsp_int(thread,&nthr);
 
391
        for(j=0; j<thread->npdls; j++)
 
392
                offsp[j] = PDL_TREPROFFS(thread->pdls[j],thread->flags[j]) +
 
393
                        (!nthr?0:
 
394
                                nthr * thread->dims[thread->mag_nth] *
 
395
                                    thread->incs[thread->mag_nth*thread->npdls + j]);
 
396
        return 0;
 
397
}
 
398
 
 
399
/* This will have to be macroized */
 
400
int pdl_iterthreadloop(pdl_thread *thread,int nth) {
 
401
        int i,j;
 
402
        int stop = 0;
 
403
        int stopdim;
 
404
        int *offsp; int nthr;
 
405
/*      printf("iterthreadloop\n"); */
 
406
        for(j=0; j<thread->npdls; j++)
 
407
                thread->offs[j] = PDL_TREPROFFS(thread->pdls[j],thread->flags[j]);
 
408
        for(i=nth; i<thread->ndims; i++) {
 
409
                thread->inds[i] ++;
 
410
                if(thread->inds[i] >= thread->dims[i])
 
411
                        thread->inds[i] = 0;
 
412
                else
 
413
                {       stopdim = i; stop = 1; break; }
 
414
        }
 
415
        if(stop) goto calc_offs;
 
416
        return 0;
 
417
calc_offs:
 
418
        offsp = pdl_get_threadoffsp_int(thread,&nthr);
 
419
        for(j=0; j<thread->npdls; j++) {
 
420
                offsp[j] = PDL_TREPROFFS(thread->pdls[j],thread->flags[j]) +
 
421
                (!nthr?0:
 
422
                        nthr * thread->dims[thread->mag_nth] *
 
423
                            thread->incs[thread->mag_nth*thread->npdls + j]);
 
424
                        ;
 
425
                for(i=nth; i<thread->ndims; i++) {
 
426
                        offsp[j] += thread->incs[i*thread->npdls+j] *
 
427
                                        thread->inds[i];
 
428
                }
 
429
        }
 
430
        return stopdim+1;
 
431
}
 
432
 
 
433
/* prototype, defined in pdlcore.c */
 
434
char *pdl_mess(const char *pat, va_list *args);
 
435
void pdl_croak_param(pdl_errorinfo *info,int j, char *pat, ...)
 
436
{
 
437
        va_list args;
 
438
        char *message; char *name;
 
439
        static char mesgbuf[200];
 
440
      static char argsbuf[256], *argb;
 
441
      int i, k, l;
 
442
      SV *msv;
 
443
 
 
444
        va_start(args,pat);
 
445
        /* was Perl_mess before; Perl_mess has changed between 5.00X and 5.6 */
 
446
        message = pdl_mess(pat,&args);  /* barf dependence !!!! */
 
447
        /* Now, croak() overwrites this string. make a copy */
 
448
        strcpy(mesgbuf,message); message = mesgbuf;
 
449
        va_end(args);
 
450
        if(!info) {croak("PDL_CROAK_PARAM: Unknown: parameter %d: %s\n",
 
451
                j,message);
 
452
        } else {
 
453
                if(j >= info->nparamnames)
 
454
                        name = "ERROR: UNKNOWN PARAMETER";
 
455
                else    name = info->paramnames[j];
 
456
              for (i=0,argb=argsbuf,l=255;i<info->nparamnames && l;i++) {
 
457
                /* Could improve method, but 256 chars should be
 
458
                     enough anyway! */
 
459
                k = strlen(info->paramnames[i]);
 
460
                if (k < l-4) {
 
461
                  memcpy(argb,info->paramnames[i],k);
 
462
                  argb += k;
 
463
                  *argb = ',';
 
464
                  argb++;
 
465
                  l -= k+1;
 
466
                } else {
 
467
                  *argb++ = '.';
 
468
                  *argb++ = '.';
 
469
                  *argb++ = '.';
 
470
                  argb++;
 
471
                  l = 0;
 
472
                }
 
473
              }
 
474
              *--argb = '\0';
 
475
/* this needs to be sorted: barf stuff ?? */
 
476
#ifdef croak
 
477
#define tcroak croak
 
478
#define croak Perl_croak
 
479
#ifdef aTHX_
 
480
#define _extra aTHX_
 
481
#else
 
482
#define _extra
 
483
#endif
 
484
#else
 
485
#define _extra
 
486
#endif
 
487
              croak(_extra "PDL: %s(%s): Parameter '%s'\n%s\n",
 
488
                    info->funcname,argsbuf,name,message);
 
489
#ifdef tcroak
 
490
#undef croak
 
491
#define croak tcroak
 
492
#undef tcroak
 
493
#endif
 
494
        }
 
495
}
 
496
 
 
497