Parallel.cs 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.Text;
  5. using System.Threading;
  6. namespace Utilities
  7. {
  8. public delegate void ForDelegate(int i);
  9. public delegate void DelegateProcess();
  10. // Based on:
  11. // http://coding-time.blogspot.pt/2008/03/implement-your-own-parallelfor-in-c.html
  12. // C# 2.0 adaptation based on:
  13. // http://dotnetgalactics.wordpress.com/2009/11/19/how-to-provide-a-parallel-for-loop-in-c2-0-2/
  14. public class Parallel
  15. {
  16. /// <summary>
  17. /// Parallel for loop. Invokes given action, passing arguments
  18. /// fromInclusive - toExclusive on multiple threads.
  19. /// Returns when loop finished.
  20. /// </summary>
  21. public static void For(int fromInclusive, int toExclusive, ForDelegate forDelegate)
  22. {
  23. int chunkSize = 4;
  24. For(fromInclusive, toExclusive, chunkSize, forDelegate);
  25. }
  26. /// <summary>
  27. /// Parallel for loop. Invokes given action, passing arguments
  28. /// fromInclusive - toExclusive on multiple threads.
  29. /// Returns when loop finished.
  30. /// </summary>
  31. /// <param name="chunkSize">
  32. /// chunkSize = 1 makes items to be processed in order.
  33. /// Bigger chunk size should reduce lock waiting time and thus
  34. /// increase paralelism.
  35. /// </param>
  36. public static void For(int fromInclusive, int toExclusive, int chunkSize, ForDelegate forDelegate)
  37. {
  38. int threadCount = Environment.ProcessorCount;
  39. For(fromInclusive, toExclusive, chunkSize, threadCount, forDelegate);
  40. }
  41. /// <summary>
  42. /// Parallel for loop. Invokes given action, passing arguments
  43. /// fromInclusive - toExclusive on multiple threads.
  44. /// Returns when loop finished.
  45. /// </summary>
  46. /// <param name="chunkSize">
  47. /// chunkSize = 1 makes items to be processed in order.
  48. /// Bigger chunk size should reduce lock waiting time and thus
  49. /// increase paralelism.
  50. /// </param>
  51. /// <param name="threadCount">number of process() threads</param>
  52. public static void For(int fromInclusive, int toExclusive, int chunkSize, int threadCount, ForDelegate forDelegate)
  53. {
  54. int index = fromInclusive - chunkSize;
  55. // locker object shared by all the process() delegates
  56. object locker = new object();
  57. // processing function
  58. // takes next chunk and processes it using action
  59. DelegateProcess process = delegate()
  60. {
  61. while (true)
  62. {
  63. int chunkStart = 0;
  64. lock (locker)
  65. {
  66. // take next chunk
  67. index += chunkSize;
  68. chunkStart = index;
  69. }
  70. // process the chunk
  71. // (another thread is processing another chunk
  72. // so the real order of items will be out-of-order)
  73. for (int i = chunkStart; i < chunkStart + chunkSize; i++)
  74. {
  75. if (i >= toExclusive) return;
  76. forDelegate(i);
  77. }
  78. }
  79. };
  80. // launch process() threads
  81. IAsyncResult[] asyncResults = new IAsyncResult[threadCount];
  82. for (int i = 0; i < threadCount; ++i)
  83. {
  84. asyncResults[i] = process.BeginInvoke(null, null);
  85. }
  86. // wait for all threads to complete
  87. for (int i = 0; i < threadCount; ++i)
  88. {
  89. process.EndInvoke(asyncResults[i]);
  90. }
  91. }
  92. }
  93. }