ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/RtraceSimulManager.cpp
(Generate patch)

Comparing ray/src/rt/RtraceSimulManager.cpp (file contents):
Revision 2.1 by greg, Wed Feb 8 17:41:48 2023 UTC vs.
Revision 2.5 by greg, Tue Mar 12 16:54:51 2024 UTC

# Line 9 | Line 9 | static const char RCSid[] = "$Id$";
9   *  Created by Greg Ward on 2/2/2023.
10   */
11  
12 + #include <unistd.h>
13   #include "RtraceSimulManager.h"
14   #include "source.h"
15  
# Line 21 | Line 22 | RadSimulManager::LoadOctree(const char *octn)
22          if (octname) {          // already running?
23                  if (octn && !strcmp(octn, octname))
24                          return true;
25 <                Cleanup();
25 >                Cleanup(false);
26          }
27          if (!octn)
28                  return false;
# Line 30 | Line 31 | RadSimulManager::LoadOctree(const char *octn)
31          return true;
32   }
33  
34 + // How many processors are available?
35 + int
36 + RadSimulManager::GetNCores()
37 + {
38 +        return sysconf(_NPROCESSORS_ONLN);
39 + }
40 +
41   // Set number of computation threads (0 => #cores)
42   int
43   RadSimulManager::SetThreadCount(int nt)
44   {
45 <        return nThreads = 1;    // XXX temporary
45 >        if (nt <= 0) nt = GetNCores();
46 >
47 >        return nThreads = nt;
48   }
49  
50 + // Assign ray to subthread (fails if NThreads()<2)
51 + bool
52 + RadSimulManager::SplitRay(RAY *r)
53 + {
54 +        if (NThreads() < 2 || ThreadsAvailable() < 1)
55 +                return false;
56 +
57 +        int     rv = ray_psend(r);
58 +        if (rv < 0)
59 +                nThreads = 1;   // someone died
60 +        return (rv > 0);
61 + }
62 +
63 + // Process a ray (in subthread), optional result
64 + bool
65 + RadSimulManager::ProcessRay(RAY *r)
66 + {
67 +        if (!r || !Ready()) return false;
68 +        if (NThreads() < 2) {   // single-threaded mode?
69 +                samplendx++;
70 +                rayvalue(r);
71 +                return true;
72 +        }
73 +        if (ThreadsAvailable() >= 1) {
74 +                SplitRay(r);    // queue not yet full
75 +                return false;
76 +        }
77 +        RAY     toDo = *r;
78 +        if (!WaitResult(r))     // need a free thread
79 +                return false;
80 +
81 +        return SplitRay(&toDo); // queue up new ray & return old
82 + }
83 +
84 + // Wait for next result (or fail)
85 + bool
86 + RadSimulManager::WaitResult(RAY *r)
87 + {
88 +        int     rv = ray_presult(r, 0);
89 +        if (rv < 0)
90 +                nThreads = 1;   // someone died
91 +        return (rv > 0);
92 + }
93 +
94   // Close octree, free data, return status
95   int
96 < RadSimulManager::Cleanup()
96 > RadSimulManager::Cleanup(bool everything)
97   {
98 <        ray_done(0);
98 >        if (NThreads() > 1)
99 >                ray_pdone(everything);
100 >        else
101 >                ray_done(everything);
102          return 0;
103   }
104  
# Line 49 | Line 106 | RadSimulManager::Cleanup()
106   int
107   RadSimulManager::ThreadsAvailable() const
108   {
109 <        return 1;       // XXX temporary
109 >        if (NThreads() == 1) return 1;
110 >        return ray_pnidle;
111   }
112  
113   // Global pointer to simulation manager for trace call-back (only one)
# Line 82 | Line 140 | RtraceSimulManager::UpdateMode()
140                  } else          // cannot undo this...
141                          rtFlags |= RTtraceSources;
142          }
143 <        if (misMatch & RTdoFIFO) {
144 <                if (!FlushQueue())
87 <                        return false;
88 <        }
143 >        if (misMatch & RTdoFIFO && FlushQueue() < 0)
144 >                return false;
145          curFlags = rtFlags;
146                                  // update trace callback
147          if (traceCall) {
# Line 132 | Line 188 | raycast(RAY *r)
188          }
189   }
190  
191 + // Add a ray result to FIFO, flushing what we can
192 + int
193 + RtraceSimulManager::QueueResult(const RAY &ra)
194 + {
195 +        return 0;       // UNIMPLEMENTED
196 + }
197 +
198   // Add ray bundle to queue w/ optional 1st ray ID
199   int
200   RtraceSimulManager::EnqueueBundle(const FVECT orig_direc[], int n, RNUMBER rID0)
# Line 149 | Line 212 | RtraceSimulManager::EnqueueBundle(const FVECT orig_dir
212                  return -1;
213  
214          while (n-- > 0) {               // queue each ray
152                double  d;
215                  VCOPY(res.rorg, orig_direc[0]);
216                  VCOPY(res.rdir, orig_direc[1]);
217                  orig_direc += 2;
# Line 160 | Line 222 | RtraceSimulManager::EnqueueBundle(const FVECT orig_dir
222                          res.revf = rayirrad;
223                  else if (castonly)
224                          res.revf = raycast;
225 <                d = normalize(res.rdir);
225 >                double  d = normalize(res.rdir);
226 >                bool    sendRes = (cookedCall != NULL);
227                  if (d > 0) {            // direction vector is valid?
228                          if (curFlags & RTlimDist)
229                                  res.rmax = d;
230 <                        samplendx++;
231 <                        rayvalue(&res);         // XXX single-threaded for now
232 <                        ++nqueued;
230 >                        if ((sendRes &= ProcessRay(&res)) &&
231 >                                        rtFlags & RTdoFIFO && NThreads() > 1) {
232 >                                if (QueueResult(res) < 0)
233 >                                        return -1;
234 >                                sendRes = false;
235 >                        }
236                  } else if (ThreadsAvailable() < NThreads() &&
237 <                                !FlushQueue())
237 >                                FlushQueue() < 0)
238                          return -1;
239 <                if (cookedCall)
239 >
240 >                if (sendRes)            // may be dummy ray
241                          (*cookedCall)(&res, ccData);
242 +                nqueued++;
243          }
244          return nqueued;
245   }
246  
247   // Finish pending rays and complete callbacks
248 < bool
248 > int
249   RtraceSimulManager::FlushQueue()
250   {
251 <        return true;            // XXX no-op for now
251 >        int     nsent = 0;
252 >        RAY     res;
253 >
254 >        while (WaitResult(&res)) {
255 >                if (!cookedCall) continue;
256 >                if (rtFlags & RTdoFIFO) {
257 >                        int     ns = QueueResult(res);
258 >                        if (ns < 0) return ns;
259 >                        nsent += ns;
260 >                } else {
261 >                        (*cookedCall)(&res, ccData);
262 >                        nsent++;
263 >                }
264 >        }
265 >        return nsent;
266   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines