1 package kmer;
2 
3 import java.util.Arrays;
4 
5 import shared.Primes;
6 import shared.Shared;
7 import shared.Tools;
8 import structures.IntList;
9 
10 public class ScheduleMaker {
11 
ScheduleMaker(int ways_, int bytesPerKmer_, boolean prealloc_, double memRatio_)12 	public ScheduleMaker(int ways_, int bytesPerKmer_, boolean prealloc_, double memRatio_){
13 		this(ways_, bytesPerKmer_, prealloc_, memRatio_, 0, 0, 0, 0);
14 	}
15 
ScheduleMaker(int ways_, int bytesPerKmer_, boolean prealloc_, double memRatio_, int initialSize_)16 	public ScheduleMaker(int ways_, int bytesPerKmer_, boolean prealloc_, double memRatio_, int initialSize_){
17 		this(ways_, bytesPerKmer_, prealloc_, memRatio_, initialSize_, 0, 0, 0);
18 	}
19 
ScheduleMaker(int ways_, int bytesPerKmer_, boolean prealloc_, double memRatio_, int initialSize_, int prepasses_, double prefilterFraction_, long filterMemoryOverride_)20 	public ScheduleMaker(int ways_, int bytesPerKmer_, boolean prealloc_, double memRatio_, int initialSize_,
21 			int prepasses_, double prefilterFraction_, long filterMemoryOverride_){
22 		bytesPerKmer=bytesPerKmer_;
23 		prealloc=prealloc_;
24 		memRatio=(float)(memRatio_<=0 ? 1 : memRatio_);
25 		prepasses=prepasses_;
26 		prefilter=(prepasses>0);
27 		prefilterFraction=prefilter ? prefilterFraction_ : 0;
28 		assert(prefilter==prefilterFraction>0) : prefilter+", "+prefilterFraction_+", "+prefilterFraction;
29 //		assert(false && prefilter==prefilterFraction>0) : prefilter+", "+prefilterFraction_+", "+prefilterFraction;
30 		if(prepasses<1){
31 			filterMemory0=filterMemory1=0;
32 		}else if(filterMemoryOverride>0){
33 			filterMemory0=filterMemory1=filterMemoryOverride;
34 		}else{
35 			double low=Tools.min(prefilterFraction, 1-prefilterFraction);
36 			double high=1-low;
37 			if(prepasses<0 || (prepasses&1)==1){//odd passes
38 				filterMemory0=(long)(usableMemory*low);
39 				filterMemory1=(long)(usableMemory*high);
40 			}else{//even passes
41 				filterMemory0=(long)(usableMemory*high);
42 				filterMemory1=(long)(usableMemory*low);
43 			}
44 		}
45 		tableMemory=(long)(usableMemory*.95-Tools.min(filterMemory0, filterMemory1));
46 
47 		if(ways_<1){
48 			long maxKmers=(2*tableMemory)/bytesPerKmer;
49 			long minWays=Tools.min(10000, maxKmers/Integer.MAX_VALUE);
50 			ways_=(int)Tools.max(31, (int)(Shared.threads()*2.5), minWays);
51 			ways_=(int)Primes.primeAtLeast(ways_);
52 			assert(ways_>0);
53 			//		System.err.println("ways="+ways_);
54 		}
55 		ways=ways_;
56 
57 		final double maxSize0=(tableMemory*0.95*memRatio)/(bytesPerKmer*ways);
58 		assert(maxPrime>1 && maxSize0>2) :
59 			"\nmaxPrime="+maxPrime+", maxSize0="+maxSize0+", tableMemory="+tableMemory+", usableMemory="+usableMemory+
60 			", \nprepasses="+prepasses+", filterMemory0="+filterMemory0+", filterMemory1="+filterMemory1+", prefilterFraction="+prefilterFraction+
61 			", \nmemRatio="+memRatio+", bytesPerKmer="+bytesPerKmer+", ways="+ways+
62 			", \ninitialSize="+initialSize_+", initialSizeDefault="+initialSizeDefault+", prealloc="+prealloc;
63 
64 		lastSizeFraction=prealloc ? 1.0 : resizeMult/(1.0+resizeMult);
65 		maxSize=Primes.primeAtMost((int)Tools.min(maxPrime, maxSize0*lastSizeFraction));
66 		initialSize=(prealloc ? maxSize : Primes.primeAtMost(initialSize_>0 ? initialSize_ : initialSizeDefault));
67 
68 		estimatedKmerCapacity=(long)(maxSize*HashArray.maxLoadFactorFinal*0.97*ways);
69 
70 //		System.err.println(Arrays.toString(makeSchedule()));
71 
72 //		System.err.println("ways="+ways+", maxSize="+maxSize+", estimatedKmerCapacity="+estimatedKmerCapacity+", "+Arrays.toString(makeSchedule()));
73 //
74 //		assert(false) :
75 //			"\nmaxPrime="+maxPrime+", maxSize0="+maxSize0+", tableMemory="+tableMemory+", usableMemory="+usableMemory+
76 //			", \nprepasses="+prepasses+", filterMemory0="+filterMemory0+", filterMemory1="+filterMemory1+", prefilterFraction="+prefilterFraction+
77 //			", \nmemRatio="+memRatio+", bytesPerKmer="+bytesPerKmer+", ways="+ways+
78 //			", \ninitialSize="+initialSize_+", initialSizeDefault="+initialSizeDefault+", prealloc="+prealloc+
79 //			", \nmaxSize="+maxSize+", initialSize="+initialSize+", estimatedKmerCapacity="+estimatedKmerCapacity+
80 //			", \n"+Arrays.toString(makeSchedule());
81 //		assert(false) : Arrays.toString(makeSchedule());
82 	}
83 
makeSchedule()84 	public int[] makeSchedule(){
85 		if(prealloc || maxSize<2L*initialSize){return new int[] {maxSize};}
86 		IntList list=new IntList(10);
87 		list.add(maxSize);
88 		for(double x=maxSize*invResizeMult; x>=initialSize; x=x*invResizeMult2){
89 			list.add((int)x);
90 		}
91 		if(list.size()>1 && list.lastElement()>=2*initialSize){
92 			list.add(initialSize);
93 		}
94 		list.reverse();
95 //		if(list.lastElement()*2L<maxPrime){list.add(2*maxSize);}//This ensures that the program will crash rather than garbage-collecting for a long time
96 		int[] array=list.toArray();
97 //		if(initialSize>2 && array.length>2 && array[0]>initialSize){array[0]=initialSize;}
98 		assert(Tools.isSorted(array)) : Arrays.toString(array);
99 		for(int i=0; i<array.length; i++){
100 			array[i]=array[i]==1 ? 1 : (int)Tools.min(maxPrime, Primes.primeAtLeast(array[i]));
101 		}
102 		return array;
103 	}
104 
105 //	public static int[] makeScheduleStatic(int initialSize, int maxSize, boolean autoResize){
106 //		if(!autoResize || initialSize>=maxSize){return null;}
107 //		IntList list=new IntList(10);
108 //		list.add((int)(maxSize*0.8));
109 //		for(long x=maxSize; x>=initialSize; x=x/5){
110 //			list.add((int)x);
111 //		}
112 //		if(list.size()>1 && list.lastElement()>=2*initialSize){
113 //			list.add(initialSize);
114 //		}
115 //		list.reverse();
116 //		int[] array=list.toArray();
117 //		for(int i=0; i<array.length; i++){
118 //			array[i]=array[i]==1 ? 1 : (int)Tools.min(maxPrime, Primes.primeAtLeast(array[i]));
119 //		}
120 //		return array;
121 //	}
122 
123 	final double resizeMult=5.0;
124 	final double resizeMult2=3.0;
125 	final double invResizeMult=1/resizeMult;
126 	final double invResizeMult2=1/resizeMult2;
127 	final double lastSizeFraction;
128 
129 	final long memory=Runtime.getRuntime().maxMemory();
130 	final double xmsRatio=Shared.xmsRatio();
131 
132 	//TODO: Add term for JDK (Oracle/Open) and version.
133 	final long usableMemory=(long)Tools.max(((memory-96000000)*
134 			(xmsRatio>0.97 ? 0.82 : 0.72)), memory*0.45);
135 
136 	final long filterMemoryOverride=0;
137 
138 	final long filterMemory0, filterMemory1;
139 	final long tableMemory;
140 	final double prefilterFraction;
141 	final int prepasses;
142 	final boolean prefilter;
143 	final int bytesPerKmer;
144 	public final long estimatedKmerCapacity;
145 
146 	public final int ways;
147 
148 	final int initialSize;
149 	final int maxSize;
150 
151 	final boolean prealloc;
152 	final float memRatio;
153 
154 	static final int initialSizeDefault=128000;
155 	static final int maxPrime=(int)Primes.primeAtMost(Integer.MAX_VALUE-100-20);
156 
157 }
158