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.4 by greg, Tue Dec 19 16:09:20 2023 UTC vs.
Revision 2.12 by greg, Tue May 21 17:39:17 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 <signal.h>
9   #include <math.h>
10   #include "platform.h"
11 + #include "rtprocess.h"
12   #include "rtio.h"
12 #include "resolu.h"
13   #include "rmatrix.h"
14   #include "calcomp.h"
15 #include "paths.h"
15  
16   #ifndef M_PI
17   #define M_PI    3.14159265358979323846
# Line 55 | Line 54 | int            cur_row;                        /* current input/output row */
54   int             cur_col;                        /* current input/output column */
55   int             cur_chan;                       /* if we're looping channels */
56  
57 + SUBPROC         *cproc = NULL;                  /* child process array */
58 + int             nchildren = 0;                  /* # of child processes */
59 + int             inchild = -1;                   /* our child ID (-1: parent) */
60 + int             gpid = -1;                      /* group process ID (parent) */
61 + int             nr_out = 0;                     /* # of rows output by kids */
62 +
63   static int      checksymbolic(ROPMAT *rop);
64  
65 + static void
66 + on_sigio(int dummy)
67 + {
68 +        nr_out++;                       /* happens when child outputs row */
69 +        signal(SIGIO, on_sigio);        /* reset to maximize portability */
70 + }
71 +
72   static int
73   split_input(ROPMAT *rop)
74   {
# Line 391 | Line 403 | apply_op(RMATRIX *dst, const RMATRIX *src, const RUNAR
403                          return(0);
404                  rmx_free(res);
405          } else if (dst != src)
406 <                memcpy(dst->mtx, src->mtx,
395 <                                sizeof(double)*dst->ncomp*dst->ncols*dst->nrows);
406 >                memcpy(dst->mtx, src->mtx, rmx_array_size(dst));
407          if (ro->nsf == dst->ncomp)
408                  rmx_scale(dst, ro->sca);
409          return(1);
# Line 540 | Line 551 | output_headinfo(FILE *fp)
551   }
552  
553   static int
554 < combine_input(ROPMAT *res, FILE *fout)
554 > spawned_children(int np)
555   {
556 <        int     set_r, set_c;
557 <        RMATRIX *tmp = NULL;
558 <        int     co_set;
559 <        int     i;
560 <                                        /* allocate input row buffers */
556 >        int     i, rv;
557 >
558 > #if defined(_WIN32) || defined(_WIN64)
559 >        if (np > 1) {
560 >                fputs("Warning: only one process under Windows\n", stderr);
561 >                np = 1;
562 >        } else
563 > #endif
564 >        if ((in_nrows > 0) & (np > in_nrows))
565 >                np = in_nrows;
566 >                                /* we'll be doing a row at a time */
567          for (i = 0; i < nmats; i++) {
568 <                mop[i].imx.nrows = 1;   /* we'll be doing a row at a time */
568 >                mop[i].imx.nrows = 1;
569                  if (!rmx_prepare(&mop[i].imx))
570                          goto memerror;
571                  if (mop[i].rmp != &mop[i].imx) {
# Line 557 | Line 574 | combine_input(ROPMAT *res, FILE *fout)
574                                  goto memerror;
575                  }
576          }
577 <                                        /* prep output row buffers */
578 <        if (mcat || res->preop.clen > 0) {
579 <                if (!split_input(res))  /* need separate buffer */
577 >                                /* prep output row buffer */
578 >        if (mcat || mop[nmats].preop.clen > 0) {
579 >                if (!split_input(&mop[nmats]))  /* need separate buffer */
580                          return(0);
581 <                if (res->preop.clen > 0)
582 <                        res->rmp->ncomp = res->preop.clen / res->imx.ncomp;
583 <                res->rmp->nrows = 1;
584 <                if (!mcat | !mcat_last && !rmx_prepare(res->rmp))
581 >                if (mop[nmats].preop.clen > 0)
582 >                        mop[nmats].rmp->ncomp = mop[nmats].preop.clen /
583 >                                                mop[nmats].imx.ncomp;
584 >                mop[nmats].rmp->nrows = 1;
585 >                if (!mcat | !mcat_last && !rmx_prepare(mop[nmats].rmp))
586                          goto memerror;
587          }
588 +        mop[nmats].imx.nrows = 1;
589 +        if (!rmx_prepare(&mop[nmats].imx))
590 +                goto memerror;
591 +        if (np <= 1) {          /* single process return point */
592 + #ifdef getc_unlocked
593 +                for (i = 0; i < nmats; i++)
594 +                        flockfile(mop[i].infp);
595 +                flockfile(stdout);
596 + #endif
597 +                return(0);
598 +        }
599 +        gpid = setpgrp();       /* set group process ID */
600 +        signal(SIGIO, on_sigio);
601 +        fflush(stdout);         /* flush header & spawn children */
602 +        cproc = (SUBPROC *)malloc(sizeof(SUBPROC)*np);
603 +        if (!cproc)
604 +                goto memerror;
605 +        nchildren = np;
606 +        for (i = 0; i < np; i++) {
607 +                cproc[i].flags = PF_FILT_OUT;
608 +                cproc[i].w = dup(1);
609 +                cproc[i].r = 0;
610 +                cproc[i].pid = -1;
611 +                rv = open_process(&cproc[i], NULL);
612 +                if (rv <= 0) break;
613 +        }
614 +        if (rv > 0)
615 +                return(1);      /* parent return value */
616 +        if (rv < 0) {
617 +                perror("fork");
618 +                exit(1);
619 +        }
620 +        inchild = i;            /* our child index */
621 +        while (i-- > 0)         /* don't share siblings' pipes */
622 +                close(cproc[i].w);
623 +        fpurge(stdin);          /* discard previous matrix input */
624 + #ifdef getc_unlocked
625 +        flockfile(stdin);
626 + #endif
627 +        for (i = 0; i < nmats; i++) {
628 +                if (mop[i].infp != stdin)
629 +                        fclose(mop[i].infp);    /* ! pclose() */
630 +                mop[i].infp = stdin;
631 +                mop[i].imx.dtype = DTdouble;
632 +        }
633 +        return(0);              /* child return */
634 + memerror:
635 +        fputs("Out of memory in spawned_children()\n", stderr);
636 +        exit(1);
637 + }
638 +
639 + static int
640 + parent_loop()
641 + {
642 +        FILE    **outfp = (FILE **)malloc(nchildren*sizeof(FILE *));
643 +        int     i;
644 +
645 +        if (!outfp) goto memerror;
646 +        for (i = 0; i < nchildren; i++) {
647 +                outfp[i] = fdopen(cproc[i].w, "w");
648 +                if (!outfp[i]) goto memerror;
649 + #ifdef getc_unlocked
650 +                flockfile(outfp[i]);
651 + #endif
652 +        }
653 + #ifdef getc_unlocked
654 +        for (i = 0; i < nmats; i++)
655 +                flockfile(mop[i].infp);
656 + #endif
657 +        for (cur_row = 0; (in_nrows <= 0) | (cur_row < in_nrows); cur_row++) {
658 +            FILE        *ofp = outfp[cur_row % nchildren];
659 +            for (i = 0; i < nmats; i++)
660 +                if (!rmx_load_row(mop[i].imx.mtx, &mop[i].imx, mop[i].infp)) {
661 +                        if (cur_row > in_nrows) /* unknown #input rows? */
662 +                                break;
663 +                        fprintf(stderr, "%s: read error at row %d\n",
664 +                                        mop[i].inspec, cur_row);
665 +                        return(0);
666 +                }
667 +            if (i < nmats)
668 +                break;
669 +            for (i = 0; i < nmats; i++)
670 +                if (!rmx_write_data(mop[i].imx.mtx, mop[i].imx.ncomp,
671 +                                        mop[i].imx.ncols, DTdouble, ofp))
672 +                        return(0);
673 +            if (fflush(ofp) == EOF)
674 +                return(0);
675 +        }
676 +        for (i = 0; i < nchildren; i++)
677 +                fclose(outfp[i]);
678 +        free(outfp);
679 +        i = close_processes(cproc, nchildren);
680 +        free(cproc); cproc = NULL;
681 +        if (i < 0) {
682 +                fputs("Warning: missing child in parent_loop()\n", stderr);
683 +                return(1);
684 +        }
685 +        if (i > 0) {
686 +                fprintf(stderr, "Child exited with status %d\n", i);
687 +                return(0);
688 +        }
689 +        return(1);
690 + memerror:
691 +        fputs("Out of memory in parent_loop()\n", stderr);
692 +        exit(1);
693 + }
694 +
695 + static int
696 + combine_input()
697 + {
698 +        const int       row0 = (inchild >= 0)*inchild;
699 +        const int       rstep = nchildren + !nchildren;
700 +        ROPMAT          *res = &mop[nmats];
701 +        int             set_r, set_c;
702 +        RMATRIX         *tmp = NULL;
703 +        int             co_set;
704 +        int             i;
705 +
706          if (mcat && mcat_last &&
707                          !(tmp = rmx_alloc(1, res->imx.ncols, res->rmp->ncomp)))
708                  goto memerror;
573        res->imx.nrows = 1;
574        if (!rmx_prepare(&res->imx))
575                goto memerror;
709                                          /* figure out what the user set */
710          co_set = fundefined("co");
711          if (!co_set)
# Line 588 | Line 721 | combine_input(ROPMAT *res, FILE *fout)
721          } else                          /* save a little time */
722                  set_r = set_c = 0;
723                                          /* read/process row-by-row */
724 <        for (cur_row = 0; (in_nrows <= 0) | (cur_row < in_nrows); cur_row++) {
724 >        for (cur_row = row0; (in_nrows <= 0) | (cur_row < in_nrows); cur_row += rstep) {
725              RMATRIX     *mres = NULL;
726 <            for (i = 0; i < nmats; i++) {
726 >            for (i = 0; i < nmats; i++)
727                  if (!rmx_load_row(mop[i].imx.mtx, &mop[i].imx, mop[i].infp)) {
728 <                        if (in_nrows <= 0)      /* normal end? */
729 <                                goto loop_exit;
728 >                        if (cur_row > in_nrows) /* unknown #input rows? */
729 >                                break;
730                          fprintf(stderr, "%s: read error at row %d\n",
731                                          mop[i].inspec, cur_row);
732                          return(0);
733                  }
734 +            if (i < nmats)
735 +                break;
736 +            for (i = 0; i < nmats; i++)
737                  if (!apply_op(mop[i].rmp, &mop[i].imx, &mop[i].preop))
738                          return(0);
603            }
739              if (set_r) varset("r", '=', cur_row);
740              for (cur_col = 0; cur_col < in_ncols; cur_col++) {
741                  if (set_c) varset("c", '=', cur_col);
# Line 637 | Line 772 | combine_input(ROPMAT *res, FILE *fout)
772                          return(0);
773              }
774              rmx_free(mres); mres = NULL;
775 +            if (inchild >= 0)           /* children share stdout */
776 +                while (nr_out < cur_row)
777 +                    pause();            /* wait for our turn */
778              if (!rmx_write_data(res->rmp->mtx, res->rmp->ncomp,
779 <                                res->rmp->ncols, res->rmp->dtype, fout))
779 >                                res->rmp->ncols, res->rmp->dtype, stdout))
780                  return(0);
781 +            if (inchild >= 0) {         /* flush and notify group */
782 +                if (fflush(stdout) == EOF)
783 +                    return(0);
784 +                killpg(gpid, SIGIO);    /* increments everyone's nr_out */
785 +            }
786          }
787 < 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);
787 >        return(inchild >= 0 || fflush(stdout) != EOF);
788   memerror:
789          fputs("Out of buffer space in combine_input()\n", stderr);
790          return(0);
# Line 680 | Line 808 | resize_inparr(int n2alloc)
808   {
809          int     i;
810  
811 <        for (i = nmats; i > n2alloc; i--) {
811 >        if (n2alloc == nall)
812 >                return;
813 >        for (i = nall; i > n2alloc; i--) {
814                  rmx_reset(&mop[i].imx);
815                  if (mop[i].rmp != &mop[i].imx)
816                          rmx_free(mop[i].rmp);
# Line 690 | Line 820 | resize_inparr(int n2alloc)
820                  fputs("Out of memory in resize_inparr()\n", stderr);
821                  exit(1);
822          }
823 <        if (n2alloc > nmats)
824 <                memset(mop+nmats, 0, (n2alloc-nmats)*sizeof(ROPMAT));
823 >        if (n2alloc > nall)
824 >                memset(mop+nall, 0, (n2alloc-nall)*sizeof(ROPMAT));
825          nall = n2alloc;
826   }
827  
# Line 704 | Line 834 | main(int argc, char *argv[])
834          const char      *defCsym = NULL;
835          int             echoheader = 1;
836          int             stdin_used = 0;
837 +        int             nproc = 1;
838          const char      *mcat_spec = NULL;
839          int             n2comp = 0;
840          uby8            comp_ndx[128];
# Line 731 | Line 862 | main(int argc, char *argv[])
862                          case 'h':
863                                  echoheader = !echoheader;
864                                  break;
865 +                        case 'n':
866 +                                nproc = atoi(argv[++i]);
867 +                                if (nproc <= 0)
868 +                                        goto userr;
869 +                                break;
870                          case 'e':
871                                  if (!n) goto userr;
872                                  comp_ndx[n2comp++] = i++;
# Line 868 | Line 1004 | main(int argc, char *argv[])
1004                  fprintf(stderr, "%s: unsupported output format\n", argv[0]);
1005                  return(1);
1006          }
1007 +        doptimize(1);                   /* optimize definitions */
1008 +        if (spawned_children(nproc))    /* running in parent process? */
1009 +                return(parent_loop() ? 0 : 1);
1010                                          /* process & write rows */
1011 <        return(combine_input(&mop[nmats], stdout) ? 0 : 1);
1011 >        return(combine_input() ? 0 : 1);
1012   stdin_error:
1013          fprintf(stderr, "%s: %s used for more than one input\n",
1014                          argv[0], stdin_name);
1015          return(1);
1016   userr:
1017          fprintf(stderr,
1018 <        "Usage: %s [-h][-f{adfc}][-e expr][-f file][-s sf .. | -c ce ..] m1 .. -m mcat > mres\n",
1018 >        "Usage: %s [-h][-f{adfc}][-n nproc][-e expr][-f file][-s sf .. | -c ce ..] m1 .. -m mcat > mres\n",
1019                          argv[0]);
1020          return(1);
1021   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines