Manta Interactive Ray Tracer Development Mailing List

Text archives Help


[MANTA] r1150 - in trunk: Engine/Control Model/Groups Model/Primitives scenes


Chronological Thread 
  • From: cgribble@sci.utah.edu
  • To: manta@sci.utah.edu
  • Subject: [MANTA] r1150 - in trunk: Engine/Control Model/Groups Model/Primitives scenes
  • Date: Thu, 20 Jul 2006 12:00:07 -0600 (MDT)

Author: cgribble
Date: Thu Jul 20 12:00:06 2006
New Revision: 1150

Modified:
   trunk/Engine/Control/DynPLTQueue.cc
   trunk/Engine/Control/DynPLTQueue.h
   trunk/Model/Groups/TimeSteppedParticles.cc
   trunk/Model/Primitives/DynPLTGridSpheres.cc
   trunk/Model/Primitives/DynPLTGridSpheres.h
   trunk/scenes/dynplt.cc
Log:
scenes/dynplt.cc
  Added "-lifo" to cmdln option help menu print-out thingy...
  Corrected queue type message for LIFO queue

Model/Groups/TimeSteppedParticles.cc
  Added call to DynPLTQueue::resizeHeapIdx (only does something interesting 
for
    PriorityQ; others are no-ops)

Model/Primitives/DynPLTGridSpheres.cc
Model/Primitives/DynPLTGridSpheres.h
  Made priority computation a new member function
  Changed requested from vector<bool> to vector<double>; now stores priorities
    (non-zero entry implies that the particle's texture has been requested)
  Toyed around with many different schemes for updating priorities, etc. and
    settled on the following:  priorities for previously requested but still
    invalid textures are not updated before some predetermined period of time
    (currently 5 seconds); even with constant time updates (see below), 
updating
    the priorities every frame is too costly; 5 seconds is reasonably 
responsive
    to user interactions, but +/- some delta might be fine, too

Engine/Control/DynPLTQueue.cc
Engine/Control/DynPLTQueue.h
  Moved priority computation from DynPLTMessage constructor to 
DynPLTGridSpheres
    member function (see above)
  Calls to updatePriority(...) were, in fact, responsible for the slow downs 
in
    the "grow-without-bound" case (linear search through heap was causing
    problems for large datasets); added array to track current heap index for
    each particle to allow constant time updates
  Made updatePriority(...) and resizeHeapIdx(...) no-ops in DynPLTQueue base
   class to prevent uniterested classes from having to implement their own 
no-op
   versions
  Added heap_idx array to PriorityQ:  stores current index into heap of each
    particle (-1 if not in heap); enables constant time priority updates at 
the
    cost of additional memory (4 bytes/particle)
  Added resizeHeapIdx(...) implementation to PriorityQ:  resizes heap_idx 
array
    to number of particles and initializes entries to -1


Modified: trunk/Engine/Control/DynPLTQueue.cc
==============================================================================
--- trunk/Engine/Control/DynPLTQueue.cc (original)
+++ trunk/Engine/Control/DynPLTQueue.cc Thu Jul 20 12:00:06 2006
@@ -11,8 +11,6 @@
   mutex("LifoQ lock"), empty("LifoQ empty condition"),
   full("LifoQ full condition"), top(-1), max_size(size)
 {
-  cerr<<"max_size = "<<max_size<<'\n';
-
   // Allocate dataspace
   dataspace=new char[max_size*sizeof(DynPLTMessage)];
   queue=reinterpret_cast<DynPLTMessage*>(dataspace);
@@ -107,6 +105,10 @@
 
   // Free dataspace
   delete [] dataspace;
+
+#ifndef FIXED_SIZE_QUEUE
+  delete [] heap_idx;
+#endif
 }
 
 bool DynPLTPriorityQ::tryReceive(DynPLTMessage& msg)
@@ -171,22 +173,20 @@
   mutex.unlock();
 }
 
-void DynPLTPriorityQ::updatePriority(int particle, Real t)
+void DynPLTPriorityQ::updatePriority(int particle, double priority)
 {
-  // NOTE:  I suspect that this code causes a lot of contention for the 
queue's
-  //        mutex, and is responsible for the huge slow down with large 
datasets;
-  //        maybe only update the priority after so many frames or something?
+#ifdef FIXED_SIZE_QUEUE
   mutex.lock();
 
   for (unsigned int i=0; i<nheap; ++i) {
     if (heap[i].particle == particle) {
       // Found particle, create new node with updated priority
-      DynPLTMessage msg(particle, t, heap[i].grid);
+      DynPLTMessage msg(particle, priority, heap[i].grid);
 
       // Staring at old node's position in the heap, walk new node up the 
heap
       // until its priority is less than its parent's
       int parent=(i + 1)/2 - 1;
-      while (i && heap[parent].priority < msg.priority) {
+      while (i && heap[parent].priority < priority) {
         heap[i]=heap[parent];
         i=parent;
         parent=(i + 1)/2 - 1;
@@ -200,11 +200,38 @@
   }
 
   mutex.unlock();
+#else
+  mutex.lock();
+
+  int idx=heap_idx[particle];
+  if (idx>-1) {
+    // Found particle, create new message with updated priority
+    DynPLTMessage msg(particle, priority, heap[idx].grid);
+
+    // Staring at old node's position in the heap, walk new node up the heap
+    // until its priority is less than its parent's
+    int parent=(idx + 1)/2 - 1;
+    while (idx && heap[parent].priority < priority) {
+      // Swap parent
+      heap[idx]=heap[parent];
+      heap_idx[heap[idx].particle]=idx;
+
+      idx=parent;
+      parent=(idx + 1)/2 - 1;
+    }
+
+    // Insert message and update heap_idx
+    heap[idx]=msg;
+    heap_idx[particle]=idx;
+  }
+
+  mutex.unlock();
+#endif
 }
 
 void DynPLTPriorityQ::push(DynPLTMessage const& msg)
 {
-#if 0
+#ifdef FIXED_SIZE_QUEUE
   // NOTE:  This code is supposed to implement a fixed size queue in which 
old
   //        requests (i.e., low priority) are dropped and new ones added; it
   //        sort of works, but I'm not sure it's bullet proof yet...
@@ -221,7 +248,7 @@
       parent=(i + 1)/2 - 1;
     }
 
-    // Insert message
+    // Insert message and update heap_idx
     heap[i]=msg;
   } else {
     // Drop last node
@@ -235,9 +262,9 @@
     heapify(0, nheap);
   }
 #else
-  // NOTE:  This code technically allows the queue to grow without bound, 
but in
-  //        practice, the qsize reaches some semi-stable length as texture
-  //        generation requests are produced/consumed by the threads
+  // NOTE:  In theory, the following code allows the queue to grow without 
bound.
+  //        However, in practice, the heap reaches some semi-stable size as
+  //        texture generation requests are produced/consumed by the threads
   ++nheap;
   if (nheap>=max_size) {
     // Save old dataspace, allocate new dataspace
@@ -255,6 +282,11 @@
     // Update heap pointer and max_size
     heap=reinterpret_cast<DynPLTMessage*>(dataspace);
     max_size *= 2;
+
+    /*
+    cerr<<"Heap is now "<<max_size*sizeof(DynPLTMessage)<<" bytes 
("<<max_size
+        <<" messages)\n";
+    */
   }
 
   // Walk node up the heap until its priority is less than its parent's
@@ -262,12 +294,15 @@
   int parent=(i + 1)/2 - 1;
   while (i && heap[parent].priority < msg.priority) {
     heap[i]=heap[parent];
+    heap_idx[heap[i].particle]=i;
+
     i=parent;
     parent=(i + 1)/2 - 1;
   }
 
-  // Insert message
+  // Insert message and update heap_idx
   heap[i]=msg;
+  heap_idx[msg.particle]=i;
 #endif
 }
 
@@ -275,10 +310,16 @@
 {
   // Grab first message
   DynPLTMessage msg=heap[0];
+#ifndef FIXED_SIZE_QUEUE
+  heap_idx[msg.particle]=-1;
+#endif
 
   // Rebuild the heap
   --nheap;
   heap[0]=heap[nheap];
+#ifndef FIXED_SIZE_QUEUE
+  heap_idx[heap[0].particle]=0;
+#endif
   heapify(0, nheap);
 
   return msg;
@@ -303,6 +344,10 @@
     DynPLTMessage tmp=heap[i];
     heap[i]=heap[highest];
     heap[highest]=tmp;
+#ifndef FIXED_SIZE_QUEUE
+    heap_idx[heap[i].particle]=i;
+    heap_idx[heap[highest].particle]=highest;
+#endif
     
     // Recursively build the heap
     heapify(highest, nnodes);

Modified: trunk/Engine/Control/DynPLTQueue.h
==============================================================================
--- trunk/Engine/Control/DynPLTQueue.h  (original)
+++ trunk/Engine/Control/DynPLTQueue.h  Thu Jul 20 12:00:06 2006
@@ -6,32 +6,20 @@
 #include <SCIRun/Core/Thread/Mailbox.h>
 #include <SCIRun/Core/Thread/ConditionVariable.h>
 #include <SCIRun/Core/Thread/Mutex.h>
-#include <SCIRun/Core/Thread/Time.h>
-
-#include <float.h>
-
-// XXX:  temporary
-#include <iostream>
-using std::cerr;
 
 using namespace SCIRun;
 
+// #define FIXED_SIZE_QUEUE
+
 namespace Manta
 {
   class DynPLTGridSpheres;
 
   struct DynPLTMessage {
-    DynPLTMessage(int particle, Real t, const DynPLTGridSpheres* grid) :
-      particle(particle), grid(grid)
+    DynPLTMessage(int particle, double priority, const DynPLTGridSpheres* 
grid) :
+      particle(particle), priority(priority), grid(grid)
     {
-      // Time-stamp only
-      priority=Time::currentSeconds();
-
-      // Time-stamp and distance
-      // priority=Time::currentSeconds() - t;
-
-      // Distance only
-      // priority=DBL_MAX - t;
+      // Do nothing
     }
 
     DynPLTMessage(void) :
@@ -57,7 +45,8 @@
     virtual bool trySend(const DynPLTMessage& msg) = 0;
     virtual void send(const DynPLTMessage& msg) = 0;
 
-    virtual void updatePriority(int particle, Real t) = 0;
+    virtual void updatePriority(int particle, double priority) { /* no-op */ 
}
+    virtual void resizeHeapIdx(unsigned int nparticles_) { /* no-op */ }
   };
 
   class DynPLTFifoQ : public DynPLTQueue
@@ -93,8 +82,6 @@
       mailbox->send(msg);
     }
 
-    void updatePriority(int particle, Real t) { /* no-op */ }
-
   private:
     SCIRun::Mailbox<DynPLTMessage>* mailbox;
   };
@@ -110,8 +97,6 @@
     bool trySend(const DynPLTMessage& msg);
     void send(const DynPLTMessage& msg);
 
-    void updatePriority(int particle, Real t) { /* no-op */ }
-
   private:
     void push(DynPLTMessage const& msg) { queue[++top]=msg; }
     DynPLTMessage pop(void) { return queue[top--]; }
@@ -138,7 +123,17 @@
     DynPLTMessage receive(void);
     bool trySend(const DynPLTMessage& msg);
     void send(const DynPLTMessage& msg);
-    void updatePriority(int particle, Real t);
+
+    void updatePriority(int particle, double priority);
+#ifndef FIXED_SIZE_QUEUE
+    void resizeHeapIdx(unsigned int nparticles_)
+    {
+      nparticles=nparticles_;
+      heap_idx=new int[nparticles];
+      for (unsigned int i=0; i<nparticles; ++i)
+        heap_idx[i]=-1;
+    }
+#endif
 
   private:
     void push(DynPLTMessage const& msg);
@@ -155,6 +150,10 @@
     char* dataspace;
     int max_size;
     int nheap;
+#ifndef FIXED_SIZE_QUEUE
+    int* heap_idx;
+    unsigned int nparticles;
+#endif
   };
 }
 

