University stuff.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Parallel.java 4.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. import java.util.ArrayList;
  2. import java.util.Arrays;
  3. class Parallel implements Solver {
  4. class SolverWorker implements Runnable {
  5. Sieve sieve;
  6. int step;
  7. int offset;
  8. SolverWorker(Sieve mainSieve, int step, int offset) {
  9. byte[] arr = new byte[mainSieve.arr.length];
  10. System.arraycopy(mainSieve.arr, 0, arr, 0, arr.length);
  11. this.sieve = new Sieve(mainSieve.maxNum, arr);
  12. this.sieve.smallPrimesGenerated = true;
  13. this.step = step;
  14. this.offset = offset;
  15. }
  16. public void run() {
  17. sieve.generatePrimes(step, offset);
  18. }
  19. }
  20. public void solve(Sieve sieve) {
  21. // Generate primes less than sqrt(n)
  22. sieve.generateSmallPrimes();
  23. int nThreads = Runtime.getRuntime().availableProcessors();
  24. nThreads = Math.min(nThreads, 8);
  25. Thread[] threads = new Thread[nThreads];
  26. SolverWorker[] workers = new SolverWorker[nThreads];
  27. // Start threads
  28. for (int i = 0; i < nThreads; ++i) {
  29. SolverWorker w = new SolverWorker(sieve, nThreads, (i * 2) + 1);
  30. workers[i] = w;
  31. Thread t = new Thread(w);
  32. threads[i] = t;
  33. t.start();
  34. }
  35. // Wait for threads
  36. for (Thread t: threads) {
  37. try { t.join(); } catch (InterruptedException ex) {}
  38. }
  39. // Merge
  40. for (int i = 0; i < sieve.arr.length; ++i) {
  41. for (SolverWorker w: workers) {
  42. sieve.arr[i] = (byte)(sieve.arr[i] | w.sieve.arr[i]);
  43. }
  44. }
  45. }
  46. class FactorWorker implements Runnable {
  47. FactorMonitor monitor;
  48. long num;
  49. int sqrt;
  50. int[] primes;
  51. int step;
  52. int offset;
  53. boolean running;
  54. boolean done;
  55. FactorWorker(FactorMonitor monitor, int step, int offset) {
  56. this.monitor = monitor;
  57. this.primes = monitor.primes;
  58. this.num = monitor.num;
  59. this.sqrt = (int)Math.sqrt(num);
  60. this.step = step;
  61. this.offset = offset;
  62. this.done = false;
  63. }
  64. void go() {
  65. int start = offset + monitor.sequentialPrimes;
  66. for (int i = start; monitor.running; i += step) {
  67. if (primes[i] == 0 || primes[i] > sqrt)
  68. break;
  69. if (num % primes[i] == 0) {
  70. monitor.addFactor(primes[i], num);
  71. break;
  72. }
  73. }
  74. running = false;
  75. monitor.workerStopped();
  76. }
  77. synchronized void start(long num) {
  78. this.num = num;
  79. this.sqrt = (int)Math.sqrt(num);
  80. running = true;
  81. notify();
  82. }
  83. synchronized void stop() {
  84. done = true;
  85. notify();
  86. }
  87. synchronized public void run() {
  88. while (!done) {
  89. while (!running && !done)
  90. try { wait(); } catch (InterruptedException ex) {}
  91. if (!done)
  92. go();
  93. }
  94. }
  95. }
  96. class FactorMonitor {
  97. final int sequentialPrimes = 4;
  98. Sieve sieve;
  99. long num;
  100. int nThreads;
  101. int[] primes;
  102. boolean running;
  103. boolean done;
  104. boolean foundFactor;
  105. int workersLeft;
  106. FactorWorker[] workers;
  107. Thread[] threads;
  108. ArrayList<Long> factors = new ArrayList<>();
  109. FactorMonitor(Sieve sieve, long num, int nThreads) {
  110. this.primes = sieve.getPrimes();
  111. this.num = num;
  112. this.nThreads = nThreads;
  113. this.done = false;
  114. // We do the first few primes sequentially, as they're
  115. // very likely to be factors
  116. for (int i = 0; i < sequentialPrimes; ++i) {
  117. while (this.num % primes[i] == 0) {
  118. factors.add(new Long(primes[i]));
  119. this.num /= primes[i];
  120. }
  121. }
  122. this.workers = new FactorWorker[nThreads];
  123. this.threads = new Thread[nThreads];
  124. for (int i = 0; i < nThreads; ++i) {
  125. FactorWorker w = new FactorWorker(this, nThreads, i);
  126. Thread t = new Thread(w);
  127. this.workers[i] = w;
  128. this.threads[i] = t;
  129. t.start();
  130. }
  131. go();
  132. }
  133. synchronized void addFactor(int prime, long num) {
  134. foundFactor = true;
  135. if (num != this.num)
  136. return;
  137. do {
  138. this.num /= prime;
  139. factors.add(new Long(prime));
  140. } while (this.num % prime == 0);
  141. running = false;
  142. }
  143. synchronized void workerStopped() {
  144. workersLeft -= 1;
  145. if (workersLeft != 0)
  146. return;
  147. if (foundFactor) {
  148. go();
  149. } else {
  150. done = true;
  151. notify();
  152. for (FactorWorker w: workers)
  153. w.stop();
  154. }
  155. }
  156. synchronized long[] getFactors() {
  157. while (!done)
  158. try { wait(); } catch (InterruptedException ex) {}
  159. if (num != 1)
  160. factors.add(new Long(num));
  161. long[] arr = new long[factors.size()];
  162. for (int i = 0; i < arr.length; ++i)
  163. arr[i] = factors.get(i);
  164. Arrays.sort(arr);
  165. return arr;
  166. }
  167. synchronized void go() {
  168. running = true;
  169. foundFactor = false;
  170. workersLeft = nThreads;
  171. for (FactorWorker w: workers)
  172. w.start(num);
  173. }
  174. }
  175. public long[] factor(Sieve sieve, long num) {
  176. int nThreads = Runtime.getRuntime().availableProcessors();
  177. nThreads = Math.min(nThreads, 8);
  178. FactorMonitor monitor = new FactorMonitor(sieve, num, nThreads);
  179. return monitor.getFactors();
  180. }
  181. public void stopThreads() {
  182. }
  183. }