Advertisement
Guest User

Untitled

a guest
Apr 19th, 2015
205
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.68 KB | None | 0 0
  1. // AForge Core Library
  2. // AForge.NET framework
  3. //
  4. // Copyright © Andrew Kirillov, 2008
  5. // andrew.kirillov@gmail.com
  6. //
  7. // Copyright © Israel Lot, 2008
  8. // israel.lot@gmail.com
  9. //
  10.  
  11. namespace AForge
  12. {
  13. using System;
  14. using System.Threading;
  15.  
  16. /// <summary>
  17. /// The class provides support for parallel computations, paralleling loop's iterations.
  18. /// </summary>
  19. ///
  20. /// <remarks><para>The class allows to parallel loop's iteration computing them in separate threads,
  21. /// what allows their simultaneous execution on multiple CPUs/cores.
  22. /// </para></remarks>
  23. ///
  24. public sealed class Parallel
  25. {
  26. /// <summary>
  27. /// Delegate defining for-loop's body.
  28. /// </summary>
  29. ///
  30. /// <param name="index">Loop's index.</param>
  31. ///
  32. public delegate void ForLoopBody( int index );
  33.  
  34. // number of threads for parallel computations
  35. private static int threadsCount = System.Environment.ProcessorCount;
  36. // object used for synchronization
  37. private static object sync = new Object( );
  38.  
  39. // single instance of the class to implement singleton pattern
  40. private static volatile Parallel instance = null;
  41. // background threads for parallel computation
  42. private Thread[] threads = null;
  43.  
  44. // events to signal about job availability and thread availability
  45. private AutoResetEvent[] jobAvailable = null;
  46. private ManualResetEvent[] threadIdle = null;
  47.  
  48. // loop's body and its current and stop index
  49. private int currentIndex;
  50. private int stopIndex;
  51. private ForLoopBody loopBody;
  52.  
  53. /// <summary>
  54. /// Number of threads used for parallel computations.
  55. /// </summary>
  56. ///
  57. /// <remarks><para>The property sets how many worker threads are created for paralleling
  58. /// loops' computations.</para>
  59. ///
  60. /// <para>By default the property is set to number of CPU's in the system
  61. /// (see <see cref="System.Environment.ProcessorCount"/>).</para>
  62. /// </remarks>
  63. ///
  64. public static int ThreadsCount
  65. {
  66. get { return threadsCount; }
  67. set
  68. {
  69. lock ( sync )
  70. {
  71. threadsCount = Math.Max( 1, value );
  72. }
  73. }
  74. }
  75.  
  76. /// <summary>
  77. /// Executes a for-loop in which iterations may run in parallel.
  78. /// </summary>
  79. ///
  80. /// <param name="start">Loop's start index.</param>
  81. /// <param name="stop">Loop's stop index.</param>
  82. /// <param name="loopBody">Loop's body.</param>
  83. ///
  84. /// <remarks><para>The method is used to parallel for-loop running its iterations in
  85. /// different threads. The <b>start</b> and <b>stop</b> parameters define loop's
  86. /// starting and ending loop's indexes. The number of iterations is equal to <b>stop - start</b>.
  87. /// </para>
  88. ///
  89. /// <para>Sample usage:</para>
  90. /// <code>
  91. /// Parallel.For( 0, 20, delegate( int i )
  92. /// // which is equivalent to
  93. /// // for ( int i = 0; i < 20; i++ )
  94. /// {
  95. /// System.Diagnostics.Debug.WriteLine( "Iteration: " + i );
  96. /// // ...
  97. /// } );
  98. /// </code>
  99. /// </remarks>
  100. ///
  101. public static void For( int start, int stop, ForLoopBody loopBody )
  102. {
  103. lock ( sync )
  104. {
  105. // get instance of parallel computation manager
  106. Parallel instance = Instance;
  107.  
  108. instance.currentIndex = start - 1;
  109. instance.stopIndex = stop;
  110. instance.loopBody = loopBody;
  111.  
  112. // signal about available job for all threads and mark them busy
  113. for ( int i = 0; i < threadsCount; i++ )
  114. {
  115. instance.threadIdle[i].Reset( );
  116. instance.jobAvailable[i].Set( );
  117. }
  118.  
  119. // wait until all threads become idle
  120. for ( int i = 0; i < threadsCount; i++ )
  121. {
  122. instance.threadIdle[i].WaitOne( );
  123. }
  124. }
  125. }
  126.  
  127. // Private constructor to avoid class instantiation
  128. private Parallel( ) { }
  129.  
  130. // Get instace of the Parallel class
  131. private static Parallel Instance
  132. {
  133. get
  134. {
  135. if ( instance == null )
  136. {
  137. instance = new Parallel( );
  138. instance.Initialize( );
  139. }
  140. else
  141. {
  142. if ( instance.threads.Length != threadsCount )
  143. {
  144. // terminate old threads
  145. instance.Terminate( );
  146. // reinitialize
  147. instance.Initialize( );
  148.  
  149. // TODO: change reinitialization to reuse already created objects
  150. }
  151. }
  152. return instance;
  153. }
  154. }
  155.  
  156. // Initialize Parallel class's instance creating required number of threads
  157. // and synchronization objects
  158. private void Initialize( )
  159. {
  160. // array of events, which signal about available job
  161. jobAvailable = new AutoResetEvent[threadsCount];
  162. // array of events, which signal about available thread
  163. threadIdle = new ManualResetEvent[threadsCount];
  164. // array of threads
  165. threads = new Thread[threadsCount];
  166.  
  167. for ( int i = 0; i < threadsCount; i++ )
  168. {
  169. jobAvailable[i] = new AutoResetEvent( false );
  170. threadIdle[i] = new ManualResetEvent( true );
  171.  
  172. threads[i] = new Thread( new ParameterizedThreadStart( WorkerThread ) );
  173. threads[i].IsBackground = true;
  174. threads[i].Start( i );
  175. }
  176. }
  177.  
  178. // Terminate all worker threads used for parallel computations and close all
  179. // synchronization objects
  180. private void Terminate( )
  181. {
  182. // finish thread by setting null loop body and signaling about available work
  183. loopBody = null;
  184. for ( int i = 0, threadsCount = threads.Length ; i < threadsCount; i++ )
  185. {
  186. jobAvailable[i].Set( );
  187. // wait for thread termination
  188. threads[i].Join( );
  189.  
  190. // close events
  191. jobAvailable[i].Close( );
  192. threadIdle[i].Close( );
  193. }
  194.  
  195. // clean all array references
  196. jobAvailable = null;
  197. threadIdle = null;
  198. threads = null;
  199. }
  200.  
  201. // Worker thread performing parallel computations in loop
  202. private void WorkerThread( object index )
  203. {
  204. int threadIndex = (int) index;
  205. int localIndex = 0;
  206.  
  207. while ( true )
  208. {
  209. // wait until there is job to do
  210. jobAvailable[threadIndex].WaitOne( );
  211.  
  212. // exit on null body
  213. if ( loopBody == null )
  214. break;
  215.  
  216. while ( true )
  217. {
  218. // get local index incrementing global loop's current index
  219. localIndex = Interlocked.Increment( ref currentIndex );
  220.  
  221. if ( localIndex >= stopIndex )
  222. break;
  223.  
  224. // run loop's body
  225. loopBody( localIndex );
  226. }
  227.  
  228. // signal about thread availability
  229. threadIdle[threadIndex].Set( );
  230. }
  231. }
  232. }
  233. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement