Задать вопрос
  • Почему Fork/Join из JDK7 медленно работает?

    lebedi
    @lebedi
    Дописал к моему методу ещё и вычисления при помощи fork, правда запускал не на 8 ядерном, а на 2 ядерном процессоре. И получил такие результаты.
    Total 38527ms (рекурсивная реализация)
    n Total 1589ms (нерекурсивная реализация)
    m Total 2167ms (многопоточная нерекурсивная реализация)
    f Total 2141ms (нерекурсивная реализация при помощи fork)
    В моей реализации я бы не сказал что особо как то тормозит. Я даже уверен что на 8 ядерной машине будет пошустрее чем 1 поточная нерекурсивная реализация. В вашей реализации порождается уж очень большое количество обьектов, возможно это и есть причина торможения ForkJoinPool.
    Исходный код
    package test;
    
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.LinkedList;
    import java.util.List;
    import java.util.ListIterator;
    import java.util.concurrent.Callable;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.ForkJoinPool;
    import java.util.concurrent.ForkJoinTask;
    import java.util.concurrent.Future;
    import java.util.concurrent.RecursiveTask;
    
    import test.NestedIntervals.FareyCallable.FareyForkJoinTask;
    
    public class NestedIntervals {
    	private static ExecutorService executor;
    	private static ForkJoinPool forkPool;
    	private final int base;
    
    	private NestedIntervals(int base) {
    		this.base = base;
    	}
    
    	public static NestedIntervals base(int base) {
    		return new NestedIntervals(base);
    	}
    
    	public static class Fraction {
    		private int denominator;
    		private int numerator;
    
    		public Fraction(int numerator, int denominator) {
    			super();
    			this.numerator = numerator;
    			this.denominator = denominator;
    		}
    
    		public int getDenominator() {
    			return denominator;
    		}
    
    		public void setDenominator(int denominator) {
    			this.denominator = denominator;
    		}
    
    		public int getNumerator() {
    			return numerator;
    		}
    
    		public void setNumerator(int numerator) {
    			this.numerator = numerator;
    		}
    
    		@Override
    		public String toString() {
    			return numerator + "/" + denominator;
    		}
    
    	}
    
    	private List<Fraction> getFarey(Fraction left, Fraction right) {
    		Fraction mediant = new Fraction(left.getNumerator()
    				+ right.getNumerator(), left.getDenominator()
    				+ right.getDenominator());
    		if (mediant.getDenominator() > base) {
    			return Collections.emptyList();
    		}
    		List<Fraction> result = new LinkedList<Fraction>();
    		result.addAll(getFarey(left, mediant));
    		result.add(mediant);
    		result.addAll(getFarey(mediant, right));
    		return result;
    	}
    
    	public List<Fraction> getFarey() {
    		List<Fraction> result = new LinkedList<Fraction>();
    
    		Fraction left = new Fraction(0, 1);
    		Fraction right = new Fraction(1, 1);
    
    		result.add(left);
    		result.addAll(getFarey(left, right));
    		result.add(right);
    
    		return result;
    	}
    
    	public List<Fraction> getFareyNonRecurcive() {
    		LinkedList<Fraction> result = new LinkedList<Fraction>();
    		Fraction left = new Fraction(0, 1);
    		Fraction right = new Fraction(1, 1);
    		Fraction mediant = null;
    		result.add(left);
    		result.add(right);
    		ListIterator<Fraction> iterator = result.listIterator();
    		left = iterator.next();
    		while (iterator.hasNext()) {
    			right = iterator.next();
    			int denominator = left.getDenominator() + right.getDenominator();
    			if (denominator <= base) {
    				mediant = new Fraction(left.getNumerator()
    						+ right.getNumerator(), denominator);
    				iterator.previous();
    				iterator.add(mediant);
    				iterator.previous();
    			} else {
    				left = right;
    			}
    		}
    		return result;
    	}
    
    	public List<Fraction> getFareyNonRecurciveMultiThread(int threads) {
    		List<Fraction> result = null;
    		if (threads <= 1) {
    			result = getFareyNonRecurcive();
    		} else {
    
    			LinkedList<Fraction> ret = new LinkedList<Fraction>();
    			List<Future<LinkedList<Fraction>>> futureList = new ArrayList<Future<LinkedList<Fraction>>>();
    			// fill params
    			LinkedList<Fraction> params = fillParams(threads);
    			ListIterator<Fraction> listIterator = params.listIterator();
    			Fraction first = listIterator.next();
    			while (listIterator.hasNext()) {
    				Fraction second = (Fraction) listIterator.next();
    				Future<LinkedList<Fraction>> future = executor
    						.submit(new FareyCallable(first, second, base));
    				futureList.add(future);
    				first = second;
    			}
    			try {
    				for (int i = 0; i < futureList.size(); i++) {
    					if (i == 0) {
    						ret.addAll(futureList.get(i).get());
    					} else {
    						LinkedList<Fraction> linkedList = futureList.get(i)
    								.get();
    						linkedList.pollFirst();
    						ret.addAll(linkedList);
    					}
    				}
    			} catch (Exception e) {
    				e.printStackTrace();
    			}
    
    			result = ret;
    		}
    		return result;
    	}
    
    	public List<Fraction> getFareyNonRecurciveFork(int parts) {
    		List<Fraction> result = null;
    		if (parts <= 1) {
    			result = getFareyNonRecurcive();
    		} else {
    
    			FareyForkMapReduceTask fareyForkMapTask = new FareyForkMapReduceTask(base, parts);
    			result = forkPool.invoke(fareyForkMapTask);
    		}
    		return result;
    	}
    
    	private LinkedList<Fraction> fillParams(int parts) {
    		LinkedList<Fraction> params = new LinkedList<Fraction>();
    		params.add(new Fraction(0, 1));
    		params.add(new Fraction(1, 1));
    		Fraction left = null;
    		Fraction right = null;
    		Fraction mediant = null;
    		for (int j = 0; j < base; j++) {
    			ListIterator<Fraction> listIterator = params.listIterator();
    			left = listIterator.next();
    
    			while (listIterator.hasNext()) {
    				if (params.size() - 1 == parts) {
    					return params;
    				}
    				right = listIterator.next();
    				int denominator = left.getDenominator()
    						+ right.getDenominator();
    				if (denominator <= base) {
    					mediant = new Fraction(left.getNumerator()
    							+ right.getNumerator(), denominator);
    					listIterator.previous();
    					listIterator.add(mediant);
    					left = listIterator.next();
    				} else {
    					left = right;
    				}
    
    			}
    		}
    		throw new RuntimeException();
    	}
    
    	public static class FareyCallable implements Callable<LinkedList<Fraction>> {
    		private Fraction first;
    		private Fraction last;
    		private int base;
    
    		public FareyCallable(Fraction first, Fraction last, int base) {
    			super();
    			this.first = first;
    			this.last = last;
    			this.base = base;
    		}
    
    		@Override
    		public LinkedList<Fraction> call() throws Exception {
    			LinkedList<Fraction> result = new LinkedList<Fraction>();
    			Fraction left = first;
    			Fraction right = last;
    			Fraction mediant = null;
    			result.add(left);
    			result.add(right);
    			ListIterator<Fraction> iterator = result.listIterator();
    			left = iterator.next();
    			while (iterator.hasNext()) {
    				right = iterator.next();
    				int denominator = left.getDenominator()
    						+ right.getDenominator();
    				if (denominator <= base) {
    					mediant = new Fraction(left.getNumerator()
    							+ right.getNumerator(), denominator);
    					iterator.previous();
    					iterator.add(mediant);
    					iterator.previous();
    				} else {
    					left = right;
    				}
    			}
    			return result;
    		}
    
    		public static class FareyForkJoinTask extends
    				RecursiveTask<LinkedList<Fraction>> {
    
    			private Fraction first;
    			private Fraction last;
    			private int base;
    
    			public FareyForkJoinTask(Fraction first, Fraction last, int base) {
    				super();
    				this.first = first;
    				this.last = last;
    				this.base = base;
    			}
    
    			@Override
    			protected LinkedList<Fraction> compute() {
    				LinkedList<Fraction> result = new LinkedList<Fraction>();
    				Fraction left = first;
    				Fraction right = last;
    				Fraction mediant = null;
    				result.add(left);
    				result.add(right);
    				ListIterator<Fraction> iterator = result.listIterator();
    				left = iterator.next();
    				while (iterator.hasNext()) {
    					right = iterator.next();
    					int denominator = left.getDenominator()
    							+ right.getDenominator();
    					if (denominator <= base) {
    						mediant = new Fraction(left.getNumerator()
    								+ right.getNumerator(), denominator);
    						iterator.previous();
    						iterator.add(mediant);
    						iterator.previous();
    					} else {
    						left = right;
    					}
    				}
    				return result;
    			}
    
    		}
    
    	}
    
    	public static class FareyForkMapReduceTask extends
    			RecursiveTask<LinkedList<Fraction>> {
    		private int base;
    		private int parts;
    
    		public FareyForkMapReduceTask(int base, int parts) {
    			super();
    			this.base = base;
    			this.parts = parts;
    		}
    
    		@Override
    		protected LinkedList<Fraction> compute() {
    			List<FareyForkJoinTask> taskList = map();
                return reduce(taskList);
    		}
    
    		private LinkedList<Fraction> reduce(List<FareyForkJoinTask> taskList) {
    			LinkedList<Fraction> ret = new LinkedList<Fraction>();
    			try {
    				
    				for (int i = 0; i < taskList.size(); i++) {
    					FareyForkJoinTask task = taskList.get(i);
    					task.join();
    					if (i == 0) {
    						ret.addAll(task.get());
    					} else {
    						LinkedList<Fraction> linkedList = task
    								.get();
    						linkedList.pollFirst();
    						ret.addAll(linkedList);
    					}
    				}
    			} catch (Exception e) {
    				e.printStackTrace();
    			}
    			return ret;
    		}
    
    		private List<FareyForkJoinTask> map() {
    			List<FareyForkJoinTask> taskList = new ArrayList<FareyForkJoinTask>();
    			// fill params
    			LinkedList<Fraction> params = fillParams(parts);
    			ListIterator<Fraction> listIterator = params.listIterator();
    			Fraction first = listIterator.next();
    			while (listIterator.hasNext()) {
    				Fraction second = (Fraction) listIterator.next();
    				FareyForkJoinTask task = new FareyForkJoinTask(first, second, base);
    				taskList.add(task);
    				task.fork();
    				first = second;
    			}
    			return taskList;
    		}
    
    		private LinkedList<Fraction> fillParams(int parts) {
    			LinkedList<Fraction> params = new LinkedList<Fraction>();
    			params.add(new Fraction(0, 1));
    			params.add(new Fraction(1, 1));
    			Fraction left = null;
    			Fraction right = null;
    			Fraction mediant = null;
    			for (int j = 0; j < base; j++) {
    				ListIterator<Fraction> listIterator = params.listIterator();
    				left = listIterator.next();
    
    				while (listIterator.hasNext()) {
    					if (params.size() - 1 == parts) {
    						return params;
    					}
    					right = listIterator.next();
    					int denominator = left.getDenominator()
    							+ right.getDenominator();
    					if (denominator <= base) {
    						mediant = new Fraction(left.getNumerator()
    								+ right.getNumerator(), denominator);
    						listIterator.previous();
    						listIterator.add(mediant);
    						left = listIterator.next();
    					} else {
    						left = right;
    					}
    
    				}
    			}
    			throw new RuntimeException();
    		}
    
    	}
    
    	public static void main(String[] args) {
    		int threads = 2;
    		int parts = 1024;
    		int base = 5000;
    		executor = Executors.newFixedThreadPool(threads);
    		forkPool = new ForkJoinPool(threads);
    
    		long time = 0;
    		List<Fraction> farey = null;
    		for (int i = 0; i < 10; i++) {
    			time = System.currentTimeMillis();
    			farey = NestedIntervals.base(base).getFarey();
    
    			System.out.printf("Total %dms ", System.currentTimeMillis() - time);
    			System.out.println(farey.size());
    
    			farey = null;
    			System.gc();
    			time = System.currentTimeMillis();
    			farey = NestedIntervals.base(base).getFareyNonRecurcive();
    
    			System.out.printf("n Total %dms ", System.currentTimeMillis()
    					- time);
    			System.out.println(farey.size());
    
    			farey = null;
    			System.gc();
    			time = System.currentTimeMillis();
    			farey = NestedIntervals.base(base).getFareyNonRecurciveMultiThread(
    					threads);
    
    			System.out.printf("m Total %dms ", System.currentTimeMillis()
    					- time);
    			System.out.println(farey.size());
    
    			farey = null;
    			System.gc();
    			time = System.currentTimeMillis();
    			farey = NestedIntervals.base(base).getFareyNonRecurciveFork(parts);
    
    			System.out.printf("f Total %dms ", System.currentTimeMillis()
    					- time);
    			System.out.println(farey.size());
    
    			farey = null;
    			System.gc();
    		}
    		executor.shutdownNow();
    		forkPool.shutdownNow();
    	}
    }