| 35 |
|
int gargc; /* global argc */ |
| 36 |
|
char **gargv; /* global argv */ |
| 37 |
|
|
| 38 |
< |
RMATRIX *cmtx = NULL; /* coefficient matrix */ |
| 38 |
> |
RMATRIX *cmtx; /* coefficient matrix */ |
| 39 |
> |
int row0, rowN; /* rows for current pass */ |
| 40 |
|
|
| 41 |
|
/* does the given spec contain integer format? */ |
| 42 |
|
int |
| 126 |
|
long data_start = ftell(fp); /* make sure input flat */ |
| 127 |
|
off_t dend = lseek(fileno(fp), 0, SEEK_END); |
| 128 |
|
if (dend < data_start + 4L*xres*yres) { |
| 129 |
< |
fputs("Warning - multi-processing requires flat input files\n", |
| 130 |
< |
stderr); |
| 129 |
> |
fprintf(stderr, "%s: warning - multi-processing requires flat input files\n", |
| 130 |
> |
gargv[0]); |
| 131 |
|
nprocs = 1; |
| 132 |
|
} |
| 133 |
|
} |
| 144 |
|
rmx_free(cmtx); |
| 145 |
|
cmtx = nmtx; |
| 146 |
|
} else if (cmtx->ncomp != ncomp) { |
| 147 |
< |
fprintf(stderr, "operation %s needs %d components, has %d\n", |
| 148 |
< |
cmtx->ncols == 1 ? "vector" : "matrix", |
| 147 |
> |
fprintf(stderr, "%s: operation %s needs %d components, has %d\n", |
| 148 |
> |
gargv[0], cmtx->ncols == 1 ? "vector" : "matrix", |
| 149 |
|
ncomp, cmtx->ncomp); |
| 150 |
|
return(0); |
| 151 |
|
} |
| 152 |
|
if ((in_type != DTrgbe) & (in_type != DTxyze) & (in_type != DTspec) & |
| 153 |
|
(in_type != DTfloat)) { |
| 154 |
< |
fprintf(stderr, "%s unsupported input data type: %s\n", |
| 154 |
> |
fprintf(stderr, "%s: unsupported input data type '%s'\n", |
| 155 |
|
fbuf, cm_fmt_id[in_type]); |
| 156 |
|
return(0); |
| 157 |
|
} |
| 163 |
|
return(1); |
| 164 |
|
} |
| 165 |
|
|
| 166 |
+ |
struct hdata { |
| 167 |
+ |
int xr, yr; /* resolution */ |
| 168 |
+ |
int fno; /* frame # */ |
| 169 |
+ |
char fmt[MAXFMTLEN]; /* format */ |
| 170 |
+ |
}; |
| 171 |
+ |
|
| 172 |
|
/* check subsequent headers match initial file */ |
| 173 |
|
int |
| 174 |
|
checkline(char *s, void *p) |
| 175 |
|
{ |
| 176 |
|
static int exposWarned = 0; |
| 177 |
< |
int *xyres = (int *)p; |
| 171 |
< |
char fmt[MAXFMTLEN]; |
| 177 |
> |
struct hdata *hp = (struct hdata *)p; |
| 178 |
|
|
| 179 |
|
if (!strncmp(s, "NCOLS=", 6)) { |
| 180 |
< |
xyres[0] = atoi(s+6); |
| 181 |
< |
if (xyres[0] <= 0) |
| 180 |
> |
hp->xr = atoi(s+6); |
| 181 |
> |
if (hp->xr <= 0) |
| 182 |
|
return(-1); |
| 183 |
|
return(1); |
| 184 |
|
} |
| 185 |
|
if (!strncmp(s, "NROWS=", 6)) { |
| 186 |
< |
xyres[1] = atoi(s+6); |
| 187 |
< |
if (xyres[1] <= 0) |
| 186 |
> |
hp->yr = atoi(s+6); |
| 187 |
> |
if (hp->yr <= 0) |
| 188 |
|
return(-1); |
| 189 |
|
return(1); |
| 190 |
|
} |
| 191 |
+ |
if (!strncmp(s, "FRAME=", 6)) { |
| 192 |
+ |
hp->fno = atoi(s+6); |
| 193 |
+ |
return(1); |
| 194 |
+ |
} |
| 195 |
|
if (isncomp(s)) { |
| 196 |
|
if (ncompval(s) != ncomp) |
| 197 |
|
return(-1); |
| 199 |
|
} |
| 200 |
|
if (isexpos(s)) { |
| 201 |
|
if (!exposWarned && fabs(1. - exposval(s)) > 0.04) { |
| 202 |
< |
fputs("Warning - ignoring EXPOSURE setting(s)\n", |
| 203 |
< |
stderr); |
| 202 |
> |
fprintf(stderr, "%s: warning - ignoring EXPOSURE setting(s)\n", |
| 203 |
> |
gargv[0]); |
| 204 |
|
exposWarned++; |
| 205 |
|
} |
| 206 |
|
return(1); |
| 207 |
|
} |
| 208 |
< |
if (formatval(fmt, s)) { |
| 199 |
< |
if (strcmp(fmt, cm_fmt_id[in_type])) |
| 200 |
< |
return(-1); |
| 208 |
> |
if (formatval(hp->fmt, s)) |
| 209 |
|
return(1); |
| 210 |
< |
} |
| 210 |
> |
|
| 211 |
|
return(0); |
| 212 |
|
} |
| 213 |
|
|
| 214 |
< |
/* open and check input file */ |
| 214 |
> |
/* open and check input/output file, read/write mode if fno >= 0 */ |
| 215 |
|
FILE * |
| 216 |
< |
open_input(char *fname) |
| 216 |
> |
open_iofile(char *fname, int fno) |
| 217 |
|
{ |
| 218 |
< |
int xyres[2]; |
| 219 |
< |
FILE *fp = fopen(fname, "rb"); |
| 218 |
> |
struct hdata hd; |
| 219 |
> |
FILE *fp = fopen(fname, fno>=0 ? "r+b" : "rb"); |
| 220 |
|
|
| 221 |
|
if (!fp) { |
| 222 |
< |
fprintf(stderr, "%s: cannot open for reading\n", fname); |
| 222 |
> |
fprintf(stderr, "%s: cannot open for reading%s\n", |
| 223 |
> |
fname, fno>=0 ? "/writing" : ""); |
| 224 |
|
return(NULL); |
| 225 |
|
} |
| 226 |
< |
xyres[0] = xyres[1] = 0; |
| 227 |
< |
if (getheader(fp, checkline, xyres) < 0) { |
| 226 |
> |
hd.xr = hd.yr = 0; |
| 227 |
> |
hd.fno = -1; |
| 228 |
> |
hd.fmt[0] = '\0'; |
| 229 |
> |
if (getheader(fp, checkline, &hd) < 0) { |
| 230 |
|
fprintf(stderr, "%s: bad/inconsistent header\n", fname); |
| 231 |
|
fclose(fp); |
| 232 |
|
return(NULL); |
| 233 |
|
} |
| 234 |
< |
if ((xyres[0] <= 0) | (xyres[1] <= 0) && |
| 235 |
< |
!fscnresolu(&xyres[0], &xyres[1], fp)) { |
| 234 |
> |
if ((hd.fno >= 0) & (fno >= 0) & (hd.fno != fno)) { |
| 235 |
> |
fprintf(stderr, "%s: unexpected frame number (%d != %d)\n", |
| 236 |
> |
fname, hd.fno, fno); |
| 237 |
> |
fclose(fp); |
| 238 |
> |
return(NULL); |
| 239 |
> |
} |
| 240 |
> |
if (strcmp(hd.fmt, cm_fmt_id[fno>=0 ? out_type : in_type])) { |
| 241 |
> |
fprintf(stderr, "%s: wrong format\n", fname); |
| 242 |
> |
fclose(fp); |
| 243 |
> |
return(NULL); |
| 244 |
> |
} |
| 245 |
> |
if ((hd.xr <= 0) | (hd.yr <= 0) && |
| 246 |
> |
!fscnresolu(&hd.xr, &hd.yr, fp)) { |
| 247 |
|
fprintf(stderr, "%s: missing resolution\n", fname); |
| 248 |
|
fclose(fp); |
| 249 |
|
return(NULL); |
| 250 |
|
} |
| 251 |
< |
if ((xyres[0] != xres) | (xyres[1] != yres)) { |
| 251 |
> |
if ((hd.xr != xres) | (hd.yr != yres)) { |
| 252 |
|
fprintf(stderr, "%s: mismatched resolution\n", fname); |
| 253 |
|
fclose(fp); |
| 254 |
|
return(NULL); |
| 256 |
|
return(fp); |
| 257 |
|
} |
| 258 |
|
|
| 259 |
+ |
/* read in previous pixel data from output and rewind to data start */ |
| 260 |
+ |
int |
| 261 |
+ |
reload_data(float *osum, FILE *fp) |
| 262 |
+ |
{ |
| 263 |
+ |
long dstart; |
| 264 |
+ |
|
| 265 |
+ |
if (!osum | !fp) |
| 266 |
+ |
return(0); |
| 267 |
+ |
if ((dstart = ftell(fp)) < 0) { |
| 268 |
+ |
fprintf(stderr, "%s: ftell() error in reload_data()\n", |
| 269 |
+ |
gargv[0]); |
| 270 |
+ |
return(0); |
| 271 |
+ |
} |
| 272 |
+ |
if (in_type == DTfloat) { |
| 273 |
+ |
if (fread(osum, sizeof(float)*ncomp, (size_t)xres*yres, fp) != |
| 274 |
+ |
(size_t)xres*yres) { |
| 275 |
+ |
fprintf(stderr, "%s: fread() error\n", gargv[0]); |
| 276 |
+ |
return(0); |
| 277 |
+ |
} |
| 278 |
+ |
} else { |
| 279 |
+ |
int y; |
| 280 |
+ |
for (y = 0; y < yres; y++, osum += ncomp*xres) |
| 281 |
+ |
if (freadsscan(osum, ncomp, xres, fp) < 0) { |
| 282 |
+ |
fprintf(stderr, "%s: freadsscan() error\n", gargv[0]); |
| 283 |
+ |
return(0); |
| 284 |
+ |
} |
| 285 |
+ |
} |
| 286 |
+ |
if (fseek(fp, dstart, SEEK_SET) < 0) { |
| 287 |
+ |
fprintf(stderr, "%s: fseek() error in reload_data()\n", |
| 288 |
+ |
gargv[0]); |
| 289 |
+ |
return(0); |
| 290 |
+ |
} |
| 291 |
+ |
return(1); |
| 292 |
+ |
} |
| 293 |
+ |
|
| 294 |
|
/* open output file or command (if !NULL) and write info header */ |
| 295 |
|
FILE * |
| 296 |
|
open_output(char *ospec, int fno) |
| 302 |
|
fp = stdout; |
| 303 |
|
} else if (ospec[0] == '!') { |
| 304 |
|
if (!(fp = popen(ospec+1, "w"))) { |
| 305 |
< |
fprintf(stderr, "Cannot start: %s\n", ospec); |
| 305 |
> |
fprintf(stderr, "%s: cannot start: %s\n", gargv[0], ospec); |
| 306 |
|
return(NULL); |
| 307 |
|
} |
| 308 |
|
} else if (!(fp = fopen(ospec, "w"))) { |
| 349 |
|
fprtresolu(xres, yres, fp); |
| 350 |
|
break; |
| 351 |
|
default: |
| 352 |
< |
fputs("Unsupported output type!\n", stderr); |
| 352 |
> |
fprintf(stderr, "%s: unsupported output type!\n", gargv[0]); |
| 353 |
|
return(NULL); |
| 354 |
|
} |
| 355 |
|
if (fflush(fp) < 0) { |
| 370 |
|
int c; |
| 371 |
|
|
| 372 |
|
if (!osum | !iscan) { |
| 373 |
< |
fprintf(stderr, "Cannot allocate %dx%d %d-component accumulator\n", |
| 374 |
< |
xres, yres, ncomp); |
| 373 |
> |
fprintf(stderr, "%s: annot allocate %dx%d %d-component accumulator\n", |
| 374 |
> |
gargv[0], xres, yres, ncomp); |
| 375 |
|
return(0); |
| 376 |
|
} |
| 377 |
|
if (sizeof(float) != sizeof(COLORV)) { |
| 378 |
< |
fputs("Code Error 1 in solo_process()\n", stderr); |
| 378 |
> |
fprintf(stderr, "%s: Code Error 1 in solo_process()\n", gargv[0]); |
| 379 |
|
return(0); |
| 380 |
|
} |
| 381 |
< |
for (c = 0; c < cmtx->ncols; c++) { /* run through each column/output */ |
| 381 |
> |
/* run through each column/output */ |
| 382 |
> |
for (c = 0; c < cmtx->ncols; c++) { |
| 383 |
> |
int rc = rowN - row0; |
| 384 |
|
FILE *fout; |
| 385 |
|
int y; |
| 386 |
< |
int rc = cmtx->nrows; |
| 387 |
< |
if (c > 0) /* clear accumulator? */ |
| 386 |
> |
/* open output (load if multipass) */ |
| 387 |
> |
if (out_spec) { /* file or command */ |
| 388 |
> |
if (cmtx->ncols > 1 && !hasFormat(out_spec)) { |
| 389 |
> |
fprintf(stderr, "%s: sequential result must go to stdout\n", |
| 390 |
> |
gargv[0]); |
| 391 |
> |
return(0); |
| 392 |
> |
} |
| 393 |
> |
sprintf(fbuf, out_spec, c); |
| 394 |
> |
if (row0) { /* another pass -- get prev. data */ |
| 395 |
> |
fout = open_iofile(fbuf, c); |
| 396 |
> |
if (!reload_data(osum, fout)) |
| 397 |
> |
return(0); |
| 398 |
> |
} else /* else new output (clobber prev. files) */ |
| 399 |
> |
fout = open_output(fbuf, c-(cmtx->ncols==1)); |
| 400 |
> |
} else { /* else stdout */ |
| 401 |
> |
if ((out_type == DTfloat) & (cmtx->ncols > 1)) { |
| 402 |
> |
fprintf(stderr, "%s: float outputs must have separate destinations\n", |
| 403 |
> |
gargv[0]); |
| 404 |
> |
return(0); |
| 405 |
> |
} |
| 406 |
> |
strcpy(fbuf, "<stdout>"); |
| 407 |
> |
fout = open_output(NULL, c-(cmtx->ncols==1)); |
| 408 |
> |
} |
| 409 |
> |
if (!fout) |
| 410 |
> |
return(0); /* assume error was reported */ |
| 411 |
> |
if (!row0 & (c > 0)) /* clear accumulator? */ |
| 412 |
|
memset(osum, 0, sizeof(float)*ncomp*xres*yres); |
| 413 |
|
while (rc-- > 0) { /* run through each input file */ |
| 414 |
< |
const int r = c&1 ? rc : cmtx->nrows-1 - rc; |
| 414 |
> |
const int r = c&1 ? row0 + rc : rowN-1 - rc; |
| 415 |
|
const rmx_dtype *cval = rmx_val(cmtx, r, c); |
| 416 |
|
FILE *finp; |
| 417 |
|
int i, x; |
| 420 |
|
if (i < 0) /* this coefficient is zero, skip */ |
| 421 |
|
continue; |
| 422 |
|
sprintf(fbuf, in_spec, r); |
| 423 |
< |
finp = open_input(fbuf); |
| 423 |
> |
finp = open_iofile(fbuf, -1); |
| 424 |
|
if (!finp) |
| 425 |
|
return(0); |
| 426 |
|
for (y = 0; y < yres; y++) { |
| 436 |
|
dst[i] += cval[i]*iscan[x*ncomp + i]; |
| 437 |
|
} |
| 438 |
|
fclose(finp); |
| 439 |
< |
} /* write out accumulated column result... */ |
| 357 |
< |
if (out_spec) { /* ...to file or command */ |
| 358 |
< |
if (cmtx->ncols > 1 && !hasFormat(out_spec)) { |
| 359 |
< |
fputs("Sequential result must go to stdout\n", stderr); |
| 360 |
< |
return(0); |
| 361 |
< |
} |
| 362 |
< |
sprintf(fbuf, out_spec, c); |
| 363 |
< |
fout = open_output(fbuf, c-(cmtx->ncols==1)); |
| 364 |
< |
} else { /* ...to stdout */ |
| 365 |
< |
if ((out_type == DTfloat) & (cmtx->ncols > 1)) { |
| 366 |
< |
fputs("Float outputs must have separate destinations\n", |
| 367 |
< |
stderr); |
| 368 |
< |
return(0); |
| 369 |
< |
} |
| 370 |
< |
strcpy(fbuf, "<stdout>"); |
| 371 |
< |
fout = open_output(NULL, c-(cmtx->ncols==1)); |
| 372 |
< |
} |
| 373 |
< |
if (!fout) |
| 374 |
< |
return(0); /* assume error was reported */ |
| 439 |
> |
} /* write accumulated picture */ |
| 440 |
|
if (out_type != DTfloat) { |
| 441 |
|
for (y = 0; y < yres; y++) |
| 442 |
|
if (fwritesscan(osum + (size_t)y*xres*ncomp, |
| 448 |
|
|
| 449 |
|
if (fbuf[0] == '!') { |
| 450 |
|
if (pclose(fout) != 0) { |
| 451 |
< |
fprintf(stderr, "Bad status from: %s\n", fbuf); |
| 451 |
> |
fprintf(stderr, "%s: bad status from: %s\n", gargv[0], fbuf); |
| 452 |
|
return(0); |
| 453 |
|
} |
| 454 |
|
} else if (fout != stdout && fclose(fout) == EOF) |
| 477 |
|
int i; |
| 478 |
|
|
| 479 |
|
if (!scarr) { |
| 480 |
< |
fprintf(stderr, "Out of memory in scramble(%d)\n", n); |
| 480 |
> |
fprintf(stderr, "%s: out of memory in scramble(%d)\n", gargv[0], n); |
| 481 |
|
exit(1); |
| 482 |
|
} |
| 483 |
|
for (i = n; i--; ) |
| 498 |
|
{ |
| 499 |
|
int coff = nprocs; |
| 500 |
|
int odd = 0; |
| 501 |
+ |
float *osum = NULL; |
| 502 |
+ |
int *syarr = NULL; |
| 503 |
|
char fbuf[512]; |
| 437 |
– |
float *osum; |
| 438 |
– |
int *syarr; |
| 504 |
|
int c; |
| 505 |
|
/* sanity check */ |
| 506 |
|
if (sizeof(float) != sizeof(COLORV)) { |
| 507 |
< |
fputs("Code Error 1 in multi_process()\n", stderr); |
| 507 |
> |
fprintf(stderr, "%s: code Error 1 in multi_process()\n", gargv[0]); |
| 508 |
|
return(0); |
| 509 |
|
} |
| 510 |
|
while (--coff > 0) { /* parent births children */ |
| 511 |
|
int pid = fork(); |
| 512 |
|
if (pid < 0) { |
| 513 |
< |
fputs("fork() call failed!\n", stderr); |
| 513 |
> |
fprintf(stderr, "%s: fork() call failed!\n", gargv[0]); |
| 514 |
|
return(0); |
| 515 |
|
} |
| 516 |
|
if (pid == 0) break; /* child gets to work */ |
| 517 |
|
} |
| 518 |
< |
osum = (float *)calloc((size_t)xres*yres, sizeof(float)*ncomp); |
| 519 |
< |
if (!osum) { |
| 520 |
< |
fprintf(stderr, "Cannot allocate %dx%d %d-component accumulator\n", |
| 521 |
< |
xres, yres, ncomp); |
| 522 |
< |
return(0); |
| 518 |
> |
if (!row0 | (out_type != DTfloat)) { |
| 519 |
> |
osum = (float *)calloc((size_t)xres*yres, sizeof(float)*ncomp); |
| 520 |
> |
if (!osum) { |
| 521 |
> |
fprintf(stderr, "%s: cannot allocate %dx%d %d-component accumulator\n", |
| 522 |
> |
gargv[0], xres, yres, ncomp); |
| 523 |
> |
return(0); |
| 524 |
> |
} |
| 525 |
|
} |
| 526 |
|
srandom(113*coff + 5669); /* randomize row access for this process */ |
| 527 |
|
syarr = scramble(yres); |
| 528 |
|
/* run through our unique set of columns */ |
| 529 |
|
for (c = coff; c < cmtx->ncols; c += nprocs) { |
| 530 |
+ |
int rc = rowN - row0; |
| 531 |
+ |
void *omap = NULL; |
| 532 |
+ |
size_t omaplen = 0; |
| 533 |
+ |
long dstart; |
| 534 |
|
FILE *fout; |
| 535 |
|
int y; |
| 536 |
< |
int rc = cmtx->nrows; |
| 537 |
< |
if (c > coff) /* clear accumulator? */ |
| 538 |
< |
memset(osum, 0, sizeof(float)*ncomp*xres*yres); |
| 536 |
> |
/* create/load output */ |
| 537 |
> |
sprintf(fbuf, out_spec, c); |
| 538 |
> |
if (row0) { /* making another pass? */ |
| 539 |
> |
fout = open_iofile(fbuf, c); |
| 540 |
> |
if (!fout) return(0); |
| 541 |
> |
if (out_type == DTfloat) { |
| 542 |
> |
dstart = ftell(fout); |
| 543 |
> |
if ((dstart < 0) | (dstart % sizeof(float))) { |
| 544 |
> |
fprintf(stderr, "%s: bad seek/alignment\n", fbuf); |
| 545 |
> |
return(0); |
| 546 |
> |
} |
| 547 |
> |
omaplen = dstart + sizeof(float)*ncomp*xres*yres; |
| 548 |
> |
omap = mmap(NULL, omaplen, PROT_READ|PROT_WRITE, |
| 549 |
> |
MAP_FILE|MAP_SHARED, fileno(fout), 0); |
| 550 |
> |
if (omap == MAP_FAILED) { |
| 551 |
> |
fprintf(stderr, "%s: cannot map file '%s'\n", |
| 552 |
> |
gargv[0], fbuf); |
| 553 |
> |
return(0); |
| 554 |
> |
} |
| 555 |
> |
osum = (float *)((char *)omap + dstart); |
| 556 |
> |
} else if (!reload_data(osum, fout)) |
| 557 |
> |
return(0); |
| 558 |
> |
} else { /* else new output (clobber prev. files) */ |
| 559 |
> |
fout = open_output(fbuf, c); |
| 560 |
> |
if (!fout) return(0); |
| 561 |
> |
if (c > coff) /* clear accumulator? */ |
| 562 |
> |
memset(osum, 0, sizeof(float)*ncomp*xres*yres); |
| 563 |
> |
} |
| 564 |
|
while (rc-- > 0) { /* map & sum each input file */ |
| 565 |
< |
const int r = odd ? rc : cmtx->nrows-1 - rc; |
| 565 |
> |
const int r = odd ? row0 + rc : rowN-1 - rc; |
| 566 |
|
const rmx_dtype *cval = rmx_val(cmtx, r, c); |
| 567 |
< |
long dstart; |
| 472 |
< |
size_t maplen; |
| 567 |
> |
size_t imaplen; |
| 568 |
|
void *imap; |
| 569 |
|
FILE *finp; |
| 570 |
|
float *dst; |
| 574 |
|
if (i < 0) /* this coefficient is zero, skip */ |
| 575 |
|
continue; |
| 576 |
|
sprintf(fbuf, in_spec, r); |
| 577 |
< |
finp = open_input(fbuf); |
| 577 |
> |
finp = open_iofile(fbuf, -1); |
| 578 |
|
if (!finp) |
| 579 |
|
return(0); |
| 580 |
|
dstart = ftell(finp); |
| 587 |
|
return(0); |
| 588 |
|
} |
| 589 |
|
i = in_type==DTfloat ? ncomp*(int)sizeof(float) : ncomp+1; |
| 590 |
< |
maplen = dstart + (size_t)yres*xres*i; |
| 591 |
< |
imap = mmap(NULL, maplen, PROT_READ, |
| 590 |
> |
imaplen = dstart + (size_t)yres*xres*i; |
| 591 |
> |
imap = mmap(NULL, imaplen, PROT_READ, |
| 592 |
|
MAP_FILE|MAP_SHARED, fileno(finp), 0); |
| 593 |
|
fclose(finp); /* will read from map (randomly) */ |
| 594 |
|
if (imap == MAP_FAILED) { |
| 615 |
|
dst[i] += cval[i]*(cvp[i]+(rmx_dtype).5)*fe; |
| 616 |
|
} |
| 617 |
|
} |
| 618 |
< |
munmap(imap, maplen); |
| 619 |
< |
} /* write accumulated column picture/matrix */ |
| 525 |
< |
sprintf(fbuf, out_spec, c); |
| 526 |
< |
fout = open_output(fbuf, c); |
| 527 |
< |
if (!fout) |
| 528 |
< |
return(0); /* assume error was reported */ |
| 618 |
> |
munmap(imap, imaplen); |
| 619 |
> |
} /* write accumulated column picture */ |
| 620 |
|
if (out_type != DTfloat) { |
| 621 |
|
for (y = 0; y < yres; y++) |
| 622 |
|
if (fwritesscan(osum + (size_t)y*xres*ncomp, |
| 623 |
|
ncomp, xres, fout) < 0) |
| 624 |
|
goto writerr; |
| 625 |
+ |
} else if (omap) { |
| 626 |
+ |
if (munmap(omap, omaplen) < 0) |
| 627 |
+ |
goto writerr; |
| 628 |
+ |
osum = NULL; |
| 629 |
|
} else if (fwrite(osum, sizeof(float)*ncomp, (size_t)xres*yres, fout) != |
| 630 |
|
(size_t)xres*yres) |
| 631 |
|
goto writerr; |
| 632 |
|
|
| 633 |
|
if (fbuf[0] == '!') { |
| 634 |
|
if (pclose(fout) != 0) { |
| 635 |
< |
fprintf(stderr, "Bad status from: %s\n", fbuf); |
| 635 |
> |
fprintf(stderr, "%s: bad status from: %s\n", gargv[0], fbuf); |
| 636 |
|
return(0); |
| 637 |
|
} |
| 638 |
|
} else if (fclose(fout) == EOF) |
| 639 |
|
goto writerr; |
| 640 |
|
odd = !odd; /* go back & forth to milk page cache */ |
| 641 |
|
} |
| 642 |
< |
free(osum); |
| 642 |
> |
if (osum) free(osum); |
| 643 |
|
free(syarr); |
| 644 |
< |
if (coff) /* child processes return here... */ |
| 645 |
< |
return(1); |
| 644 |
> |
if (coff) /* child exits here... */ |
| 645 |
> |
_exit(0); |
| 646 |
|
c = 0; /* ...but parent waits for children */ |
| 647 |
|
while (++coff < nprocs) { |
| 648 |
|
int st; |
| 649 |
< |
if (wait(&st) < 0) |
| 649 |
> |
if (wait(&st) < 0) { |
| 650 |
> |
fprintf(stderr, "%s: warning - wait() call failed unexpectedly\n", gargv[0]); |
| 651 |
|
break; |
| 652 |
+ |
} |
| 653 |
|
if (st) c = st; |
| 654 |
|
} |
| 655 |
|
return(c == 0); |
| 663 |
|
int |
| 664 |
|
main(int argc, char *argv[]) |
| 665 |
|
{ |
| 666 |
+ |
double cacheGB = 0; |
| 667 |
+ |
int rintvl; |
| 668 |
|
int a; |
| 669 |
|
|
| 670 |
|
gargc = argc; /* for header output */ |
| 687 |
|
goto badopt; |
| 688 |
|
} |
| 689 |
|
break; |
| 690 |
+ |
case 'm': /* cache size in GigaBytes */ |
| 691 |
+ |
cacheGB = atof(argv[++a]); |
| 692 |
+ |
break; |
| 693 |
|
case 'N': /* number of desired processes */ |
| 694 |
|
case 'n': /* quietly supported alternate */ |
| 695 |
|
nprocs = atoi(argv[++a]); |
| 707 |
|
cmtx = rmx_load(argv[a+1]); /* loads from stdin if a+1==argc */ |
| 708 |
|
if (cmtx == NULL) |
| 709 |
|
return(1); /* error reported */ |
| 710 |
+ |
cacheGB *= (cmtx->ncols > 1); |
| 711 |
+ |
if (cacheGB > 0 && (!out_spec || *out_spec == '!')) { |
| 712 |
+ |
fprintf(stderr, "%s: -m option incompatible with output to %s\n", |
| 713 |
+ |
argv[0], out_spec ? "command" : "stdout"); |
| 714 |
+ |
return(1); |
| 715 |
+ |
} |
| 716 |
|
if (nprocs > cmtx->ncols) |
| 717 |
|
nprocs = cmtx->ncols; |
| 718 |
|
#if defined(_WIN32) || defined(_WIN64) |
| 739 |
|
} |
| 740 |
|
if (!get_iotypes()) |
| 741 |
|
return(1); |
| 742 |
< |
if (!(nprocs == 1 ? solo_process() : multi_process())) |
| 743 |
< |
return(1); |
| 742 |
> |
if (cacheGB > 1e-4) { /* figure out # of passes => rintvl */ |
| 743 |
> |
size_t inp_bytes = (in_type==DTfloat ? sizeof(float)*ncomp |
| 744 |
> |
: (size_t)(ncomp+1)) * xres*yres; |
| 745 |
> |
size_t mem_bytes = sizeof(float)*ncomp*xres*yres; |
| 746 |
> |
int npasses = (double)inp_bytes*cmtx->nrows / |
| 747 |
> |
(cacheGB*(1L<<30) - (double)mem_bytes*nprocs) + 1; |
| 748 |
> |
if ((npasses <= 0) | (npasses*8 >= cmtx->nrows)) |
| 749 |
> |
npasses = 1; /* let's not go there... */ |
| 750 |
> |
rintvl = cmtx->nrows / npasses; |
| 751 |
> |
rintvl += (rintvl*npasses < cmtx->nrows); |
| 752 |
> |
} else |
| 753 |
> |
rintvl = cmtx->nrows; |
| 754 |
> |
/* make our passes */ |
| 755 |
> |
for (row0 = 0; row0 < cmtx->nrows; row0 += rintvl) { |
| 756 |
> |
if ((rowN = row0 + rintvl) > cmtx->nrows) |
| 757 |
> |
rowN = cmtx->nrows; |
| 758 |
> |
if (nprocs==1 ? !solo_process() : !multi_process()) |
| 759 |
> |
return(1); |
| 760 |
> |
} |
| 761 |
|
return(0); |
| 762 |
|
userr: |
| 763 |
< |
fprintf(stderr, "Usage: %s [-oc | -of][-o ospec][-N nproc] inpspec [mtx]\n", |
| 763 |
> |
fprintf(stderr, "Usage: %s [-oc | -of][-o ospec][-N nproc][-m cacheGB] inpspec [mtx]\n", |
| 764 |
|
argv[0]); |
| 765 |
|
return(1); |
| 766 |
|
} |