Revision: 7910
          http://playerstage.svn.sourceforge.net/playerstage/?rev=7910&view=rev
Author:   rtv
Date:     2009-06-26 05:55:33 +0000 (Fri, 26 Jun 2009)

Log Message:
-----------
new multithread model seems to perform pretty well

Modified Paths:
--------------
    code/stage/trunk/examples/ctrl/CMakeLists.txt
    code/stage/trunk/libstage/model.cc
    code/stage/trunk/libstage/model_laser.cc
    code/stage/trunk/libstage/stage.hh
    code/stage/trunk/libstage/world.cc
    code/stage/trunk/worlds/benchmark/cave.world
    code/stage/trunk/worlds/fasr.world

Modified: code/stage/trunk/examples/ctrl/CMakeLists.txt
===================================================================
--- code/stage/trunk/examples/ctrl/CMakeLists.txt       2009-06-26 01:48:30 UTC 
(rev 7909)
+++ code/stage/trunk/examples/ctrl/CMakeLists.txt       2009-06-26 05:55:33 UTC 
(rev 7910)
@@ -5,7 +5,7 @@
      sink
      source
      wander
-     rasterize
+#     rasterize
 )
 
 # need plaer's wavefront planning library for this one

Modified: code/stage/trunk/libstage/model.cc
===================================================================
--- code/stage/trunk/libstage/model.cc  2009-06-26 01:48:30 UTC (rev 7909)
+++ code/stage/trunk/libstage/model.cc  2009-06-26 05:55:33 UTC (rev 7910)
@@ -706,19 +706,20 @@
   //                    this->world->sim_time, this->token, this->subs );
   
   // if we're drawing current and a power pack has been installed
+
   
   PowerPack* pp = FindPowerPack();
   if( pp && ( watts > 0 ))
-    {
-      // consume  energy stored in the power pack
-      stg_joules_t consumed =  watts * (world->interval_sim * 1e-6); 
-      pp->Dissipate( consumed, GetGlobalPose() );      
-    }
-
+        {
+               // consume  energy stored in the power pack
+               stg_joules_t consumed =  watts * (world->interval_sim * 1e-6); 
+               pp->Dissipate( consumed, GetGlobalPose() );      
+        }
+  
   last_update = world->sim_time;
   
   if( log_state )
-        world->Log( this );
+        world->Log( this );
 }
 
 void Model::CallUpdateCallbacks( void )

Modified: code/stage/trunk/libstage/model_laser.cc
===================================================================
--- code/stage/trunk/libstage/model_laser.cc    2009-06-26 01:48:30 UTC (rev 
7909)
+++ code/stage/trunk/libstage/model_laser.cc    2009-06-26 05:55:33 UTC (rev 
7910)
@@ -168,10 +168,11 @@
 
 void ModelLaser::Update( void )
 {     
+  // removed UnMapFromRoot() optimization - though neat, it breaks
+  // thread-safety by messing with the Cell contents - rtv.
+
   assert( samples.size() == sample_count );
-  
-  UnMapFromRoot(); // Don't raytrace self
-  
+    
   double bearing( -fov/2.0 );
   // make the first and last rays exactly at the extremes of the FOV
   double sample_incr( fov / MAX(sample_count-1,1) );
@@ -222,8 +223,9 @@
                  }
        }
   
-  MapFromRoot();
-       
+  // removed MapFromRoot() optimization - though neat, it breaks
+  // thread-safety by messing with the Cell contents - rtv
+
   Model::Update();
 }
 

Modified: code/stage/trunk/libstage/stage.hh
===================================================================
--- code/stage/trunk/libstage/stage.hh  2009-06-26 01:48:30 UTC (rev 7909)
+++ code/stage/trunk/libstage/stage.hh  2009-06-26 05:55:33 UTC (rev 7910)
@@ -952,7 +952,7 @@
         bool show_clock; ///< iff true, print the sim time on stdout
         unsigned int show_clock_interval; ///< updates between clock xoutputs
     GMutex* thread_mutex; ///< protect the worker thread management stuff
-    GThreadPool *threadpool; ///<worker threads for updating some sensor 
models in parallel
+    //GThreadPool *threadpool; ///<worker threads for updating some sensor 
models in parallel
     int total_subs; ///< the total number of subscriptions to all models
     GList* velocity_list; ///< Models with non-zero velocity and should have 
their poses updated
        

