ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/rcomb.c
(Generate patch)

Comparing ray/src/util/rcomb.c (file contents):
Revision 2.7 by greg, Fri Feb 23 03:47:57 2024 UTC vs.
Revision 2.10 by greg, Mon May 20 23:21:29 2024 UTC

# Line 5 | Line 5 | static const char RCSid[] = "$Id$";
5   * General component matrix combiner, operating on a row at a time.
6   */
7  
8 #include <errno.h>
8   #include <math.h>
9   #include "platform.h"
10 + #include "rtprocess.h"
11   #include "rtio.h"
12 #include "resolu.h"
12   #include "rmatrix.h"
13   #include "calcomp.h"
15 #include "paths.h"
14  
15   #ifndef M_PI
16   #define M_PI    3.14159265358979323846
# Line 55 | Line 53 | int            cur_row;                        /* current input/output row */
53   int             cur_col;                        /* current input/output column */
54   int             cur_chan;                       /* if we're looping channels */
55  
56 + SUBPROC         *cproc = NULL;                  /* child process array */
57 + int             nchildren = 0;                  /* # of child processes */
58 + int             inchild = -1;                   /* our child ID (-1: parent) */
59 +
60   static int      checksymbolic(ROPMAT *rop);
61  
62   static int
# Line 391 | Line 393 | apply_op(RMATRIX *dst, const RMATRIX *src, const RUNAR
393                          return(0);
394                  rmx_free(res);
395          } else if (dst != src)
396 <                memcpy(dst->mtx, src->mtx,
395 <                                sizeof(double)*dst->ncomp*dst->ncols*dst->nrows);
396 >                memcpy(dst->mtx, src->mtx, rmx_array_size(dst));
397          if (ro->nsf == dst->ncomp)
398                  rmx_scale(dst, ro->sca);
399          return(1);
# Line 540 | Line 541 | output_headinfo(FILE *fp)
541   }
542  
543   static int
544 < combine_input(ROPMAT *res, FILE *fout)
544 > spawned_children(int np)
545   {
546 <        int     set_r, set_c;
547 <        RMATRIX *tmp = NULL;
548 <        int     co_set;
549 <        int     i;
550 <                                        /* allocate input row buffers */
546 >        int     i, rv;
547 >
548 > #if defined(_WIN32) || defined(_WIN64)
549 >        if (np > 1) {
550 >                fputs("Warning: only one process under Windows\n", stderr);
551 >                np = 1;
552 >        } else
553 > #endif
554 >        if ((in_nrows > 0) & (np > in_nrows))
555 >                np = in_nrows;
556 >                                /* we'll be doing a row at a time */
557          for (i = 0; i < nmats; i++) {
558 <                mop[i].imx.nrows = 1;   /* we'll be doing a row at a time */
558 >                mop[i].imx.nrows = 1;
559                  if (!rmx_prepare(&mop[i].imx))
560                          goto memerror;
561                  if (mop[i].rmp != &mop[i].imx) {
# Line 557 | Line 564 | combine_input(ROPMAT *res, FILE *fout)
564                                  goto memerror;
565                  }
566          }
567 <                                        /* prep output row buffers */
568 <        if (mcat || res->preop.clen > 0) {
569 <                if (!split_input(res))  /* need separate buffer */
567 >                                /* prep output row buffer */
568 >        if (mcat || mop[nmats].preop.clen > 0) {
569 >                if (!split_input(&mop[nmats]))  /* need separate buffer */
570                          return(0);
571 <                if (res->preop.clen > 0)
572 <                        res->rmp->ncomp = res->preop.clen / res->imx.ncomp;
573 <                res->rmp->nrows = 1;
574 <                if (!mcat | !mcat_last && !rmx_prepare(res->rmp))
571 >                if (mop[nmats].preop.clen > 0)
572 >                        mop[nmats].rmp->ncomp = mop[nmats].preop.clen /
573 >                                                mop[nmats].imx.ncomp;
574 >                mop[nmats].rmp->nrows = 1;
575 >                if (!mcat | !mcat_last && !rmx_prepare(mop[nmats].rmp))
576                          goto memerror;
577          }
578 +        mop[nmats].imx.nrows = 1;
579 +        if (!rmx_prepare(&mop[nmats].imx))
580 +                goto memerror;
581 +        if (np <= 1) {          /* single process return point */
582 + #ifdef getc_unlocked
583 +                for (i = 0; i < nmats; i++)
584 +                        flockfile(mop[i].infp);
585 +                flockfile(stdout);
586 + #endif
587 +                return(0);
588 +        }
589 +        fflush(stdout);         /* flush header & spawn children */
590 +        cproc = (SUBPROC *)malloc(sizeof(SUBPROC)*np);
591 +        if (!cproc)
592 +                goto memerror;
593 +        nchildren = np;
594 +        for (i = 0; i < np; i++) {
595 +                cproc[i].flags = PF_FILT_OUT;
596 +                cproc[i].w = dup(1);
597 +                cproc[i].r = 0;
598 +                cproc[i].pid = -1;
599 +                rv = open_process(&cproc[i], NULL);
600 +                if (rv <= 0) break;
601 +        }
602 +        if (rv > 0)
603 +                return(1);      /* parent return value */
604 +        if (rv < 0) {
605 +                perror("fork");
606 +                exit(1);
607 +        }
608 +        inchild = i;            /* child index */
609 +        fpurge(stdin);          /* discard previous matrix input */
610 + #ifdef getc_unlocked
611 +        flockfile(stdin);
612 + #endif
613 +        for (i = 0; i < nmats; i++) {
614 +                if (mop[i].infp != stdin)
615 +                        fclose(mop[i].infp);
616 +                mop[i].infp = stdin;
617 +                mop[i].imx.dtype = DTdouble;
618 +        }
619 +        return(0);              /* child return */
620 + memerror:
621 +        fputs("Out of memory in spawned_children()\n", stderr);
622 +        exit(1);
623 + }
624 +
625 + static int
626 + parent_loop()
627 + {
628 +        FILE    **outfp = (FILE **)malloc(nchildren*sizeof(FILE *));
629 +        int     i;
630 +
631 +        if (!outfp) goto memerror;
632 +        for (i = 0; i < nchildren; i++) {
633 +                outfp[i] = fdopen(cproc[i].w, "w");
634 +                if (!outfp[i]) goto memerror;
635 + #ifdef getc_unlocked
636 +                flockfile(outfp[i]);
637 + #endif
638 +        }
639 + #ifdef getc_unlocked
640 +        for (i = 0; i < nmats; i++)
641 +                flockfile(mop[i].infp);
642 + #endif
643 +        for (cur_row = 0; (in_nrows <= 0) | (cur_row < in_nrows); cur_row++) {
644 +            FILE        *ofp = outfp[cur_row % nchildren];
645 +            for (i = 0; i < nmats; i++) {
646 +                if (!rmx_load_row(mop[i].imx.mtx, &mop[i].imx, mop[i].infp)) {
647 +                        if (cur_row > in_nrows) /* unknown #input rows? */
648 +                                break;
649 +                        fprintf(stderr, "%s: read error at row %d\n",
650 +                                        mop[i].inspec, cur_row);
651 +                        return(0);
652 +                }
653 +                if (!rmx_write_data(mop[i].imx.mtx, mop[i].imx.ncomp,
654 +                                mop[i].imx.ncols, DTdouble, ofp))
655 +                        return(0);
656 +            }
657 +            if (i < nmats)
658 +                break;
659 +            if (fflush(ofp) == EOF)
660 +                return(0);
661 +        }
662 +        for (i = 0; i < nchildren; i++)
663 +                fclose(outfp[i]);
664 +        free(outfp);
665 +        i = close_processes(cproc, nchildren);
666 +        free(cproc); cproc = NULL;
667 +        if (i < 0) {
668 +                fputs("Warning: missing child in parent_loop()\n", stderr);
669 +                return(1);
670 +        }
671 +        if (i > 0) {
672 +                fprintf(stderr, "Child exited with status %d\n", i);
673 +                return(0);
674 +        }
675 +        return(1);
676 + memerror:
677 +        fputs("Out of memory in parent_loop()\n", stderr);
678 +        exit(1);
679 + }
680 +
681 + static int
682 + combine_input()
683 + {
684 +        const int       row0 = (inchild >= 0)*inchild;
685 +        const int       rstep = nchildren + !nchildren;
686 +        ROPMAT          *res = &mop[nmats];
687 +        int             set_r, set_c;
688 +        RMATRIX         *tmp = NULL;
689 +        int             co_set;
690 +        int             i;
691 +
692          if (mcat && mcat_last &&
693                          !(tmp = rmx_alloc(1, res->imx.ncols, res->rmp->ncomp)))
694                  goto memerror;
573        res->imx.nrows = 1;
574        if (!rmx_prepare(&res->imx))
575                goto memerror;
695                                          /* figure out what the user set */
696          co_set = fundefined("co");
697          if (!co_set)
# Line 588 | Line 707 | combine_input(ROPMAT *res, FILE *fout)
707          } else                          /* save a little time */
708                  set_r = set_c = 0;
709                                          /* read/process row-by-row */
710 <        for (cur_row = 0; (in_nrows <= 0) | (cur_row < in_nrows); cur_row++) {
710 >        for (cur_row = row0; (in_nrows <= 0) | (cur_row < in_nrows); cur_row += rstep) {
711              RMATRIX     *mres = NULL;
712 <            for (i = 0; i < nmats; i++) {
712 >            for (i = 0; i < nmats; i++)
713                  if (!rmx_load_row(mop[i].imx.mtx, &mop[i].imx, mop[i].infp)) {
714                          if (cur_row > in_nrows) /* unknown #input rows? */
715 <                                goto loop_exit;
715 >                                break;
716                          fprintf(stderr, "%s: read error at row %d\n",
717                                          mop[i].inspec, cur_row);
718                          return(0);
719                  }
720 +            if (i < nmats)
721 +                break;
722 +            for (i = 0; i < nmats; i++)
723                  if (!apply_op(mop[i].rmp, &mop[i].imx, &mop[i].preop))
724                          return(0);
603            }
725              if (set_r) varset("r", '=', cur_row);
726              for (cur_col = 0; cur_col < in_ncols; cur_col++) {
727                  if (set_c) varset("c", '=', cur_col);
# Line 637 | Line 758 | combine_input(ROPMAT *res, FILE *fout)
758                          return(0);
759              }
760              rmx_free(mres); mres = NULL;
761 +            if (inchild >= 0) {
762 +                i = getc(stdin);        /* child waits for turn to output */
763 +                if (i != EOF) ungetc(i, stdin);
764 +            }
765              if (!rmx_write_data(res->rmp->mtx, res->rmp->ncomp,
766 <                                res->rmp->ncols, res->rmp->dtype, fout))
766 >                                res->rmp->ncols, res->rmp->dtype, stdout))
767                  return(0);
768 +            if (inchild >= 0 && fflush(stdout) == EOF)
769 +                return(0);
770          }
771 < loop_exit:
645 < #if 0           /* we're about to exit, so who cares? */
646 <        rmx_free(tmp);                  /* clean up */
647 <        rmx_reset(res->rmp);
648 <        rmx_reset(&res->imx);
649 <        for (i = 0; i < nmats; i++) {
650 <                rmx_reset(mop[i].rmp);
651 <                rmx_reset(&mop[i].imx);
652 <                if (mop[i].inspec[0] == '!')
653 <                        pclose(mop[i].infp);
654 <                else if (mop[i].inspec != stdin_name)
655 <                        fclose(mop[i].infp);
656 <                mop[i].infp = NULL;
657 <        }
658 < #endif
659 <        return(fflush(fout) != EOF);
771 >        return(inchild >= 0 || fflush(stdout) != EOF);
772   memerror:
773          fputs("Out of buffer space in combine_input()\n", stderr);
774          return(0);
# Line 706 | Line 818 | main(int argc, char *argv[])
818          const char      *defCsym = NULL;
819          int             echoheader = 1;
820          int             stdin_used = 0;
821 +        int             nproc = 1;
822          const char      *mcat_spec = NULL;
823          int             n2comp = 0;
824          uby8            comp_ndx[128];
# Line 733 | Line 846 | main(int argc, char *argv[])
846                          case 'h':
847                                  echoheader = !echoheader;
848                                  break;
849 +                        case 'n':
850 +                                nproc = atoi(argv[++i]);
851 +                                if (nproc <= 0)
852 +                                        goto userr;
853 +                                break;
854                          case 'e':
855                                  if (!n) goto userr;
856                                  comp_ndx[n2comp++] = i++;
# Line 871 | Line 989 | main(int argc, char *argv[])
989                  return(1);
990          }
991          doptimize(1);                   /* optimize definitions */
992 +        if (spawned_children(nproc))    /* running in children? */
993 +                return(parent_loop() ? 0 : 1);
994                                          /* process & write rows */
995 <        return(combine_input(&mop[nmats], stdout) ? 0 : 1);
995 >        return(combine_input() ? 0 : 1);
996   stdin_error:
997          fprintf(stderr, "%s: %s used for more than one input\n",
998                          argv[0], stdin_name);
999          return(1);
1000   userr:
1001          fprintf(stderr,
1002 <        "Usage: %s [-h][-f{adfc}][-e expr][-f file][-s sf .. | -c ce ..] m1 .. -m mcat > mres\n",
1002 >        "Usage: %s [-h][-f{adfc}][-n nproc][-e expr][-f file][-s sf .. | -c ce ..] m1 .. -m mcat > mres\n",
1003                          argv[0]);
1004          return(1);
1005   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines