Guest User

Untitled

a guest
Jan 5th, 2018
81
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.55 KB | None | 0 0
  1. //#define ORDER
  2. //-----------------------------------------------------------------------------
  3. using System;
  4. using System.Collections;
  5. using System.Collections.Concurrent;
  6. using System.Collections.Generic;
  7. using System.Linq;
  8. using System.Threading;
  9. using System.Threading.Tasks;
  10.  
  11. namespace ConsoleApp1
  12. {
  13. static class Program
  14. {
  15. static void Main()
  16. {
  17. var arr = new int[21];
  18. int arrayLength = arr.Length;
  19. var myPartitioner = new MyPartitioner(arrayLength);
  20.  
  21. Console.WriteLine("Parallel.ForEach");
  22. Parallel.ForEach(
  23. myPartitioner,
  24. range => Console.WriteLine(range)
  25. );
  26. Console.WriteLine();
  27.  
  28. Console.WriteLine("PLinq");
  29. myPartitioner
  30. .AsParallel()
  31. #if ORDER
  32. .OrderBy(a => a.Start)
  33. .ToList()
  34. .ForEach(a => Console.WriteLine(a));
  35. #else
  36. .ForAll(a => Console.WriteLine(a));
  37. #endif
  38. }
  39. }
  40. //-------------------------------------------------------------------------
  41. internal class MyPartitioner : OrderablePartitioner<(int Start, int End)>
  42. {
  43. private int _arrayLength;
  44. //---------------------------------------------------------------------
  45. public MyPartitioner(int arrayLength)
  46. : base(true, true, true)
  47. => _arrayLength = arrayLength;
  48. //---------------------------------------------------------------------
  49. public override bool SupportsDynamicPartitions => true;
  50. //---------------------------------------------------------------------
  51. // For Parallel.ForEach this method is not needed, only for PLinq
  52. public override IList<IEnumerator<KeyValuePair<long, (int Start, int End)>>> GetOrderablePartitions(int partitionCount)
  53. {
  54. var dynamicPartitions = this.GetOrderableDynamicPartitions();
  55. var partitions = new IEnumerator<KeyValuePair<long, (int Start, int End)>>[partitionCount];
  56.  
  57. for (int i = 0; i < partitions.Length; ++i)
  58. partitions[i] = dynamicPartitions.GetEnumerator();
  59.  
  60. return partitions;
  61. }
  62. //---------------------------------------------------------------------
  63. public override IEnumerable<KeyValuePair<long, (int Start, int End)>> GetOrderableDynamicPartitions()
  64. => new ArrayRangePartitions(_arrayLength);
  65. //---------------------------------------------------------------------
  66. // Could be implemented as enumerator in GetOrderableDynamicPartitions
  67. // and with the fields of the class.
  68. // But then only one "iteration" Parallel.ForEach or PLinq can be done.
  69. // With the separate class multiple iterations can be done.
  70. private class ArrayRangePartitions : IEnumerable<KeyValuePair<long, (int Start, int End)>>
  71. {
  72. private readonly int _arrayLen;
  73. private readonly int _chunkSize;
  74. private readonly int _noOfChunks;
  75. private int _chunkIdx;
  76. //-----------------------------------------------------------------
  77. public ArrayRangePartitions(int arrayLen)
  78. {
  79. int chunkSize = arrayLen / Environment.ProcessorCount;
  80. _noOfChunks = arrayLen / chunkSize;
  81. _arrayLen = arrayLen;
  82. _chunkSize = chunkSize;
  83. }
  84. //-----------------------------------------------------------------
  85. IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator();
  86. //-----------------------------------------------------------------
  87. public IEnumerator<KeyValuePair<long, (int Start, int End)>> GetEnumerator()
  88. {
  89. while (true)
  90. {
  91. int chunkIdx = Interlocked.Increment(ref _chunkIdx) - 1;
  92.  
  93. if (chunkIdx > _noOfChunks) yield break;
  94.  
  95. if (chunkIdx < _noOfChunks)
  96. {
  97. int start = chunkIdx * _chunkSize;
  98. int end = start + _chunkSize;
  99.  
  100. yield return new KeyValuePair<long, (int Start, int End)>(chunkIdx, (start, end));
  101. }
  102. else
  103. {
  104. int start = chunkIdx * _chunkSize;
  105. int end = _arrayLen;
  106.  
  107. yield return new KeyValuePair<long, (int Start, int End)>(chunkIdx, (start, end));
  108. }
  109. }
  110. }
  111. }
  112. }
  113. }
Add Comment
Please, Sign In to add comment