Modified: code/stage/trunk/libstage/world.cc
===================================================================
--- code/stage/trunk/libstage/world.cc  2009-06-26 01:48:30 UTC (rev 7909)
+++ code/stage/trunk/libstage/world.cc  2009-06-26 05:55:33 UTC (rev 7910)
@@ -14,22 +14,36 @@
     interval_real   100
     interval_sim    100
     resolution      0.02
+    threads         0
 
     @endverbatim
 
     @par Details
+
     - interval_sim <int>\n
-    the length of each simulation update cycle in milliseconds.
+    The length of each simulation update cycle in milliseconds.
+
     - interval_real <int>\n
-    the amount of real-world (wall-clock) time the siulator will attempt to 
spend on each simulation cycle.
+    The amount of real-world (wall-clock) time the siulator will
+    attempt to spend on each simulation cycle.
+
     - resolution <float>\n
-    The resolution (in meters) of the underlying bitmap model. Larger values 
speed up raytracing at the expense of fidelity in collision detection and 
sensing. 
+    The resolution (in meters) of the underlying bitmap model. Larger
+    values speed up raytracing at the expense of fidelity in collision
+    detection and sensing.
 
+    - threads <int>\n
+        The number of worker threads to spawn. Some models can be updated
+        in parallel (e.g. laser, ranger), and running 2 or more threads
+        here may make the simulation run faster, depending on the number
+        of CPU cores available and the worldfile. As a guideline, use one
+        thread per core if you have high-resolution models, e.g. a laser
+        with hundreds of samples
+        
     @par More examples
     The Stage source distribution contains several example world files in
     <tt>(stage src)/worlds</tt> along with the worldfile properties
     described on the manual page for each model type.
-
 */
 
 #ifndef _GNU_SOURCE
@@ -76,7 +90,6 @@
   show_clock( false ),
   show_clock_interval( 100 ), // 10 simulated seconds using defaults
   thread_mutex( g_mutex_new() ),
-  //threadpool( NULL ),
   total_subs( 0 ), 
   velocity_list( NULL ),
   worker_threads( 0 ),
@@ -163,30 +176,31 @@
          //puts( "worker waiting for start signal" );
          g_cond_wait( world->threads_start_cond, world->thread_mutex );
          g_mutex_unlock( world->thread_mutex );
+         //puts( "worker thread awakes" );
          
-         //puts( "worker thread awakes" );
-
-         //r loop over the list of rentrant models for this thread
+         // loop over the list of rentrant models for this thread
          FOR_EACH( it, world->reentrant_update_lists[thread_instance] )
-               {
-                 Model* mod = *it;
-                 //printf( "thread %d updating model %s (%p)\n", 
thread_instance, mod->Token(), mod );
-                 mod->UpdateIfDue();
-                 mod->CallUpdateCallbacks();
-               }
+                {
+                       Model* mod = *it;
+                       //printf( "thread %d updating model %s (%p)\n", 
thread_instance, mod->Token(), mod );
+                       
+                       // TODO - some of this (Model::Update()) is not thread 
safe!
+                       if( mod->UpdateDue() )
+                         mod->Update();
+                }
          
          // done working, so increment the counter. If this was the last
          // thread to finish working, signal the main thread, which is
          // blocked waiting for this to happen
          g_mutex_lock( world->thread_mutex );    
          if( --world->threads_working == 0 )
-               {
-                 //puts( "last worker signalling main thread" );
-                 g_cond_signal( world->threads_done_cond );
-               }
-         //g_mutex_unlock( world->thread_mutex );        
-    }
-
+                {
+                       //puts( "last worker signalling main thread" );
+                       g_cond_signal( world->threads_done_cond );
+                }
+         // keep lock going round the loop
+       }
+  
   return NULL;
 }
 
@@ -341,7 +355,7 @@
                                                           NULL );              
  
                        }
                  
-                 printf( "[threadpool %u]", worker_threads );  
+                 printf( "[threads %u]", worker_threads );     
                }
     }
 
@@ -529,7 +543,10 @@
   
   // then update all models on the update lists
   FOR_EACH( it, nonreentrant_update_list )
-       (*it)->UpdateIfDue();
+        {
+               //printf( "thread MAIN updating model %s\n", (*it)->Token() );
+               (*it)->UpdateIfDue();
+        }
   
   //printf( "nonre list length %d\n", g_list_length( nonreentrant_update_list 
) );
   //printf( "re list length %d\n", g_list_length( reentrant_update_list ) );