Modified: trunk/Model/Groups/TimeSteppedParticles.cc
==============================================================================
--- trunk/Model/Groups/TimeSteppedParticles.cc  (original)
+++ trunk/Model/Groups/TimeSteppedParticles.cc  Thu Jul 20 12:00:06 2006
@@ -1,6 +1,7 @@
 
 #include <Core/Exceptions/InputError.h>
 #include <Core/Exceptions/OutputError.h>
+#include <Engine/Control/DynPLTQueue.h>
 #include <Model/Groups/TimeSteppedParticles.h>
 #include <Model/Primitives/GridSpheres.h>
 #include <Model/Readers/ParticleNRRD.h>
@@ -25,6 +26,7 @@
   if (pos != string::npos) {
     ParticleNRRD pnrrd(filename);
     if (queue) {
+      queue->resizeHeapIdx(pnrrd.getNParticles());
       add(new DynPLTGridSpheres(queue, pnrrd.getParticleData(),
                                 pnrrd.getNParticles(), pnrrd.getNVars(), 
ncells,
                                 depth, radius, ridx, cmap, cidx));

Modified: trunk/Model/Primitives/DynPLTGridSpheres.cc
==============================================================================
--- trunk/Model/Primitives/DynPLTGridSpheres.cc (original)
+++ trunk/Model/Primitives/DynPLTGridSpheres.cc Thu Jul 20 12:00:06 2006
@@ -13,6 +13,8 @@
 using namespace Manta;
 using namespace SCIRun;
 
+#define UPDATE_TIME 5.
+
 DynPLTGridSpheres::DynPLTGridSpheres(DynPLTQueue* queue,
                                      float* spheres, int nspheres, int nvars,
                                      int ncells, int depth, Real radius,
@@ -27,7 +29,7 @@
   requested.resize(nspheres);
   for (unsigned int i=0; i<nspheres; ++i) {
     plts[i]=0;
-    requested[i]=false;
+    requested[i]=0.;
     allocated[i]=false;
     valid[i]=false;
   }
@@ -87,13 +89,24 @@
       }
     } else {
       // Request texture generation, if necessary
-      if (!requested[particle]) {
+      if (requested[particle]==0.) {
         // Create and post message
-        DynPLTMessage msg(particle, rays.getMinT(i), this);
+        double priority=computePriority(rays.getMinT(i));
+        DynPLTMessage msg(particle, priority, this);
         if (queue->trySend(msg))
-          requested[particle]=true;
-      } else
-        queue->updatePriority(particle, rays.getMinT(i));
+          requested[particle]=priority;
+      } else {
+#if 1
+        // Update priority only after UPDATE_TIME seconds
+        if (Time::currentSeconds() - requested[particle] > UPDATE_TIME) {
+          requested[particle]=computePriority(rays.getMinT(i));
+          queue->updatePriority(particle, requested[particle]);
+        }
+#else
+        requested[particle]=computePriority(rays.getMinT(i));
+        queue->updatePriority(particle, requested[particle]);
+#endif
+      }
 
       // Use default ambient light while texture is invalid
       activeLights->getAmbientLight()->computeAmbient(context, sub, ambient);
@@ -134,13 +147,24 @@
       }
     } else {
       // Request texture generation, if necessary
-      if (!requested[particle]) {
+      if (requested[particle]==0.) {
         // Create and post message
-        DynPLTMessage msg(particle, rays.getMinT(i), this);
+        double priority=computePriority(rays.getMinT(i));
+        DynPLTMessage msg(particle, priority, this);
         if (queue->trySend(msg))
-          requested[particle]=true;
-      } else
-        queue->updatePriority(particle, rays.getMinT(i));
+          requested[particle]=priority;
+      } else {
+#if 1
+        // Update priority only after UPDATE_TIME seconds
+        if (Time::currentSeconds() - requested[particle] > UPDATE_TIME) {
+          requested[particle]=computePriority(rays.getMinT(i));
+          queue->updatePriority(particle, requested[particle]);
+        }
+#else
+        requested[particle]=computePriority(rays.getMinT(i));
+        queue->updatePriority(particle, requested[particle]);
+#endif
+      }
 
       // Use Lambertian shading while texture is invalid
       GridSpheres::shade(context, sub);

Modified: trunk/Model/Primitives/DynPLTGridSpheres.h
==============================================================================
--- trunk/Model/Primitives/DynPLTGridSpheres.h  (original)
+++ trunk/Model/Primitives/DynPLTGridSpheres.h  Thu Jul 20 12:00:06 2006
@@ -4,10 +4,13 @@
 
 #include <Model/Primitives/GridSpheres.h>
 #include <SCIRun/Core/Thread/Mailbox.h>
+#include <SCIRun/Core/Thread/Time.h>
 
 #include <vector>
 using std::vector;
 
+#include <float.h>
+
 #define XRES 16
 #define YRES 16
 
@@ -101,9 +104,20 @@
     DynPLT* getTexture(int idx) {
       return plts[idx];
     }
+    
+    double computePriority(Real t) const {
+      // Time-stamp only
+      return SCIRun::Time::currentSeconds();
+
+      // Distance only (closest first)
+      // return DBL_MAX - t;
+
+      // Time-stamp and distance
+      // return SCIRun::Time::currentSeconds() - t;
+    }
 
     void resetRequested(int idx) {
-      requested[idx]=false;
+      requested[idx]=0.;
     }
 
   private:
@@ -121,7 +135,7 @@
     }
 
     DynPLTQueue* queue;
-    mutable vector<bool> requested;
+    mutable vector<double> requested;
     vector<bool> allocated;
     vector<bool> valid;
     vector<DynPLT*> plts;

Modified: trunk/scenes/dynplt.cc
==============================================================================
--- trunk/scenes/dynplt.cc      (original)
+++ trunk/scenes/dynplt.cc      Thu Jul 20 12:00:06 2006
@@ -146,6 +146,7 @@
       cerr<<"  -fifo                             use fifo queue for texture 
requests\n";
       cerr<<"  -envmap [bg] <string>             environment map filename\n";
       cerr<<"  -i <string>                       particle data filename\n";
+      cerr<<"  -lifo                             use lifo queue for texture 
requests\n";
       cerr<<"  -nbounces <int>                   number of indirect 
nbounces\n";
       cerr<<"  -ncells <int>                     grid resolution\n";
       cerr<<"  -ngroups <int>                    number of sample groups\n";
@@ -172,7 +173,7 @@
     cerr<<"Using FIFO Queue\n";
   } else if (lifo) {
     queue=new DynPLTLifoQ(nthreads*qsize);
-    cerr<<"Using FIFO Queue\n";
+    cerr<<"Using LIFO Queue\n";
   } else {
     queue=new DynPLTPriorityQ(nthreads*qsize);
     cerr<<"Using Priority Queue\n";




  • [MANTA] r1150 - in trunk: Engine/Control Model/Groups Model/Primitives scenes, cgribble, 07/20/2006

Archive powered by MHonArc 2.6.16.

Top of page