@@ -555,13 +572,15 @@
                  g_cond_wait( threads_done_cond, thread_mutex );
                }
       g_mutex_unlock( thread_mutex );           
-
          //puts( "main thread awakes" );
 
-         // TODO - move this back here!
-         // now call all the callbacks - ignores dueness, but not a big deal
-         //FOR_EACH( it, reentrant_update_list )
-         //(*it)->CallUpdateCallbacks();
+               // TODO: allow threadsafe callbacks to be called in worker
+               // threads
+
+               // now call all the callbacks in each list
+               FOR_EACH( it1, reentrant_update_lists )
+                 FOR_EACH( it2, *it1 )
+                 (*it2)->CallUpdateCallbacks();
     }
   
   if( show_clock && ((this->updates % show_clock_interval) == 0) )
@@ -660,7 +679,6 @@
   RaytraceResult sample( r.origin, r.range );
        
   // our global position in (floating point) cell coordinates
-  //stg_point_t glob( r.origin.x * ppm, r.origin.y * ppm );
   double globx( r.origin.x * ppm );
   double globy( r.origin.y * ppm );
        
@@ -709,7 +727,7 @@
                        
   // Stage spends up to 95% of its time in this loop! It would be
   // neater with more function calls encapsulating things, but even
-  // inline calls have a noticeable (2-3%) effect on performance  
+  // inline calls have a noticeable (2-3%) effect on performance.
   while( n > 0  ) // while we are still not at the ray end
     { 
          Region* reg( GetSuperRegionCached( GETSREG(globx), GETSREG(globy) )
@@ -727,7 +745,7 @@
                                        
                  Cell* c( &reg->cells[ cx + cy * REGIONWIDTH ] );
                  assert(c); // should be good: we know the region contains 
objects
-                                       
+
                  // while within the bounds of this region and while some ray 
remains
                  // we'll tweak the cell pointer directly to move around 
quickly
                  while( (cx>=0) && (cx<REGIONWIDTH) && 
@@ -1106,7 +1124,7 @@
 {
   LogEntry( sim_time, mod);
 
-  printf( "log entry count %d\n", LogEntry::Count() );
+  printf( "log entry count %u\n", (unsigned int)LogEntry::Count() );
   //LogEntry::Print();
 }
  

Modified: code/stage/trunk/worlds/benchmark/cave.world
===================================================================
--- code/stage/trunk/worlds/benchmark/cave.world        2009-06-26 01:48:30 UTC 
(rev 7909)
+++ code/stage/trunk/worlds/benchmark/cave.world        2009-06-26 05:55:33 UTC 
(rev 7910)
@@ -11,8 +11,6 @@
 interval_real 0 # real-time interval between simulation updates in 
milliseconds 
 paused 1
 
-threadpool 0
-
 # configure the GUI window
 window
 (
@@ -57,6 +55,8 @@
 define goldrob rob( color "gold" )
 define darkredrob rob( color "DarkRed" )
 
+# 100 robots in assorted colors
+
 redrob( pose [-5.285 4.915 0 150.459] )
 redrob( pose [-4.458 5.785 0 -85.494] )
 redrob( pose [-5.518 4.157 0 -10.236] )

Modified: code/stage/trunk/worlds/fasr.world
===================================================================
--- code/stage/trunk/worlds/fasr.world  2009-06-26 01:48:30 UTC (rev 7909)
+++ code/stage/trunk/worlds/fasr.world  2009-06-26 05:55:33 UTC (rev 7910)
@@ -11,12 +11,12 @@
 paused 1
 
 # time to pause (in GUI mode) or quit (in headless mode) the simulation
-quit_time 3600 # 1 hour of simulated time
+quit_time 360 # 1 hour of simulated time
 
 resolution 0.02
 
 # threads may speed things up here depending on available CPU cores & workload 
-# threads 3
+threads 0
 
 # configure the GUI window
 window
@@ -133,7 +133,7 @@
 
 define autorob pioneer2dx                
 (               
- sicklaser( samples 32 range_max 5 laser_return 2 watts 30 )
+ sicklaser( samples 320 range_max 5 laser_return 2 watts 30 )
  ctrl "fasr"
  joules 100000 
  joules_capacity 400000 


This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.

------------------------------------------------------------------------------
_______________________________________________
Playerstage-commit mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/playerstage-commit

Reply via email to